From 2fbc1432025dd478cf9e940e3c2a1952b218c6dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Tue, 28 Mar 2017 21:31:37 +0200 Subject: QtWidgets: Fix white text color on tabs on macOS for non-macOS styles Apply white text only for macOS style. Amends 2c0033983bc53e906eab3f4b2fae836ff8472713 Task-number: QTBUG-59784 Change-Id: I9e66e929699efd715ed4565394f1aba763aeb32a Reviewed-by: Jake Petroules --- src/widgets/widgets/qtabbar.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 35d9498413..f14e63c584 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -176,12 +176,11 @@ void QTabBarPrivate::initBasicStyleOption(QStyleOptionTab *option, int tabIndex) if (tab.textColor.isValid()) option->palette.setColor(q->foregroundRole(), tab.textColor); -#ifdef Q_OS_MACOS - else if (isCurrent && !documentMode + else if (q->style()->inherits("QMacStyle") + && isCurrent && !documentMode && (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10 || q->isActiveWindow())) { option->palette.setColor(QPalette::WindowText, Qt::white); } -#endif option->icon = tab.icon; option->iconSize = q->iconSize(); // Will get the default value then. -- cgit v1.2.3 From cd9e850f9e9620a8bafec964efad8098443be7f1 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 30 Mar 2017 16:23:58 +0100 Subject: QCryptographicHash: fix documentation of the supported algorithms Change-Id: Idfa7843ef8a8e3410ae0a8cf5311b8b598299730 Reviewed-by: Thiago Macieira --- src/corelib/tools/qcryptographichash.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index 08f89d2f02..cdd7f6f4f6 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -196,7 +196,8 @@ public: QCryptographicHash can be used to generate cryptographic hashes of binary or text data. - Currently MD4, MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512 are supported. + Refer to the documentation of the \l QCryptographicHash::Algorithm enum for a + list of the supported algorithms. */ /*! -- cgit v1.2.3 From 88a8feeacb9bdaff9ee06164424e407eb904cd10 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 28 Mar 2017 20:09:22 +0100 Subject: QCryptographicHash: make SHA3 calculate SHA3, not Keccak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SHA3 family is a modified version of Keccak. We were incorrectly calculating Keccak (and even *testing* Keccak!), but claiming it was SHA3. To actually calculate SHA3, we need invoke Keccak on the original message followed by the two bits sequence 0b01, cf. §6.1 [1]. [1] http://dx.doi.org/10.6028/NIST.FIPS.202 [ChangeLog][QtCore][QCryptographicHash] QCryptographicHash now properly calculates SHA3 message digests. Before, when asked to calculate a SHA3 digest, it calculated a Keccak digest instead. Task-number: QTBUG-59770 Change-Id: Iae694d1a1668aa676922e3e00a292cddc30d3e0d Reviewed-by: Thiago Macieira --- src/corelib/tools/qcryptographichash.cpp | 52 ++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index cdd7f6f4f6..963a91b9a9 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -180,9 +180,45 @@ public: SHA3Context sha3Context; #endif }; +#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 + void sha3Finish(int bitCount); +#endif QByteArray result; }; +#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 +void QCryptographicHashPrivate::sha3Finish(int bitCount) +{ + /* + FIPS 202 §6.1 defines SHA-3 in terms of calculating the Keccak function + over the original message with the two-bit suffix "01" appended to it. + This variable stores that suffix (and it's fed into the calculations + when the hash is returned to users). + + Only 2 bits of this variable are actually used (see the call to sha3Update + below). The Keccak implementation we're using will actually use the + *leftmost* 2 bits, and interpret them right-to-left. In other words, the + bits must appear in order of *increasing* significance; and as the two most + significant bits of the byte -- the rightmost 6 are ignored. (Yes, this + seems self-contradictory, but it's the way it is...) + + Overall, this means: + * the leftmost two bits must be "10" (not "01"!); + * we don't care what the other six bits are set to (they can be set to + any value), but we arbitrarily set them to 0; + + and for an unsigned char this gives us 0b10'00'00'00, or 0x80. + */ + static const unsigned char sha3FinalSuffix = 0x80; + + result.resize(bitCount / 8); + + SHA3Context copy = sha3Context; + sha3Update(©, reinterpret_cast(&sha3FinalSuffix), 2); + sha3Final(©, reinterpret_cast(result.data())); +} +#endif + /*! \class QCryptographicHash \inmodule QtCore @@ -427,27 +463,19 @@ QByteArray QCryptographicHash::result() const break; } case Sha3_224: { - SHA3Context copy = d->sha3Context; - d->result.resize(224/8); - sha3Final(©, reinterpret_cast(d->result.data())); + d->sha3Finish(224); break; } case Sha3_256: { - SHA3Context copy = d->sha3Context; - d->result.resize(256/8); - sha3Final(©, reinterpret_cast(d->result.data())); + d->sha3Finish(256); break; } case Sha3_384: { - SHA3Context copy = d->sha3Context; - d->result.resize(384/8); - sha3Final(©, reinterpret_cast(d->result.data())); + d->sha3Finish(384); break; } case Sha3_512: { - SHA3Context copy = d->sha3Context; - d->result.resize(512/8); - sha3Final(©, reinterpret_cast(d->result.data())); + d->sha3Finish(512); break; } #endif -- cgit v1.2.3 From 507223a218aa218e80dd9eae9bd3958efda301cf Mon Sep 17 00:00:00 2001 From: Tobias Sung Date: Fri, 31 Mar 2017 17:08:50 +0200 Subject: Don't use non-POD type as variadic argument Implicit conversion from QByteArray to const char* works for most gtk functions. But gtk_file_chooser_dialog_new() uses varargs and passing the non-POD QByteArray through varargs does not work (it's UB). Task-number: QTBUG-59763 Change-Id: I85f9323d99342896e6921cdeb85f5a1af7377b4f Reviewed-by: Thiago Macieira Reviewed-by: Marc Mutz --- src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp index 8b6ec31400..eb7f0d8c2c 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp @@ -245,8 +245,8 @@ QGtk3FileDialogHelper::QGtk3FileDialogHelper() { d.reset(new QGtk3Dialog(gtk_file_chooser_dialog_new("", 0, GTK_FILE_CHOOSER_ACTION_OPEN, - standardButtonText(QPlatformDialogHelper::Cancel), GTK_RESPONSE_CANCEL, - standardButtonText(QPlatformDialogHelper::Ok), GTK_RESPONSE_OK, + standardButtonText(QPlatformDialogHelper::Cancel).constData(), GTK_RESPONSE_CANCEL, + standardButtonText(QPlatformDialogHelper::Ok).constData(), GTK_RESPONSE_OK, NULL))); connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted())); -- cgit v1.2.3 From 62013d77721820976102581b4cbd31404c109903 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 3 Mar 2017 11:46:26 -0800 Subject: Mark to remove const from function parameters in QtCore public headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some compilers are known to complain about this with a warning. GCC complains about const on return values on -Wignored-qualifiers (enabled at -Wextra), so it's not too much of a jump to assume that others do too. Besides, this is not Qt Library API policy. As maintainer for QtCore, I'm exercising my prerrogative in specifying certain unspecified parts of the coding style, like I've done for constructor initializer lists. Since all the classes involved are exported (including QVector, through derived classes), we can't remove the qualifier until Qt 6, since there are compilers known to encode the qualifier in the mangled name (suncc). I'm not introducing #ifdef to silence unknown compilers unless we get an actual complaint. Change-Id: I33850dcdb2ce4a47878efffd14a876edef843c46 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qmetatype.h | 2 +- src/corelib/kernel/qvariant.h | 2 +- src/corelib/tools/qvector.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 7b0a9f986b..5a90314735 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -526,7 +526,7 @@ public: static bool load(QDataStream &stream, int type, void *data); #endif - explicit QMetaType(const int type); + explicit QMetaType(const int type); // ### Qt6: drop const inline ~QMetaType(); inline bool isValid() const; diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index c0e5f2f591..a2c5711993 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -464,7 +464,7 @@ public: void create(int type, const void *copy); bool cmp(const QVariant &other) const; int compare(const QVariant &other) const; - bool convert(const int t, void *ptr) const; + bool convert(const int t, void *ptr) const; // ### Qt6: drop const private: // force compile error, prevent QVariant(bool) to be called diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index a526d35ddc..e345163c2f 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -291,6 +291,7 @@ public: private: friend class QRegion; // Optimization for QRegion::rects() + // ### Qt6: remove const from int parameters void reallocData(const int size, const int alloc, QArrayData::AllocationOptions options = QArrayData::Default); void reallocData(const int sz) { reallocData(sz, d->alloc); } void freeData(Data *d); -- cgit v1.2.3 From 392294936ed14ee75b3d1cdae559bd41bbf63ef2 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 1 Apr 2017 18:37:36 -0700 Subject: qfloat16: suppress warning caused by Clang macro we used Clang implements the _cvtss_sh intrinsic by way of a macro, which uses a C99 extension and that's not allowed in C++ mode: float16.h:119:11: error: compound literals are a C99-specific feature [-Werror,-Wc99-extensions] /usr/bin/../lib64/clang/3.9.1/include/f16cintrin.h:76:55: note: expanded from macro '_cvtss_sh' Reported at https://bugs.llvm.org/show_bug.cgi?id=32491. Change-Id: I27b55fdf514247549455fffd14b170df75dd4e1f Reviewed-by: Marc Mutz --- src/corelib/global/qfloat16.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 651057f8e2..0fa83db93f 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -113,6 +113,8 @@ inline Q_REQUIRED_RESULT bool qIsNull(qfloat16 f) Q_DECL_NOTHROW inline int qIntCast(qfloat16 f) Q_DECL_NOTHROW { return int(static_cast(f)); } +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wc99-extensions") inline qfloat16::qfloat16(float f) Q_DECL_NOTHROW { #if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__) @@ -127,6 +129,7 @@ inline qfloat16::qfloat16(float f) Q_DECL_NOTHROW + ((u & 0x007fffff) >> shifttable[(u >> 23) & 0x1ff]); #endif } +QT_WARNING_POP inline qfloat16::operator float() const Q_DECL_NOTHROW { -- cgit v1.2.3 From e94e4d002e977c8a1f0ff8dda9b4d6bcd0743336 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 31 Mar 2017 08:37:24 +0200 Subject: QMenu: Do not unnecessarily call QPlatformMenu::menuItemForTag() When handling QActionEvent / ActionAdded, QActionEvent::before() is 0 for the common 'append' case. Do not try to find a QPlatformMenuItem for this. Change-Id: I535b675fda6a2812b61eb8d7eec01da378ece413 Reviewed-by: Dmitry Shachnev Reviewed-by: Albert Astals Cid Reviewed-by: Shawn Rutledge --- src/widgets/widgets/qmenu.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 1925b58326..2b10ae7261 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -3456,7 +3456,9 @@ void QMenu::actionEvent(QActionEvent *e) QObject::connect(menuItem, SIGNAL(activated()), e->action(), SLOT(trigger())); QObject::connect(menuItem, SIGNAL(hovered()), e->action(), SIGNAL(hovered())); copyActionToPlatformItem(e->action(), menuItem, d->platformMenu); - QPlatformMenuItem* beforeItem = d->platformMenu->menuItemForTag(reinterpret_cast(e->before())); + QPlatformMenuItem *beforeItem = e->before() + ? d->platformMenu->menuItemForTag(reinterpret_cast(e->before())) + : nullptr; d->platformMenu->insertMenuItem(menuItem, beforeItem); } else if (e->type() == QEvent::ActionRemoved) { QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast(e->action())); -- cgit v1.2.3 From e0e6cbdacb7520a6d9906e16a517c9932702d1aa Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 13 Mar 2017 20:35:24 +0100 Subject: xcb: prevent dangling pointer when window focus changes With the current implementation, the QXcbConnection::m_focusWindow was holding a dangling pointer during the focus transition from a dying modal window to other modal window. 1) QXcbConnection::m_focusWindow holds a pointer to A; 2) A is closed; 3) relayFocusToModalWindow B; => m_focusWindow now points to a dead window. 4) We get a reply back from WM in a respone to relayFocusToModalWindow (_NET_ACTIVE_WINDOW) => m_focusWindow now points to a valid window. The fix is to update m_focusWindow to nullptr, when the current focus window was destroyed and the new focus window has not been set yet by WM. This patch actually solves a more general case - whenever we get a focus-out event, we should set m_focusWindow to nullptr. It is ok for none of the windows to be in-focus while focus transition is happening. The focusInPeeker will make sure to "optimize out" (when possible) this no-window-in-focus state, and GUI won't be bothered by this extra event. This is how things were working before relayFocusToModalWindow was introduced. Having a focus-relay mechanism in-between is ok, but it should not have changed the original behavior. Task-number: QTBUG-48391 Task-number: QTBUG-55197 Change-Id: I6fdda9de73f999dad84000059ce4b89c0d1a964c Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection.cpp | 4 ++-- src/plugins/platforms/xcb/qxcbconnection.h | 2 +- src/plugins/platforms/xcb/qxcbwindow.cpp | 20 +++++++++----------- 3 files changed, 12 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 5e600c740b..5e52d4d80f 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1382,9 +1382,9 @@ void QXcbEventReader::unlock() m_mutex.unlock(); } -void QXcbConnection::setFocusWindow(QXcbWindow *w) +void QXcbConnection::setFocusWindow(QWindow *w) { - m_focusWindow = w; + m_focusWindow = w ? static_cast(w->handle()) : nullptr; } void QXcbConnection::setMouseGrabber(QXcbWindow *w) { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 01a97a187a..22c7d1aa8e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -480,7 +480,7 @@ public: Qt::MouseButton translateMouseButton(xcb_button_t s); QXcbWindow *focusWindow() const { return m_focusWindow; } - void setFocusWindow(QXcbWindow *); + void setFocusWindow(QWindow *); QXcbWindow *mouseGrabber() const { return m_mouseGrabber; } void setMouseGrabber(QXcbWindow *); QXcbWindow *mousePressWindow() const { return m_mousePressWindow; } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 15ca68c663..509bc9b038 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -941,7 +941,7 @@ void QXcbWindow::doFocusIn() if (relayFocusToModalWindow()) return; QWindow *w = static_cast(QObjectPrivate::get(window()))->eventReceiver(); - connection()->setFocusWindow(static_cast(w->handle())); + connection()->setFocusWindow(w); QWindowSystemInterface::handleWindowActivated(w, Qt::ActiveWindowFocusReason); } @@ -949,7 +949,7 @@ static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event { if (!event) { // FocusIn event is not in the queue, proceed with FocusOut normally. - QWindowSystemInterface::handleWindowActivated(0, Qt::ActiveWindowFocusReason); + QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason); return true; } uint response_type = event->response_type & ~0x80; @@ -974,12 +974,10 @@ static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event void QXcbWindow::doFocusOut() { - if (relayFocusToModalWindow()) - return; - connection()->setFocusWindow(0); - // Do not set the active window to 0 if there is a FocusIn coming. - // There is however no equivalent for XPutBackEvent so register a - // callback for QXcbConnection instead. + connection()->setFocusWindow(nullptr); + relayFocusToModalWindow(); + // Do not set the active window to nullptr if there is a FocusIn coming. + // The FocusIn handler will update QXcbConnection::setFocusWindow() accordingly. connection()->addPeekFunc(focusInPeeker); } @@ -2834,14 +2832,14 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event) reason = Qt::OtherFocusReason; break; } - connection()->setFocusWindow(static_cast(window()->handle())); + connection()->setFocusWindow(window()); QWindowSystemInterface::handleWindowActivated(window(), reason); break; case XEMBED_FOCUS_OUT: if (window() == QGuiApplication::focusWindow() && !activeWindowChangeQueued(window())) { - connection()->setFocusWindow(0); - QWindowSystemInterface::handleWindowActivated(0); + connection()->setFocusWindow(nullptr); + QWindowSystemInterface::handleWindowActivated(nullptr); } break; } -- cgit v1.2.3 From c9f5607500a998d1f00737aca17ff73fb16775b8 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Tue, 21 Feb 2017 13:32:00 +0100 Subject: xcb: fix build when xlib is not present Remove Xutil.h include from qxcbmime.cpp as it does not use any Xlib APIs. Using API from Xutil.h requires Xlib as noted in Xutil.h: /* You must include before including this file */ Everywhere else we do check for presence of Xlib, before including Xutil.h And remove some useless #undef(s) Task-number: QTBUG-39665 Change-Id: Ibfd2341338fe7e902b47eae2df6b9dafe4ab962d Reviewed-by: Alexander Volkov Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbmime.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp index 7592eb2887..3ec8fa491f 100644 --- a/src/plugins/platforms/xcb/qxcbmime.cpp +++ b/src/plugins/platforms/xcb/qxcbmime.cpp @@ -44,12 +44,6 @@ #include #include -#include - -#undef XCB_ATOM_STRING -#undef XCB_ATOM_PIXMAP -#undef XCB_ATOM_BITMAP - QT_BEGIN_NAMESPACE #if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD)) -- cgit v1.2.3 From e1d3c8e203cc6b47535a846a143b808894942446 Mon Sep 17 00:00:00 2001 From: Eric Lemanissier Date: Tue, 28 Mar 2017 08:39:33 +0200 Subject: qtconcurrent: correct whitespaces Change-Id: Idaec09b75767a072bd817416c3cc2b19e3a0e03b Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Oswald Buddenhagen --- src/concurrent/qtconcurrentstoredfunctioncall.h | 100 ++++++++++++------------ 1 file changed, 50 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/concurrent/qtconcurrentstoredfunctioncall.h b/src/concurrent/qtconcurrentstoredfunctioncall.h index 750ece1ef1..eba6a1aad0 100644 --- a/src/concurrent/qtconcurrentstoredfunctioncall.h +++ b/src/concurrent/qtconcurrentstoredfunctioncall.h @@ -103,7 +103,7 @@ template class StoredMemberFunctionCall0 : public RunFunctionTask { public: - StoredMemberFunctionCall0(T (Class::*_fn)() , const Class &_object) + StoredMemberFunctionCall0(T (Class::*_fn)(), const Class &_object) : fn(_fn), object(_object){ } void runFunctor() override @@ -119,7 +119,7 @@ template class VoidStoredMemberFunctionCall0 : public RunFunctionTask { public: - VoidStoredMemberFunctionCall0(T (Class::*_fn)() , const Class &_object) + VoidStoredMemberFunctionCall0(T (Class::*_fn)(), const Class &_object) : fn(_fn), object(_object){ } void runFunctor() override @@ -150,7 +150,7 @@ public: this->result = (object.*fn)(); } private: - T (Class::*fn)()const; + T (Class::*fn)() const; const Class object; }; @@ -166,7 +166,7 @@ public: (object.*fn)(); } private: - T (Class::*fn)()const; + T (Class::*fn)() const; const Class object; }; @@ -181,7 +181,7 @@ template class StoredMemberFunctionPointerCall0 : public RunFunctionTask { public: - StoredMemberFunctionPointerCall0(T (Class::*_fn)() , Class *_object) + StoredMemberFunctionPointerCall0(T (Class::*_fn)(), Class *_object) : fn(_fn), object(_object){ } void runFunctor() override @@ -197,7 +197,7 @@ template class VoidStoredMemberFunctionPointerCall0 : public RunFunctionTask { public: - VoidStoredMemberFunctionPointerCall0(T (Class::*_fn)() , Class *_object) + VoidStoredMemberFunctionPointerCall0(T (Class::*_fn)(), Class *_object) : fn(_fn), object(_object){ } void runFunctor() override @@ -228,7 +228,7 @@ public: this->result = (object->*fn)(); } private: - T (Class::*fn)()const; + T (Class::*fn)() const; Class const *object; }; @@ -244,7 +244,7 @@ public: (object->*fn)(); } private: - T (Class::*fn)()const; + T (Class::*fn)() const; Class const *object; }; @@ -306,7 +306,7 @@ template class StoredMemberFunctionCall1 : public RunFunctionTask { public: - StoredMemberFunctionCall1(T (Class::*_fn)(Param1) , const Class &_object, const Arg1 &_arg1) + StoredMemberFunctionCall1(T (Class::*_fn)(Param1), const Class &_object, const Arg1 &_arg1) : fn(_fn), object(_object), arg1(_arg1){ } void runFunctor() override @@ -322,7 +322,7 @@ template class VoidStoredMemberFunctionCall1 : public RunFunctionTask { public: - VoidStoredMemberFunctionCall1(T (Class::*_fn)(Param1) , const Class &_object, const Arg1 &_arg1) + VoidStoredMemberFunctionCall1(T (Class::*_fn)(Param1), const Class &_object, const Arg1 &_arg1) : fn(_fn), object(_object), arg1(_arg1){ } void runFunctor() override @@ -353,7 +353,7 @@ public: this->result = (object.*fn)(arg1); } private: - T (Class::*fn)(Param1)const; + T (Class::*fn)(Param1) const; const Class object; Arg1 arg1; }; @@ -369,7 +369,7 @@ public: (object.*fn)(arg1); } private: - T (Class::*fn)(Param1)const; + T (Class::*fn)(Param1) const; const Class object; Arg1 arg1; }; @@ -384,7 +384,7 @@ template class StoredMemberFunctionPointerCall1 : public RunFunctionTask { public: - StoredMemberFunctionPointerCall1(T (Class::*_fn)(Param1) , Class *_object, const Arg1 &_arg1) + StoredMemberFunctionPointerCall1(T (Class::*_fn)(Param1), Class *_object, const Arg1 &_arg1) : fn(_fn), object(_object), arg1(_arg1){ } void runFunctor() override @@ -400,7 +400,7 @@ template class VoidStoredMemberFunctionPointerCall1 : public RunFunctionTask { public: - VoidStoredMemberFunctionPointerCall1(T (Class::*_fn)(Param1) , Class *_object, const Arg1 &_arg1) + VoidStoredMemberFunctionPointerCall1(T (Class::*_fn)(Param1), Class *_object, const Arg1 &_arg1) : fn(_fn), object(_object), arg1(_arg1){ } void runFunctor() override @@ -431,7 +431,7 @@ public: this->result = (object->*fn)(arg1); } private: - T (Class::*fn)(Param1)const; + T (Class::*fn)(Param1) const; Class const *object; Arg1 arg1; }; @@ -447,7 +447,7 @@ public: (object->*fn)(arg1); } private: - T (Class::*fn)(Param1)const; + T (Class::*fn)(Param1) const; Class const *object; Arg1 arg1; }; @@ -492,7 +492,7 @@ template struct VoidStoredFunctorPointerCall2: public RunFunctionTask { inline VoidStoredFunctorPointerCall2(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2) - : function(_function), arg1(_arg1), arg2(_arg2) {} + : function(_function), arg1(_arg1), arg2(_arg2) {} void runFunctor() override { (*function)(arg1, arg2); } FunctionPointer * function; Arg1 arg1; Arg2 arg2; @@ -509,7 +509,7 @@ template { public: - StoredMemberFunctionCall2(T (Class::*_fn)(Param1, Param2) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2) + StoredMemberFunctionCall2(T (Class::*_fn)(Param1, Param2), const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ } void runFunctor() override @@ -525,7 +525,7 @@ template { public: - VoidStoredMemberFunctionCall2(T (Class::*_fn)(Param1, Param2) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2) + VoidStoredMemberFunctionCall2(T (Class::*_fn)(Param1, Param2), const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ } void runFunctor() override @@ -556,7 +556,7 @@ public: this->result = (object.*fn)(arg1, arg2); } private: - T (Class::*fn)(Param1, Param2)const; + T (Class::*fn)(Param1, Param2) const; const Class object; Arg1 arg1; Arg2 arg2; }; @@ -572,7 +572,7 @@ public: (object.*fn)(arg1, arg2); } private: - T (Class::*fn)(Param1, Param2)const; + T (Class::*fn)(Param1, Param2) const; const Class object; Arg1 arg1; Arg2 arg2; }; @@ -587,7 +587,7 @@ template { public: - StoredMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2) + StoredMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2), Class *_object, const Arg1 &_arg1, const Arg2 &_arg2) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ } void runFunctor() override @@ -603,7 +603,7 @@ template { public: - VoidStoredMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2) + VoidStoredMemberFunctionPointerCall2(T (Class::*_fn)(Param1, Param2), Class *_object, const Arg1 &_arg1, const Arg2 &_arg2) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2){ } void runFunctor() override @@ -634,7 +634,7 @@ public: this->result = (object->*fn)(arg1, arg2); } private: - T (Class::*fn)(Param1, Param2)const; + T (Class::*fn)(Param1, Param2) const; Class const *object; Arg1 arg1; Arg2 arg2; }; @@ -650,7 +650,7 @@ public: (object->*fn)(arg1, arg2); } private: - T (Class::*fn)(Param1, Param2)const; + T (Class::*fn)(Param1, Param2) const; Class const *object; Arg1 arg1; Arg2 arg2; }; @@ -712,7 +712,7 @@ template { public: - StoredMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3) + StoredMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3), const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ } void runFunctor() override @@ -728,7 +728,7 @@ template { public: - VoidStoredMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3) + VoidStoredMemberFunctionCall3(T (Class::*_fn)(Param1, Param2, Param3), const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ } void runFunctor() override @@ -759,7 +759,7 @@ public: this->result = (object.*fn)(arg1, arg2, arg3); } private: - T (Class::*fn)(Param1, Param2, Param3)const; + T (Class::*fn)(Param1, Param2, Param3) const; const Class object; Arg1 arg1; Arg2 arg2; Arg3 arg3; }; @@ -775,7 +775,7 @@ public: (object.*fn)(arg1, arg2, arg3); } private: - T (Class::*fn)(Param1, Param2, Param3)const; + T (Class::*fn)(Param1, Param2, Param3) const; const Class object; Arg1 arg1; Arg2 arg2; Arg3 arg3; }; @@ -790,7 +790,7 @@ template { public: - StoredMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3) + StoredMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3), Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ } void runFunctor() override @@ -806,7 +806,7 @@ template { public: - VoidStoredMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3) + VoidStoredMemberFunctionPointerCall3(T (Class::*_fn)(Param1, Param2, Param3), Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3){ } void runFunctor() override @@ -837,7 +837,7 @@ public: this->result = (object->*fn)(arg1, arg2, arg3); } private: - T (Class::*fn)(Param1, Param2, Param3)const; + T (Class::*fn)(Param1, Param2, Param3) const; Class const *object; Arg1 arg1; Arg2 arg2; Arg3 arg3; }; @@ -853,7 +853,7 @@ public: (object->*fn)(arg1, arg2, arg3); } private: - T (Class::*fn)(Param1, Param2, Param3)const; + T (Class::*fn)(Param1, Param2, Param3) const; Class const *object; Arg1 arg1; Arg2 arg2; Arg3 arg3; }; @@ -915,7 +915,7 @@ template { public: - StoredMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4) + StoredMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4), const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ } void runFunctor() override @@ -931,7 +931,7 @@ template { public: - VoidStoredMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4) + VoidStoredMemberFunctionCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4), const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ } void runFunctor() override @@ -962,7 +962,7 @@ public: this->result = (object.*fn)(arg1, arg2, arg3, arg4); } private: - T (Class::*fn)(Param1, Param2, Param3, Param4)const; + T (Class::*fn)(Param1, Param2, Param3, Param4) const; const Class object; Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; }; @@ -978,7 +978,7 @@ public: (object.*fn)(arg1, arg2, arg3, arg4); } private: - T (Class::*fn)(Param1, Param2, Param3, Param4)const; + T (Class::*fn)(Param1, Param2, Param3, Param4) const; const Class object; Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; }; @@ -993,7 +993,7 @@ template { public: - StoredMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4) + StoredMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4), Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ } void runFunctor() override @@ -1009,7 +1009,7 @@ template { public: - VoidStoredMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4) + VoidStoredMemberFunctionPointerCall4(T (Class::*_fn)(Param1, Param2, Param3, Param4), Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4){ } void runFunctor() override @@ -1040,7 +1040,7 @@ public: this->result = (object->*fn)(arg1, arg2, arg3, arg4); } private: - T (Class::*fn)(Param1, Param2, Param3, Param4)const; + T (Class::*fn)(Param1, Param2, Param3, Param4) const; Class const *object; Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; }; @@ -1056,7 +1056,7 @@ public: (object->*fn)(arg1, arg2, arg3, arg4); } private: - T (Class::*fn)(Param1, Param2, Param3, Param4)const; + T (Class::*fn)(Param1, Param2, Param3, Param4) const; Class const *object; Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; }; @@ -1102,7 +1102,7 @@ struct VoidStoredFunctorPointerCall5: public RunFunctionTask { inline VoidStoredFunctorPointerCall5(FunctionPointer * _function, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5) : function(_function), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5) {} - void runFunctor() override {(*function)(arg1, arg2, arg3, arg4, arg5); } + void runFunctor() override { (*function)(arg1, arg2, arg3, arg4, arg5); } FunctionPointer * function; Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5; }; @@ -1118,7 +1118,7 @@ template { public: - StoredMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5) + StoredMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5), const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ } void runFunctor() override @@ -1134,7 +1134,7 @@ template { public: - VoidStoredMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5) + VoidStoredMemberFunctionCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5), const Class &_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ } void runFunctor() override @@ -1165,7 +1165,7 @@ public: this->result = (object.*fn)(arg1, arg2, arg3, arg4, arg5); } private: - T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const; + T (Class::*fn)(Param1, Param2, Param3, Param4, Param5) const; const Class object; Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5; }; @@ -1181,7 +1181,7 @@ public: (object.*fn)(arg1, arg2, arg3, arg4, arg5); } private: - T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const; + T (Class::*fn)(Param1, Param2, Param3, Param4, Param5) const; const Class object; Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5; }; @@ -1196,7 +1196,7 @@ template { public: - StoredMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5) + StoredMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5), Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ } void runFunctor() override @@ -1212,7 +1212,7 @@ template { public: - VoidStoredMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5) , Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5) + VoidStoredMemberFunctionPointerCall5(T (Class::*_fn)(Param1, Param2, Param3, Param4, Param5), Class *_object, const Arg1 &_arg1, const Arg2 &_arg2, const Arg3 &_arg3, const Arg4 &_arg4, const Arg5 &_arg5) : fn(_fn), object(_object), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5){ } void runFunctor() override @@ -1243,7 +1243,7 @@ public: this->result = (object->*fn)(arg1, arg2, arg3, arg4, arg5); } private: - T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const; + T (Class::*fn)(Param1, Param2, Param3, Param4, Param5) const; Class const *object; Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5; }; @@ -1259,7 +1259,7 @@ public: (object->*fn)(arg1, arg2, arg3, arg4, arg5); } private: - T (Class::*fn)(Param1, Param2, Param3, Param4, Param5)const; + T (Class::*fn)(Param1, Param2, Param3, Param4, Param5) const; Class const *object; Arg1 arg1; Arg2 arg2; Arg3 arg3; Arg4 arg4; Arg5 arg5; }; -- cgit v1.2.3 From c807dc3c122a2e21d6446231cd94f51cb0cf65d2 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 3 Apr 2017 20:48:33 +0100 Subject: Use fallthrough attributes only in C++ mode GCC 7 defines __has_cpp_attribute even when invoked as "gcc" (possibly, Clang does the same, according to a comment in the code, did not test myself). Hence, define the fallthrough declaration (as C++11 attributes) only when compiling as C++, otherwise we pick them up even in C mode, and they cause build failures. Change-Id: I3f13205e014bb1dea59ee3664b29111521a7eae3 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/global/qcompilerdetection.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 3b83d81f02..eacb7a04d7 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1328,15 +1328,14 @@ Q_ASSUME_IMPL(valueOfExpression);\ } while (0) +#if defined(__cplusplus) #if QT_HAS_CPP_ATTRIBUTE(fallthrough) # define Q_FALLTHROUGH() [[fallthrough]] -#elif defined(__cplusplus) -/* Clang can not parse namespaced attributes in C mode, but defines __has_cpp_attribute */ -# if QT_HAS_CPP_ATTRIBUTE(clang::fallthrough) +#elif QT_HAS_CPP_ATTRIBUTE(clang::fallthrough) # define Q_FALLTHROUGH() [[clang::fallthrough]] -# elif QT_HAS_CPP_ATTRIBUTE(gnu::fallthrough) +#elif QT_HAS_CPP_ATTRIBUTE(gnu::fallthrough) # define Q_FALLTHROUGH() [[gnu::fallthrough]] -# endif +#endif #endif #ifndef Q_FALLTHROUGH # if defined(Q_CC_GNU) && Q_CC_GNU >= 700 -- cgit v1.2.3 From 116ade88ea20d8b43a4cafac4ad23289f123b532 Mon Sep 17 00:00:00 2001 From: Pavol Markovic Date: Thu, 23 Feb 2017 15:20:04 +1300 Subject: macOS: Replace deprecated NSOpenSavePanelDelegate method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit shouldShowFilename method has been deprecated since macOS 10.6. In 10.11 the behavior of this method has been broken, causing files containing metadata (e.g. audio) to be incorrectly filtered out, displayed them as disabled in file dialog even though they shouldn’t be. This erratic behavior applies also to NSOpenPanel setAllowedFileTypes if set to anything but nil. This has been confirmed to be a known bug in Cocoa. Using shouldEnableURL solves this problem and also removes risk of breaking compatibility with future SDKs. Renamed and simplified private method isHiddenFile to isHiddenFileAtURL. Renamed to be consistent with other Cocoa file query methods. Simplified to return true only if the file is hidden as the name of the method implies. Previously it might have returned true also if the file has not existed which was in fact very metaphysical answer. Check for presence of the file is done by other method before calling this one and the scope of the method is limited to one source file. Task-number: QTBUG-57527 Change-Id: I2fded712d4e7098eb444331d92e38cee71655100 Reviewed-by: Tor Arne Vestbø --- .../platforms/cocoa/qcocoafiledialoghelper.mm | 52 ++++++++++++---------- 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index e39d5e4546..4ba3dcb9a6 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -101,7 +101,7 @@ typedef QSharedPointer SharedPointerFileDialogOptions; } - (NSString *)strip:(const QString &)label; -- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename; +- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url; - (void)filterChanged:(id)sender; - (void)showModelessPanel; - (BOOL)runApplicationModalPanel; @@ -222,12 +222,12 @@ static QString strippedText(QString s) if (mOpenPanel){ QFileInfo info(*mCurrentSelection); NSString *filepath = info.filePath().toNSString(); + NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()]; bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) - || [self panel:nil shouldShowFilename:filepath]; + || [self panel:nil shouldEnableURL:url]; [self updateProperties]; QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder(); - [mOpenPanel setAllowedFileTypes:nil]; [mSavePanel setNameFieldStringValue:selectable ? info.fileName().toNSString() : @""]; [mOpenPanel beginWithCompletionHandler:^(NSInteger result){ @@ -242,8 +242,9 @@ static QString strippedText(QString s) { QFileInfo info(*mCurrentSelection); NSString *filepath = info.filePath().toNSString(); + NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()]; bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) - || [self panel:nil shouldShowFilename:filepath]; + || [self panel:nil shouldEnableURL:url]; [mSavePanel setDirectoryURL: [NSURL fileURLWithPath:mCurrentDir]]; [mSavePanel setNameFieldStringValue:selectable ? info.fileName().toNSString() : @""]; @@ -273,8 +274,9 @@ static QString strippedText(QString s) { QFileInfo info(*mCurrentSelection); NSString *filepath = info.filePath().toNSString(); + NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()]; bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) - || [self panel:nil shouldShowFilename:filepath]; + || [self panel:nil shouldEnableURL:url]; [self updateProperties]; QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder(); @@ -290,26 +292,24 @@ static QString strippedText(QString s) }]; } -- (BOOL)isHiddenFile:(NSString *)filename isDir:(BOOL)isDir +- (BOOL)isHiddenFileAtURL:(NSURL *)url { - CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)filename, kCFURLPOSIXPathStyle, isDir); - CFBooleanRef isHidden; - Boolean errorOrHidden = false; - if (!CFURLCopyResourcePropertyForKey(url, kCFURLIsHiddenKey, &isHidden, NULL)) { - errorOrHidden = true; - } else { - if (CFBooleanGetValue(isHidden)) - errorOrHidden = true; - CFRelease(isHidden); + BOOL hidden = NO; + if (url) { + CFBooleanRef isHiddenProperty; + if (CFURLCopyResourcePropertyForKey((__bridge CFURLRef)url, kCFURLIsHiddenKey, &isHiddenProperty, NULL)) { + hidden = CFBooleanGetValue(isHiddenProperty); + CFRelease(isHiddenProperty); + } } - CFRelease(url); - return errorOrHidden; + return hidden; } -- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename +- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url { Q_UNUSED(sender); + NSString *filename = [url path]; if ([filename length] == 0) return NO; @@ -353,7 +353,7 @@ static QString strippedText(QString s) return NO; } if (!(filter & QDir::Hidden) - && (qtFileName.startsWith(QLatin1Char('.')) || [self isHiddenFile:filename isDir:isDir])) + && (qtFileName.startsWith(QLatin1Char('.')) || [self isHiddenFileAtURL:url])) return NO; return YES; @@ -446,11 +446,15 @@ static QString strippedText(QString s) [mSavePanel setTitle:mOptions->windowTitle().toNSString()]; [mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead? - QStringList ext = [self acceptableExtensionsForSave]; - const QString defaultSuffix = mOptions->defaultSuffix(); - if (!ext.isEmpty() && !defaultSuffix.isEmpty()) - ext.prepend(defaultSuffix); - [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(ext)]; + if (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) { + QStringList ext = [self acceptableExtensionsForSave]; + const QString defaultSuffix = mOptions->defaultSuffix(); + if (!ext.isEmpty() && !defaultSuffix.isEmpty()) + ext.prepend(defaultSuffix); + [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(ext)]; + } else { + [mOpenPanel setAllowedFileTypes:nil]; // delegate panel:shouldEnableURL: does the file filtering for NSOpenPanel + } if ([mSavePanel respondsToSelector:@selector(isVisible)] && [mSavePanel isVisible]) { if ([mSavePanel respondsToSelector:@selector(validateVisibleColumns)]) -- cgit v1.2.3 From b53c229a4b394e6b83268151845e1fee734f633d Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Sat, 14 Jan 2017 12:22:53 +0900 Subject: Fix build without features.networkinterface Change-Id: I9fd2a7ec402a1d2d99e30f08554d86f18c6424ff Reviewed-by: Paul Olav Tvete --- src/network/socket/qnativesocketengine_p.h | 4 ++++ src/network/socket/qnativesocketengine_unix.cpp | 2 ++ 2 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 4d1d8e1eb1..08e72072ef 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -286,8 +286,10 @@ public: bool checkProxy(const QHostAddress &address); bool fetchConnectionParameters(); +#if QT_CONFIG(networkinterface) static uint scopeIdFromString(const QString &scopeid) { return QNetworkInterface::interfaceIndexFromName(scopeid); } +#endif /*! \internal Sets \a address and \a port in the \a aa sockaddr structure and the size in \a sockAddrSize. @@ -301,7 +303,9 @@ public: || socketProtocol == QAbstractSocket::AnyIPProtocol) { memset(&aa->a6, 0, sizeof(sockaddr_in6)); aa->a6.sin6_family = AF_INET6; +#if QT_CONFIG(networkinterface) aa->a6.sin6_scope_id = scopeIdFromString(address.scopeId()); +#endif aa->a6.sin6_port = htons(port); Q_IPV6ADDR tmp = address.toIPv6Address(); memcpy(&aa->a6.sin6_addr, &tmp, sizeof(tmp)); diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index e140b33ce9..09c06adb1e 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -121,8 +121,10 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po QHostAddress tmpAddress; tmpAddress.setAddress(tmp); *addr = tmpAddress; +#if QT_CONFIG(networkinterface) if (s->a6.sin6_scope_id) addr->setScopeId(QNetworkInterface::interfaceNameFromIndex(s->a6.sin6_scope_id)); +#endif } if (port) *port = ntohs(s->a6.sin6_port); -- cgit v1.2.3 From a7b32ff63c1ed915ac9173dfdc99555cd2e303e6 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Mon, 3 Apr 2017 11:38:52 +0900 Subject: Fix build without features.qeventtransition Change-Id: I498d482b01d9dcaf794d35ecc26110c9a2d45ce0 Reviewed-by: Kevin Funk Reviewed-by: Lars Knoll --- src/corelib/statemachine/qstatemachine.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index d7cdec9aac..1d80da55c9 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -2331,6 +2331,7 @@ void QStateMachinePrivate::unregisterAllTransitions() unregisterSignalTransition(t); } } +#if QT_CONFIG(qeventtransition) { QList transitions = rootState()->findChildren(); for (int i = 0; i < transitions.size(); ++i) { @@ -2339,6 +2340,7 @@ void QStateMachinePrivate::unregisterAllTransitions() unregisterEventTransition(t); } } +#endif } #if QT_CONFIG(qeventtransition) -- cgit v1.2.3 From 6a83f9aa98760d0ed1ab4c216a28a10862e86f00 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 29 Mar 2017 16:38:54 -0700 Subject: Fix qReallocAligned for reallocation when alignment > 2*sizeof(void*) When we call realloc, the alignment of the new block may be different from the old one. When that happens, we need to memmove the data to the new position, before we start overwriting things. Task-number: QTBUG-59804 Change-Id: I27b55fdf514247549455fffd14b07ea78918a3d0 Reviewed-by: Oswald Buddenhagen --- src/corelib/global/qmalloc.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qmalloc.cpp b/src/corelib/global/qmalloc.cpp index f83cecd499..05676a0da2 100644 --- a/src/corelib/global/qmalloc.cpp +++ b/src/corelib/global/qmalloc.cpp @@ -40,6 +40,7 @@ #include "qplatformdefs.h" #include +#include /* Define the container allocation functions in a separate file, so that our @@ -79,8 +80,6 @@ void *qMallocAligned(size_t size, size_t alignment) void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t alignment) { // fake an aligned allocation - Q_UNUSED(oldsize); - void *actualptr = oldptr ? static_cast(oldptr)[-1] : 0; if (alignment <= sizeof(void*)) { // special, fast case @@ -110,9 +109,15 @@ void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t align quintptr faked = reinterpret_cast(real) + alignment; faked &= ~(alignment - 1); - void **faked_ptr = reinterpret_cast(faked); + if (oldptr) { + qptrdiff oldoffset = static_cast(oldptr) - static_cast(actualptr); + qptrdiff newoffset = reinterpret_cast(faked_ptr) - static_cast(real); + if (oldoffset != newoffset) + memmove(faked_ptr, static_cast(real) + oldoffset, qMin(oldsize, newsize)); + } + // now save the value of the real pointer at faked-sizeof(void*) // by construction, alignment > sizeof(void*) and is a power of 2, so // faked-sizeof(void*) is properly aligned for a pointer -- cgit v1.2.3 From 229fd2cecef4798328b0510a31fac98be85ed81b Mon Sep 17 00:00:00 2001 From: Andreas Holzammer Date: Mon, 3 Apr 2017 16:38:35 +0200 Subject: CMAKE: Fix EGL link extensions Targets were always exported as .lib, for all windows compilers which is correct for msvc, but not for mingw. Hence use QMAKE_EXTENSION_STATICLIB to switch between .lib and .a Task-number: QTBUG-59906 Change-Id: I948f5dd96e0fb46d679c474b7beececc379ad436 Reviewed-by: Volker Krause Reviewed-by: Friedemann Kleint Reviewed-by: Kevin Funk Reviewed-by: Oswald Buddenhagen --- src/gui/gui.pro | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 511cfd1d22..cfdb5e889b 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -57,13 +57,13 @@ win32: CMAKE_WINDOWS_BUILD = True qtConfig(angle) { CMAKE_GL_INCDIRS = $$CMAKE_INCLUDE_DIR CMAKE_ANGLE_EGL_DLL_RELEASE = libEGL.dll - CMAKE_ANGLE_EGL_IMPLIB_RELEASE = libEGL.lib + CMAKE_ANGLE_EGL_IMPLIB_RELEASE = libEGL.$${QMAKE_EXTENSION_STATICLIB} CMAKE_ANGLE_GLES2_DLL_RELEASE = libGLESv2.dll - CMAKE_ANGLE_GLES2_IMPLIB_RELEASE = libGLESv2.lib + CMAKE_ANGLE_GLES2_IMPLIB_RELEASE = libGLESv2.$${QMAKE_EXTENSION_STATICLIB} CMAKE_ANGLE_EGL_DLL_DEBUG = libEGLd.dll - CMAKE_ANGLE_EGL_IMPLIB_DEBUG = libEGLd.lib + CMAKE_ANGLE_EGL_IMPLIB_DEBUG = libEGLd.$${QMAKE_EXTENSION_STATICLIB} CMAKE_ANGLE_GLES2_DLL_DEBUG = libGLESv2d.dll - CMAKE_ANGLE_GLES2_IMPLIB_DEBUG = libGLESv2d.lib + CMAKE_ANGLE_GLES2_IMPLIB_DEBUG = libGLESv2d.$${QMAKE_EXTENSION_STATICLIB} CMAKE_QT_OPENGL_IMPLEMENTATION = GLESv2 } else { -- cgit v1.2.3 From 22d43c9e51e377cbc00aee362a740ab578a8158b Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 4 Apr 2017 10:13:08 +0200 Subject: xcb: Get rid of qCInfo in the GLX backend qCInfo must never be used. For qt.* logging categories Debug is disabled while everything else is enabled by default. This means that doing qCInfo is equivalent to putting a qDebug which is not acceptable. Amends 3e0355014edda23d94605c77dd8c1582b91f9c18 Change-Id: I428e620f12afa324cf6af8dbe3912a55189a38a9 Reviewed-by: Andy Shaw --- .../platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index caa4b7361a..7640a711a9 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -693,7 +693,7 @@ void QGLXContext::queryDummyContext() if (const char *renderer = (const char *) glGetString(GL_RENDERER)) { for (int i = 0; qglx_threadedgl_blacklist_renderer[i]; ++i) { if (strstr(renderer, qglx_threadedgl_blacklist_renderer[i]) != 0) { - qCInfo(lcQpaGl).nospace() << "Multithreaded OpenGL disabled: " + qCDebug(lcQpaGl).nospace() << "Multithreaded OpenGL disabled: " "blacklisted renderer \"" << qglx_threadedgl_blacklist_renderer[i] << "\""; @@ -706,7 +706,7 @@ void QGLXContext::queryDummyContext() if (glxvendor) { for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) { if (strstr(glxvendor, qglx_threadedgl_blacklist_vendor[i]) != 0) { - qCInfo(lcQpaGl).nospace() << "Multithreaded OpenGL disabled: " + qCDebug(lcQpaGl).nospace() << "Multithreaded OpenGL disabled: " "blacklisted vendor \"" << qglx_threadedgl_blacklist_vendor[i] << "\""; @@ -722,7 +722,7 @@ void QGLXContext::queryDummyContext() oldContext->makeCurrent(oldSurface); if (!m_supportsThreading) { - qCInfo(lcQpaGl) << "Force-enable multithreaded OpenGL by setting " + qCDebug(lcQpaGl) << "Force-enable multithreaded OpenGL by setting " "environment variable QT_OPENGL_NO_SANITY_CHECK"; } } -- cgit v1.2.3 From 267c2c2a93eb3aa09b01f0fe383ee01a6fcdbec2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 4 Apr 2017 10:32:06 +0200 Subject: QFusionStyle::drawPrimitive(): Use color in cache key of PE_PanelButtonCommand Previously, only bool isDefault was used, which did not discriminate changes in ButtonColor. Use the color name instead. Task-number: QTBUG-59850 Change-Id: I1e006f98371a5f2039dcca1207addc0396e7c1e5 Reviewed-by: J-P Nurmi --- src/widgets/styles/qfusionstyle.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 98d45587f0..19b1cc2c57 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -908,8 +908,6 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, return; } - BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("pushbutton-%1").arg(isDefault)) - r = rect.adjusted(0, 1, -1, 0); bool isEnabled = option->state & State_Enabled; bool hasFocus = (option->state & State_HasFocus && option->state & State_KeyboardFocusChange); @@ -923,6 +921,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, if (isDefault) buttonColor = mergedColors(buttonColor, highlightedOutline.lighter(130), 90); + BEGIN_STYLE_PIXMAPCACHE(QStringLiteral("pushbutton-") + buttonColor.name(QColor::HexArgb)) + r = rect.adjusted(0, 1, -1, 0); + p->setRenderHint(QPainter::Antialiasing, true); p->translate(0.5, -0.5); -- cgit v1.2.3 From 876563ced0219bb2fac1d323a3c3f79ac3141455 Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Mon, 3 Apr 2017 20:47:20 +0200 Subject: No divide by zero if all imageformat features are disabled Change-Id: Ib3e8a4b62ae627bc3dc8541767dafff4e493d2f8 Reviewed-by: Tasuku Suzuki Reviewed-by: Eirik Aavitsland --- src/gui/image/qimagereader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 2f25f4dcbc..d01f0d640b 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -471,7 +471,8 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, --numFormats; ++currentFormat; - currentFormat %= _qt_NumFormats; + if (currentFormat >= _qt_NumFormats) + currentFormat = 0; } } -- cgit v1.2.3 From e33b0118b402224e75cb7bd6468d719312505b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 24 Mar 2017 14:29:03 +0100 Subject: Rename QBasicFontDatabase to QFreeTypeFontDatabase which is what it is Change-Id: I8def2f7ae1e4c8d8a3e1f8e60549da5d691e4fb3 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/platformsupport/fontdatabases/basic/basic.pri | 9 - .../fontdatabases/basic/qbasicfontdatabase.cpp | 282 --- .../fontdatabases/basic/qbasicfontdatabase_p.h | 80 - .../fontdatabases/basic/qfontengine_ft.cpp | 2214 -------------------- .../fontdatabases/basic/qfontengine_ft_p.h | 360 ---- .../fontconfig/qfontconfigdatabase.cpp | 4 +- .../fontconfig/qfontconfigdatabase_p.h | 4 +- .../fontdatabases/fontdatabases.pro | 2 +- .../fontdatabases/freetype/freetype.pri | 9 + .../fontdatabases/freetype/qfontengine_ft.cpp | 2214 ++++++++++++++++++++ .../fontdatabases/freetype/qfontengine_ft_p.h | 360 ++++ .../freetype/qfreetypefontdatabase.cpp | 282 +++ .../freetype/qfreetypefontdatabase_p.h | 80 + .../genericunix/qgenericunixfontdatabase_p.h | 4 +- src/platformsupport/fontdatabases/mac/coretext.pri | 4 +- .../windows/qwindowsfontdatabase_ft.cpp | 6 +- .../windows/qwindowsfontdatabase_ft_p.h | 4 +- .../fontdatabases/winrt/qwinrtfontdatabase.cpp | 14 +- .../fontdatabases/winrt/qwinrtfontdatabase_p.h | 4 +- .../android/qandroidplatformfontdatabase.cpp | 4 +- .../android/qandroidplatformfontdatabase.h | 4 +- .../platforms/minimal/qminimalintegration.cpp | 2 +- .../platforms/offscreen/qoffscreenintegration.cpp | 4 +- 23 files changed, 2975 insertions(+), 2975 deletions(-) delete mode 100644 src/platformsupport/fontdatabases/basic/basic.pri delete mode 100644 src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp delete mode 100644 src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h delete mode 100644 src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp delete mode 100644 src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h create mode 100644 src/platformsupport/fontdatabases/freetype/freetype.pri create mode 100644 src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp create mode 100644 src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h create mode 100644 src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp create mode 100644 src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase_p.h (limited to 'src') diff --git a/src/platformsupport/fontdatabases/basic/basic.pri b/src/platformsupport/fontdatabases/basic/basic.pri deleted file mode 100644 index 0617bf74d7..0000000000 --- a/src/platformsupport/fontdatabases/basic/basic.pri +++ /dev/null @@ -1,9 +0,0 @@ -HEADERS += \ - $$PWD/qbasicfontdatabase_p.h \ - $$PWD/qfontengine_ft_p.h - -SOURCES += \ - $$PWD/qbasicfontdatabase.cpp \ - $$PWD/qfontengine_ft.cpp - -QMAKE_USE_PRIVATE += freetype diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp deleted file mode 100644 index 0826b0f2fb..0000000000 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbasicfontdatabase_p.h" - -#include -#include - -#include -#include -#include -#include -#include - -#undef QT_NO_FREETYPE -#include - -#include -#include FT_TRUETYPE_TABLES_H -#include FT_ERRORS_H - -QT_BEGIN_NAMESPACE - -void QBasicFontDatabase::populateFontDatabase() -{ - QString fontpath = fontDir(); - QDir dir(fontpath); - - if (!dir.exists()) { - qWarning("QFontDatabase: Cannot find font directory %s.\n" - "Note that Qt no longer ships fonts. Deploy some (from http://dejavu-fonts.org for example) or switch to fontconfig.", - qPrintable(fontpath)); - return; - } - - QStringList nameFilters; - nameFilters << QLatin1String("*.ttf") - << QLatin1String("*.ttc") - << QLatin1String("*.pfa") - << QLatin1String("*.pfb") - << QLatin1String("*.otf"); - - const auto fis = dir.entryInfoList(nameFilters, QDir::Files); - for (const QFileInfo &fi : fis) { - const QByteArray file = QFile::encodeName(fi.absoluteFilePath()); - QBasicFontDatabase::addTTFile(QByteArray(), file); - } -} - -QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPtr) -{ - FontFile *fontfile = static_cast (usrPtr); - QFontEngine::FaceId fid; - fid.filename = QFile::encodeName(fontfile->fileName); - fid.index = fontfile->indexValue; - - bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - QFontEngineFT *engine = new QFontEngineFT(fontDef); - QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono; - if (antialias) { - QFontEngine::SubpixelAntialiasingType subpixelType = subpixelAntialiasingTypeHint(); - if (subpixelType == QFontEngine::Subpixel_None || (fontDef.styleStrategy & QFont::NoSubpixelAntialias)) { - format = QFontEngineFT::Format_A8; - engine->subpixelType = QFontEngine::Subpixel_None; - } else { - format = QFontEngineFT::Format_A32; - engine->subpixelType = subpixelType; - } - } - - if (!engine->init(fid, antialias, format) || engine->invalid()) { - delete engine; - engine = 0; - } else { - engine->setQtDefaultHintStyle(static_cast(fontDef.hintingPreference)); - } - - return engine; -} - -namespace { - - class QFontEngineFTRawData: public QFontEngineFT - { - public: - QFontEngineFTRawData(const QFontDef &fontDef) : QFontEngineFT(fontDef) - { - } - - void updateFamilyNameAndStyle() - { - fontDef.family = QString::fromLatin1(freetype->face->family_name); - - if (freetype->face->style_flags & FT_STYLE_FLAG_ITALIC) - fontDef.style = QFont::StyleItalic; - - if (freetype->face->style_flags & FT_STYLE_FLAG_BOLD) - fontDef.weight = QFont::Bold; - } - - bool initFromData(const QByteArray &fontData) - { - FaceId faceId; - faceId.filename = ""; - faceId.index = 0; - faceId.uuid = QUuid::createUuid().toByteArray(); - - return init(faceId, true, Format_None, fontData); - } - }; - -} - -QFontEngine *QBasicFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, - QFont::HintingPreference hintingPreference) -{ - QFontDef fontDef; - fontDef.pixelSize = pixelSize; - fontDef.hintingPreference = hintingPreference; - - QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef); - if (!fe->initFromData(fontData)) { - delete fe; - return 0; - } - - fe->updateFamilyNameAndStyle(); - fe->setQtDefaultHintStyle(static_cast(fontDef.hintingPreference)); - - return fe; -} - -QStringList QBasicFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) -{ - return QBasicFontDatabase::addTTFile(fontData, fileName.toLocal8Bit()); -} - -void QBasicFontDatabase::releaseHandle(void *handle) -{ - FontFile *file = static_cast(handle); - delete file; -} - -extern FT_Library qt_getFreetype(); - -QStringList QBasicFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file) -{ - FT_Library library = qt_getFreetype(); - - int index = 0; - int numFaces = 0; - QStringList families; - 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; - - QFont::Weight 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; - - bool fixedPitch = (face->face_flags & FT_FACE_FLAG_FIXED_WIDTH); - - 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_MS_SYMBOL) { - writingSystems.setSupported(QFontDatabase::Symbol); - break; - } - } - - TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); - if (os2) { - quint32 unicodeRange[4] = { - quint32(os2->ulUnicodeRange1), - quint32(os2->ulUnicodeRange2), - quint32(os2->ulUnicodeRange3), - quint32(os2->ulUnicodeRange4) - }; - quint32 codePageRange[2] = { - quint32(os2->ulCodePageRange1), - quint32(os2->ulCodePageRange2) - }; - - writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); - - if (os2->usWeightClass) { - weight = QPlatformFontDatabase::weightFromInteger(os2->usWeightClass); - } else if (os2->panose[2]) { - int w = os2->panose[2]; - if (w <= 1) - weight = QFont::Thin; - else if (w <= 2) - weight = QFont::ExtraLight; - else if (w <= 3) - weight = QFont::Light; - else if (w <= 5) - weight = QFont::Normal; - else if (w <= 6) - weight = QFont::Medium; - else if (w <= 7) - weight = QFont::DemiBold; - else if (w <= 8) - weight = QFont::Bold; - else if (w <= 9) - weight = QFont::ExtraBold; - else if (w <= 10) - weight = QFont::Black; - } - } - - QString family = QString::fromLatin1(face->family_name); - FontFile *fontFile = new FontFile; - fontFile->fileName = QFile::decodeName(file); - fontFile->indexValue = index; - - QFont::Stretch stretch = QFont::Unstretched; - - registerFont(family,QString::fromLatin1(face->style_name),QString(),weight,style,stretch,true,true,0,fixedPitch,writingSystems,fontFile); - - families.append(family); - - FT_Done_Face(face); - ++index; - } while (index < numFaces); - return families; -} - -QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h deleted file mode 100644 index 8d8f61973b..0000000000 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QBASICFONTDATABASE_H -#define QBASICFONTDATABASE_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 - -QT_BEGIN_NAMESPACE - -struct FontFile -{ - QString fileName; - int indexValue; -}; - -class QBasicFontDatabase : public QPlatformFontDatabase -{ -public: - void populateFontDatabase() Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE; - QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) Q_DECL_OVERRIDE; - void releaseHandle(void *handle) Q_DECL_OVERRIDE; - - static QStringList addTTFile(const QByteArray &fontData, const QByteArray &file); -}; - -QT_END_NAMESPACE - -#endif // QBASICFONTDATABASE_H diff --git a/src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp deleted file mode 100644 index 03e72546eb..0000000000 --- a/src/platformsupport/fontdatabases/basic/qfontengine_ft.cpp +++ /dev/null @@ -1,2214 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdir.h" -#include "qmetatype.h" -#include "qtextstream.h" -#include "qvariant.h" -#include "qfontengine_ft_p.h" -#include "private/qimage_p.h" -#include - -#ifndef QT_NO_FREETYPE - -#include "qfile.h" -#include "qfileinfo.h" -#include -#include "qthreadstorage.h" -#include -#include - -#include -#include FT_FREETYPE_H -#include FT_OUTLINE_H -#include FT_SYNTHESIS_H -#include FT_TRUETYPE_TABLES_H -#include FT_TYPE1_TABLES_H -#include FT_GLYPH_H -#include FT_MODULE_H - -#if defined(FT_LCD_FILTER_H) -#include FT_LCD_FILTER_H -#define QT_USE_FREETYPE_LCDFILTER -#endif - -#if defined(FT_CONFIG_OPTIONS_H) -#include FT_CONFIG_OPTIONS_H -#endif - -#if defined(FT_FONT_FORMATS_H) -#include FT_FONT_FORMATS_H -#endif - -#ifdef QT_LINUXBASE -#include FT_ERRORS_H -#endif - -#if !defined(QT_MAX_CACHED_GLYPH_SIZE) -# define QT_MAX_CACHED_GLYPH_SIZE 64 -#endif - -QT_BEGIN_NAMESPACE - -#define FLOOR(x) ((x) & -64) -#define CEIL(x) (((x)+63) & -64) -#define TRUNC(x) ((x) >> 6) -#define ROUND(x) (((x)+32) & -64) - -static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length) -{ - FT_Face face = (FT_Face)user_data; - - bool result = false; - if (FT_IS_SFNT(face)) { - FT_ULong len = *length; - result = FT_Load_Sfnt_Table(face, tag, 0, buffer, &len) == FT_Err_Ok; - *length = len; - Q_ASSERT(!result || int(*length) > 0); - } - - return result; -} - -static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0}; - -static const QFontEngine::HintStyle ftInitialDefaultHintStyle = -#ifdef Q_OS_WIN - QFontEngineFT::HintFull; -#else - QFontEngineFT::HintNone; -#endif - -// -------------------------- Freetype support ------------------------------ - -class QtFreetypeData -{ -public: - QtFreetypeData() - : library(0) - { } - ~QtFreetypeData(); - - FT_Library library; - QHash faces; -}; - -QtFreetypeData::~QtFreetypeData() -{ - for (QHash::ConstIterator iter = faces.cbegin(); iter != faces.cend(); ++iter) - iter.value()->cleanup(); - faces.clear(); - FT_Done_FreeType(library); - library = 0; -} - -#ifdef QT_NO_THREAD -Q_GLOBAL_STATIC(QtFreetypeData, theFreetypeData) - -QtFreetypeData *qt_getFreetypeData() -{ - return theFreetypeData(); -} -#else -Q_GLOBAL_STATIC(QThreadStorage, theFreetypeData) - -QtFreetypeData *qt_getFreetypeData() -{ - QtFreetypeData *&freetypeData = theFreetypeData()->localData(); - if (!freetypeData) - freetypeData = new QtFreetypeData; - if (!freetypeData->library) { - FT_Init_FreeType(&freetypeData->library); -#if defined(FT_FONT_FORMATS_H) - // Freetype defaults to disabling stem-darkening on CFF, we re-enable it. - FT_Bool no_darkening = false; - FT_Property_Set(freetypeData->library, "cff", "no-stem-darkening", &no_darkening); -#endif - } - return freetypeData; -} -#endif - -FT_Library qt_getFreetype() -{ - QtFreetypeData *freetypeData = qt_getFreetypeData(); - Q_ASSERT(freetypeData->library); - return freetypeData->library; -} - -int QFreetypeFace::fsType() const -{ - int fsType = 0; - TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); - if (os2) - fsType = os2->fsType; - return fsType; -} - -int QFreetypeFace::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) -{ - if (int error = FT_Load_Glyph(face, glyph, flags)) - return error; - - if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) - return Err_Invalid_SubTable; - - *nPoints = face->glyph->outline.n_points; - if (!(*nPoints)) - return Err_Ok; - - if (point > *nPoints) - return Err_Invalid_SubTable; - - *xpos = QFixed::fromFixed(face->glyph->outline.points[point].x); - *ypos = QFixed::fromFixed(face->glyph->outline.points[point].y); - - return Err_Ok; -} - -bool QFreetypeFace::isScalableBitmap() const -{ -#ifdef FT_HAS_COLOR - return !FT_IS_SCALABLE(face) && FT_HAS_COLOR(face); -#else - return false; -#endif -} - -extern QByteArray qt_fontdata_from_index(int); - -/* - * One font file can contain more than one font (bold/italic for example) - * find the right one and return it. - * - * Returns the freetype face or 0 in case of an empty file or any other problems - * (like not being able to open the file) - */ -QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, - const QByteArray &fontData) -{ - if (face_id.filename.isEmpty() && fontData.isEmpty()) - return 0; - - QtFreetypeData *freetypeData = qt_getFreetypeData(); - - QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0); - if (freetype) { - freetype->ref.ref(); - } else { - QScopedPointer newFreetype(new QFreetypeFace); - FT_Face face; - if (!face_id.filename.isEmpty()) { - QString fileName = QFile::decodeName(face_id.filename); - if (face_id.filename.startsWith(":qmemoryfonts/")) { - // from qfontdatabase.cpp - QByteArray idx = face_id.filename; - idx.remove(0, 14); // remove ':qmemoryfonts/' - bool ok = false; - newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok)); - if (!ok) - newFreetype->fontData = QByteArray(); - } else if (!QFileInfo(fileName).isNativePath()) { - QFile file(fileName); - if (!file.open(QIODevice::ReadOnly)) { - return 0; - } - newFreetype->fontData = file.readAll(); - } - } else { - newFreetype->fontData = fontData; - } - if (!newFreetype->fontData.isEmpty()) { - if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)newFreetype->fontData.constData(), newFreetype->fontData.size(), face_id.index, &face)) { - return 0; - } - } else if (FT_New_Face(freetypeData->library, face_id.filename, face_id.index, &face)) { - return 0; - } - newFreetype->face = face; - - newFreetype->ref.store(1); - newFreetype->xsize = 0; - newFreetype->ysize = 0; - newFreetype->matrix.xx = 0x10000; - newFreetype->matrix.yy = 0x10000; - newFreetype->matrix.xy = 0; - newFreetype->matrix.yx = 0; - newFreetype->unicode_map = 0; - newFreetype->symbol_map = 0; - - memset(newFreetype->cmapCache, 0, sizeof(newFreetype->cmapCache)); - - for (int i = 0; i < newFreetype->face->num_charmaps; ++i) { - FT_CharMap cm = newFreetype->face->charmaps[i]; - switch(cm->encoding) { - case FT_ENCODING_UNICODE: - newFreetype->unicode_map = cm; - break; - case FT_ENCODING_APPLE_ROMAN: - case FT_ENCODING_ADOBE_LATIN_1: - if (!newFreetype->unicode_map || newFreetype->unicode_map->encoding != FT_ENCODING_UNICODE) - newFreetype->unicode_map = cm; - break; - case FT_ENCODING_ADOBE_CUSTOM: - case FT_ENCODING_MS_SYMBOL: - if (!newFreetype->symbol_map) - newFreetype->symbol_map = cm; - break; - default: - break; - } - } - - if (!FT_IS_SCALABLE(newFreetype->face) && newFreetype->face->num_fixed_sizes == 1) - FT_Set_Char_Size(face, newFreetype->face->available_sizes[0].x_ppem, newFreetype->face->available_sizes[0].y_ppem, 0, 0); - - FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map); - QT_TRY { - freetypeData->faces.insert(face_id, newFreetype.data()); - } QT_CATCH(...) { - newFreetype.take()->release(face_id); - // we could return null in principle instead of throwing - QT_RETHROW; - } - freetype = newFreetype.take(); - } - return freetype; -} - -void QFreetypeFace::cleanup() -{ - hbFace.reset(); - FT_Done_Face(face); - face = 0; -} - -void QFreetypeFace::release(const QFontEngine::FaceId &face_id) -{ - if (!ref.deref()) { - if (face) { - QtFreetypeData *freetypeData = qt_getFreetypeData(); - - cleanup(); - - auto it = freetypeData->faces.constFind(face_id); - if (it != freetypeData->faces.constEnd()) - freetypeData->faces.erase(it); - - if (freetypeData->faces.isEmpty()) { - FT_Done_FreeType(freetypeData->library); - freetypeData->library = 0; - } - } - - delete this; - } -} - - -void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor) -{ - *ysize = qRound(fontDef.pixelSize * 64); - *xsize = *ysize * fontDef.stretch / 100; - *scalableBitmapScaleFactor = 1; - *outline_drawing = false; - - if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) { - int best = 0; - if (!isScalableBitmap()) { - /* - * Bitmap only faces must match exactly, so find the closest - * one (height dominant search) - */ - for (int i = 1; i < face->num_fixed_sizes; i++) { - if (qAbs(*ysize - face->available_sizes[i].y_ppem) < - qAbs(*ysize - face->available_sizes[best].y_ppem) || - (qAbs(*ysize - face->available_sizes[i].y_ppem) == - qAbs(*ysize - face->available_sizes[best].y_ppem) && - qAbs(*xsize - face->available_sizes[i].x_ppem) < - qAbs(*xsize - face->available_sizes[best].x_ppem))) { - best = i; - } - } - } else { - // Select the shortest bitmap strike whose height is larger than the desired height - for (int i = 1; i < face->num_fixed_sizes; i++) { - if (face->available_sizes[i].y_ppem < *ysize) { - if (face->available_sizes[i].y_ppem > face->available_sizes[best].y_ppem) - best = i; - } else if (face->available_sizes[best].y_ppem < *ysize) { - best = i; - } else if (face->available_sizes[i].y_ppem < face->available_sizes[best].y_ppem) { - best = i; - } - } - } - - // According to freetype documentation we must use FT_Select_Size - // to make sure we can select the desired bitmap strike index - if (FT_Select_Size(face, best) == 0) { - if (isScalableBitmap()) - *scalableBitmapScaleFactor = QFixed::fromReal((qreal)fontDef.pixelSize / face->available_sizes[best].height); - *xsize = face->available_sizes[best].x_ppem; - *ysize = face->available_sizes[best].y_ppem; - } else { - *xsize = *ysize = 0; - } - } else { - *outline_drawing = (*xsize > (QT_MAX_CACHED_GLYPH_SIZE<<6) || *ysize > (QT_MAX_CACHED_GLYPH_SIZE<<6)); - } -} - -QFontEngine::Properties QFreetypeFace::properties() const -{ - QFontEngine::Properties p; - p.postscriptName = FT_Get_Postscript_Name(face); - PS_FontInfoRec font_info; - if (FT_Get_PS_Font_Info(face, &font_info) == 0) - p.copyright = font_info.notice; - if (FT_IS_SCALABLE(face)) { - p.ascent = face->ascender; - p.descent = -face->descender; - p.leading = face->height - face->ascender + face->descender; - p.emSquare = face->units_per_EM; - p.boundingBox = QRectF(face->bbox.xMin, -face->bbox.yMax, - face->bbox.xMax - face->bbox.xMin, - face->bbox.yMax - face->bbox.yMin); - } else { - p.ascent = QFixed::fromFixed(face->size->metrics.ascender); - p.descent = QFixed::fromFixed(-face->size->metrics.descender); - p.leading = QFixed::fromFixed(face->size->metrics.height - face->size->metrics.ascender + face->size->metrics.descender); - p.emSquare = face->size->metrics.y_ppem; -// p.boundingBox = QRectF(-p.ascent.toReal(), 0, (p.ascent + p.descent).toReal(), face->size->metrics.max_advance/64.); - p.boundingBox = QRectF(0, -p.ascent.toReal(), - face->size->metrics.max_advance/64, (p.ascent + p.descent).toReal() ); - } - p.italicAngle = 0; - p.capHeight = p.ascent; - p.lineWidth = face->underline_thickness; - - return p; -} - -bool QFreetypeFace::getSfntTable(uint tag, uchar *buffer, uint *length) const -{ - return ft_getSfntTable(face, tag, buffer, length); -} - -/* Some fonts (such as MingLiu rely on hinting to scale different - components to their correct sizes. While this is really broken (it - should be done in the component glyph itself, not the hinter) we - will have to live with it. - - This means we can not use FT_LOAD_NO_HINTING to get the glyph - outline. All we can do is to load the unscaled glyph and scale it - down manually when required. -*/ -static void scaleOutline(FT_Face face, FT_GlyphSlot g, FT_Fixed x_scale, FT_Fixed y_scale) -{ - x_scale = FT_MulDiv(x_scale, 1 << 10, face->units_per_EM); - y_scale = FT_MulDiv(y_scale, 1 << 10, face->units_per_EM); - FT_Vector *p = g->outline.points; - const FT_Vector *e = p + g->outline.n_points; - while (p < e) { - p->x = FT_MulFix(p->x, x_scale); - p->y = FT_MulFix(p->y, y_scale); - ++p; - } -} - -#define GLYPH2PATH_DEBUG QT_NO_QDEBUG_MACRO // qDebug -void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale) -{ - const qreal factor = 1/64.; - scaleOutline(face, g, x_scale, y_scale); - - QPointF cp = point.toPointF(); - - // convert the outline to a painter path - int i = 0; - for (int j = 0; j < g->outline.n_contours; ++j) { - int last_point = g->outline.contours[j]; - GLYPH2PATH_DEBUG() << "contour:" << i << "to" << last_point; - QPointF start = QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor); - if (!(g->outline.tags[i] & 1)) { // start point is not on curve: - if (!(g->outline.tags[last_point] & 1)) { // end point is not on curve: - GLYPH2PATH_DEBUG() << " start and end point are not on curve"; - start = (QPointF(g->outline.points[last_point].x*factor, - -g->outline.points[last_point].y*factor) + start) / 2.0; - } else { - GLYPH2PATH_DEBUG() << " end point is on curve, start is not"; - start = QPointF(g->outline.points[last_point].x*factor, - -g->outline.points[last_point].y*factor); - } - --i; // to use original start point as control point below - } - start += cp; - GLYPH2PATH_DEBUG() << " start at" << start; - - path->moveTo(start); - QPointF c[4]; - c[0] = start; - int n = 1; - while (i < last_point) { - ++i; - c[n] = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor); - GLYPH2PATH_DEBUG() << " " << i << c[n] << "tag =" << (int)g->outline.tags[i] - << ": on curve =" << (bool)(g->outline.tags[i] & 1); - ++n; - switch (g->outline.tags[i] & 3) { - case 2: - // cubic bezier element - if (n < 4) - continue; - c[3] = (c[3] + c[2])/2; - --i; - break; - case 0: - // quadratic bezier element - if (n < 3) - continue; - c[3] = (c[1] + c[2])/2; - c[2] = (2*c[1] + c[3])/3; - c[1] = (2*c[1] + c[0])/3; - --i; - break; - case 1: - case 3: - if (n == 2) { - GLYPH2PATH_DEBUG() << " lineTo" << c[1]; - path->lineTo(c[1]); - c[0] = c[1]; - n = 1; - continue; - } else if (n == 3) { - c[3] = c[2]; - c[2] = (2*c[1] + c[3])/3; - c[1] = (2*c[1] + c[0])/3; - } - break; - } - GLYPH2PATH_DEBUG() << " cubicTo" << c[1] << c[2] << c[3]; - path->cubicTo(c[1], c[2], c[3]); - c[0] = c[3]; - n = 1; - } - - if (n == 1) { - GLYPH2PATH_DEBUG() << " closeSubpath"; - path->closeSubpath(); - } else { - c[3] = start; - if (n == 2) { - c[2] = (2*c[1] + c[3])/3; - c[1] = (2*c[1] + c[0])/3; - } - GLYPH2PATH_DEBUG() << " close cubicTo" << c[1] << c[2] << c[3]; - path->cubicTo(c[1], c[2], c[3]); - } - ++i; - } -} - -extern void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path); - -void QFreetypeFace::addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path) -{ - if (slot->format != FT_GLYPH_FORMAT_BITMAP - || slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO) - return; - - QPointF cp = point.toPointF(); - qt_addBitmapToPath(cp.x() + TRUNC(slot->metrics.horiBearingX), cp.y() - TRUNC(slot->metrics.horiBearingY), - slot->bitmap.buffer, slot->bitmap.pitch, slot->bitmap.width, slot->bitmap.rows, path); -} - -QFontEngineFT::Glyph::~Glyph() -{ - delete [] data; -} - -struct LcdFilterDummy -{ - static inline void filterPixel(uchar &, uchar &, uchar &) - {} -}; - -struct LcdFilterLegacy -{ - static inline void filterPixel(uchar &red, uchar &green, uchar &blue) - { - uint r = red, g = green, b = blue; - // intra-pixel filter used by the legacy filter (adopted from _ft_lcd_filter_legacy) - red = (r * uint(65538 * 9/13) + g * uint(65538 * 1/6) + b * uint(65538 * 1/13)) / 65536; - green = (r * uint(65538 * 3/13) + g * uint(65538 * 4/6) + b * uint(65538 * 3/13)) / 65536; - blue = (r * uint(65538 * 1/13) + g * uint(65538 * 1/6) + b * uint(65538 * 9/13)) / 65536; - } -}; - -template -static void convertRGBToARGB_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr) -{ - const int offs = bgr ? -1 : 1; - const int w = width * 3; - while (height--) { - uint *dd = dst; - for (int x = 0; x < w; x += 3) { - uchar red = src[x + 1 - offs]; - uchar green = src[x + 1]; - uchar blue = src[x + 1 + offs]; - LcdFilter::filterPixel(red, green, blue); - *dd++ = (0xFF << 24) | (red << 16) | (green << 8) | blue; - } - dst += width; - src += src_pitch; - } -} - -static inline void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter) -{ - if (!legacyFilter) - convertRGBToARGB_helper(src, dst, width, height, src_pitch, bgr); - else - convertRGBToARGB_helper(src, dst, width, height, src_pitch, bgr); -} - -template -static void convertRGBToARGB_V_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr) -{ - const int offs = bgr ? -src_pitch : src_pitch; - while (height--) { - for (int x = 0; x < width; x++) { - uchar red = src[x + src_pitch - offs]; - uchar green = src[x + src_pitch]; - uchar blue = src[x + src_pitch + offs]; - LcdFilter::filterPixel(red, green, blue); - *dst++ = (0XFF << 24) | (red << 16) | (green << 8) | blue; - } - src += 3*src_pitch; - } -} - -static inline void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter) -{ - if (!legacyFilter) - convertRGBToARGB_V_helper(src, dst, width, height, src_pitch, bgr); - else - convertRGBToARGB_V_helper(src, dst, width, height, src_pitch, bgr); -} - -static inline void convertGRAYToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch) -{ - while (height--) { - const uchar *p = src; - const uchar * const e = p + width; - while (p < e) { - uchar gray = *p++; - *dst++ = (0xFF << 24) | (gray << 16) | (gray << 8) | gray; - } - src += src_pitch; - } -} - -static void convoluteBitmap(const uchar *src, uchar *dst, int width, int height, int pitch) -{ - // convolute the bitmap with a triangle filter to get rid of color fringes - // If we take account for a gamma value of 2, we end up with - // weights of 1, 4, 9, 4, 1. We use an approximation of 1, 3, 8, 3, 1 here, - // as this nicely sums up to 16 :) - int h = height; - while (h--) { - dst[0] = dst[1] = 0; - // - for (int x = 2; x < width - 2; ++x) { - uint sum = src[x-2] + 3*src[x-1] + 8*src[x] + 3*src[x+1] + src[x+2]; - dst[x] = (uchar) (sum >> 4); - } - dst[width - 2] = dst[width - 1] = 0; - src += pitch; - dst += pitch; - } -} - -QFontEngineFT::QFontEngineFT(const QFontDef &fd) - : QFontEngine(Freetype) -{ - fontDef = fd; - matrix.xx = 0x10000; - matrix.yy = 0x10000; - matrix.xy = 0; - matrix.yx = 0; - cache_cost = 100 * 1024; - kerning_pairs_loaded = false; - transform = false; - embolden = false; - obliquen = false; - antialias = true; - freetype = 0; - default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; - default_hint_style = ftInitialDefaultHintStyle; - subpixelType = Subpixel_None; - lcdFilterType = 0; -#if defined(FT_LCD_FILTER_H) - lcdFilterType = (int)((quintptr) FT_LCD_FILTER_DEFAULT); -#endif - defaultFormat = Format_None; - embeddedbitmap = false; - const QByteArray env = qgetenv("QT_NO_FT_CACHE"); - cacheEnabled = env.isEmpty() || env.toInt() == 0; - m_subPixelPositionCount = 4; - forceAutoHint = false; - stemDarkeningDriver = false; -} - -QFontEngineFT::~QFontEngineFT() -{ - if (freetype) - freetype->release(face_id); -} - -bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, - const QByteArray &fontData) -{ - return init(faceId, antialias, format, QFreetypeFace::getFace(faceId, fontData)); -} - -static void dont_delete(void*) {} - -bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, - QFreetypeFace *freetypeFace) -{ - freetype = freetypeFace; - if (!freetype) { - xsize = 0; - ysize = 0; - return false; - } - defaultFormat = format; - this->antialias = antialias; - - if (!antialias) - glyphFormat = QFontEngine::Format_Mono; - else - glyphFormat = defaultFormat; - - face_id = faceId; - - symbol = freetype->symbol_map != 0; - PS_FontInfoRec psrec; - // don't assume that type1 fonts are symbol fonts by default - if (FT_Get_PS_Font_Info(freetype->face, &psrec) == FT_Err_Ok) { - symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive)); - } - - freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing, &scalableBitmapScaleFactor); - - FT_Face face = lockFace(); - - if (FT_IS_SCALABLE(face)) { - bool fake_oblique = (fontDef.style != QFont::StyleNormal) && !(face->style_flags & FT_STYLE_FLAG_ITALIC); - if (fake_oblique) - obliquen = true; - FT_Set_Transform(face, &matrix, 0); - freetype->matrix = matrix; - // fake bold - if ((fontDef.weight >= QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face)) { - if (const TT_OS2 *os2 = reinterpret_cast(FT_Get_Sfnt_Table(face, ft_sfnt_os2))) { - if (os2->usWeightClass < 750) - embolden = true; - } - } - // underline metrics - line_thickness = QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)); - underline_position = QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale)); - } else { - // ad hoc algorithm - int score = fontDef.weight * fontDef.pixelSize; - line_thickness = score / 700; - // looks better with thicker line for small pointsizes - if (line_thickness < 2 && score >= 1050) - line_thickness = 2; - underline_position = ((line_thickness * 2) + 3) / 6; - - if (isScalableBitmap()) { - glyphFormat = defaultFormat = GlyphFormat::Format_ARGB; - cacheEnabled = false; - } - } - if (line_thickness < 1) - line_thickness = 1; - - metrics = face->size->metrics; - - /* - TrueType fonts with embedded bitmaps may have a bitmap font specific - ascent/descent in the EBLC table. There is no direct public API - to extract those values. The only way we've found is to trick freetype - into thinking that it's not a scalable font in FT_SelectSize so that - the metrics are retrieved from the bitmap strikes. - */ - if (FT_IS_SCALABLE(face)) { - for (int i = 0; i < face->num_fixed_sizes; ++i) { - if (xsize == face->available_sizes[i].x_ppem && ysize == face->available_sizes[i].y_ppem) { - face->face_flags &= ~FT_FACE_FLAG_SCALABLE; - - FT_Select_Size(face, i); - if (face->size->metrics.ascender + face->size->metrics.descender > 0) { - FT_Pos leading = metrics.height - metrics.ascender + metrics.descender; - metrics.ascender = face->size->metrics.ascender; - metrics.descender = face->size->metrics.descender; - if (metrics.descender > 0 - && QString::fromUtf8(face->family_name) == QLatin1String("Courier New")) { - metrics.descender *= -1; - } - metrics.height = metrics.ascender - metrics.descender + leading; - } - FT_Set_Char_Size(face, xsize, ysize, 0, 0); - - face->face_flags |= FT_FACE_FLAG_SCALABLE; - break; - } - } - } -#if defined(FT_FONT_FORMATS_H) - const char *fmt = FT_Get_Font_Format(face); - if (fmt && qstrncmp(fmt, "CFF", 4) == 0) { - FT_Bool no_stem_darkening = true; - FT_Error err = FT_Property_Get(qt_getFreetype(), "cff", "no-stem-darkening", &no_stem_darkening); - if (err == FT_Err_Ok) - stemDarkeningDriver = !no_stem_darkening; - else - stemDarkeningDriver = false; - } -#endif - - fontDef.styleName = QString::fromUtf8(face->style_name); - - if (!freetype->hbFace) { - faceData.user_data = face; - faceData.get_font_table = ft_getSfntTable; - (void)harfbuzzFace(); // populates face_ - freetype->hbFace = std::move(face_); - } else { - Q_ASSERT(!face_); - } - // we share the HB face in QFreeTypeFace, so do not let ~QFontEngine() destroy it - face_ = Holder(freetype->hbFace.get(), dont_delete); - - unlockFace(); - - fsType = freetype->fsType(); - return true; -} - -void QFontEngineFT::setQtDefaultHintStyle(QFont::HintingPreference hintingPreference) -{ - switch (hintingPreference) { - case QFont::PreferNoHinting: - setDefaultHintStyle(HintNone); - break; - case QFont::PreferFullHinting: - setDefaultHintStyle(HintFull); - break; - case QFont::PreferVerticalHinting: - setDefaultHintStyle(HintLight); - break; - case QFont::PreferDefaultHinting: - setDefaultHintStyle(ftInitialDefaultHintStyle); - break; - } -} - -void QFontEngineFT::setDefaultHintStyle(HintStyle style) -{ - default_hint_style = style; -} - -bool QFontEngineFT::expectsGammaCorrectedBlending() const -{ - return stemDarkeningDriver; -} - -int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags, - bool &hsubpixel, int &vfactor) const -{ - int load_flags = FT_LOAD_DEFAULT | default_load_flags; - int load_target = default_hint_style == HintLight - ? FT_LOAD_TARGET_LIGHT - : FT_LOAD_TARGET_NORMAL; - - if (format == Format_Mono) { - load_target = FT_LOAD_TARGET_MONO; - } else if (format == Format_A32) { - if (subpixelType == Subpixel_RGB || subpixelType == Subpixel_BGR) { - if (default_hint_style == HintFull) - load_target = FT_LOAD_TARGET_LCD; - hsubpixel = true; - } else if (subpixelType == Subpixel_VRGB || subpixelType == Subpixel_VBGR) { - if (default_hint_style == HintFull) - load_target = FT_LOAD_TARGET_LCD_V; - vfactor = 3; - } - } else if (format == Format_ARGB) { -#ifdef FT_LOAD_COLOR - load_flags |= FT_LOAD_COLOR; -#endif - } - - if (set && set->outline_drawing) - load_flags |= FT_LOAD_NO_BITMAP; - - if (default_hint_style == HintNone || (flags & DesignMetrics) || (set && set->outline_drawing)) - load_flags |= FT_LOAD_NO_HINTING; - else - load_flags |= load_target; - - if (forceAutoHint) - load_flags |= FT_LOAD_FORCE_AUTOHINT; - - return load_flags; -} - -static inline bool areMetricsTooLarge(const QFontEngineFT::GlyphInfo &info) -{ - // false if exceeds QFontEngineFT::Glyph metrics - return (short)(info.linearAdvance) != info.linearAdvance - || (uchar)(info.width) != info.width - || (uchar)(info.height) != info.height; -} - -static inline void transformBoundingBox(int *left, int *top, int *right, int *bottom, FT_Matrix *matrix) -{ - int l, r, t, b; - FT_Vector vector; - vector.x = *left; - vector.y = *top; - FT_Vector_Transform(&vector, matrix); - l = r = vector.x; - t = b = vector.y; - vector.x = *right; - vector.y = *top; - FT_Vector_Transform(&vector, matrix); - if (l > vector.x) l = vector.x; - if (r < vector.x) r = vector.x; - if (t < vector.y) t = vector.y; - if (b > vector.y) b = vector.y; - vector.x = *right; - vector.y = *bottom; - FT_Vector_Transform(&vector, matrix); - if (l > vector.x) l = vector.x; - if (r < vector.x) r = vector.x; - if (t < vector.y) t = vector.y; - if (b > vector.y) b = vector.y; - vector.x = *left; - vector.y = *bottom; - FT_Vector_Transform(&vector, matrix); - if (l > vector.x) l = vector.x; - if (r < vector.x) r = vector.x; - if (t < vector.y) t = vector.y; - if (b > vector.y) b = vector.y; - *left = l; - *right = r; - *top = t; - *bottom = b; -} - -QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, - QFixed subPixelPosition, - GlyphFormat format, - bool fetchMetricsOnly, - bool disableOutlineDrawing) const -{ -// Q_ASSERT(freetype->lock == 1); - - if (format == Format_None) - format = defaultFormat != Format_None ? defaultFormat : Format_Mono; - Q_ASSERT(format != Format_None); - - Glyph *g = set ? set->getGlyph(glyph, subPixelPosition) : 0; - if (g && g->format == format && (fetchMetricsOnly || g->data)) - return g; - - if (!g && set && set->isGlyphMissing(glyph)) - return &emptyGlyph; - - - FT_Face face = freetype->face; - - FT_Matrix matrix = freetype->matrix; - - FT_Vector v; - v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.value()); - v.y = 0; - FT_Set_Transform(face, &matrix, &v); - - bool hsubpixel = false; - int vfactor = 1; - int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor); - - bool transform = matrix.xx != 0x10000 - || matrix.yy != 0x10000 - || matrix.xy != 0 - || matrix.yx != 0; - - if (transform || (format != Format_Mono && !isScalableBitmap())) - load_flags |= FT_LOAD_NO_BITMAP; - - FT_Error err = FT_Load_Glyph(face, glyph, load_flags); - if (err && (load_flags & FT_LOAD_NO_BITMAP)) { - load_flags &= ~FT_LOAD_NO_BITMAP; - err = FT_Load_Glyph(face, glyph, load_flags); - } - if (err == FT_Err_Too_Few_Arguments) { - // this is an error in the bytecode interpreter, just try to run without it - load_flags |= FT_LOAD_FORCE_AUTOHINT; - err = FT_Load_Glyph(face, glyph, load_flags); - } else if (err == FT_Err_Execution_Too_Long) { - // This is an error in the bytecode, probably a web font made by someone who - // didn't test bytecode hinting at all so disable for it for all glyphs. - qWarning("load glyph failed due to broken hinting bytecode in font, switching to auto hinting"); - default_load_flags |= FT_LOAD_FORCE_AUTOHINT; - load_flags |= FT_LOAD_FORCE_AUTOHINT; - err = FT_Load_Glyph(face, glyph, load_flags); - } - if (err != FT_Err_Ok) { - qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph); - if (set) - set->setGlyphMissing(glyph); - return &emptyGlyph; - } - - FT_GlyphSlot slot = face->glyph; - - if (embolden) - FT_GlyphSlot_Embolden(slot); - if (obliquen) { - FT_GlyphSlot_Oblique(slot); - - // While Embolden alters the metrics of the slot, oblique does not, so we need - // to fix this ourselves. - transform = true; - FT_Matrix m; - m.xx = 0x10000; - m.yx = 0x0; - m.xy = 0x6000; - m.yy = 0x10000; - - FT_Matrix_Multiply(&m, &matrix); - } - - GlyphInfo info; - info.linearAdvance = slot->linearHoriAdvance >> 10; - info.xOff = TRUNC(ROUND(slot->advance.x)); - info.yOff = 0; - - if ((set && set->outline_drawing && !disableOutlineDrawing) || fetchMetricsOnly) { - int left = slot->metrics.horiBearingX; - int right = slot->metrics.horiBearingX + slot->metrics.width; - int top = slot->metrics.horiBearingY; - int bottom = slot->metrics.horiBearingY - slot->metrics.height; - - if (transform && slot->format != FT_GLYPH_FORMAT_BITMAP) - transformBoundingBox(&left, &top, &right, &bottom, &matrix); - - left = FLOOR(left); - right = CEIL(right); - bottom = FLOOR(bottom); - top = CEIL(top); - - info.x = TRUNC(left); - info.y = TRUNC(top); - info.width = TRUNC(right - left); - info.height = TRUNC(top - bottom); - - // If any of the metrics are too large to fit, don't cache them - if (areMetricsTooLarge(info)) - return 0; - - g = new Glyph; - g->data = 0; - g->linearAdvance = info.linearAdvance; - g->width = info.width; - g->height = info.height; - g->x = info.x; - g->y = info.y; - g->advance = info.xOff; - g->format = format; - - if (set) - set->setGlyph(glyph, subPixelPosition, g); - - return g; - } - - int glyph_buffer_size = 0; - QScopedArrayPointer glyph_buffer; -#if defined(QT_USE_FREETYPE_LCDFILTER) - bool useFreetypeRenderGlyph = false; - if (slot->format == FT_GLYPH_FORMAT_OUTLINE && (hsubpixel || vfactor != 1)) { - err = FT_Library_SetLcdFilter(slot->library, (FT_LcdFilter)lcdFilterType); - if (err == FT_Err_Ok) - useFreetypeRenderGlyph = true; - } - - if (useFreetypeRenderGlyph) { - err = FT_Render_Glyph(slot, hsubpixel ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_LCD_V); - - if (err != FT_Err_Ok) - qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph); - - FT_Library_SetLcdFilter(slot->library, FT_LCD_FILTER_NONE); - - info.height = slot->bitmap.rows / vfactor; - info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width; - info.x = slot->bitmap_left; - info.y = slot->bitmap_top; - - glyph_buffer_size = info.width * info.height * 4; - glyph_buffer.reset(new uchar[glyph_buffer_size]); - - if (hsubpixel) - convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB, false); - else if (vfactor != 1) - convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB, false); - } else -#endif - { - int left = slot->metrics.horiBearingX; - int right = slot->metrics.horiBearingX + slot->metrics.width; - int top = slot->metrics.horiBearingY; - int bottom = slot->metrics.horiBearingY - slot->metrics.height; - if (transform && slot->format != FT_GLYPH_FORMAT_BITMAP) - transformBoundingBox(&left, &top, &right, &bottom, &matrix); - left = FLOOR(left); - right = CEIL(right); - bottom = FLOOR(bottom); - top = CEIL(top); - - int hpixels = TRUNC(right - left); - // subpixel position requires one more pixel - if (subPixelPosition > 0 && format != Format_Mono) - hpixels++; - - if (hsubpixel) - hpixels = hpixels*3 + 8; - info.width = hpixels; - info.height = TRUNC(top - bottom); - info.x = TRUNC(left); - info.y = TRUNC(top); - if (hsubpixel) { - info.width /= 3; - info.x -= 1; - } - - // If any of the metrics are too large to fit, don't cache them - if (areMetricsTooLarge(info)) - return 0; - - int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 : - (format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4)); - if (glyph_buffer_size < pitch * info.height) { - glyph_buffer_size = pitch * info.height; - glyph_buffer.reset(new uchar[glyph_buffer_size]); - memset(glyph_buffer.data(), 0, glyph_buffer_size); - } - - if (slot->format == FT_GLYPH_FORMAT_OUTLINE) { - FT_Bitmap bitmap; - bitmap.rows = info.height*vfactor; - bitmap.width = hpixels; - bitmap.pitch = format == Format_Mono ? (((info.width + 31) & ~31) >> 3) : ((bitmap.width + 3) & ~3); - int bitmap_buffer_size = bitmap.rows * bitmap.pitch; - if (!hsubpixel && vfactor == 1 && format != Format_A32) { - Q_ASSERT(glyph_buffer_size <= bitmap_buffer_size); - bitmap.buffer = glyph_buffer.data(); - } else { - bitmap.buffer = new uchar[bitmap_buffer_size]; - memset(bitmap.buffer, 0, bitmap_buffer_size); - } - bitmap.pixel_mode = format == Format_Mono ? FT_PIXEL_MODE_MONO : FT_PIXEL_MODE_GRAY; - FT_Matrix matrix; - matrix.xx = (hsubpixel ? 3 : 1) << 16; - matrix.yy = vfactor << 16; - matrix.yx = matrix.xy = 0; - - FT_Outline_Transform(&slot->outline, &matrix); - FT_Outline_Translate (&slot->outline, (hsubpixel ? -3*left +(4<<6) : -left), -bottom*vfactor); - FT_Outline_Get_Bitmap(slot->library, &slot->outline, &bitmap); - if (hsubpixel) { - Q_ASSERT (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY); - Q_ASSERT(antialias); - uchar *convoluted = new uchar[bitmap_buffer_size]; - bool useLegacyLcdFilter = false; -#if defined(FC_LCD_FILTER) && defined(FT_LCD_FILTER_H) - useLegacyLcdFilter = (lcdFilterType == FT_LCD_FILTER_LEGACY); -#endif - uchar *buffer = bitmap.buffer; - if (!useLegacyLcdFilter) { - convoluteBitmap(bitmap.buffer, convoluted, bitmap.width, info.height, bitmap.pitch); - buffer = convoluted; - } - convertRGBToARGB(buffer + 1, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch, subpixelType != Subpixel_RGB, useLegacyLcdFilter); - delete [] convoluted; - } else if (vfactor != 1) { - convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch, subpixelType != Subpixel_VRGB, true); - } else if (format == Format_A32 && bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) { - convertGRAYToARGB(bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch); - } - - if (bitmap.buffer != glyph_buffer.data()) - delete [] bitmap.buffer; - } else if (slot->format == FT_GLYPH_FORMAT_BITMAP) { -#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100) >= 20500) - Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO || slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA); -#else - Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO); -#endif - uchar *src = slot->bitmap.buffer; - uchar *dst = glyph_buffer.data(); - int h = slot->bitmap.rows; - if (format == Format_Mono) { - int bytes = ((info.width + 7) & ~7) >> 3; - while (h--) { - memcpy (dst, src, bytes); - dst += pitch; - src += slot->bitmap.pitch; - } - } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { - if (hsubpixel) { - while (h--) { - uint *dd = (uint *)dst; - *dd++ = 0; - for (int x = 0; x < static_cast(slot->bitmap.width); x++) { - uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000); - *dd++ = a; - } - *dd++ = 0; - dst += pitch; - src += slot->bitmap.pitch; - } - } else if (vfactor != 1) { - while (h--) { - uint *dd = (uint *)dst; - for (int x = 0; x < static_cast(slot->bitmap.width); x++) { - uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000); - *dd++ = a; - } - dst += pitch; - src += slot->bitmap.pitch; - } - } else { - while (h--) { - for (int x = 0; x < static_cast(slot->bitmap.width); x++) { - unsigned char a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xff : 0x00); - dst[x] = a; - } - dst += pitch; - src += slot->bitmap.pitch; - } - } - } -#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100) >= 20500) - else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) - { - while (h--) { -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - const quint32 *srcPixel = (const quint32 *)src; - quint32 *dstPixel = (quint32 *)dst; - for (int x = 0; x < static_cast(slot->bitmap.width); x++, srcPixel++, dstPixel++) { - const quint32 pixel = *srcPixel; - *dstPixel = qbswap(pixel); - } -#else - memcpy(dst, src, slot->bitmap.width * 4); -#endif - dst += slot->bitmap.pitch; - src += slot->bitmap.pitch; - } - info.width = info.linearAdvance = info.xOff = slot->bitmap.width; - info.height = slot->bitmap.rows; - info.x = slot->bitmap_left; - info.y = slot->bitmap_top; - } -#endif - } else { - qWarning("QFontEngine: Glyph neither outline nor bitmap format=%d", slot->format); - return 0; - } - } - - - if (!g) { - g = new Glyph; - g->data = 0; - } - - g->linearAdvance = info.linearAdvance; - g->width = info.width; - g->height = info.height; - g->x = info.x; - g->y = info.y; - g->advance = info.xOff; - g->format = format; - delete [] g->data; - g->data = glyph_buffer.take(); - - if (set) - set->setGlyph(glyph, subPixelPosition, g); - - return g; -} - -QFontEngine::FaceId QFontEngineFT::faceId() const -{ - return face_id; -} - -QFontEngine::Properties QFontEngineFT::properties() const -{ - Properties p = freetype->properties(); - if (p.postscriptName.isEmpty()) { - p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(fontDef.family.toUtf8()); - } - - return freetype->properties(); -} - -QFixed QFontEngineFT::emSquareSize() const -{ - if (FT_IS_SCALABLE(freetype->face)) - return freetype->face->units_per_EM; - else - return freetype->face->size->metrics.y_ppem; -} - -bool QFontEngineFT::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - return ft_getSfntTable(freetype->face, tag, buffer, length); -} - -int QFontEngineFT::synthesized() const -{ - int s = 0; - if ((fontDef.style != QFont::StyleNormal) && !(freetype->face->style_flags & FT_STYLE_FLAG_ITALIC)) - s = SynthesizedItalic; - if ((fontDef.weight >= QFont::Bold) && !(freetype->face->style_flags & FT_STYLE_FLAG_BOLD)) - s |= SynthesizedBold; - if (fontDef.stretch != 100 && FT_IS_SCALABLE(freetype->face)) - s |= SynthesizedStretch; - return s; -} - -QFixed QFontEngineFT::ascent() const -{ - QFixed v = QFixed::fromFixed(metrics.ascender); - if (scalableBitmapScaleFactor != 1) - v *= scalableBitmapScaleFactor; - return v; -} - -QFixed QFontEngineFT::capHeight() const -{ - TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); - if (os2 && os2->version >= 2) { - lockFace(); - QFixed answer = QFixed::fromFixed(FT_MulFix(os2->sCapHeight, freetype->face->size->metrics.y_scale)); - unlockFace(); - return answer; - } - return calculatedCapHeight(); -} - -QFixed QFontEngineFT::descent() const -{ - QFixed v = QFixed::fromFixed(-metrics.descender); - if (scalableBitmapScaleFactor != 1) - v *= scalableBitmapScaleFactor; - return v; -} - -QFixed QFontEngineFT::leading() const -{ - QFixed v = QFixed::fromFixed(metrics.height - metrics.ascender + metrics.descender); - if (scalableBitmapScaleFactor != 1) - v *= scalableBitmapScaleFactor; - return v; -} - -QFixed QFontEngineFT::xHeight() const -{ - TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); - if (os2 && os2->sxHeight) { - lockFace(); - QFixed answer = QFixed(os2->sxHeight * freetype->face->size->metrics.y_ppem) / emSquareSize(); - unlockFace(); - return answer; - } - - return QFontEngine::xHeight(); -} - -QFixed QFontEngineFT::averageCharWidth() const -{ - TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); - if (os2 && os2->xAvgCharWidth) { - lockFace(); - QFixed answer = QFixed(os2->xAvgCharWidth * freetype->face->size->metrics.x_ppem) / emSquareSize(); - unlockFace(); - return answer; - } - - return QFontEngine::averageCharWidth(); -} - -qreal QFontEngineFT::maxCharWidth() const -{ - QFixed max_advance = QFixed::fromFixed(metrics.max_advance); - if (scalableBitmapScaleFactor != 1) - max_advance *= scalableBitmapScaleFactor; - return max_advance.toReal(); -} - -QFixed QFontEngineFT::lineThickness() const -{ - return line_thickness; -} - -QFixed QFontEngineFT::underlinePosition() const -{ - return underline_position; -} - -void QFontEngineFT::doKerning(QGlyphLayout *g, QFontEngine::ShaperFlags flags) const -{ - if (!kerning_pairs_loaded) { - kerning_pairs_loaded = true; - lockFace(); - if (freetype->face->size->metrics.x_ppem != 0) { - QFixed scalingFactor = emSquareSize() / QFixed(freetype->face->size->metrics.x_ppem); - unlockFace(); - const_cast(this)->loadKerningPairs(scalingFactor); - } else { - unlockFace(); - } - } - - if (shouldUseDesignMetrics(flags) && !(fontDef.styleStrategy & QFont::ForceIntegerMetrics)) - flags |= DesignMetrics; - else - flags &= ~DesignMetrics; - - QFontEngine::doKerning(g, flags); -} - -static inline FT_Matrix QTransformToFTMatrix(const QTransform &matrix) -{ - FT_Matrix m; - - m.xx = FT_Fixed(matrix.m11() * 65536); - m.xy = FT_Fixed(-matrix.m21() * 65536); - m.yx = FT_Fixed(-matrix.m12() * 65536); - m.yy = FT_Fixed(matrix.m22() * 65536); - - return m; -} - -QFontEngineFT::QGlyphSet *QFontEngineFT::loadGlyphSet(const QTransform &matrix) -{ - if (matrix.type() > QTransform::TxShear || !cacheEnabled) - return 0; - - // FT_Set_Transform only supports scalable fonts - if (!FT_IS_SCALABLE(freetype->face)) - return matrix.type() <= QTransform::TxTranslate ? &defaultGlyphSet : Q_NULLPTR; - - FT_Matrix m = QTransformToFTMatrix(matrix); - - QGlyphSet *gs = 0; - - for (int i = 0; i < transformedGlyphSets.count(); ++i) { - const QGlyphSet &g = transformedGlyphSets.at(i); - if (g.transformationMatrix.xx == m.xx - && g.transformationMatrix.xy == m.xy - && g.transformationMatrix.yx == m.yx - && g.transformationMatrix.yy == m.yy) { - - // found a match, move it to the front - transformedGlyphSets.move(i, 0); - gs = &transformedGlyphSets[0]; - break; - } - } - - if (!gs) { - // don't cache more than 10 transformations - if (transformedGlyphSets.count() >= 10) { - transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0); - } else { - transformedGlyphSets.prepend(QGlyphSet()); - } - gs = &transformedGlyphSets[0]; - gs->clear(); - gs->transformationMatrix = m; - gs->outline_drawing = fontDef.pixelSize * fontDef.pixelSize * qAbs(matrix.det()) >= QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE; - } - Q_ASSERT(gs != 0); - - return gs; -} - -void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) -{ - FT_Face face = lockFace(Unscaled); - FT_Set_Transform(face, 0, 0); - FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP); - - int left = face->glyph->metrics.horiBearingX; - int right = face->glyph->metrics.horiBearingX + face->glyph->metrics.width; - int top = face->glyph->metrics.horiBearingY; - int bottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height; - - QFixedPoint p; - p.x = 0; - p.y = 0; - - metrics->width = QFixed::fromFixed(right-left); - metrics->height = QFixed::fromFixed(top-bottom); - metrics->x = QFixed::fromFixed(left); - metrics->y = QFixed::fromFixed(-top); - metrics->xoff = QFixed::fromFixed(face->glyph->advance.x); - - if (!FT_IS_SCALABLE(freetype->face)) - QFreetypeFace::addBitmapToPath(face->glyph, p, path); - else - QFreetypeFace::addGlyphToPath(face, face->glyph, p, path, face->units_per_EM << 6, face->units_per_EM << 6); - - FT_Set_Transform(face, &freetype->matrix, 0); - unlockFace(); -} - -bool QFontEngineFT::supportsTransformation(const QTransform &transform) const -{ - return transform.type() <= QTransform::TxRotate; -} - -void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) -{ - if (!glyphs.numGlyphs) - return; - - if (FT_IS_SCALABLE(freetype->face)) { - QFontEngine::addOutlineToPath(x, y, glyphs, path, flags); - } else { - QVarLengthArray positions; - QVarLengthArray positioned_glyphs; - QTransform matrix; - matrix.translate(x, y); - getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions); - - FT_Face face = lockFace(Unscaled); - for (int gl = 0; gl < glyphs.numGlyphs; gl++) { - FT_UInt glyph = positioned_glyphs[gl]; - FT_Load_Glyph(face, glyph, FT_LOAD_TARGET_MONO); - QFreetypeFace::addBitmapToPath(face->glyph, positions[gl], path); - } - unlockFace(); - } -} - -void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, - QPainterPath *path, QTextItem::RenderFlags) -{ - FT_Face face = lockFace(Unscaled); - - for (int gl = 0; gl < numGlyphs; gl++) { - FT_UInt glyph = glyphs[gl]; - - FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP); - - FT_GlyphSlot g = face->glyph; - if (g->format != FT_GLYPH_FORMAT_OUTLINE) - continue; - if (embolden) - FT_GlyphSlot_Embolden(g); - if (obliquen) - FT_GlyphSlot_Oblique(g); - QFreetypeFace::addGlyphToPath(face, g, positions[gl], path, xsize, ysize); - } - unlockFace(); -} - -glyph_t QFontEngineFT::glyphIndex(uint ucs4) const -{ - glyph_t glyph = ucs4 < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[ucs4] : 0; - if (glyph == 0) { - FT_Face face = freetype->face; - glyph = FT_Get_Char_Index(face, ucs4); - if (glyph == 0) { - // Certain fonts don't have no-break space and tab, - // while we usually want to render them as space - if (ucs4 == QChar::Nbsp || ucs4 == QChar::Tabulation) { - glyph = FT_Get_Char_Index(face, QChar::Space); - } else if (freetype->symbol_map) { - // Symbol fonts can have more than one CMAPs, FreeType should take the - // correct one for us by default, so we always try FT_Get_Char_Index - // first. If it didn't work (returns 0), we will explicitly set the - // CMAP to symbol font one and try again. symbol_map is not always the - // correct one because in certain fonts like Wingdings symbol_map only - // contains PUA codepoints instead of the common ones. - FT_Set_Charmap(face, freetype->symbol_map); - glyph = FT_Get_Char_Index(face, ucs4); - FT_Set_Charmap(face, freetype->unicode_map); - } - } - if (ucs4 < QFreetypeFace::cmapCacheSize) - freetype->cmapCache[ucs4] = glyph; - } - - return glyph; -} - -bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, - QFontEngine::ShaperFlags flags) const -{ - Q_ASSERT(glyphs->numGlyphs >= *nglyphs); - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - int glyph_pos = 0; - if (freetype->symbol_map) { - FT_Face face = freetype->face; - QStringIterator it(str, str + len); - while (it.hasNext()) { - uint uc = it.next(); - glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; - if ( !glyphs->glyphs[glyph_pos] ) { - // Symbol fonts can have more than one CMAPs, FreeType should take the - // correct one for us by default, so we always try FT_Get_Char_Index - // first. If it didn't work (returns 0), we will explicitly set the - // CMAP to symbol font one and try again. symbol_map is not always the - // correct one because in certain fonts like Wingdings symbol_map only - // contains PUA codepoints instead of the common ones. - glyph_t glyph = FT_Get_Char_Index(face, uc); - // Certain symbol fonts don't have no-break space (0xa0) and tab (0x9), - // while we usually want to render them as space - if (!glyph && (uc == 0xa0 || uc == 0x9)) { - uc = 0x20; - glyph = FT_Get_Char_Index(face, uc); - } - if (!glyph) { - FT_Set_Charmap(face, freetype->symbol_map); - glyph = FT_Get_Char_Index(face, uc); - FT_Set_Charmap(face, freetype->unicode_map); - } - glyphs->glyphs[glyph_pos] = glyph; - if (uc < QFreetypeFace::cmapCacheSize) - freetype->cmapCache[uc] = glyph; - } - ++glyph_pos; - } - } else { - FT_Face face = freetype->face; - QStringIterator it(str, str + len); - while (it.hasNext()) { - uint uc = it.next(); - glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; - if (!glyphs->glyphs[glyph_pos]) { - { - redo: - glyph_t glyph = FT_Get_Char_Index(face, uc); - if (!glyph && (uc == 0xa0 || uc == 0x9)) { - uc = 0x20; - goto redo; - } - glyphs->glyphs[glyph_pos] = glyph; - if (uc < QFreetypeFace::cmapCacheSize) - freetype->cmapCache[uc] = glyph; - } - } - ++glyph_pos; - } - } - - *nglyphs = glyph_pos; - glyphs->numGlyphs = glyph_pos; - - if (!(flags & GlyphIndicesOnly)) - recalcAdvances(glyphs, flags); - - return true; -} - -bool QFontEngineFT::shouldUseDesignMetrics(QFontEngine::ShaperFlags flags) const -{ - if (!FT_IS_SCALABLE(freetype->face)) - return false; - - return default_hint_style == HintNone || default_hint_style == HintLight || (flags & DesignMetrics); -} - -QFixed QFontEngineFT::scaledBitmapMetrics(QFixed m) const -{ - return m * scalableBitmapScaleFactor; -} - -glyph_metrics_t QFontEngineFT::scaledBitmapMetrics(const glyph_metrics_t &m) const -{ - glyph_metrics_t metrics; - metrics.x = scaledBitmapMetrics(m.x); - metrics.y = scaledBitmapMetrics(m.y); - metrics.width = scaledBitmapMetrics(m.width); - metrics.height = scaledBitmapMetrics(m.height); - metrics.xoff = scaledBitmapMetrics(m.xoff); - metrics.yoff = scaledBitmapMetrics(m.yoff); - return metrics; -} - -void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const -{ - FT_Face face = 0; - bool design = shouldUseDesignMetrics(flags); - for (int i = 0; i < glyphs->numGlyphs; i++) { - Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyphs->glyphs[i]) : 0; - // Since we are passing Format_None to loadGlyph, use same default format logic as loadGlyph - GlyphFormat acceptableFormat = (defaultFormat != Format_None) ? defaultFormat : Format_Mono; - if (g && g->format == acceptableFormat) { - glyphs->advances[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance); - } else { - if (!face) - face = lockFace(); - g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs->glyphs[i], 0, Format_None, true); - if (g) - glyphs->advances[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance); - else - glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10) - : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round(); - if (!cacheEnabled && g != &emptyGlyph) - delete g; - } - - if (scalableBitmapScaleFactor != 1) - glyphs->advances[i] *= scalableBitmapScaleFactor; - } - if (face) - unlockFace(); - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - for (int i = 0; i < glyphs->numGlyphs; ++i) - glyphs->advances[i] = glyphs->advances[i].round(); - } -} - -glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) -{ - FT_Face face = 0; - - glyph_metrics_t overall; - // initialize with line height, we get the same behaviour on all platforms - if (!isScalableBitmap()) { - overall.y = -ascent(); - overall.height = ascent() + descent(); - } else { - overall.y = QFixed::fromFixed(-metrics.ascender); - overall.height = QFixed::fromFixed(metrics.ascender - metrics.descender); - } - - QFixed ymax = 0; - QFixed xmax = 0; - for (int i = 0; i < glyphs.numGlyphs; i++) { - Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyphs.glyphs[i]) : 0; - if (!g) { - if (!face) - face = lockFace(); - g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs.glyphs[i], 0, Format_None, true); - } - if (g) { - 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; - if (!cacheEnabled && g != &emptyGlyph) - delete g; - } else { - int left = FLOOR(face->glyph->metrics.horiBearingX); - int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width); - int top = CEIL(face->glyph->metrics.horiBearingY); - int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height); - - QFixed x = overall.xoff + glyphs.offsets[i].x - (-TRUNC(left)); - QFixed y = overall.yoff + glyphs.offsets[i].y - TRUNC(top); - overall.x = qMin(overall.x, x); - overall.y = qMin(overall.y, y); - xmax = qMax(xmax, x + TRUNC(right - left)); - ymax = qMax(ymax, y + TRUNC(top - bottom)); - overall.xoff += int(TRUNC(ROUND(face->glyph->advance.x))); - } - } - overall.height = qMax(overall.height, ymax - overall.y); - overall.width = xmax - overall.x; - - if (face) - unlockFace(); - - if (isScalableBitmap()) - overall = scaledBitmapMetrics(overall); - return overall; -} - -glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) -{ - FT_Face face = 0; - glyph_metrics_t overall; - Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyph) : 0; - if (!g) { - face = lockFace(); - g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, 0, Format_None, true); - } - if (g) { - overall.x = g->x; - overall.y = -g->y; - overall.width = g->width; - overall.height = g->height; - overall.xoff = g->advance; - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - overall.xoff = overall.xoff.round(); - if (!cacheEnabled && g != &emptyGlyph) - delete g; - } else { - int left = FLOOR(face->glyph->metrics.horiBearingX); - int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width); - int top = CEIL(face->glyph->metrics.horiBearingY); - int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height); - - overall.width = TRUNC(right-left); - overall.height = TRUNC(top-bottom); - overall.x = TRUNC(left); - overall.y = -TRUNC(top); - overall.xoff = TRUNC(ROUND(face->glyph->advance.x)); - } - if (face) - unlockFace(); - - if (isScalableBitmap()) - overall = scaledBitmapMetrics(overall); - return overall; -} - -glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matrix) -{ - return alphaMapBoundingBox(glyph, 0, matrix, QFontEngine::Format_None); -} - -glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, QFontEngine::GlyphFormat format) -{ - Glyph *g = loadGlyphFor(glyph, subPixelPosition, format, matrix, true); - - glyph_metrics_t overall; - if (g) { - overall.x = g->x; - overall.y = -g->y; - overall.width = g->width; - overall.height = g->height; - overall.xoff = g->advance; - if (!cacheEnabled && g != &emptyGlyph) - delete g; - } else { - FT_Face face = lockFace(); - int left = FLOOR(face->glyph->metrics.horiBearingX); - int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width); - int top = CEIL(face->glyph->metrics.horiBearingY); - int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height); - - overall.width = TRUNC(right-left); - overall.height = TRUNC(top-bottom); - overall.x = TRUNC(left); - overall.y = -TRUNC(top); - overall.xoff = TRUNC(ROUND(face->glyph->advance.x)); - unlockFace(); - } - - if (isScalableBitmap()) - overall = scaledBitmapMetrics(overall); - return overall; -} - -static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEngine::GlyphFormat glyphFormat) -{ - if (glyph == Q_NULLPTR || glyph->height == 0 || glyph->width == 0) - return QImage(); - - QImage::Format format = QImage::Format_Invalid; - int bytesPerLine = -1; - switch (glyphFormat) { - case QFontEngine::Format_Mono: - format = QImage::Format_Mono; - bytesPerLine = ((glyph->width + 31) & ~31) >> 3; - break; - case QFontEngine::Format_A8: - format = QImage::Format_Alpha8; - bytesPerLine = (glyph->width + 3) & ~3; - break; - case QFontEngine::Format_A32: - format = QImage::Format_RGB32; - bytesPerLine = glyph->width * 4; - break; - default: - Q_UNREACHABLE(); - }; - - QImage img(static_cast(glyph->data), glyph->width, glyph->height, bytesPerLine, format); - if (format == QImage::Format_Mono) - img.setColor(1, QColor(Qt::white).rgba()); // Expands color table to 2 items; item 0 set to transparent. - return img; -} - -QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixelPosition, - QFontEngine::GlyphFormat neededFormat, - const QTransform &t, QPoint *offset) -{ - Q_ASSERT(currentlyLockedAlphaMap.isNull()); - - if (isBitmapFont()) - neededFormat = Format_Mono; - else if (neededFormat == Format_None && defaultFormat != Format_None) - neededFormat = defaultFormat; - else if (neededFormat == Format_None) - neededFormat = Format_A8; - - Glyph *glyph = loadGlyphFor(glyphIndex, subPixelPosition, neededFormat, t); - - if (offset != 0 && glyph != 0) - *offset = QPoint(glyph->x, -glyph->y); - - currentlyLockedAlphaMap = alphaMapFromGlyphData(glyph, neededFormat); - - const bool glyphHasGeometry = glyph != Q_NULLPTR && glyph->height != 0 && glyph->width != 0; - if (!cacheEnabled && glyph != &emptyGlyph) { - currentlyLockedAlphaMap = currentlyLockedAlphaMap.copy(); - delete glyph; - } - - if (!glyphHasGeometry) - return Q_NULLPTR; - - if (currentlyLockedAlphaMap.isNull()) - return QFontEngine::lockedAlphaMapForGlyph(glyphIndex, subPixelPosition, neededFormat, t, offset); - - QImageData *data = currentlyLockedAlphaMap.data_ptr(); - data->is_locked = true; - - return ¤tlyLockedAlphaMap; -} - -void QFontEngineFT::unlockAlphaMapForGlyph() -{ - QFontEngine::unlockAlphaMapForGlyph(); -} - -static inline bool is2dRotation(const QTransform &t) -{ - return qFuzzyCompare(t.m11(), t.m22()) && qFuzzyCompare(t.m12(), -t.m21()) - && qFuzzyCompare(t.m11()*t.m22() - t.m12()*t.m21(), qreal(1.0)); -} - -QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, - QFixed subPixelPosition, - GlyphFormat format, - const QTransform &t, - bool fetchBoundingBox, - bool disableOutlineDrawing) -{ - QGlyphSet *glyphSet = loadGlyphSet(t); - if (glyphSet != 0 && glyphSet->outline_drawing && !disableOutlineDrawing && !fetchBoundingBox) - return 0; - - Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0; - if (!glyph || glyph->format != format || (!fetchBoundingBox && !glyph->data)) { - QScopedValueRollback saved_default_hint_style(default_hint_style); - if (t.type() >= QTransform::TxScale && !is2dRotation(t)) - default_hint_style = HintNone; // disable hinting if the glyphs are transformed - - lockFace(); - FT_Matrix m = this->matrix; - FT_Matrix ftMatrix = glyphSet != 0 ? glyphSet->transformationMatrix : QTransformToFTMatrix(t); - FT_Matrix_Multiply(&ftMatrix, &m); - freetype->matrix = m; - glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false, disableOutlineDrawing); - unlockFace(); - } - - return glyph; -} - -QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition) -{ - return alphaMapForGlyph(g, subPixelPosition, QTransform()); -} - -QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t) -{ - const GlyphFormat neededFormat = antialias ? Format_A8 : Format_Mono; - - Glyph *glyph = loadGlyphFor(g, subPixelPosition, neededFormat, t, false, true); - - QImage img = alphaMapFromGlyphData(glyph, neededFormat); - img = img.copy(); - - if (!cacheEnabled && glyph != &emptyGlyph) - delete glyph; - - if (!img.isNull()) - return img; - - return QFontEngine::alphaMapForGlyph(g, subPixelPosition, t); -} - -QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t) -{ - if (t.type() > QTransform::TxRotate) - return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t); - - const GlyphFormat neededFormat = Format_A32; - - Glyph *glyph = loadGlyphFor(g, subPixelPosition, neededFormat, t, false, true); - - QImage img = alphaMapFromGlyphData(glyph, neededFormat); - img = img.copy(); - - if (!cacheEnabled && glyph != &emptyGlyph) - delete glyph; - - if (!img.isNull()) - return img; - - return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t); -} - -QImage QFontEngineFT::bitmapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t) -{ - Glyph *glyph = loadGlyphFor(g, subPixelPosition, defaultFormat, t); - if (glyph == Q_NULLPTR) - return QImage(); - - QImage img; - if (defaultFormat == GlyphFormat::Format_ARGB) - img = QImage(glyph->data, glyph->width, glyph->height, QImage::Format_ARGB32_Premultiplied).copy(); - else if (defaultFormat == GlyphFormat::Format_Mono) - img = QImage(glyph->data, glyph->width, glyph->height, QImage::Format_Mono).copy(); - - if (!img.isNull() && (!t.isIdentity() || scalableBitmapScaleFactor != 1)) { - QTransform trans(t); - const qreal scaleFactor = scalableBitmapScaleFactor.toReal(); - trans.scale(scaleFactor, scaleFactor); - img = img.transformed(trans, Qt::SmoothTransformation); - } - - if (!cacheEnabled && glyph != &emptyGlyph) - delete glyph; - - return img; -} - -void QFontEngineFT::removeGlyphFromCache(glyph_t glyph) -{ - defaultGlyphSet.removeGlyphFromCache(glyph, 0); -} - -int QFontEngineFT::glyphCount() const -{ - int count = 0; - FT_Face face = lockFace(); - if (face) { - count = face->num_glyphs; - unlockFace(); - } - return count; -} - -FT_Face QFontEngineFT::lockFace(Scaling scale) const -{ - freetype->lock(); - FT_Face face = freetype->face; - if (scale == Unscaled) { - if (FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0) == 0) { - freetype->xsize = face->units_per_EM << 6; - freetype->ysize = face->units_per_EM << 6; - } - } else if (freetype->xsize != xsize || freetype->ysize != ysize) { - FT_Set_Char_Size(face, xsize, ysize, 0, 0); - freetype->xsize = xsize; - freetype->ysize = ysize; - } - if (freetype->matrix.xx != matrix.xx || - freetype->matrix.yy != matrix.yy || - freetype->matrix.xy != matrix.xy || - freetype->matrix.yx != matrix.yx) { - freetype->matrix = matrix; - FT_Set_Transform(face, &freetype->matrix, 0); - } - - return face; -} - -void QFontEngineFT::unlockFace() const -{ - freetype->unlock(); -} - -FT_Face QFontEngineFT::non_locked_face() const -{ - return freetype->face; -} - - -QFontEngineFT::QGlyphSet::QGlyphSet() - : outline_drawing(false) -{ - transformationMatrix.xx = 0x10000; - transformationMatrix.yy = 0x10000; - transformationMatrix.xy = 0; - transformationMatrix.yx = 0; - memset(fast_glyph_data, 0, sizeof(fast_glyph_data)); - fast_glyph_count = 0; -} - -QFontEngineFT::QGlyphSet::~QGlyphSet() -{ - clear(); -} - -void QFontEngineFT::QGlyphSet::clear() -{ - if (fast_glyph_count > 0) { - for (int i = 0; i < 256; ++i) { - if (fast_glyph_data[i]) { - delete fast_glyph_data[i]; - fast_glyph_data[i] = 0; - } - } - fast_glyph_count = 0; - } - qDeleteAll(glyph_data); - glyph_data.clear(); -} - -void QFontEngineFT::QGlyphSet::removeGlyphFromCache(glyph_t index, QFixed subPixelPosition) -{ - if (useFastGlyphData(index, subPixelPosition)) { - if (fast_glyph_data[index]) { - delete fast_glyph_data[index]; - fast_glyph_data[index] = 0; - if (fast_glyph_count > 0) - --fast_glyph_count; - } - } else { - delete glyph_data.take(GlyphAndSubPixelPosition(index, subPixelPosition)); - } -} - -void QFontEngineFT::QGlyphSet::setGlyph(glyph_t index, QFixed subPixelPosition, Glyph *glyph) -{ - if (useFastGlyphData(index, subPixelPosition)) { - if (!fast_glyph_data[index]) - ++fast_glyph_count; - fast_glyph_data[index] = glyph; - } else { - glyph_data.insert(GlyphAndSubPixelPosition(index, subPixelPosition), glyph); - } -} - -int QFontEngineFT::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) -{ - lockFace(); - bool hsubpixel = true; - int vfactor = 1; - int load_flags = loadFlags(0, Format_A8, flags, hsubpixel, vfactor); - int result = freetype->getPointInOutline(glyph, load_flags, point, xpos, ypos, nPoints); - unlockFace(); - return result; -} - -bool QFontEngineFT::initFromFontEngine(const QFontEngineFT *fe) -{ - if (!init(fe->faceId(), fe->antialias, fe->defaultFormat, fe->freetype)) - return false; - - // Increase the reference of this QFreetypeFace since one more QFontEngineFT - // will be using it - freetype->ref.ref(); - - default_load_flags = fe->default_load_flags; - default_hint_style = fe->default_hint_style; - antialias = fe->antialias; - transform = fe->transform; - embolden = fe->embolden; - obliquen = fe->obliquen; - subpixelType = fe->subpixelType; - lcdFilterType = fe->lcdFilterType; - embeddedbitmap = fe->embeddedbitmap; - - return true; -} - -QFontEngine *QFontEngineFT::cloneWithSize(qreal pixelSize) const -{ - QFontDef fontDef(this->fontDef); - fontDef.pixelSize = pixelSize; - QFontEngineFT *fe = new QFontEngineFT(fontDef); - if (!fe->initFromFontEngine(this)) { - delete fe; - return 0; - } else { - return fe; - } -} - -Qt::HANDLE QFontEngineFT::handle() const -{ - return non_locked_face(); -} - -QT_END_NAMESPACE - -#endif // QT_NO_FREETYPE diff --git a/src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h deleted file mode 100644 index 3b751eae3e..0000000000 --- a/src/platformsupport/fontdatabases/basic/qfontengine_ft_p.h +++ /dev/null @@ -1,360 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QFONTENGINE_FT_P_H -#define QFONTENGINE_FT_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 "private/qfontengine_p.h" - -#ifndef QT_NO_FREETYPE - -#include -#include FT_FREETYPE_H - - -#ifndef Q_OS_WIN -#include -#endif - -#include - -QT_BEGIN_NAMESPACE - -class QFontEngineFTRawFont; -class QFontconfigDatabase; - -/* - * This class represents one font file on disk (like Arial.ttf) and is shared between all the font engines - * that show this font file (at different pixel sizes). - */ -class QFreetypeFace -{ -public: - void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor); - QFontEngine::Properties properties() const; - bool getSfntTable(uint tag, uchar *buffer, uint *length) const; - - static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id, - const QByteArray &fontData = QByteArray()); - void release(const QFontEngine::FaceId &face_id); - - // locks the struct for usage. Any read/write operations require locking. - void lock() - { - _lock.lock(); - } - void unlock() - { - _lock.unlock(); - } - - FT_Face face; - int xsize; // 26.6 - int ysize; // 26.6 - FT_Matrix matrix; - FT_CharMap unicode_map; - FT_CharMap symbol_map; - - enum { cmapCacheSize = 0x200 }; - glyph_t cmapCache[cmapCacheSize]; - - int fsType() const; - - int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints); - - bool isScalableBitmap() const; - - static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale); - static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path); - -private: - friend class QFontEngineFT; - friend class QtFreetypeData; - friend struct QScopedPointerDeleter; - QFreetypeFace() : _lock(QMutex::Recursive) {} - ~QFreetypeFace() {} - void cleanup(); - QAtomicInt ref; - QMutex _lock; - QByteArray fontData; - - QFontEngine::Holder hbFace; -}; - -class QFontEngineFT : public QFontEngine -{ -public: - - /* we don't cache glyphs that are too large anyway, so we can make this struct rather small */ - struct Glyph { - ~Glyph(); - short linearAdvance; - unsigned char width; - unsigned char height; - short x; - short y; - short advance; - signed char format; - uchar *data; - }; - - struct GlyphInfo { - int linearAdvance; - unsigned short width; - unsigned short height; - short x; - short y; - short xOff; - short yOff; - }; - - struct GlyphAndSubPixelPosition - { - GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {} - - bool operator==(const GlyphAndSubPixelPosition &other) const - { - return glyph == other.glyph && subPixelPosition == other.subPixelPosition; - } - - glyph_t glyph; - QFixed subPixelPosition; - }; - - struct QGlyphSet - { - QGlyphSet(); - ~QGlyphSet(); - FT_Matrix transformationMatrix; - bool outline_drawing; - - void removeGlyphFromCache(glyph_t index, QFixed subPixelPosition); - void clear(); - inline bool useFastGlyphData(glyph_t index, QFixed subPixelPosition) const { - return (index < 256 && subPixelPosition == 0); - } - inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const; - void setGlyph(glyph_t index, QFixed spp, Glyph *glyph); - - inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); } - inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); } -private: - mutable QHash glyph_data; // maps from glyph index to glyph data - mutable QSet missing_glyphs; - mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256 - mutable int fast_glyph_count; - }; - - QFontEngine::FaceId faceId() const Q_DECL_OVERRIDE; - QFontEngine::Properties properties() const Q_DECL_OVERRIDE; - QFixed emSquareSize() const Q_DECL_OVERRIDE; - bool supportsSubPixelPositions() const Q_DECL_OVERRIDE - { - return default_hint_style == HintLight || - default_hint_style == HintNone; - } - - bool getSfntTableData(uint tag, uchar *buffer, uint *length) const Q_DECL_OVERRIDE; - int synthesized() const Q_DECL_OVERRIDE; - - QFixed ascent() const Q_DECL_OVERRIDE; - QFixed capHeight() const Q_DECL_OVERRIDE; - QFixed descent() const Q_DECL_OVERRIDE; - QFixed leading() const Q_DECL_OVERRIDE; - QFixed xHeight() const Q_DECL_OVERRIDE; - QFixed averageCharWidth() const Q_DECL_OVERRIDE; - - qreal maxCharWidth() const Q_DECL_OVERRIDE; - QFixed lineThickness() const Q_DECL_OVERRIDE; - QFixed underlinePosition() const Q_DECL_OVERRIDE; - - glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE; - void doKerning(QGlyphLayout *, ShaperFlags) const Q_DECL_OVERRIDE; - - void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) Q_DECL_OVERRIDE; - - bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE; - - void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; - void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, - QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; - - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const Q_DECL_OVERRIDE; - - glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE; - glyph_metrics_t boundingBox(glyph_t glyph) Q_DECL_OVERRIDE; - glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix) Q_DECL_OVERRIDE; - - void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const Q_DECL_OVERRIDE; - QImage alphaMapForGlyph(glyph_t g) Q_DECL_OVERRIDE { return alphaMapForGlyph(g, 0); } - QImage alphaMapForGlyph(glyph_t, QFixed) Q_DECL_OVERRIDE; - QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; - QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; - QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; - glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, - QFixed subPixelPosition, - const QTransform &matrix, - QFontEngine::GlyphFormat format) Q_DECL_OVERRIDE; - QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, - GlyphFormat neededFormat, const QTransform &t, - QPoint *offset) Q_DECL_OVERRIDE; - bool hasInternalCaching() const Q_DECL_OVERRIDE { return cacheEnabled; } - void unlockAlphaMapForGlyph() Q_DECL_OVERRIDE; - bool expectsGammaCorrectedBlending() const Q_DECL_OVERRIDE; - - void removeGlyphFromCache(glyph_t glyph) Q_DECL_OVERRIDE; - int glyphMargin(QFontEngine::GlyphFormat /* format */) Q_DECL_OVERRIDE { return 0; } - - int glyphCount() const Q_DECL_OVERRIDE; - - enum Scaling { - Scaled, - Unscaled - }; - FT_Face lockFace(Scaling scale = Scaled) const; - void unlockFace() const; - - FT_Face non_locked_face() const; - - inline bool drawAntialiased() const { return antialias; } - inline bool invalid() const { return xsize == 0 && ysize == 0; } - inline bool isBitmapFont() const { return defaultFormat == Format_Mono; } - inline bool isScalableBitmap() const { return freetype->isScalableBitmap(); } - - inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const - { return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly, disableOutlineDrawing); } - Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const; - Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t, bool fetchBoundingBox = false, bool disableOutlineDrawing = false); - - QGlyphSet *loadGlyphSet(const QTransform &matrix); - - QFontEngineFT(const QFontDef &fd); - virtual ~QFontEngineFT(); - - bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat = Format_None, - const QByteArray &fontData = QByteArray()); - bool init(FaceId faceId, bool antialias, GlyphFormat format, - QFreetypeFace *freetypeFace); - - int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) Q_DECL_OVERRIDE; - - void setQtDefaultHintStyle(QFont::HintingPreference hintingPreference); - void setDefaultHintStyle(HintStyle style) Q_DECL_OVERRIDE; - - QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; - Qt::HANDLE handle() const Q_DECL_OVERRIDE; - bool initFromFontEngine(const QFontEngineFT *fontEngine); - - HintStyle defaultHintStyle() const { return default_hint_style; } -protected: - - QFreetypeFace *freetype; - mutable int default_load_flags; - HintStyle default_hint_style; - bool antialias; - bool transform; - bool embolden; - bool obliquen; - SubpixelAntialiasingType subpixelType; - int lcdFilterType; - bool embeddedbitmap; - bool cacheEnabled; - bool forceAutoHint; - bool stemDarkeningDriver; - -private: - friend class QFontEngineFTRawFont; - friend class QFontconfigDatabase; - friend class QBasicFontDatabase; - friend class QCoreTextFontDatabase; - friend class QFontEngineMultiFontConfig; - - int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const; - bool shouldUseDesignMetrics(ShaperFlags flags) const; - QFixed scaledBitmapMetrics(QFixed m) const; - glyph_metrics_t scaledBitmapMetrics(const glyph_metrics_t &m) const; - - GlyphFormat defaultFormat; - FT_Matrix matrix; - - QList transformedGlyphSets; - mutable QGlyphSet defaultGlyphSet; - - QFontEngine::FaceId face_id; - - int xsize; - int ysize; - - QFixed line_thickness; - QFixed underline_position; - - FT_Size_Metrics metrics; - mutable bool kerning_pairs_loaded; - QFixed scalableBitmapScaleFactor; -}; - -inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g) -{ - return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt(); -} - -inline QFontEngineFT::Glyph *QFontEngineFT::QGlyphSet::getGlyph(glyph_t index, QFixed subPixelPosition) const -{ - if (useFastGlyphData(index, subPixelPosition)) - return fast_glyph_data[index]; - return glyph_data.value(GlyphAndSubPixelPosition(index, subPixelPosition)); -} - -extern FT_Library qt_getFreetype(); - -QT_END_NAMESPACE - -#endif // QT_NO_FREETYPE - -#endif // QFONTENGINE_FT_P_H diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 2c5ce3e87d..4464e93bbd 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -692,7 +692,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) QFontEngine *QFontconfigDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { - QFontEngineFT *engine = static_cast(QBasicFontDatabase::fontEngine(fontData, pixelSize, hintingPreference)); + QFontEngineFT *engine = static_cast(QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference)); if (engine == 0) return 0; @@ -844,7 +844,7 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, QString QFontconfigDatabase::resolveFontFamilyAlias(const QString &family) const { - QString resolved = QBasicFontDatabase::resolveFontFamilyAlias(family); + QString resolved = QFreeTypeFontDatabase::resolveFontFamilyAlias(family); if (!resolved.isEmpty() && resolved != family) return resolved; FcPattern *pattern = FcPatternCreate(); diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h index f7e3172b65..6a3261de30 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h @@ -52,13 +52,13 @@ // #include -#include +#include QT_BEGIN_NAMESPACE class QFontEngineFT; -class QFontconfigDatabase : public QBasicFontDatabase +class QFontconfigDatabase : public QFreeTypeFontDatabase { public: void populateFontDatabase() Q_DECL_OVERRIDE; diff --git a/src/platformsupport/fontdatabases/fontdatabases.pro b/src/platformsupport/fontdatabases/fontdatabases.pro index 49dead4668..d2726d08a0 100644 --- a/src/platformsupport/fontdatabases/fontdatabases.pro +++ b/src/platformsupport/fontdatabases/fontdatabases.pro @@ -11,7 +11,7 @@ darwin { include($$PWD/mac/coretext.pri) } else { qtConfig(freetype) { - include($$PWD/basic/basic.pri) + include($$PWD/freetype/freetype.pri) } unix { diff --git a/src/platformsupport/fontdatabases/freetype/freetype.pri b/src/platformsupport/fontdatabases/freetype/freetype.pri new file mode 100644 index 0000000000..7bda687ef4 --- /dev/null +++ b/src/platformsupport/fontdatabases/freetype/freetype.pri @@ -0,0 +1,9 @@ +HEADERS += \ + $$PWD/qfreetypefontdatabase_p.h \ + $$PWD/qfontengine_ft_p.h + +SOURCES += \ + $$PWD/qfreetypefontdatabase.cpp \ + $$PWD/qfontengine_ft.cpp + +QMAKE_USE_PRIVATE += freetype diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp new file mode 100644 index 0000000000..03e72546eb --- /dev/null +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp @@ -0,0 +1,2214 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdir.h" +#include "qmetatype.h" +#include "qtextstream.h" +#include "qvariant.h" +#include "qfontengine_ft_p.h" +#include "private/qimage_p.h" +#include + +#ifndef QT_NO_FREETYPE + +#include "qfile.h" +#include "qfileinfo.h" +#include +#include "qthreadstorage.h" +#include +#include + +#include +#include FT_FREETYPE_H +#include FT_OUTLINE_H +#include FT_SYNTHESIS_H +#include FT_TRUETYPE_TABLES_H +#include FT_TYPE1_TABLES_H +#include FT_GLYPH_H +#include FT_MODULE_H + +#if defined(FT_LCD_FILTER_H) +#include FT_LCD_FILTER_H +#define QT_USE_FREETYPE_LCDFILTER +#endif + +#if defined(FT_CONFIG_OPTIONS_H) +#include FT_CONFIG_OPTIONS_H +#endif + +#if defined(FT_FONT_FORMATS_H) +#include FT_FONT_FORMATS_H +#endif + +#ifdef QT_LINUXBASE +#include FT_ERRORS_H +#endif + +#if !defined(QT_MAX_CACHED_GLYPH_SIZE) +# define QT_MAX_CACHED_GLYPH_SIZE 64 +#endif + +QT_BEGIN_NAMESPACE + +#define FLOOR(x) ((x) & -64) +#define CEIL(x) (((x)+63) & -64) +#define TRUNC(x) ((x) >> 6) +#define ROUND(x) (((x)+32) & -64) + +static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length) +{ + FT_Face face = (FT_Face)user_data; + + bool result = false; + if (FT_IS_SFNT(face)) { + FT_ULong len = *length; + result = FT_Load_Sfnt_Table(face, tag, 0, buffer, &len) == FT_Err_Ok; + *length = len; + Q_ASSERT(!result || int(*length) > 0); + } + + return result; +} + +static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0}; + +static const QFontEngine::HintStyle ftInitialDefaultHintStyle = +#ifdef Q_OS_WIN + QFontEngineFT::HintFull; +#else + QFontEngineFT::HintNone; +#endif + +// -------------------------- Freetype support ------------------------------ + +class QtFreetypeData +{ +public: + QtFreetypeData() + : library(0) + { } + ~QtFreetypeData(); + + FT_Library library; + QHash faces; +}; + +QtFreetypeData::~QtFreetypeData() +{ + for (QHash::ConstIterator iter = faces.cbegin(); iter != faces.cend(); ++iter) + iter.value()->cleanup(); + faces.clear(); + FT_Done_FreeType(library); + library = 0; +} + +#ifdef QT_NO_THREAD +Q_GLOBAL_STATIC(QtFreetypeData, theFreetypeData) + +QtFreetypeData *qt_getFreetypeData() +{ + return theFreetypeData(); +} +#else +Q_GLOBAL_STATIC(QThreadStorage, theFreetypeData) + +QtFreetypeData *qt_getFreetypeData() +{ + QtFreetypeData *&freetypeData = theFreetypeData()->localData(); + if (!freetypeData) + freetypeData = new QtFreetypeData; + if (!freetypeData->library) { + FT_Init_FreeType(&freetypeData->library); +#if defined(FT_FONT_FORMATS_H) + // Freetype defaults to disabling stem-darkening on CFF, we re-enable it. + FT_Bool no_darkening = false; + FT_Property_Set(freetypeData->library, "cff", "no-stem-darkening", &no_darkening); +#endif + } + return freetypeData; +} +#endif + +FT_Library qt_getFreetype() +{ + QtFreetypeData *freetypeData = qt_getFreetypeData(); + Q_ASSERT(freetypeData->library); + return freetypeData->library; +} + +int QFreetypeFace::fsType() const +{ + int fsType = 0; + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); + if (os2) + fsType = os2->fsType; + return fsType; +} + +int QFreetypeFace::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) +{ + if (int error = FT_Load_Glyph(face, glyph, flags)) + return error; + + if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) + return Err_Invalid_SubTable; + + *nPoints = face->glyph->outline.n_points; + if (!(*nPoints)) + return Err_Ok; + + if (point > *nPoints) + return Err_Invalid_SubTable; + + *xpos = QFixed::fromFixed(face->glyph->outline.points[point].x); + *ypos = QFixed::fromFixed(face->glyph->outline.points[point].y); + + return Err_Ok; +} + +bool QFreetypeFace::isScalableBitmap() const +{ +#ifdef FT_HAS_COLOR + return !FT_IS_SCALABLE(face) && FT_HAS_COLOR(face); +#else + return false; +#endif +} + +extern QByteArray qt_fontdata_from_index(int); + +/* + * One font file can contain more than one font (bold/italic for example) + * find the right one and return it. + * + * Returns the freetype face or 0 in case of an empty file or any other problems + * (like not being able to open the file) + */ +QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, + const QByteArray &fontData) +{ + if (face_id.filename.isEmpty() && fontData.isEmpty()) + return 0; + + QtFreetypeData *freetypeData = qt_getFreetypeData(); + + QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0); + if (freetype) { + freetype->ref.ref(); + } else { + QScopedPointer newFreetype(new QFreetypeFace); + FT_Face face; + if (!face_id.filename.isEmpty()) { + QString fileName = QFile::decodeName(face_id.filename); + if (face_id.filename.startsWith(":qmemoryfonts/")) { + // from qfontdatabase.cpp + QByteArray idx = face_id.filename; + idx.remove(0, 14); // remove ':qmemoryfonts/' + bool ok = false; + newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok)); + if (!ok) + newFreetype->fontData = QByteArray(); + } else if (!QFileInfo(fileName).isNativePath()) { + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) { + return 0; + } + newFreetype->fontData = file.readAll(); + } + } else { + newFreetype->fontData = fontData; + } + if (!newFreetype->fontData.isEmpty()) { + if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)newFreetype->fontData.constData(), newFreetype->fontData.size(), face_id.index, &face)) { + return 0; + } + } else if (FT_New_Face(freetypeData->library, face_id.filename, face_id.index, &face)) { + return 0; + } + newFreetype->face = face; + + newFreetype->ref.store(1); + newFreetype->xsize = 0; + newFreetype->ysize = 0; + newFreetype->matrix.xx = 0x10000; + newFreetype->matrix.yy = 0x10000; + newFreetype->matrix.xy = 0; + newFreetype->matrix.yx = 0; + newFreetype->unicode_map = 0; + newFreetype->symbol_map = 0; + + memset(newFreetype->cmapCache, 0, sizeof(newFreetype->cmapCache)); + + for (int i = 0; i < newFreetype->face->num_charmaps; ++i) { + FT_CharMap cm = newFreetype->face->charmaps[i]; + switch(cm->encoding) { + case FT_ENCODING_UNICODE: + newFreetype->unicode_map = cm; + break; + case FT_ENCODING_APPLE_ROMAN: + case FT_ENCODING_ADOBE_LATIN_1: + if (!newFreetype->unicode_map || newFreetype->unicode_map->encoding != FT_ENCODING_UNICODE) + newFreetype->unicode_map = cm; + break; + case FT_ENCODING_ADOBE_CUSTOM: + case FT_ENCODING_MS_SYMBOL: + if (!newFreetype->symbol_map) + newFreetype->symbol_map = cm; + break; + default: + break; + } + } + + if (!FT_IS_SCALABLE(newFreetype->face) && newFreetype->face->num_fixed_sizes == 1) + FT_Set_Char_Size(face, newFreetype->face->available_sizes[0].x_ppem, newFreetype->face->available_sizes[0].y_ppem, 0, 0); + + FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map); + QT_TRY { + freetypeData->faces.insert(face_id, newFreetype.data()); + } QT_CATCH(...) { + newFreetype.take()->release(face_id); + // we could return null in principle instead of throwing + QT_RETHROW; + } + freetype = newFreetype.take(); + } + return freetype; +} + +void QFreetypeFace::cleanup() +{ + hbFace.reset(); + FT_Done_Face(face); + face = 0; +} + +void QFreetypeFace::release(const QFontEngine::FaceId &face_id) +{ + if (!ref.deref()) { + if (face) { + QtFreetypeData *freetypeData = qt_getFreetypeData(); + + cleanup(); + + auto it = freetypeData->faces.constFind(face_id); + if (it != freetypeData->faces.constEnd()) + freetypeData->faces.erase(it); + + if (freetypeData->faces.isEmpty()) { + FT_Done_FreeType(freetypeData->library); + freetypeData->library = 0; + } + } + + delete this; + } +} + + +void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor) +{ + *ysize = qRound(fontDef.pixelSize * 64); + *xsize = *ysize * fontDef.stretch / 100; + *scalableBitmapScaleFactor = 1; + *outline_drawing = false; + + if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) { + int best = 0; + if (!isScalableBitmap()) { + /* + * Bitmap only faces must match exactly, so find the closest + * one (height dominant search) + */ + for (int i = 1; i < face->num_fixed_sizes; i++) { + if (qAbs(*ysize - face->available_sizes[i].y_ppem) < + qAbs(*ysize - face->available_sizes[best].y_ppem) || + (qAbs(*ysize - face->available_sizes[i].y_ppem) == + qAbs(*ysize - face->available_sizes[best].y_ppem) && + qAbs(*xsize - face->available_sizes[i].x_ppem) < + qAbs(*xsize - face->available_sizes[best].x_ppem))) { + best = i; + } + } + } else { + // Select the shortest bitmap strike whose height is larger than the desired height + for (int i = 1; i < face->num_fixed_sizes; i++) { + if (face->available_sizes[i].y_ppem < *ysize) { + if (face->available_sizes[i].y_ppem > face->available_sizes[best].y_ppem) + best = i; + } else if (face->available_sizes[best].y_ppem < *ysize) { + best = i; + } else if (face->available_sizes[i].y_ppem < face->available_sizes[best].y_ppem) { + best = i; + } + } + } + + // According to freetype documentation we must use FT_Select_Size + // to make sure we can select the desired bitmap strike index + if (FT_Select_Size(face, best) == 0) { + if (isScalableBitmap()) + *scalableBitmapScaleFactor = QFixed::fromReal((qreal)fontDef.pixelSize / face->available_sizes[best].height); + *xsize = face->available_sizes[best].x_ppem; + *ysize = face->available_sizes[best].y_ppem; + } else { + *xsize = *ysize = 0; + } + } else { + *outline_drawing = (*xsize > (QT_MAX_CACHED_GLYPH_SIZE<<6) || *ysize > (QT_MAX_CACHED_GLYPH_SIZE<<6)); + } +} + +QFontEngine::Properties QFreetypeFace::properties() const +{ + QFontEngine::Properties p; + p.postscriptName = FT_Get_Postscript_Name(face); + PS_FontInfoRec font_info; + if (FT_Get_PS_Font_Info(face, &font_info) == 0) + p.copyright = font_info.notice; + if (FT_IS_SCALABLE(face)) { + p.ascent = face->ascender; + p.descent = -face->descender; + p.leading = face->height - face->ascender + face->descender; + p.emSquare = face->units_per_EM; + p.boundingBox = QRectF(face->bbox.xMin, -face->bbox.yMax, + face->bbox.xMax - face->bbox.xMin, + face->bbox.yMax - face->bbox.yMin); + } else { + p.ascent = QFixed::fromFixed(face->size->metrics.ascender); + p.descent = QFixed::fromFixed(-face->size->metrics.descender); + p.leading = QFixed::fromFixed(face->size->metrics.height - face->size->metrics.ascender + face->size->metrics.descender); + p.emSquare = face->size->metrics.y_ppem; +// p.boundingBox = QRectF(-p.ascent.toReal(), 0, (p.ascent + p.descent).toReal(), face->size->metrics.max_advance/64.); + p.boundingBox = QRectF(0, -p.ascent.toReal(), + face->size->metrics.max_advance/64, (p.ascent + p.descent).toReal() ); + } + p.italicAngle = 0; + p.capHeight = p.ascent; + p.lineWidth = face->underline_thickness; + + return p; +} + +bool QFreetypeFace::getSfntTable(uint tag, uchar *buffer, uint *length) const +{ + return ft_getSfntTable(face, tag, buffer, length); +} + +/* Some fonts (such as MingLiu rely on hinting to scale different + components to their correct sizes. While this is really broken (it + should be done in the component glyph itself, not the hinter) we + will have to live with it. + + This means we can not use FT_LOAD_NO_HINTING to get the glyph + outline. All we can do is to load the unscaled glyph and scale it + down manually when required. +*/ +static void scaleOutline(FT_Face face, FT_GlyphSlot g, FT_Fixed x_scale, FT_Fixed y_scale) +{ + x_scale = FT_MulDiv(x_scale, 1 << 10, face->units_per_EM); + y_scale = FT_MulDiv(y_scale, 1 << 10, face->units_per_EM); + FT_Vector *p = g->outline.points; + const FT_Vector *e = p + g->outline.n_points; + while (p < e) { + p->x = FT_MulFix(p->x, x_scale); + p->y = FT_MulFix(p->y, y_scale); + ++p; + } +} + +#define GLYPH2PATH_DEBUG QT_NO_QDEBUG_MACRO // qDebug +void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale) +{ + const qreal factor = 1/64.; + scaleOutline(face, g, x_scale, y_scale); + + QPointF cp = point.toPointF(); + + // convert the outline to a painter path + int i = 0; + for (int j = 0; j < g->outline.n_contours; ++j) { + int last_point = g->outline.contours[j]; + GLYPH2PATH_DEBUG() << "contour:" << i << "to" << last_point; + QPointF start = QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor); + if (!(g->outline.tags[i] & 1)) { // start point is not on curve: + if (!(g->outline.tags[last_point] & 1)) { // end point is not on curve: + GLYPH2PATH_DEBUG() << " start and end point are not on curve"; + start = (QPointF(g->outline.points[last_point].x*factor, + -g->outline.points[last_point].y*factor) + start) / 2.0; + } else { + GLYPH2PATH_DEBUG() << " end point is on curve, start is not"; + start = QPointF(g->outline.points[last_point].x*factor, + -g->outline.points[last_point].y*factor); + } + --i; // to use original start point as control point below + } + start += cp; + GLYPH2PATH_DEBUG() << " start at" << start; + + path->moveTo(start); + QPointF c[4]; + c[0] = start; + int n = 1; + while (i < last_point) { + ++i; + c[n] = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor); + GLYPH2PATH_DEBUG() << " " << i << c[n] << "tag =" << (int)g->outline.tags[i] + << ": on curve =" << (bool)(g->outline.tags[i] & 1); + ++n; + switch (g->outline.tags[i] & 3) { + case 2: + // cubic bezier element + if (n < 4) + continue; + c[3] = (c[3] + c[2])/2; + --i; + break; + case 0: + // quadratic bezier element + if (n < 3) + continue; + c[3] = (c[1] + c[2])/2; + c[2] = (2*c[1] + c[3])/3; + c[1] = (2*c[1] + c[0])/3; + --i; + break; + case 1: + case 3: + if (n == 2) { + GLYPH2PATH_DEBUG() << " lineTo" << c[1]; + path->lineTo(c[1]); + c[0] = c[1]; + n = 1; + continue; + } else if (n == 3) { + c[3] = c[2]; + c[2] = (2*c[1] + c[3])/3; + c[1] = (2*c[1] + c[0])/3; + } + break; + } + GLYPH2PATH_DEBUG() << " cubicTo" << c[1] << c[2] << c[3]; + path->cubicTo(c[1], c[2], c[3]); + c[0] = c[3]; + n = 1; + } + + if (n == 1) { + GLYPH2PATH_DEBUG() << " closeSubpath"; + path->closeSubpath(); + } else { + c[3] = start; + if (n == 2) { + c[2] = (2*c[1] + c[3])/3; + c[1] = (2*c[1] + c[0])/3; + } + GLYPH2PATH_DEBUG() << " close cubicTo" << c[1] << c[2] << c[3]; + path->cubicTo(c[1], c[2], c[3]); + } + ++i; + } +} + +extern void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path); + +void QFreetypeFace::addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path) +{ + if (slot->format != FT_GLYPH_FORMAT_BITMAP + || slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO) + return; + + QPointF cp = point.toPointF(); + qt_addBitmapToPath(cp.x() + TRUNC(slot->metrics.horiBearingX), cp.y() - TRUNC(slot->metrics.horiBearingY), + slot->bitmap.buffer, slot->bitmap.pitch, slot->bitmap.width, slot->bitmap.rows, path); +} + +QFontEngineFT::Glyph::~Glyph() +{ + delete [] data; +} + +struct LcdFilterDummy +{ + static inline void filterPixel(uchar &, uchar &, uchar &) + {} +}; + +struct LcdFilterLegacy +{ + static inline void filterPixel(uchar &red, uchar &green, uchar &blue) + { + uint r = red, g = green, b = blue; + // intra-pixel filter used by the legacy filter (adopted from _ft_lcd_filter_legacy) + red = (r * uint(65538 * 9/13) + g * uint(65538 * 1/6) + b * uint(65538 * 1/13)) / 65536; + green = (r * uint(65538 * 3/13) + g * uint(65538 * 4/6) + b * uint(65538 * 3/13)) / 65536; + blue = (r * uint(65538 * 1/13) + g * uint(65538 * 1/6) + b * uint(65538 * 9/13)) / 65536; + } +}; + +template +static void convertRGBToARGB_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr) +{ + const int offs = bgr ? -1 : 1; + const int w = width * 3; + while (height--) { + uint *dd = dst; + for (int x = 0; x < w; x += 3) { + uchar red = src[x + 1 - offs]; + uchar green = src[x + 1]; + uchar blue = src[x + 1 + offs]; + LcdFilter::filterPixel(red, green, blue); + *dd++ = (0xFF << 24) | (red << 16) | (green << 8) | blue; + } + dst += width; + src += src_pitch; + } +} + +static inline void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter) +{ + if (!legacyFilter) + convertRGBToARGB_helper(src, dst, width, height, src_pitch, bgr); + else + convertRGBToARGB_helper(src, dst, width, height, src_pitch, bgr); +} + +template +static void convertRGBToARGB_V_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr) +{ + const int offs = bgr ? -src_pitch : src_pitch; + while (height--) { + for (int x = 0; x < width; x++) { + uchar red = src[x + src_pitch - offs]; + uchar green = src[x + src_pitch]; + uchar blue = src[x + src_pitch + offs]; + LcdFilter::filterPixel(red, green, blue); + *dst++ = (0XFF << 24) | (red << 16) | (green << 8) | blue; + } + src += 3*src_pitch; + } +} + +static inline void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter) +{ + if (!legacyFilter) + convertRGBToARGB_V_helper(src, dst, width, height, src_pitch, bgr); + else + convertRGBToARGB_V_helper(src, dst, width, height, src_pitch, bgr); +} + +static inline void convertGRAYToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch) +{ + while (height--) { + const uchar *p = src; + const uchar * const e = p + width; + while (p < e) { + uchar gray = *p++; + *dst++ = (0xFF << 24) | (gray << 16) | (gray << 8) | gray; + } + src += src_pitch; + } +} + +static void convoluteBitmap(const uchar *src, uchar *dst, int width, int height, int pitch) +{ + // convolute the bitmap with a triangle filter to get rid of color fringes + // If we take account for a gamma value of 2, we end up with + // weights of 1, 4, 9, 4, 1. We use an approximation of 1, 3, 8, 3, 1 here, + // as this nicely sums up to 16 :) + int h = height; + while (h--) { + dst[0] = dst[1] = 0; + // + for (int x = 2; x < width - 2; ++x) { + uint sum = src[x-2] + 3*src[x-1] + 8*src[x] + 3*src[x+1] + src[x+2]; + dst[x] = (uchar) (sum >> 4); + } + dst[width - 2] = dst[width - 1] = 0; + src += pitch; + dst += pitch; + } +} + +QFontEngineFT::QFontEngineFT(const QFontDef &fd) + : QFontEngine(Freetype) +{ + fontDef = fd; + matrix.xx = 0x10000; + matrix.yy = 0x10000; + matrix.xy = 0; + matrix.yx = 0; + cache_cost = 100 * 1024; + kerning_pairs_loaded = false; + transform = false; + embolden = false; + obliquen = false; + antialias = true; + freetype = 0; + default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; + default_hint_style = ftInitialDefaultHintStyle; + subpixelType = Subpixel_None; + lcdFilterType = 0; +#if defined(FT_LCD_FILTER_H) + lcdFilterType = (int)((quintptr) FT_LCD_FILTER_DEFAULT); +#endif + defaultFormat = Format_None; + embeddedbitmap = false; + const QByteArray env = qgetenv("QT_NO_FT_CACHE"); + cacheEnabled = env.isEmpty() || env.toInt() == 0; + m_subPixelPositionCount = 4; + forceAutoHint = false; + stemDarkeningDriver = false; +} + +QFontEngineFT::~QFontEngineFT() +{ + if (freetype) + freetype->release(face_id); +} + +bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, + const QByteArray &fontData) +{ + return init(faceId, antialias, format, QFreetypeFace::getFace(faceId, fontData)); +} + +static void dont_delete(void*) {} + +bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, + QFreetypeFace *freetypeFace) +{ + freetype = freetypeFace; + if (!freetype) { + xsize = 0; + ysize = 0; + return false; + } + defaultFormat = format; + this->antialias = antialias; + + if (!antialias) + glyphFormat = QFontEngine::Format_Mono; + else + glyphFormat = defaultFormat; + + face_id = faceId; + + symbol = freetype->symbol_map != 0; + PS_FontInfoRec psrec; + // don't assume that type1 fonts are symbol fonts by default + if (FT_Get_PS_Font_Info(freetype->face, &psrec) == FT_Err_Ok) { + symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive)); + } + + freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing, &scalableBitmapScaleFactor); + + FT_Face face = lockFace(); + + if (FT_IS_SCALABLE(face)) { + bool fake_oblique = (fontDef.style != QFont::StyleNormal) && !(face->style_flags & FT_STYLE_FLAG_ITALIC); + if (fake_oblique) + obliquen = true; + FT_Set_Transform(face, &matrix, 0); + freetype->matrix = matrix; + // fake bold + if ((fontDef.weight >= QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face)) { + if (const TT_OS2 *os2 = reinterpret_cast(FT_Get_Sfnt_Table(face, ft_sfnt_os2))) { + if (os2->usWeightClass < 750) + embolden = true; + } + } + // underline metrics + line_thickness = QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)); + underline_position = QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale)); + } else { + // ad hoc algorithm + int score = fontDef.weight * fontDef.pixelSize; + line_thickness = score / 700; + // looks better with thicker line for small pointsizes + if (line_thickness < 2 && score >= 1050) + line_thickness = 2; + underline_position = ((line_thickness * 2) + 3) / 6; + + if (isScalableBitmap()) { + glyphFormat = defaultFormat = GlyphFormat::Format_ARGB; + cacheEnabled = false; + } + } + if (line_thickness < 1) + line_thickness = 1; + + metrics = face->size->metrics; + + /* + TrueType fonts with embedded bitmaps may have a bitmap font specific + ascent/descent in the EBLC table. There is no direct public API + to extract those values. The only way we've found is to trick freetype + into thinking that it's not a scalable font in FT_SelectSize so that + the metrics are retrieved from the bitmap strikes. + */ + if (FT_IS_SCALABLE(face)) { + for (int i = 0; i < face->num_fixed_sizes; ++i) { + if (xsize == face->available_sizes[i].x_ppem && ysize == face->available_sizes[i].y_ppem) { + face->face_flags &= ~FT_FACE_FLAG_SCALABLE; + + FT_Select_Size(face, i); + if (face->size->metrics.ascender + face->size->metrics.descender > 0) { + FT_Pos leading = metrics.height - metrics.ascender + metrics.descender; + metrics.ascender = face->size->metrics.ascender; + metrics.descender = face->size->metrics.descender; + if (metrics.descender > 0 + && QString::fromUtf8(face->family_name) == QLatin1String("Courier New")) { + metrics.descender *= -1; + } + metrics.height = metrics.ascender - metrics.descender + leading; + } + FT_Set_Char_Size(face, xsize, ysize, 0, 0); + + face->face_flags |= FT_FACE_FLAG_SCALABLE; + break; + } + } + } +#if defined(FT_FONT_FORMATS_H) + const char *fmt = FT_Get_Font_Format(face); + if (fmt && qstrncmp(fmt, "CFF", 4) == 0) { + FT_Bool no_stem_darkening = true; + FT_Error err = FT_Property_Get(qt_getFreetype(), "cff", "no-stem-darkening", &no_stem_darkening); + if (err == FT_Err_Ok) + stemDarkeningDriver = !no_stem_darkening; + else + stemDarkeningDriver = false; + } +#endif + + fontDef.styleName = QString::fromUtf8(face->style_name); + + if (!freetype->hbFace) { + faceData.user_data = face; + faceData.get_font_table = ft_getSfntTable; + (void)harfbuzzFace(); // populates face_ + freetype->hbFace = std::move(face_); + } else { + Q_ASSERT(!face_); + } + // we share the HB face in QFreeTypeFace, so do not let ~QFontEngine() destroy it + face_ = Holder(freetype->hbFace.get(), dont_delete); + + unlockFace(); + + fsType = freetype->fsType(); + return true; +} + +void QFontEngineFT::setQtDefaultHintStyle(QFont::HintingPreference hintingPreference) +{ + switch (hintingPreference) { + case QFont::PreferNoHinting: + setDefaultHintStyle(HintNone); + break; + case QFont::PreferFullHinting: + setDefaultHintStyle(HintFull); + break; + case QFont::PreferVerticalHinting: + setDefaultHintStyle(HintLight); + break; + case QFont::PreferDefaultHinting: + setDefaultHintStyle(ftInitialDefaultHintStyle); + break; + } +} + +void QFontEngineFT::setDefaultHintStyle(HintStyle style) +{ + default_hint_style = style; +} + +bool QFontEngineFT::expectsGammaCorrectedBlending() const +{ + return stemDarkeningDriver; +} + +int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags, + bool &hsubpixel, int &vfactor) const +{ + int load_flags = FT_LOAD_DEFAULT | default_load_flags; + int load_target = default_hint_style == HintLight + ? FT_LOAD_TARGET_LIGHT + : FT_LOAD_TARGET_NORMAL; + + if (format == Format_Mono) { + load_target = FT_LOAD_TARGET_MONO; + } else if (format == Format_A32) { + if (subpixelType == Subpixel_RGB || subpixelType == Subpixel_BGR) { + if (default_hint_style == HintFull) + load_target = FT_LOAD_TARGET_LCD; + hsubpixel = true; + } else if (subpixelType == Subpixel_VRGB || subpixelType == Subpixel_VBGR) { + if (default_hint_style == HintFull) + load_target = FT_LOAD_TARGET_LCD_V; + vfactor = 3; + } + } else if (format == Format_ARGB) { +#ifdef FT_LOAD_COLOR + load_flags |= FT_LOAD_COLOR; +#endif + } + + if (set && set->outline_drawing) + load_flags |= FT_LOAD_NO_BITMAP; + + if (default_hint_style == HintNone || (flags & DesignMetrics) || (set && set->outline_drawing)) + load_flags |= FT_LOAD_NO_HINTING; + else + load_flags |= load_target; + + if (forceAutoHint) + load_flags |= FT_LOAD_FORCE_AUTOHINT; + + return load_flags; +} + +static inline bool areMetricsTooLarge(const QFontEngineFT::GlyphInfo &info) +{ + // false if exceeds QFontEngineFT::Glyph metrics + return (short)(info.linearAdvance) != info.linearAdvance + || (uchar)(info.width) != info.width + || (uchar)(info.height) != info.height; +} + +static inline void transformBoundingBox(int *left, int *top, int *right, int *bottom, FT_Matrix *matrix) +{ + int l, r, t, b; + FT_Vector vector; + vector.x = *left; + vector.y = *top; + FT_Vector_Transform(&vector, matrix); + l = r = vector.x; + t = b = vector.y; + vector.x = *right; + vector.y = *top; + FT_Vector_Transform(&vector, matrix); + if (l > vector.x) l = vector.x; + if (r < vector.x) r = vector.x; + if (t < vector.y) t = vector.y; + if (b > vector.y) b = vector.y; + vector.x = *right; + vector.y = *bottom; + FT_Vector_Transform(&vector, matrix); + if (l > vector.x) l = vector.x; + if (r < vector.x) r = vector.x; + if (t < vector.y) t = vector.y; + if (b > vector.y) b = vector.y; + vector.x = *left; + vector.y = *bottom; + FT_Vector_Transform(&vector, matrix); + if (l > vector.x) l = vector.x; + if (r < vector.x) r = vector.x; + if (t < vector.y) t = vector.y; + if (b > vector.y) b = vector.y; + *left = l; + *right = r; + *top = t; + *bottom = b; +} + +QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, + QFixed subPixelPosition, + GlyphFormat format, + bool fetchMetricsOnly, + bool disableOutlineDrawing) const +{ +// Q_ASSERT(freetype->lock == 1); + + if (format == Format_None) + format = defaultFormat != Format_None ? defaultFormat : Format_Mono; + Q_ASSERT(format != Format_None); + + Glyph *g = set ? set->getGlyph(glyph, subPixelPosition) : 0; + if (g && g->format == format && (fetchMetricsOnly || g->data)) + return g; + + if (!g && set && set->isGlyphMissing(glyph)) + return &emptyGlyph; + + + FT_Face face = freetype->face; + + FT_Matrix matrix = freetype->matrix; + + FT_Vector v; + v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.value()); + v.y = 0; + FT_Set_Transform(face, &matrix, &v); + + bool hsubpixel = false; + int vfactor = 1; + int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor); + + bool transform = matrix.xx != 0x10000 + || matrix.yy != 0x10000 + || matrix.xy != 0 + || matrix.yx != 0; + + if (transform || (format != Format_Mono && !isScalableBitmap())) + load_flags |= FT_LOAD_NO_BITMAP; + + FT_Error err = FT_Load_Glyph(face, glyph, load_flags); + if (err && (load_flags & FT_LOAD_NO_BITMAP)) { + load_flags &= ~FT_LOAD_NO_BITMAP; + err = FT_Load_Glyph(face, glyph, load_flags); + } + if (err == FT_Err_Too_Few_Arguments) { + // this is an error in the bytecode interpreter, just try to run without it + load_flags |= FT_LOAD_FORCE_AUTOHINT; + err = FT_Load_Glyph(face, glyph, load_flags); + } else if (err == FT_Err_Execution_Too_Long) { + // This is an error in the bytecode, probably a web font made by someone who + // didn't test bytecode hinting at all so disable for it for all glyphs. + qWarning("load glyph failed due to broken hinting bytecode in font, switching to auto hinting"); + default_load_flags |= FT_LOAD_FORCE_AUTOHINT; + load_flags |= FT_LOAD_FORCE_AUTOHINT; + err = FT_Load_Glyph(face, glyph, load_flags); + } + if (err != FT_Err_Ok) { + qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph); + if (set) + set->setGlyphMissing(glyph); + return &emptyGlyph; + } + + FT_GlyphSlot slot = face->glyph; + + if (embolden) + FT_GlyphSlot_Embolden(slot); + if (obliquen) { + FT_GlyphSlot_Oblique(slot); + + // While Embolden alters the metrics of the slot, oblique does not, so we need + // to fix this ourselves. + transform = true; + FT_Matrix m; + m.xx = 0x10000; + m.yx = 0x0; + m.xy = 0x6000; + m.yy = 0x10000; + + FT_Matrix_Multiply(&m, &matrix); + } + + GlyphInfo info; + info.linearAdvance = slot->linearHoriAdvance >> 10; + info.xOff = TRUNC(ROUND(slot->advance.x)); + info.yOff = 0; + + if ((set && set->outline_drawing && !disableOutlineDrawing) || fetchMetricsOnly) { + int left = slot->metrics.horiBearingX; + int right = slot->metrics.horiBearingX + slot->metrics.width; + int top = slot->metrics.horiBearingY; + int bottom = slot->metrics.horiBearingY - slot->metrics.height; + + if (transform && slot->format != FT_GLYPH_FORMAT_BITMAP) + transformBoundingBox(&left, &top, &right, &bottom, &matrix); + + left = FLOOR(left); + right = CEIL(right); + bottom = FLOOR(bottom); + top = CEIL(top); + + info.x = TRUNC(left); + info.y = TRUNC(top); + info.width = TRUNC(right - left); + info.height = TRUNC(top - bottom); + + // If any of the metrics are too large to fit, don't cache them + if (areMetricsTooLarge(info)) + return 0; + + g = new Glyph; + g->data = 0; + g->linearAdvance = info.linearAdvance; + g->width = info.width; + g->height = info.height; + g->x = info.x; + g->y = info.y; + g->advance = info.xOff; + g->format = format; + + if (set) + set->setGlyph(glyph, subPixelPosition, g); + + return g; + } + + int glyph_buffer_size = 0; + QScopedArrayPointer glyph_buffer; +#if defined(QT_USE_FREETYPE_LCDFILTER) + bool useFreetypeRenderGlyph = false; + if (slot->format == FT_GLYPH_FORMAT_OUTLINE && (hsubpixel || vfactor != 1)) { + err = FT_Library_SetLcdFilter(slot->library, (FT_LcdFilter)lcdFilterType); + if (err == FT_Err_Ok) + useFreetypeRenderGlyph = true; + } + + if (useFreetypeRenderGlyph) { + err = FT_Render_Glyph(slot, hsubpixel ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_LCD_V); + + if (err != FT_Err_Ok) + qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph); + + FT_Library_SetLcdFilter(slot->library, FT_LCD_FILTER_NONE); + + info.height = slot->bitmap.rows / vfactor; + info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width; + info.x = slot->bitmap_left; + info.y = slot->bitmap_top; + + glyph_buffer_size = info.width * info.height * 4; + glyph_buffer.reset(new uchar[glyph_buffer_size]); + + if (hsubpixel) + convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB, false); + else if (vfactor != 1) + convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB, false); + } else +#endif + { + int left = slot->metrics.horiBearingX; + int right = slot->metrics.horiBearingX + slot->metrics.width; + int top = slot->metrics.horiBearingY; + int bottom = slot->metrics.horiBearingY - slot->metrics.height; + if (transform && slot->format != FT_GLYPH_FORMAT_BITMAP) + transformBoundingBox(&left, &top, &right, &bottom, &matrix); + left = FLOOR(left); + right = CEIL(right); + bottom = FLOOR(bottom); + top = CEIL(top); + + int hpixels = TRUNC(right - left); + // subpixel position requires one more pixel + if (subPixelPosition > 0 && format != Format_Mono) + hpixels++; + + if (hsubpixel) + hpixels = hpixels*3 + 8; + info.width = hpixels; + info.height = TRUNC(top - bottom); + info.x = TRUNC(left); + info.y = TRUNC(top); + if (hsubpixel) { + info.width /= 3; + info.x -= 1; + } + + // If any of the metrics are too large to fit, don't cache them + if (areMetricsTooLarge(info)) + return 0; + + int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 : + (format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4)); + if (glyph_buffer_size < pitch * info.height) { + glyph_buffer_size = pitch * info.height; + glyph_buffer.reset(new uchar[glyph_buffer_size]); + memset(glyph_buffer.data(), 0, glyph_buffer_size); + } + + if (slot->format == FT_GLYPH_FORMAT_OUTLINE) { + FT_Bitmap bitmap; + bitmap.rows = info.height*vfactor; + bitmap.width = hpixels; + bitmap.pitch = format == Format_Mono ? (((info.width + 31) & ~31) >> 3) : ((bitmap.width + 3) & ~3); + int bitmap_buffer_size = bitmap.rows * bitmap.pitch; + if (!hsubpixel && vfactor == 1 && format != Format_A32) { + Q_ASSERT(glyph_buffer_size <= bitmap_buffer_size); + bitmap.buffer = glyph_buffer.data(); + } else { + bitmap.buffer = new uchar[bitmap_buffer_size]; + memset(bitmap.buffer, 0, bitmap_buffer_size); + } + bitmap.pixel_mode = format == Format_Mono ? FT_PIXEL_MODE_MONO : FT_PIXEL_MODE_GRAY; + FT_Matrix matrix; + matrix.xx = (hsubpixel ? 3 : 1) << 16; + matrix.yy = vfactor << 16; + matrix.yx = matrix.xy = 0; + + FT_Outline_Transform(&slot->outline, &matrix); + FT_Outline_Translate (&slot->outline, (hsubpixel ? -3*left +(4<<6) : -left), -bottom*vfactor); + FT_Outline_Get_Bitmap(slot->library, &slot->outline, &bitmap); + if (hsubpixel) { + Q_ASSERT (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY); + Q_ASSERT(antialias); + uchar *convoluted = new uchar[bitmap_buffer_size]; + bool useLegacyLcdFilter = false; +#if defined(FC_LCD_FILTER) && defined(FT_LCD_FILTER_H) + useLegacyLcdFilter = (lcdFilterType == FT_LCD_FILTER_LEGACY); +#endif + uchar *buffer = bitmap.buffer; + if (!useLegacyLcdFilter) { + convoluteBitmap(bitmap.buffer, convoluted, bitmap.width, info.height, bitmap.pitch); + buffer = convoluted; + } + convertRGBToARGB(buffer + 1, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch, subpixelType != Subpixel_RGB, useLegacyLcdFilter); + delete [] convoluted; + } else if (vfactor != 1) { + convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch, subpixelType != Subpixel_VRGB, true); + } else if (format == Format_A32 && bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) { + convertGRAYToARGB(bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch); + } + + if (bitmap.buffer != glyph_buffer.data()) + delete [] bitmap.buffer; + } else if (slot->format == FT_GLYPH_FORMAT_BITMAP) { +#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100) >= 20500) + Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO || slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA); +#else + Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO); +#endif + uchar *src = slot->bitmap.buffer; + uchar *dst = glyph_buffer.data(); + int h = slot->bitmap.rows; + if (format == Format_Mono) { + int bytes = ((info.width + 7) & ~7) >> 3; + while (h--) { + memcpy (dst, src, bytes); + dst += pitch; + src += slot->bitmap.pitch; + } + } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { + if (hsubpixel) { + while (h--) { + uint *dd = (uint *)dst; + *dd++ = 0; + for (int x = 0; x < static_cast(slot->bitmap.width); x++) { + uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000); + *dd++ = a; + } + *dd++ = 0; + dst += pitch; + src += slot->bitmap.pitch; + } + } else if (vfactor != 1) { + while (h--) { + uint *dd = (uint *)dst; + for (int x = 0; x < static_cast(slot->bitmap.width); x++) { + uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000); + *dd++ = a; + } + dst += pitch; + src += slot->bitmap.pitch; + } + } else { + while (h--) { + for (int x = 0; x < static_cast(slot->bitmap.width); x++) { + unsigned char a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xff : 0x00); + dst[x] = a; + } + dst += pitch; + src += slot->bitmap.pitch; + } + } + } +#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100) >= 20500) + else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) + { + while (h--) { +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + const quint32 *srcPixel = (const quint32 *)src; + quint32 *dstPixel = (quint32 *)dst; + for (int x = 0; x < static_cast(slot->bitmap.width); x++, srcPixel++, dstPixel++) { + const quint32 pixel = *srcPixel; + *dstPixel = qbswap(pixel); + } +#else + memcpy(dst, src, slot->bitmap.width * 4); +#endif + dst += slot->bitmap.pitch; + src += slot->bitmap.pitch; + } + info.width = info.linearAdvance = info.xOff = slot->bitmap.width; + info.height = slot->bitmap.rows; + info.x = slot->bitmap_left; + info.y = slot->bitmap_top; + } +#endif + } else { + qWarning("QFontEngine: Glyph neither outline nor bitmap format=%d", slot->format); + return 0; + } + } + + + if (!g) { + g = new Glyph; + g->data = 0; + } + + g->linearAdvance = info.linearAdvance; + g->width = info.width; + g->height = info.height; + g->x = info.x; + g->y = info.y; + g->advance = info.xOff; + g->format = format; + delete [] g->data; + g->data = glyph_buffer.take(); + + if (set) + set->setGlyph(glyph, subPixelPosition, g); + + return g; +} + +QFontEngine::FaceId QFontEngineFT::faceId() const +{ + return face_id; +} + +QFontEngine::Properties QFontEngineFT::properties() const +{ + Properties p = freetype->properties(); + if (p.postscriptName.isEmpty()) { + p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(fontDef.family.toUtf8()); + } + + return freetype->properties(); +} + +QFixed QFontEngineFT::emSquareSize() const +{ + if (FT_IS_SCALABLE(freetype->face)) + return freetype->face->units_per_EM; + else + return freetype->face->size->metrics.y_ppem; +} + +bool QFontEngineFT::getSfntTableData(uint tag, uchar *buffer, uint *length) const +{ + return ft_getSfntTable(freetype->face, tag, buffer, length); +} + +int QFontEngineFT::synthesized() const +{ + int s = 0; + if ((fontDef.style != QFont::StyleNormal) && !(freetype->face->style_flags & FT_STYLE_FLAG_ITALIC)) + s = SynthesizedItalic; + if ((fontDef.weight >= QFont::Bold) && !(freetype->face->style_flags & FT_STYLE_FLAG_BOLD)) + s |= SynthesizedBold; + if (fontDef.stretch != 100 && FT_IS_SCALABLE(freetype->face)) + s |= SynthesizedStretch; + return s; +} + +QFixed QFontEngineFT::ascent() const +{ + QFixed v = QFixed::fromFixed(metrics.ascender); + if (scalableBitmapScaleFactor != 1) + v *= scalableBitmapScaleFactor; + return v; +} + +QFixed QFontEngineFT::capHeight() const +{ + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); + if (os2 && os2->version >= 2) { + lockFace(); + QFixed answer = QFixed::fromFixed(FT_MulFix(os2->sCapHeight, freetype->face->size->metrics.y_scale)); + unlockFace(); + return answer; + } + return calculatedCapHeight(); +} + +QFixed QFontEngineFT::descent() const +{ + QFixed v = QFixed::fromFixed(-metrics.descender); + if (scalableBitmapScaleFactor != 1) + v *= scalableBitmapScaleFactor; + return v; +} + +QFixed QFontEngineFT::leading() const +{ + QFixed v = QFixed::fromFixed(metrics.height - metrics.ascender + metrics.descender); + if (scalableBitmapScaleFactor != 1) + v *= scalableBitmapScaleFactor; + return v; +} + +QFixed QFontEngineFT::xHeight() const +{ + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); + if (os2 && os2->sxHeight) { + lockFace(); + QFixed answer = QFixed(os2->sxHeight * freetype->face->size->metrics.y_ppem) / emSquareSize(); + unlockFace(); + return answer; + } + + return QFontEngine::xHeight(); +} + +QFixed QFontEngineFT::averageCharWidth() const +{ + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); + if (os2 && os2->xAvgCharWidth) { + lockFace(); + QFixed answer = QFixed(os2->xAvgCharWidth * freetype->face->size->metrics.x_ppem) / emSquareSize(); + unlockFace(); + return answer; + } + + return QFontEngine::averageCharWidth(); +} + +qreal QFontEngineFT::maxCharWidth() const +{ + QFixed max_advance = QFixed::fromFixed(metrics.max_advance); + if (scalableBitmapScaleFactor != 1) + max_advance *= scalableBitmapScaleFactor; + return max_advance.toReal(); +} + +QFixed QFontEngineFT::lineThickness() const +{ + return line_thickness; +} + +QFixed QFontEngineFT::underlinePosition() const +{ + return underline_position; +} + +void QFontEngineFT::doKerning(QGlyphLayout *g, QFontEngine::ShaperFlags flags) const +{ + if (!kerning_pairs_loaded) { + kerning_pairs_loaded = true; + lockFace(); + if (freetype->face->size->metrics.x_ppem != 0) { + QFixed scalingFactor = emSquareSize() / QFixed(freetype->face->size->metrics.x_ppem); + unlockFace(); + const_cast(this)->loadKerningPairs(scalingFactor); + } else { + unlockFace(); + } + } + + if (shouldUseDesignMetrics(flags) && !(fontDef.styleStrategy & QFont::ForceIntegerMetrics)) + flags |= DesignMetrics; + else + flags &= ~DesignMetrics; + + QFontEngine::doKerning(g, flags); +} + +static inline FT_Matrix QTransformToFTMatrix(const QTransform &matrix) +{ + FT_Matrix m; + + m.xx = FT_Fixed(matrix.m11() * 65536); + m.xy = FT_Fixed(-matrix.m21() * 65536); + m.yx = FT_Fixed(-matrix.m12() * 65536); + m.yy = FT_Fixed(matrix.m22() * 65536); + + return m; +} + +QFontEngineFT::QGlyphSet *QFontEngineFT::loadGlyphSet(const QTransform &matrix) +{ + if (matrix.type() > QTransform::TxShear || !cacheEnabled) + return 0; + + // FT_Set_Transform only supports scalable fonts + if (!FT_IS_SCALABLE(freetype->face)) + return matrix.type() <= QTransform::TxTranslate ? &defaultGlyphSet : Q_NULLPTR; + + FT_Matrix m = QTransformToFTMatrix(matrix); + + QGlyphSet *gs = 0; + + for (int i = 0; i < transformedGlyphSets.count(); ++i) { + const QGlyphSet &g = transformedGlyphSets.at(i); + if (g.transformationMatrix.xx == m.xx + && g.transformationMatrix.xy == m.xy + && g.transformationMatrix.yx == m.yx + && g.transformationMatrix.yy == m.yy) { + + // found a match, move it to the front + transformedGlyphSets.move(i, 0); + gs = &transformedGlyphSets[0]; + break; + } + } + + if (!gs) { + // don't cache more than 10 transformations + if (transformedGlyphSets.count() >= 10) { + transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0); + } else { + transformedGlyphSets.prepend(QGlyphSet()); + } + gs = &transformedGlyphSets[0]; + gs->clear(); + gs->transformationMatrix = m; + gs->outline_drawing = fontDef.pixelSize * fontDef.pixelSize * qAbs(matrix.det()) >= QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE; + } + Q_ASSERT(gs != 0); + + return gs; +} + +void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) +{ + FT_Face face = lockFace(Unscaled); + FT_Set_Transform(face, 0, 0); + FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP); + + int left = face->glyph->metrics.horiBearingX; + int right = face->glyph->metrics.horiBearingX + face->glyph->metrics.width; + int top = face->glyph->metrics.horiBearingY; + int bottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height; + + QFixedPoint p; + p.x = 0; + p.y = 0; + + metrics->width = QFixed::fromFixed(right-left); + metrics->height = QFixed::fromFixed(top-bottom); + metrics->x = QFixed::fromFixed(left); + metrics->y = QFixed::fromFixed(-top); + metrics->xoff = QFixed::fromFixed(face->glyph->advance.x); + + if (!FT_IS_SCALABLE(freetype->face)) + QFreetypeFace::addBitmapToPath(face->glyph, p, path); + else + QFreetypeFace::addGlyphToPath(face, face->glyph, p, path, face->units_per_EM << 6, face->units_per_EM << 6); + + FT_Set_Transform(face, &freetype->matrix, 0); + unlockFace(); +} + +bool QFontEngineFT::supportsTransformation(const QTransform &transform) const +{ + return transform.type() <= QTransform::TxRotate; +} + +void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) +{ + if (!glyphs.numGlyphs) + return; + + if (FT_IS_SCALABLE(freetype->face)) { + QFontEngine::addOutlineToPath(x, y, glyphs, path, flags); + } else { + QVarLengthArray positions; + QVarLengthArray positioned_glyphs; + QTransform matrix; + matrix.translate(x, y); + getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions); + + FT_Face face = lockFace(Unscaled); + for (int gl = 0; gl < glyphs.numGlyphs; gl++) { + FT_UInt glyph = positioned_glyphs[gl]; + FT_Load_Glyph(face, glyph, FT_LOAD_TARGET_MONO); + QFreetypeFace::addBitmapToPath(face->glyph, positions[gl], path); + } + unlockFace(); + } +} + +void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, + QPainterPath *path, QTextItem::RenderFlags) +{ + FT_Face face = lockFace(Unscaled); + + for (int gl = 0; gl < numGlyphs; gl++) { + FT_UInt glyph = glyphs[gl]; + + FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP); + + FT_GlyphSlot g = face->glyph; + if (g->format != FT_GLYPH_FORMAT_OUTLINE) + continue; + if (embolden) + FT_GlyphSlot_Embolden(g); + if (obliquen) + FT_GlyphSlot_Oblique(g); + QFreetypeFace::addGlyphToPath(face, g, positions[gl], path, xsize, ysize); + } + unlockFace(); +} + +glyph_t QFontEngineFT::glyphIndex(uint ucs4) const +{ + glyph_t glyph = ucs4 < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[ucs4] : 0; + if (glyph == 0) { + FT_Face face = freetype->face; + glyph = FT_Get_Char_Index(face, ucs4); + if (glyph == 0) { + // Certain fonts don't have no-break space and tab, + // while we usually want to render them as space + if (ucs4 == QChar::Nbsp || ucs4 == QChar::Tabulation) { + glyph = FT_Get_Char_Index(face, QChar::Space); + } else if (freetype->symbol_map) { + // Symbol fonts can have more than one CMAPs, FreeType should take the + // correct one for us by default, so we always try FT_Get_Char_Index + // first. If it didn't work (returns 0), we will explicitly set the + // CMAP to symbol font one and try again. symbol_map is not always the + // correct one because in certain fonts like Wingdings symbol_map only + // contains PUA codepoints instead of the common ones. + FT_Set_Charmap(face, freetype->symbol_map); + glyph = FT_Get_Char_Index(face, ucs4); + FT_Set_Charmap(face, freetype->unicode_map); + } + } + if (ucs4 < QFreetypeFace::cmapCacheSize) + freetype->cmapCache[ucs4] = glyph; + } + + return glyph; +} + +bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, + QFontEngine::ShaperFlags flags) const +{ + Q_ASSERT(glyphs->numGlyphs >= *nglyphs); + if (*nglyphs < len) { + *nglyphs = len; + return false; + } + + int glyph_pos = 0; + if (freetype->symbol_map) { + FT_Face face = freetype->face; + QStringIterator it(str, str + len); + while (it.hasNext()) { + uint uc = it.next(); + glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; + if ( !glyphs->glyphs[glyph_pos] ) { + // Symbol fonts can have more than one CMAPs, FreeType should take the + // correct one for us by default, so we always try FT_Get_Char_Index + // first. If it didn't work (returns 0), we will explicitly set the + // CMAP to symbol font one and try again. symbol_map is not always the + // correct one because in certain fonts like Wingdings symbol_map only + // contains PUA codepoints instead of the common ones. + glyph_t glyph = FT_Get_Char_Index(face, uc); + // Certain symbol fonts don't have no-break space (0xa0) and tab (0x9), + // while we usually want to render them as space + if (!glyph && (uc == 0xa0 || uc == 0x9)) { + uc = 0x20; + glyph = FT_Get_Char_Index(face, uc); + } + if (!glyph) { + FT_Set_Charmap(face, freetype->symbol_map); + glyph = FT_Get_Char_Index(face, uc); + FT_Set_Charmap(face, freetype->unicode_map); + } + glyphs->glyphs[glyph_pos] = glyph; + if (uc < QFreetypeFace::cmapCacheSize) + freetype->cmapCache[uc] = glyph; + } + ++glyph_pos; + } + } else { + FT_Face face = freetype->face; + QStringIterator it(str, str + len); + while (it.hasNext()) { + uint uc = it.next(); + glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0; + if (!glyphs->glyphs[glyph_pos]) { + { + redo: + glyph_t glyph = FT_Get_Char_Index(face, uc); + if (!glyph && (uc == 0xa0 || uc == 0x9)) { + uc = 0x20; + goto redo; + } + glyphs->glyphs[glyph_pos] = glyph; + if (uc < QFreetypeFace::cmapCacheSize) + freetype->cmapCache[uc] = glyph; + } + } + ++glyph_pos; + } + } + + *nglyphs = glyph_pos; + glyphs->numGlyphs = glyph_pos; + + if (!(flags & GlyphIndicesOnly)) + recalcAdvances(glyphs, flags); + + return true; +} + +bool QFontEngineFT::shouldUseDesignMetrics(QFontEngine::ShaperFlags flags) const +{ + if (!FT_IS_SCALABLE(freetype->face)) + return false; + + return default_hint_style == HintNone || default_hint_style == HintLight || (flags & DesignMetrics); +} + +QFixed QFontEngineFT::scaledBitmapMetrics(QFixed m) const +{ + return m * scalableBitmapScaleFactor; +} + +glyph_metrics_t QFontEngineFT::scaledBitmapMetrics(const glyph_metrics_t &m) const +{ + glyph_metrics_t metrics; + metrics.x = scaledBitmapMetrics(m.x); + metrics.y = scaledBitmapMetrics(m.y); + metrics.width = scaledBitmapMetrics(m.width); + metrics.height = scaledBitmapMetrics(m.height); + metrics.xoff = scaledBitmapMetrics(m.xoff); + metrics.yoff = scaledBitmapMetrics(m.yoff); + return metrics; +} + +void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const +{ + FT_Face face = 0; + bool design = shouldUseDesignMetrics(flags); + for (int i = 0; i < glyphs->numGlyphs; i++) { + Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyphs->glyphs[i]) : 0; + // Since we are passing Format_None to loadGlyph, use same default format logic as loadGlyph + GlyphFormat acceptableFormat = (defaultFormat != Format_None) ? defaultFormat : Format_Mono; + if (g && g->format == acceptableFormat) { + glyphs->advances[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance); + } else { + if (!face) + face = lockFace(); + g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs->glyphs[i], 0, Format_None, true); + if (g) + glyphs->advances[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance); + else + glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10) + : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round(); + if (!cacheEnabled && g != &emptyGlyph) + delete g; + } + + if (scalableBitmapScaleFactor != 1) + glyphs->advances[i] *= scalableBitmapScaleFactor; + } + if (face) + unlockFace(); + + if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { + for (int i = 0; i < glyphs->numGlyphs; ++i) + glyphs->advances[i] = glyphs->advances[i].round(); + } +} + +glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) +{ + FT_Face face = 0; + + glyph_metrics_t overall; + // initialize with line height, we get the same behaviour on all platforms + if (!isScalableBitmap()) { + overall.y = -ascent(); + overall.height = ascent() + descent(); + } else { + overall.y = QFixed::fromFixed(-metrics.ascender); + overall.height = QFixed::fromFixed(metrics.ascender - metrics.descender); + } + + QFixed ymax = 0; + QFixed xmax = 0; + for (int i = 0; i < glyphs.numGlyphs; i++) { + Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyphs.glyphs[i]) : 0; + if (!g) { + if (!face) + face = lockFace(); + g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs.glyphs[i], 0, Format_None, true); + } + if (g) { + 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; + if (!cacheEnabled && g != &emptyGlyph) + delete g; + } else { + int left = FLOOR(face->glyph->metrics.horiBearingX); + int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width); + int top = CEIL(face->glyph->metrics.horiBearingY); + int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height); + + QFixed x = overall.xoff + glyphs.offsets[i].x - (-TRUNC(left)); + QFixed y = overall.yoff + glyphs.offsets[i].y - TRUNC(top); + overall.x = qMin(overall.x, x); + overall.y = qMin(overall.y, y); + xmax = qMax(xmax, x + TRUNC(right - left)); + ymax = qMax(ymax, y + TRUNC(top - bottom)); + overall.xoff += int(TRUNC(ROUND(face->glyph->advance.x))); + } + } + overall.height = qMax(overall.height, ymax - overall.y); + overall.width = xmax - overall.x; + + if (face) + unlockFace(); + + if (isScalableBitmap()) + overall = scaledBitmapMetrics(overall); + return overall; +} + +glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) +{ + FT_Face face = 0; + glyph_metrics_t overall; + Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyph) : 0; + if (!g) { + face = lockFace(); + g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, 0, Format_None, true); + } + if (g) { + overall.x = g->x; + overall.y = -g->y; + overall.width = g->width; + overall.height = g->height; + overall.xoff = g->advance; + if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) + overall.xoff = overall.xoff.round(); + if (!cacheEnabled && g != &emptyGlyph) + delete g; + } else { + int left = FLOOR(face->glyph->metrics.horiBearingX); + int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width); + int top = CEIL(face->glyph->metrics.horiBearingY); + int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height); + + overall.width = TRUNC(right-left); + overall.height = TRUNC(top-bottom); + overall.x = TRUNC(left); + overall.y = -TRUNC(top); + overall.xoff = TRUNC(ROUND(face->glyph->advance.x)); + } + if (face) + unlockFace(); + + if (isScalableBitmap()) + overall = scaledBitmapMetrics(overall); + return overall; +} + +glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matrix) +{ + return alphaMapBoundingBox(glyph, 0, matrix, QFontEngine::Format_None); +} + +glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, QFontEngine::GlyphFormat format) +{ + Glyph *g = loadGlyphFor(glyph, subPixelPosition, format, matrix, true); + + glyph_metrics_t overall; + if (g) { + overall.x = g->x; + overall.y = -g->y; + overall.width = g->width; + overall.height = g->height; + overall.xoff = g->advance; + if (!cacheEnabled && g != &emptyGlyph) + delete g; + } else { + FT_Face face = lockFace(); + int left = FLOOR(face->glyph->metrics.horiBearingX); + int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width); + int top = CEIL(face->glyph->metrics.horiBearingY); + int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height); + + overall.width = TRUNC(right-left); + overall.height = TRUNC(top-bottom); + overall.x = TRUNC(left); + overall.y = -TRUNC(top); + overall.xoff = TRUNC(ROUND(face->glyph->advance.x)); + unlockFace(); + } + + if (isScalableBitmap()) + overall = scaledBitmapMetrics(overall); + return overall; +} + +static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEngine::GlyphFormat glyphFormat) +{ + if (glyph == Q_NULLPTR || glyph->height == 0 || glyph->width == 0) + return QImage(); + + QImage::Format format = QImage::Format_Invalid; + int bytesPerLine = -1; + switch (glyphFormat) { + case QFontEngine::Format_Mono: + format = QImage::Format_Mono; + bytesPerLine = ((glyph->width + 31) & ~31) >> 3; + break; + case QFontEngine::Format_A8: + format = QImage::Format_Alpha8; + bytesPerLine = (glyph->width + 3) & ~3; + break; + case QFontEngine::Format_A32: + format = QImage::Format_RGB32; + bytesPerLine = glyph->width * 4; + break; + default: + Q_UNREACHABLE(); + }; + + QImage img(static_cast(glyph->data), glyph->width, glyph->height, bytesPerLine, format); + if (format == QImage::Format_Mono) + img.setColor(1, QColor(Qt::white).rgba()); // Expands color table to 2 items; item 0 set to transparent. + return img; +} + +QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixelPosition, + QFontEngine::GlyphFormat neededFormat, + const QTransform &t, QPoint *offset) +{ + Q_ASSERT(currentlyLockedAlphaMap.isNull()); + + if (isBitmapFont()) + neededFormat = Format_Mono; + else if (neededFormat == Format_None && defaultFormat != Format_None) + neededFormat = defaultFormat; + else if (neededFormat == Format_None) + neededFormat = Format_A8; + + Glyph *glyph = loadGlyphFor(glyphIndex, subPixelPosition, neededFormat, t); + + if (offset != 0 && glyph != 0) + *offset = QPoint(glyph->x, -glyph->y); + + currentlyLockedAlphaMap = alphaMapFromGlyphData(glyph, neededFormat); + + const bool glyphHasGeometry = glyph != Q_NULLPTR && glyph->height != 0 && glyph->width != 0; + if (!cacheEnabled && glyph != &emptyGlyph) { + currentlyLockedAlphaMap = currentlyLockedAlphaMap.copy(); + delete glyph; + } + + if (!glyphHasGeometry) + return Q_NULLPTR; + + if (currentlyLockedAlphaMap.isNull()) + return QFontEngine::lockedAlphaMapForGlyph(glyphIndex, subPixelPosition, neededFormat, t, offset); + + QImageData *data = currentlyLockedAlphaMap.data_ptr(); + data->is_locked = true; + + return ¤tlyLockedAlphaMap; +} + +void QFontEngineFT::unlockAlphaMapForGlyph() +{ + QFontEngine::unlockAlphaMapForGlyph(); +} + +static inline bool is2dRotation(const QTransform &t) +{ + return qFuzzyCompare(t.m11(), t.m22()) && qFuzzyCompare(t.m12(), -t.m21()) + && qFuzzyCompare(t.m11()*t.m22() - t.m12()*t.m21(), qreal(1.0)); +} + +QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, + QFixed subPixelPosition, + GlyphFormat format, + const QTransform &t, + bool fetchBoundingBox, + bool disableOutlineDrawing) +{ + QGlyphSet *glyphSet = loadGlyphSet(t); + if (glyphSet != 0 && glyphSet->outline_drawing && !disableOutlineDrawing && !fetchBoundingBox) + return 0; + + Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0; + if (!glyph || glyph->format != format || (!fetchBoundingBox && !glyph->data)) { + QScopedValueRollback saved_default_hint_style(default_hint_style); + if (t.type() >= QTransform::TxScale && !is2dRotation(t)) + default_hint_style = HintNone; // disable hinting if the glyphs are transformed + + lockFace(); + FT_Matrix m = this->matrix; + FT_Matrix ftMatrix = glyphSet != 0 ? glyphSet->transformationMatrix : QTransformToFTMatrix(t); + FT_Matrix_Multiply(&ftMatrix, &m); + freetype->matrix = m; + glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false, disableOutlineDrawing); + unlockFace(); + } + + return glyph; +} + +QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition) +{ + return alphaMapForGlyph(g, subPixelPosition, QTransform()); +} + +QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t) +{ + const GlyphFormat neededFormat = antialias ? Format_A8 : Format_Mono; + + Glyph *glyph = loadGlyphFor(g, subPixelPosition, neededFormat, t, false, true); + + QImage img = alphaMapFromGlyphData(glyph, neededFormat); + img = img.copy(); + + if (!cacheEnabled && glyph != &emptyGlyph) + delete glyph; + + if (!img.isNull()) + return img; + + return QFontEngine::alphaMapForGlyph(g, subPixelPosition, t); +} + +QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t) +{ + if (t.type() > QTransform::TxRotate) + return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t); + + const GlyphFormat neededFormat = Format_A32; + + Glyph *glyph = loadGlyphFor(g, subPixelPosition, neededFormat, t, false, true); + + QImage img = alphaMapFromGlyphData(glyph, neededFormat); + img = img.copy(); + + if (!cacheEnabled && glyph != &emptyGlyph) + delete glyph; + + if (!img.isNull()) + return img; + + return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t); +} + +QImage QFontEngineFT::bitmapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t) +{ + Glyph *glyph = loadGlyphFor(g, subPixelPosition, defaultFormat, t); + if (glyph == Q_NULLPTR) + return QImage(); + + QImage img; + if (defaultFormat == GlyphFormat::Format_ARGB) + img = QImage(glyph->data, glyph->width, glyph->height, QImage::Format_ARGB32_Premultiplied).copy(); + else if (defaultFormat == GlyphFormat::Format_Mono) + img = QImage(glyph->data, glyph->width, glyph->height, QImage::Format_Mono).copy(); + + if (!img.isNull() && (!t.isIdentity() || scalableBitmapScaleFactor != 1)) { + QTransform trans(t); + const qreal scaleFactor = scalableBitmapScaleFactor.toReal(); + trans.scale(scaleFactor, scaleFactor); + img = img.transformed(trans, Qt::SmoothTransformation); + } + + if (!cacheEnabled && glyph != &emptyGlyph) + delete glyph; + + return img; +} + +void QFontEngineFT::removeGlyphFromCache(glyph_t glyph) +{ + defaultGlyphSet.removeGlyphFromCache(glyph, 0); +} + +int QFontEngineFT::glyphCount() const +{ + int count = 0; + FT_Face face = lockFace(); + if (face) { + count = face->num_glyphs; + unlockFace(); + } + return count; +} + +FT_Face QFontEngineFT::lockFace(Scaling scale) const +{ + freetype->lock(); + FT_Face face = freetype->face; + if (scale == Unscaled) { + if (FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0) == 0) { + freetype->xsize = face->units_per_EM << 6; + freetype->ysize = face->units_per_EM << 6; + } + } else if (freetype->xsize != xsize || freetype->ysize != ysize) { + FT_Set_Char_Size(face, xsize, ysize, 0, 0); + freetype->xsize = xsize; + freetype->ysize = ysize; + } + if (freetype->matrix.xx != matrix.xx || + freetype->matrix.yy != matrix.yy || + freetype->matrix.xy != matrix.xy || + freetype->matrix.yx != matrix.yx) { + freetype->matrix = matrix; + FT_Set_Transform(face, &freetype->matrix, 0); + } + + return face; +} + +void QFontEngineFT::unlockFace() const +{ + freetype->unlock(); +} + +FT_Face QFontEngineFT::non_locked_face() const +{ + return freetype->face; +} + + +QFontEngineFT::QGlyphSet::QGlyphSet() + : outline_drawing(false) +{ + transformationMatrix.xx = 0x10000; + transformationMatrix.yy = 0x10000; + transformationMatrix.xy = 0; + transformationMatrix.yx = 0; + memset(fast_glyph_data, 0, sizeof(fast_glyph_data)); + fast_glyph_count = 0; +} + +QFontEngineFT::QGlyphSet::~QGlyphSet() +{ + clear(); +} + +void QFontEngineFT::QGlyphSet::clear() +{ + if (fast_glyph_count > 0) { + for (int i = 0; i < 256; ++i) { + if (fast_glyph_data[i]) { + delete fast_glyph_data[i]; + fast_glyph_data[i] = 0; + } + } + fast_glyph_count = 0; + } + qDeleteAll(glyph_data); + glyph_data.clear(); +} + +void QFontEngineFT::QGlyphSet::removeGlyphFromCache(glyph_t index, QFixed subPixelPosition) +{ + if (useFastGlyphData(index, subPixelPosition)) { + if (fast_glyph_data[index]) { + delete fast_glyph_data[index]; + fast_glyph_data[index] = 0; + if (fast_glyph_count > 0) + --fast_glyph_count; + } + } else { + delete glyph_data.take(GlyphAndSubPixelPosition(index, subPixelPosition)); + } +} + +void QFontEngineFT::QGlyphSet::setGlyph(glyph_t index, QFixed subPixelPosition, Glyph *glyph) +{ + if (useFastGlyphData(index, subPixelPosition)) { + if (!fast_glyph_data[index]) + ++fast_glyph_count; + fast_glyph_data[index] = glyph; + } else { + glyph_data.insert(GlyphAndSubPixelPosition(index, subPixelPosition), glyph); + } +} + +int QFontEngineFT::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) +{ + lockFace(); + bool hsubpixel = true; + int vfactor = 1; + int load_flags = loadFlags(0, Format_A8, flags, hsubpixel, vfactor); + int result = freetype->getPointInOutline(glyph, load_flags, point, xpos, ypos, nPoints); + unlockFace(); + return result; +} + +bool QFontEngineFT::initFromFontEngine(const QFontEngineFT *fe) +{ + if (!init(fe->faceId(), fe->antialias, fe->defaultFormat, fe->freetype)) + return false; + + // Increase the reference of this QFreetypeFace since one more QFontEngineFT + // will be using it + freetype->ref.ref(); + + default_load_flags = fe->default_load_flags; + default_hint_style = fe->default_hint_style; + antialias = fe->antialias; + transform = fe->transform; + embolden = fe->embolden; + obliquen = fe->obliquen; + subpixelType = fe->subpixelType; + lcdFilterType = fe->lcdFilterType; + embeddedbitmap = fe->embeddedbitmap; + + return true; +} + +QFontEngine *QFontEngineFT::cloneWithSize(qreal pixelSize) const +{ + QFontDef fontDef(this->fontDef); + fontDef.pixelSize = pixelSize; + QFontEngineFT *fe = new QFontEngineFT(fontDef); + if (!fe->initFromFontEngine(this)) { + delete fe; + return 0; + } else { + return fe; + } +} + +Qt::HANDLE QFontEngineFT::handle() const +{ + return non_locked_face(); +} + +QT_END_NAMESPACE + +#endif // QT_NO_FREETYPE diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h new file mode 100644 index 0000000000..3fa0b2e7d6 --- /dev/null +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h @@ -0,0 +1,360 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QFONTENGINE_FT_P_H +#define QFONTENGINE_FT_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 "private/qfontengine_p.h" + +#ifndef QT_NO_FREETYPE + +#include +#include FT_FREETYPE_H + + +#ifndef Q_OS_WIN +#include +#endif + +#include + +QT_BEGIN_NAMESPACE + +class QFontEngineFTRawFont; +class QFontconfigDatabase; + +/* + * This class represents one font file on disk (like Arial.ttf) and is shared between all the font engines + * that show this font file (at different pixel sizes). + */ +class QFreetypeFace +{ +public: + void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor); + QFontEngine::Properties properties() const; + bool getSfntTable(uint tag, uchar *buffer, uint *length) const; + + static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id, + const QByteArray &fontData = QByteArray()); + void release(const QFontEngine::FaceId &face_id); + + // locks the struct for usage. Any read/write operations require locking. + void lock() + { + _lock.lock(); + } + void unlock() + { + _lock.unlock(); + } + + FT_Face face; + int xsize; // 26.6 + int ysize; // 26.6 + FT_Matrix matrix; + FT_CharMap unicode_map; + FT_CharMap symbol_map; + + enum { cmapCacheSize = 0x200 }; + glyph_t cmapCache[cmapCacheSize]; + + int fsType() const; + + int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints); + + bool isScalableBitmap() const; + + static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale); + static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path); + +private: + friend class QFontEngineFT; + friend class QtFreetypeData; + friend struct QScopedPointerDeleter; + QFreetypeFace() : _lock(QMutex::Recursive) {} + ~QFreetypeFace() {} + void cleanup(); + QAtomicInt ref; + QMutex _lock; + QByteArray fontData; + + QFontEngine::Holder hbFace; +}; + +class QFontEngineFT : public QFontEngine +{ +public: + + /* we don't cache glyphs that are too large anyway, so we can make this struct rather small */ + struct Glyph { + ~Glyph(); + short linearAdvance; + unsigned char width; + unsigned char height; + short x; + short y; + short advance; + signed char format; + uchar *data; + }; + + struct GlyphInfo { + int linearAdvance; + unsigned short width; + unsigned short height; + short x; + short y; + short xOff; + short yOff; + }; + + struct GlyphAndSubPixelPosition + { + GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {} + + bool operator==(const GlyphAndSubPixelPosition &other) const + { + return glyph == other.glyph && subPixelPosition == other.subPixelPosition; + } + + glyph_t glyph; + QFixed subPixelPosition; + }; + + struct QGlyphSet + { + QGlyphSet(); + ~QGlyphSet(); + FT_Matrix transformationMatrix; + bool outline_drawing; + + void removeGlyphFromCache(glyph_t index, QFixed subPixelPosition); + void clear(); + inline bool useFastGlyphData(glyph_t index, QFixed subPixelPosition) const { + return (index < 256 && subPixelPosition == 0); + } + inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const; + void setGlyph(glyph_t index, QFixed spp, Glyph *glyph); + + inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); } + inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); } +private: + mutable QHash glyph_data; // maps from glyph index to glyph data + mutable QSet missing_glyphs; + mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256 + mutable int fast_glyph_count; + }; + + QFontEngine::FaceId faceId() const Q_DECL_OVERRIDE; + QFontEngine::Properties properties() const Q_DECL_OVERRIDE; + QFixed emSquareSize() const Q_DECL_OVERRIDE; + bool supportsSubPixelPositions() const Q_DECL_OVERRIDE + { + return default_hint_style == HintLight || + default_hint_style == HintNone; + } + + bool getSfntTableData(uint tag, uchar *buffer, uint *length) const Q_DECL_OVERRIDE; + int synthesized() const Q_DECL_OVERRIDE; + + QFixed ascent() const Q_DECL_OVERRIDE; + QFixed capHeight() const Q_DECL_OVERRIDE; + QFixed descent() const Q_DECL_OVERRIDE; + QFixed leading() const Q_DECL_OVERRIDE; + QFixed xHeight() const Q_DECL_OVERRIDE; + QFixed averageCharWidth() const Q_DECL_OVERRIDE; + + qreal maxCharWidth() const Q_DECL_OVERRIDE; + QFixed lineThickness() const Q_DECL_OVERRIDE; + QFixed underlinePosition() const Q_DECL_OVERRIDE; + + glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE; + void doKerning(QGlyphLayout *, ShaperFlags) const Q_DECL_OVERRIDE; + + void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) Q_DECL_OVERRIDE; + + bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE; + + void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, + QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; + void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, + QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; + + bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const Q_DECL_OVERRIDE; + + glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE; + glyph_metrics_t boundingBox(glyph_t glyph) Q_DECL_OVERRIDE; + glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix) Q_DECL_OVERRIDE; + + void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const Q_DECL_OVERRIDE; + QImage alphaMapForGlyph(glyph_t g) Q_DECL_OVERRIDE { return alphaMapForGlyph(g, 0); } + QImage alphaMapForGlyph(glyph_t, QFixed) Q_DECL_OVERRIDE; + QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; + QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; + QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; + glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, + QFixed subPixelPosition, + const QTransform &matrix, + QFontEngine::GlyphFormat format) Q_DECL_OVERRIDE; + QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, + GlyphFormat neededFormat, const QTransform &t, + QPoint *offset) Q_DECL_OVERRIDE; + bool hasInternalCaching() const Q_DECL_OVERRIDE { return cacheEnabled; } + void unlockAlphaMapForGlyph() Q_DECL_OVERRIDE; + bool expectsGammaCorrectedBlending() const Q_DECL_OVERRIDE; + + void removeGlyphFromCache(glyph_t glyph) Q_DECL_OVERRIDE; + int glyphMargin(QFontEngine::GlyphFormat /* format */) Q_DECL_OVERRIDE { return 0; } + + int glyphCount() const Q_DECL_OVERRIDE; + + enum Scaling { + Scaled, + Unscaled + }; + FT_Face lockFace(Scaling scale = Scaled) const; + void unlockFace() const; + + FT_Face non_locked_face() const; + + inline bool drawAntialiased() const { return antialias; } + inline bool invalid() const { return xsize == 0 && ysize == 0; } + inline bool isBitmapFont() const { return defaultFormat == Format_Mono; } + inline bool isScalableBitmap() const { return freetype->isScalableBitmap(); } + + inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const + { return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly, disableOutlineDrawing); } + Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const; + Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t, bool fetchBoundingBox = false, bool disableOutlineDrawing = false); + + QGlyphSet *loadGlyphSet(const QTransform &matrix); + + QFontEngineFT(const QFontDef &fd); + virtual ~QFontEngineFT(); + + bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat = Format_None, + const QByteArray &fontData = QByteArray()); + bool init(FaceId faceId, bool antialias, GlyphFormat format, + QFreetypeFace *freetypeFace); + + int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) Q_DECL_OVERRIDE; + + void setQtDefaultHintStyle(QFont::HintingPreference hintingPreference); + void setDefaultHintStyle(HintStyle style) Q_DECL_OVERRIDE; + + QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; + Qt::HANDLE handle() const Q_DECL_OVERRIDE; + bool initFromFontEngine(const QFontEngineFT *fontEngine); + + HintStyle defaultHintStyle() const { return default_hint_style; } +protected: + + QFreetypeFace *freetype; + mutable int default_load_flags; + HintStyle default_hint_style; + bool antialias; + bool transform; + bool embolden; + bool obliquen; + SubpixelAntialiasingType subpixelType; + int lcdFilterType; + bool embeddedbitmap; + bool cacheEnabled; + bool forceAutoHint; + bool stemDarkeningDriver; + +private: + friend class QFontEngineFTRawFont; + friend class QFontconfigDatabase; + friend class QFreeTypeFontDatabase; + friend class QCoreTextFontDatabase; + friend class QFontEngineMultiFontConfig; + + int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const; + bool shouldUseDesignMetrics(ShaperFlags flags) const; + QFixed scaledBitmapMetrics(QFixed m) const; + glyph_metrics_t scaledBitmapMetrics(const glyph_metrics_t &m) const; + + GlyphFormat defaultFormat; + FT_Matrix matrix; + + QList transformedGlyphSets; + mutable QGlyphSet defaultGlyphSet; + + QFontEngine::FaceId face_id; + + int xsize; + int ysize; + + QFixed line_thickness; + QFixed underline_position; + + FT_Size_Metrics metrics; + mutable bool kerning_pairs_loaded; + QFixed scalableBitmapScaleFactor; +}; + +inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g) +{ + return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt(); +} + +inline QFontEngineFT::Glyph *QFontEngineFT::QGlyphSet::getGlyph(glyph_t index, QFixed subPixelPosition) const +{ + if (useFastGlyphData(index, subPixelPosition)) + return fast_glyph_data[index]; + return glyph_data.value(GlyphAndSubPixelPosition(index, subPixelPosition)); +} + +extern FT_Library qt_getFreetype(); + +QT_END_NAMESPACE + +#endif // QT_NO_FREETYPE + +#endif // QFONTENGINE_FT_P_H diff --git a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp new file mode 100644 index 0000000000..97be1606b4 --- /dev/null +++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp @@ -0,0 +1,282 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfreetypefontdatabase_p.h" + +#include +#include + +#include +#include +#include +#include +#include + +#undef QT_NO_FREETYPE +#include + +#include +#include FT_TRUETYPE_TABLES_H +#include FT_ERRORS_H + +QT_BEGIN_NAMESPACE + +void QFreeTypeFontDatabase::populateFontDatabase() +{ + QString fontpath = fontDir(); + QDir dir(fontpath); + + if (!dir.exists()) { + qWarning("QFontDatabase: Cannot find font directory %s.\n" + "Note that Qt no longer ships fonts. Deploy some (from http://dejavu-fonts.org for example) or switch to fontconfig.", + qPrintable(fontpath)); + return; + } + + QStringList nameFilters; + nameFilters << QLatin1String("*.ttf") + << QLatin1String("*.ttc") + << QLatin1String("*.pfa") + << QLatin1String("*.pfb") + << QLatin1String("*.otf"); + + const auto fis = dir.entryInfoList(nameFilters, QDir::Files); + for (const QFileInfo &fi : fis) { + const QByteArray file = QFile::encodeName(fi.absoluteFilePath()); + QFreeTypeFontDatabase::addTTFile(QByteArray(), file); + } +} + +QFontEngine *QFreeTypeFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPtr) +{ + FontFile *fontfile = static_cast (usrPtr); + QFontEngine::FaceId fid; + fid.filename = QFile::encodeName(fontfile->fileName); + fid.index = fontfile->indexValue; + + bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + QFontEngineFT *engine = new QFontEngineFT(fontDef); + QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono; + if (antialias) { + QFontEngine::SubpixelAntialiasingType subpixelType = subpixelAntialiasingTypeHint(); + if (subpixelType == QFontEngine::Subpixel_None || (fontDef.styleStrategy & QFont::NoSubpixelAntialias)) { + format = QFontEngineFT::Format_A8; + engine->subpixelType = QFontEngine::Subpixel_None; + } else { + format = QFontEngineFT::Format_A32; + engine->subpixelType = subpixelType; + } + } + + if (!engine->init(fid, antialias, format) || engine->invalid()) { + delete engine; + engine = 0; + } else { + engine->setQtDefaultHintStyle(static_cast(fontDef.hintingPreference)); + } + + return engine; +} + +namespace { + + class QFontEngineFTRawData: public QFontEngineFT + { + public: + QFontEngineFTRawData(const QFontDef &fontDef) : QFontEngineFT(fontDef) + { + } + + void updateFamilyNameAndStyle() + { + fontDef.family = QString::fromLatin1(freetype->face->family_name); + + if (freetype->face->style_flags & FT_STYLE_FLAG_ITALIC) + fontDef.style = QFont::StyleItalic; + + if (freetype->face->style_flags & FT_STYLE_FLAG_BOLD) + fontDef.weight = QFont::Bold; + } + + bool initFromData(const QByteArray &fontData) + { + FaceId faceId; + faceId.filename = ""; + faceId.index = 0; + faceId.uuid = QUuid::createUuid().toByteArray(); + + return init(faceId, true, Format_None, fontData); + } + }; + +} + +QFontEngine *QFreeTypeFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, + QFont::HintingPreference hintingPreference) +{ + QFontDef fontDef; + fontDef.pixelSize = pixelSize; + fontDef.hintingPreference = hintingPreference; + + QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef); + if (!fe->initFromData(fontData)) { + delete fe; + return 0; + } + + fe->updateFamilyNameAndStyle(); + fe->setQtDefaultHintStyle(static_cast(fontDef.hintingPreference)); + + return fe; +} + +QStringList QFreeTypeFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) +{ + return QFreeTypeFontDatabase::addTTFile(fontData, fileName.toLocal8Bit()); +} + +void QFreeTypeFontDatabase::releaseHandle(void *handle) +{ + FontFile *file = static_cast(handle); + delete file; +} + +extern FT_Library qt_getFreetype(); + +QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file) +{ + FT_Library library = qt_getFreetype(); + + int index = 0; + int numFaces = 0; + QStringList families; + 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; + + QFont::Weight 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; + + bool fixedPitch = (face->face_flags & FT_FACE_FLAG_FIXED_WIDTH); + + 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_MS_SYMBOL) { + writingSystems.setSupported(QFontDatabase::Symbol); + break; + } + } + + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); + if (os2) { + quint32 unicodeRange[4] = { + quint32(os2->ulUnicodeRange1), + quint32(os2->ulUnicodeRange2), + quint32(os2->ulUnicodeRange3), + quint32(os2->ulUnicodeRange4) + }; + quint32 codePageRange[2] = { + quint32(os2->ulCodePageRange1), + quint32(os2->ulCodePageRange2) + }; + + writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); + + if (os2->usWeightClass) { + weight = QPlatformFontDatabase::weightFromInteger(os2->usWeightClass); + } else if (os2->panose[2]) { + int w = os2->panose[2]; + if (w <= 1) + weight = QFont::Thin; + else if (w <= 2) + weight = QFont::ExtraLight; + else if (w <= 3) + weight = QFont::Light; + else if (w <= 5) + weight = QFont::Normal; + else if (w <= 6) + weight = QFont::Medium; + else if (w <= 7) + weight = QFont::DemiBold; + else if (w <= 8) + weight = QFont::Bold; + else if (w <= 9) + weight = QFont::ExtraBold; + else if (w <= 10) + weight = QFont::Black; + } + } + + QString family = QString::fromLatin1(face->family_name); + FontFile *fontFile = new FontFile; + fontFile->fileName = QFile::decodeName(file); + fontFile->indexValue = index; + + QFont::Stretch stretch = QFont::Unstretched; + + registerFont(family,QString::fromLatin1(face->style_name),QString(),weight,style,stretch,true,true,0,fixedPitch,writingSystems,fontFile); + + families.append(family); + + FT_Done_Face(face); + ++index; + } while (index < numFaces); + return families; +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase_p.h b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase_p.h new file mode 100644 index 0000000000..6d51361400 --- /dev/null +++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFREETYPEFONTDATABASE_H +#define QFREETYPEFONTDATABASE_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 + +QT_BEGIN_NAMESPACE + +struct FontFile +{ + QString fileName; + int indexValue; +}; + +class QFreeTypeFontDatabase : public QPlatformFontDatabase +{ +public: + void populateFontDatabase() Q_DECL_OVERRIDE; + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; + QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE; + QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) Q_DECL_OVERRIDE; + void releaseHandle(void *handle) Q_DECL_OVERRIDE; + + static QStringList addTTFile(const QByteArray &fontData, const QByteArray &file); +}; + +QT_END_NAMESPACE + +#endif // QFREETYPEFONTDATABASE_H diff --git a/src/platformsupport/fontdatabases/genericunix/qgenericunixfontdatabase_p.h b/src/platformsupport/fontdatabases/genericunix/qgenericunixfontdatabase_p.h index 37c667eeb3..ccf5ad6d13 100644 --- a/src/platformsupport/fontdatabases/genericunix/qgenericunixfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/genericunix/qgenericunixfontdatabase_p.h @@ -57,8 +57,8 @@ #include typedef QFontconfigDatabase QGenericUnixFontDatabase; #else -#include -typedef QBasicFontDatabase QGenericUnixFontDatabase; +#include +typedef QFreeTypeFontDatabase QGenericUnixFontDatabase; #endif //Q_FONTCONFIGDATABASE #endif // QGENERICUNIXFONTDATABASE_H diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri index f73e22eb1a..a533234c26 100644 --- a/src/platformsupport/fontdatabases/mac/coretext.pri +++ b/src/platformsupport/fontdatabases/mac/coretext.pri @@ -3,8 +3,8 @@ OBJECTIVE_SOURCES += $$PWD/qfontengine_coretext.mm $$PWD/qcoretextfontdatabase.m qtConfig(freetype) { QMAKE_USE_PRIVATE += freetype - HEADERS += basic/qfontengine_ft_p.h - SOURCES += basic/qfontengine_ft.cpp + HEADERS += freetype/qfontengine_ft_p.h + SOURCES += freetype/qfontengine_ft.cpp } uikit: \ diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp index 65947ab7da..3f03b30f10 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp @@ -393,14 +393,14 @@ void QWindowsFontDatabaseFT::populateFontDatabase() QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, void *handle) { - QFontEngine *fe = QBasicFontDatabase::fontEngine(fontDef, handle); + QFontEngine *fe = QFreeTypeFontDatabase::fontEngine(fontDef, handle); qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef.family << fe << handle; return fe; } QFontEngine *QWindowsFontDatabaseFT::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { - QFontEngine *fe = QBasicFontDatabase::fontEngine(fontData, pixelSize, hintingPreference); + QFontEngine *fe = QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference); qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDATA" << fontData << pixelSize << hintingPreference << fe; return fe; } @@ -410,7 +410,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF QStringList result; result.append(QWindowsFontDatabase::familyForStyleHint(styleHint)); result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); - result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script)); + result.append(QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script)); qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint << script << result; diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h index 3a432842e5..2df81274ad 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h @@ -51,13 +51,13 @@ // We mean it. // -#include +#include #include #include QT_BEGIN_NAMESPACE -class QWindowsFontDatabaseFT : public QBasicFontDatabase +class QWindowsFontDatabaseFT : public QFreeTypeFontDatabase { public: void populateFontDatabase() Q_DECL_OVERRIDE; diff --git a/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp b/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp index eb5a38855e..6ac092aa0e 100644 --- a/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp @@ -144,7 +144,7 @@ QWinRTFontDatabase::~QWinRTFontDatabase() QString QWinRTFontDatabase::fontDir() const { qCDebug(lcQpaFonts) << __FUNCTION__; - QString fontDirectory = QBasicFontDatabase::fontDir(); + QString fontDirectory = QFreeTypeFontDatabase::fontDir(); if (!QFile::exists(fontDirectory)) { // Fall back to app directory + fonts, and just app directory after that const QString applicationDirPath = QCoreApplication::applicationDirPath(); @@ -176,7 +176,7 @@ void QWinRTFontDatabase::populateFontDatabase() HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory1), &factory); if (FAILED(hr)) { qWarning("Failed to create DirectWrite factory: %s", qPrintable(qt_error_string(hr))); - QBasicFontDatabase::populateFontDatabase(); + QFreeTypeFontDatabase::populateFontDatabase(); return; } @@ -184,7 +184,7 @@ void QWinRTFontDatabase::populateFontDatabase() hr = factory->GetSystemFontCollection(&fontCollection); if (FAILED(hr)) { qWarning("Failed to open system font collection: %s", qPrintable(qt_error_string(hr))); - QBasicFontDatabase::populateFontDatabase(); + QFreeTypeFontDatabase::populateFontDatabase(); return; } @@ -222,7 +222,7 @@ void QWinRTFontDatabase::populateFontDatabase() registerFontFamily(familyName); } - QBasicFontDatabase::populateFontDatabase(); + QFreeTypeFontDatabase::populateFontDatabase(); } void QWinRTFontDatabase::populateFamily(const QString &familyName) @@ -399,7 +399,7 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl IDWriteFontFile *fontFile = reinterpret_cast(handle); if (!m_fonts.contains(fontFile)) - return QBasicFontDatabase::fontEngine(fontDef, handle); + return QFreeTypeFontDatabase::fontEngine(fontDef, handle); const void *referenceKey; quint32 referenceKeySize; @@ -468,7 +468,7 @@ QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont: QStringList result; if (family == QLatin1String("Helvetica")) result.append(QStringLiteral("Arial")); - result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script)); + result.append(QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script)); return result; } @@ -486,7 +486,7 @@ void QWinRTFontDatabase::releaseHandle(void *handle) return; } - QBasicFontDatabase::releaseHandle(handle); + QFreeTypeFontDatabase::releaseHandle(handle); } QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase_p.h b/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase_p.h index 3b803d7613..9a2bf00fab 100644 --- a/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include +#include #include struct IDWriteFontFile; @@ -67,7 +67,7 @@ struct FontDescription QByteArray uuid; }; -class QWinRTFontDatabase : public QBasicFontDatabase +class QWinRTFontDatabase : public QFreeTypeFontDatabase { public: ~QWinRTFontDatabase(); diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp index a14271c8f5..2fdf269566 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp @@ -66,7 +66,7 @@ void QAndroidPlatformFontDatabase::populateFontDatabase() const auto entries = dir.entryInfoList(nameFilters, QDir::Files); for (const QFileInfo &fi : entries) { const QByteArray file = QFile::encodeName(fi.absoluteFilePath()); - QBasicFontDatabase::addTTFile(QByteArray(), file); + QFreeTypeFontDatabase::addTTFile(QByteArray(), file); } } @@ -82,7 +82,7 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(QLatin1Char(';'))); else result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(QLatin1Char(';'))); - result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script)); + result.append(QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script)); return result; } diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.h b/src/plugins/platforms/android/qandroidplatformfontdatabase.h index 533d6e50a9..166a590698 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.h +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.h @@ -40,11 +40,11 @@ #ifndef QANDROIDPLATFORMFONTDATABASE_H #define QANDROIDPLATFORMFONTDATABASE_H -#include +#include QT_BEGIN_NAMESPACE -class QAndroidPlatformFontDatabase: public QBasicFontDatabase +class QAndroidPlatformFontDatabase: public QFreeTypeFontDatabase { public: QString fontDir() const override; diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp index aa0037f187..820c4891ca 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.cpp +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -44,7 +44,7 @@ #include #include -#include +#include #if defined(Q_OS_WINRT) # include #elif defined(Q_OS_WIN) diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp index 56e6075cb2..0c39950019 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp @@ -49,7 +49,7 @@ #include #endif #elif defined(Q_OS_WIN) -#include +#include #ifndef Q_OS_WINRT #include #else @@ -103,7 +103,7 @@ QOffscreenIntegration::QOffscreenIntegration() m_fontDatabase.reset(new QGenericUnixFontDatabase()); #endif #elif defined(Q_OS_WIN) - m_fontDatabase.reset(new QBasicFontDatabase()); + m_fontDatabase.reset(new QFreeTypeFontDatabase()); #endif #ifndef QT_NO_DRAGANDDROP -- cgit v1.2.3 From 0d12ebd7e7e4de2c60faa443c9e711bba281de88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 24 Mar 2017 11:56:57 +0100 Subject: Share FreeType font engine creation code between platforms The FreeType font engine setup is spread out between factory functions, constructors, and init() functions, so let's at least try to share as much as possible of it to make it easier to reason about and possibly refactor in the future. Change-Id: Ic39353d2b3111024e0589a70211bac80feb8498e Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qplatformfontdatabase.cpp | 10 ------ src/gui/text/qplatformfontdatabase.h | 1 - .../fontconfig/qfontconfigdatabase.cpp | 1 + .../fontdatabases/freetype/qfontengine_ft.cpp | 40 ++++++++++++++++++++++ .../fontdatabases/freetype/qfontengine_ft_p.h | 4 ++- .../freetype/qfreetypefontdatabase.cpp | 31 +++-------------- .../fontdatabases/mac/qcoretextfontdatabase.mm | 23 +------------ .../fontdatabases/winrt/qwinrtfontdatabase.cpp | 9 +---- 8 files changed, 51 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp index ac3d274b36..599b18ac05 100644 --- a/src/gui/text/qplatformfontdatabase.cpp +++ b/src/gui/text/qplatformfontdatabase.cpp @@ -465,16 +465,6 @@ bool QPlatformFontDatabase::fontsAlwaysScalable() const return ret; } -QFontEngine::SubpixelAntialiasingType QPlatformFontDatabase::subpixelAntialiasingTypeHint() const -{ - static int type = -1; - if (type == -1) { - if (QScreen *screen = QGuiApplication::primaryScreen()) - type = screen->handle()->subpixelAntialiasingTypeHint(); - } - return static_cast(type); -} - // ### copied to tools/makeqpf/qpf2.cpp // see the Unicode subset bitfields in the MSDN docs diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h index 13d8cbde60..2d99183ca3 100644 --- a/src/gui/text/qplatformfontdatabase.h +++ b/src/gui/text/qplatformfontdatabase.h @@ -116,7 +116,6 @@ public: virtual QString resolveFontFamilyAlias(const QString &family) const; virtual bool fontsAlwaysScalable() const; virtual QList standardSizes() const; - QFontEngine::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const; // helper static QSupportedWritingSystems writingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2]); diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 4464e93bbd..a997bf0ba1 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -677,6 +677,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) fid.filename = QFile::encodeName(fontfile->fileName); fid.index = fontfile->indexValue; + // FIXME: Unify with logic in QFontEngineFT::create() QFontEngineFT *engine = new QFontEngineFT(f); engine->face_id = fid; diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp index 03e72546eb..98bf91fa9d 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp @@ -44,6 +44,9 @@ #include "qfontengine_ft_p.h" #include "private/qimage_p.h" #include +#include +#include +#include #ifndef QT_NO_FREETYPE @@ -666,6 +669,43 @@ static void convoluteBitmap(const uchar *src, uchar *dst, int width, int height, } } +static QFontEngine::SubpixelAntialiasingType subpixelAntialiasingTypeHint() +{ + static int type = -1; + if (type == -1) { + if (QScreen *screen = QGuiApplication::primaryScreen()) + type = screen->handle()->subpixelAntialiasingTypeHint(); + } + return static_cast(type); +} + +QFontEngineFT *QFontEngineFT::create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData) +{ + QScopedPointer engine(new QFontEngineFT(fontDef)); + + QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono; + const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + + if (antialias) { + QFontEngine::SubpixelAntialiasingType subpixelType = subpixelAntialiasingTypeHint(); + if (subpixelType == QFontEngine::Subpixel_None || (fontDef.styleStrategy & QFont::NoSubpixelAntialias)) { + format = QFontEngineFT::Format_A8; + engine->subpixelType = QFontEngine::Subpixel_None; + } else { + format = QFontEngineFT::Format_A32; + engine->subpixelType = subpixelType; + } + } + + if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) { + qWarning("QFontEngineFT: Failed to create FreeType font engine"); + return nullptr; + } + + engine->setQtDefaultHintStyle(static_cast(fontDef.hintingPreference)); + return engine.take(); +} + QFontEngineFT::QFontEngineFT(const QFontDef &fd) : QFontEngine(Freetype) { diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h index 3fa0b2e7d6..fc923d196b 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h @@ -292,6 +292,9 @@ private: bool initFromFontEngine(const QFontEngineFT *fontEngine); HintStyle defaultHintStyle() const { return default_hint_style; } + + static QFontEngineFT *create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData = QByteArray()); + protected: QFreetypeFace *freetype; @@ -312,7 +315,6 @@ private: friend class QFontEngineFTRawFont; friend class QFontconfigDatabase; friend class QFreeTypeFontDatabase; - friend class QCoreTextFontDatabase; friend class QFontEngineMultiFontConfig; int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const; diff --git a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp index 97be1606b4..764f2d8868 100644 --- a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp @@ -85,33 +85,12 @@ void QFreeTypeFontDatabase::populateFontDatabase() QFontEngine *QFreeTypeFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPtr) { - FontFile *fontfile = static_cast (usrPtr); - QFontEngine::FaceId fid; - fid.filename = QFile::encodeName(fontfile->fileName); - fid.index = fontfile->indexValue; - - bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - QFontEngineFT *engine = new QFontEngineFT(fontDef); - QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono; - if (antialias) { - QFontEngine::SubpixelAntialiasingType subpixelType = subpixelAntialiasingTypeHint(); - if (subpixelType == QFontEngine::Subpixel_None || (fontDef.styleStrategy & QFont::NoSubpixelAntialias)) { - format = QFontEngineFT::Format_A8; - engine->subpixelType = QFontEngine::Subpixel_None; - } else { - format = QFontEngineFT::Format_A32; - engine->subpixelType = subpixelType; - } - } - - if (!engine->init(fid, antialias, format) || engine->invalid()) { - delete engine; - engine = 0; - } else { - engine->setQtDefaultHintStyle(static_cast(fontDef.hintingPreference)); - } + FontFile *fontfile = static_cast(usrPtr); + QFontEngine::FaceId faceId; + faceId.filename = QFile::encodeName(fontfile->fileName); + faceId.index = fontfile->indexValue; - return engine; + return QFontEngineFT::create(fontDef, faceId); } namespace { diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 3588948133..b8097702ed 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -890,28 +890,7 @@ QFontEngine *QCoreTextFontDatabase::freeTypeFontEngine(const QFontDef &fontDef, { QFontEngine::FaceId faceId; faceId.filename = filename; - const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - - QScopedPointer engine(new QFontEngineFT(fontDef)); - QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono; - if (antialias) { - QFontEngine::SubpixelAntialiasingType subpixelType = subpixelAntialiasingTypeHint(); - if (subpixelType == QFontEngine::Subpixel_None || (fontDef.styleStrategy & QFont::NoSubpixelAntialias)) { - format = QFontEngineFT::Format_A8; - engine->subpixelType = QFontEngine::Subpixel_None; - } else { - format = QFontEngineFT::Format_A32; - engine->subpixelType = subpixelType; - } - } - - if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) { - qWarning("QCoreTextFontDatabase::freeTypefontEngine Failed to create engine"); - return Q_NULLPTR; - } - engine->setQtDefaultHintStyle(static_cast(fontDef.hintingPreference)); - - return engine.take(); + return QFontEngineFT::create(fontDef, faceId, fontData); } #endif diff --git a/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp b/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp index 6ac092aa0e..2a95ca26a9 100644 --- a/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/winrt/qwinrtfontdatabase.cpp @@ -444,15 +444,8 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl const FontDescription description = m_fonts.value(fontFile); faceId.uuid = description.uuid; faceId.index = description.index; - const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - QFontEngineFT::GlyphFormat format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; - QFontEngineFT *engine = new QFontEngineFT(fontDef); - if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) { - delete engine; - return 0; - } - return engine; + return QFontEngineFT::create(fontDef, faceId, fontData); } QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, -- cgit v1.2.3 From de4aeade5ed86b008e6d497563cfcce9583b0c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 3 Apr 2017 16:04:05 +0200 Subject: Delete QRasterWindow backingstore while window is still alive The platform backingstore might need access to the window that the backingstore was created for, e.g. for makingCurrent to release OpenGL resources. In that case leaving it to the QRasterWindowPrivate destructor would be too late, as the QWindow was gone. This was seen on iOS, where the backingstore inherits QRasterBackingStore, and uses composeAndFlush to composit via GL. The raster backingstore cleans up these GL resources in its destructor, so the QIOSBackingStore destructor makes sure that the GL context is current for the window, resulting in a crash since the window is long gone by then. Change-Id: I5a22597842819f0fe3b580856b9e75e4fab32ae5 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qrasterwindow.cpp | 8 ++++++++ src/gui/kernel/qrasterwindow.h | 1 + 2 files changed, 9 insertions(+) (limited to 'src') diff --git a/src/gui/kernel/qrasterwindow.cpp b/src/gui/kernel/qrasterwindow.cpp index d8d448249e..73871e0f39 100644 --- a/src/gui/kernel/qrasterwindow.cpp +++ b/src/gui/kernel/qrasterwindow.cpp @@ -105,6 +105,14 @@ QRasterWindow::QRasterWindow(QWindow *parent) d_func()->backingstore.reset(new QBackingStore(this)); } +QRasterWindow::~QRasterWindow() +{ + Q_D(QRasterWindow); + // Delete backingstore while window is still alive, as it + // might need to reference the window in the process + d->backingstore.reset(nullptr); +} + /*! \internal */ diff --git a/src/gui/kernel/qrasterwindow.h b/src/gui/kernel/qrasterwindow.h index 76312bcda2..9b29183ad6 100644 --- a/src/gui/kernel/qrasterwindow.h +++ b/src/gui/kernel/qrasterwindow.h @@ -54,6 +54,7 @@ class Q_GUI_EXPORT QRasterWindow : public QPaintDeviceWindow public: explicit QRasterWindow(QWindow *parent = Q_NULLPTR); + ~QRasterWindow(); protected: int metric(PaintDeviceMetric metric) const Q_DECL_OVERRIDE; -- cgit v1.2.3 From 5377f4ec0e82dbfbd0d148ed3affc0c7b2a3cade Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Wed, 1 Feb 2017 13:55:32 +0100 Subject: Allow Secure Transport backend to use a temporary keychain Cherry picked: this change was first merged into dev, but now we also need it in 5.9 to enable SSL socket tests on the new CI VMs (macOS 10.11, 10.12). As we do not merge dev->5.9, we need this cherry-pick. Since day one Secure Transport socket has two annoying problems on macOS: when we call SecPKCS12Import, we indeed import certs and keys into the default keychain and also (which is more serious) later a dialog can pop up, asking for permission to use a private key (this is especially annoying if you're running SSL autotests or have a server application). Apparently, it's possible to work around those problems if we create our own (temporary) keychain and pass it in the 'options' parameter to SecPKCS12Import. [ChangeLog][QtNetwork] Allow QSslSocket to use a temporary keychain on macOS. Task-number: QTBUG-56102 Change-Id: Ic3a56c905100dc80d907a25fe6ebfa232dcf5b9e Reviewed-by: Edward Welbourne (cherry picked from commit 17927392cf1cecb20cef7cb9cd77131391de087c) Reviewed-by: Timur Pocheptsov --- src/network/ssl/qsslsocket.cpp | 7 +++ src/network/ssl/qsslsocket_mac.cpp | 124 +++++++++++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index e655f4becd..84b8f3a8d9 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -972,6 +972,13 @@ QList QSslSocket::localCertificateChain() const sockets, but are also rarely used by client sockets if the server requires the client to authenticate. + \note Secure Transport SSL backend on macOS may update the default keychain + (the default is probably your login keychain) by importing your local certificates + and keys. This can also result in system dialogs showing up and asking for + permission when your application is using these private keys. If such behavior + is undesired, set the QT_SSL_USE_TEMPORARY_KEYCHAIN environment variable to a + non-zero value; this will prompt QSslSocket to use its own temporary keychain. + \sa localCertificate(), setPrivateKey() */ void QSslSocket::setLocalCertificate(const QSslCertificate &certificate) diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 3e56eac803..a2dee75895 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -53,9 +53,12 @@ #include #include #include +#include +#include #include #include +#include #include @@ -65,6 +68,102 @@ QT_BEGIN_NAMESPACE +namespace +{ +#ifdef Q_OS_MACOS +/* + +Our own temporarykeychain is needed only on macOS where SecPKCS12Import changes +the default keychain and where we see annoying pop-ups asking about accessing a +private key. + +*/ + +struct EphemeralSecKeychain +{ + EphemeralSecKeychain(); + ~EphemeralSecKeychain(); + + SecKeychainRef keychain = nullptr; + Q_DISABLE_COPY(EphemeralSecKeychain) +}; + +EphemeralSecKeychain::EphemeralSecKeychain() +{ + const auto uuid = QUuid::createUuid(); + if (uuid.isNull()) { + qCWarning(lcSsl) << "Failed to create an unique keychain name"; + return; + } + + QString uuidAsString(uuid.toString()); + Q_ASSERT(uuidAsString.size() > 2); + Q_ASSERT(uuidAsString.startsWith(QLatin1Char('{')) + && uuidAsString.endsWith(QLatin1Char('}'))); + uuidAsString = uuidAsString.mid(1, uuidAsString.size() - 2); + + QString keychainName(QDir::tempPath()); + keychainName.append(QDir::separator()); + keychainName += uuidAsString; + keychainName += QLatin1String(".keychain"); + // SecKeychainCreate, pathName parameter: + // + // "A constant character string representing the POSIX path indicating where + // to store the keychain." + // + // Internally they seem to use std::string, but this does not really help. + // Fortunately, CFString has a convenient API. + QCFType cfName = keychainName.toCFString(); + std::vector posixPath; + // "Extracts the contents of a string as a NULL-terminated 8-bit string + // appropriate for passing to POSIX APIs." + posixPath.resize(CFStringGetMaximumSizeOfFileSystemRepresentation(cfName)); + const auto ok = CFStringGetFileSystemRepresentation(cfName, &posixPath[0], + CFIndex(posixPath.size())); + if (!ok) { + qCWarning(lcSsl) << "Failed to create a unique keychain name from" + << "QDir::tempPath()"; + return; + } + + std::vector passUtf8(256); + if (SecRandomCopyBytes(kSecRandomDefault, passUtf8.size(), &passUtf8[0])) { + qCWarning(lcSsl) << "SecRandomCopyBytes: failed to create a key"; + return; + } + + const OSStatus status = SecKeychainCreate(&posixPath[0], passUtf8.size(), + &passUtf8[0], FALSE, nullptr, + &keychain); + if (status != errSecSuccess || !keychain) { + qCWarning(lcSsl) << "SecKeychainCreate: failed to create a custom keychain"; + if (keychain) { + SecKeychainDelete(keychain); + CFRelease(keychain); + keychain = nullptr; + } + } + +#ifdef QSSLSOCKET_DEBUG + if (keychain) { + qCDebug(lcSsl) << "Custom keychain with name" << keychainName << "was created" + << "successfully"; + } +#endif +} + +EphemeralSecKeychain::~EphemeralSecKeychain() +{ + if (keychain) { + // clear file off disk + SecKeychainDelete(keychain); + CFRelease(keychain); + } +} + +#endif // Q_OS_MACOS +} + static SSLContextRef qt_createSecureTransportContext(QSslSocket::SslMode mode) { const bool isServer = mode == QSslSocket::SslServerMode; @@ -815,11 +914,24 @@ bool QSslSocketBackendPrivate::setSessionCertificate(QString &errorDescription, QCFType pkcs12 = _q_makePkcs12(configuration.localCertificateChain, configuration.privateKey, passPhrase).toCFData(); QCFType password = passPhrase.toCFString(); - const void *keys[] = { kSecImportExportPassphrase }; - const void *values[] = { password }; - QCFType options(CFDictionaryCreate(Q_NULLPTR, keys, values, 1, - Q_NULLPTR, Q_NULLPTR)); - CFArrayRef items = Q_NULLPTR; + const void *keys[2] = { kSecImportExportPassphrase }; + const void *values[2] = { password }; + CFIndex nKeys = 1; +#ifdef Q_OS_MACOS + bool envOk = false; + const int env = qEnvironmentVariableIntValue("QT_SSL_USE_TEMPORARY_KEYCHAIN", &envOk); + if (envOk && env) { + static const EphemeralSecKeychain temporaryKeychain; + if (temporaryKeychain.keychain) { + nKeys = 2; + keys[1] = kSecImportExportKeychain; + values[1] = temporaryKeychain.keychain; + } + } +#endif + QCFType options = CFDictionaryCreate(nullptr, keys, values, nKeys, + nullptr, nullptr); + CFArrayRef items = nullptr; OSStatus err = SecPKCS12Import(pkcs12, options, &items); if (err != noErr) { #ifdef QSSLSOCKET_DEBUG @@ -851,7 +963,7 @@ bool QSslSocketBackendPrivate::setSessionCertificate(QString &errorDescription, return false; } - QCFType certs = CFArrayCreateMutable(Q_NULLPTR, 0, &kCFTypeArrayCallBacks); + QCFType certs = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks); if (!certs) { errorCode = QAbstractSocket::SslInternalError; errorDescription = QStringLiteral("Failed to allocate certificates array"); -- cgit v1.2.3 From 5b78fcd03b63241fa0382aa196afe789740fd5b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 28 Mar 2017 12:23:44 +0200 Subject: QRasterBackingStore: Correct high-dpi image size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix QT_SCALE_FACTOR usage on macOS. Follow-up to 2d2d9078 QRasterBackingStore should account for native scaling only. Any Qt scaling will have already been factored into the size argument. Change-Id: I26a67addfcbec3d45f4ed87f03b8dd79fd99cb62 Reviewed-by: Tor Arne Vestbø --- src/platformsupport/graphics/qrasterbackingstore.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/platformsupport/graphics/qrasterbackingstore.cpp b/src/platformsupport/graphics/qrasterbackingstore.cpp index ef26edc494..2f7074403c 100644 --- a/src/platformsupport/graphics/qrasterbackingstore.cpp +++ b/src/platformsupport/graphics/qrasterbackingstore.cpp @@ -42,6 +42,9 @@ #include #include +#include +#include + QT_BEGIN_NAMESPACE QRasterBackingStore::QRasterBackingStore(QWindow *window) @@ -57,14 +60,14 @@ void QRasterBackingStore::resize(const QSize &size, const QRegion &staticContent { Q_UNUSED(staticContents); - int windowDevicePixelRatio = window()->devicePixelRatio(); - QSize effectiveBufferSize = size * windowDevicePixelRatio; + qreal nativeWindowDevicePixelRatio = window()->handle()->devicePixelRatio(); + QSize effectiveBufferSize = size * nativeWindowDevicePixelRatio; if (m_image.size() == effectiveBufferSize) return; m_image = QImage(effectiveBufferSize, format()); - m_image.setDevicePixelRatio(windowDevicePixelRatio); + m_image.setDevicePixelRatio(nativeWindowDevicePixelRatio); if (m_image.format() == QImage::Format_ARGB32_Premultiplied) m_image.fill(Qt::transparent); } @@ -106,8 +109,11 @@ bool QRasterBackingStore::scroll(const QRegion ®ion, int dx, int dy) void QRasterBackingStore::beginPaint(const QRegion ®ion) { // Keep backing store device pixel ratio in sync with window - if (m_image.devicePixelRatio() != window()->devicePixelRatio()) - resize(backingStore()->size(), backingStore()->staticContents()); + qreal nativeWindowDevicePixelRatio = window()->handle()->devicePixelRatio(); + if (m_image.devicePixelRatio() != nativeWindowDevicePixelRatio) { + const QSize nativeSize = QHighDpi::toNativePixels(backingStore()->size(), window()); + resize(nativeSize, backingStore()->staticContents()); + } if (!m_image.hasAlphaChannel()) return; -- cgit v1.2.3 From 4fda233ad7bf5a3a820f5b84dba74f05bae01f03 Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Mon, 3 Apr 2017 19:40:03 +0200 Subject: Fix warning for -no-feature-menubar Change-Id: I58573d769897c956144604d51d38cad1c121f751 Reviewed-by: Tasuku Suzuki Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qlayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp index b90be2b4f1..f88ed350c7 100644 --- a/src/widgets/kernel/qlayout.cpp +++ b/src/widgets/kernel/qlayout.cpp @@ -581,7 +581,7 @@ void QLayoutPrivate::doResize(const QSize &r) QWidget *mw = q->parentWidget(); QRect rect = mw->testAttribute(Qt::WA_LayoutOnEntireRect) ? mw->rect() : mw->contentsRect(); const int mbTop = rect.top(); - rect.setTop(rect.top() + mbh); + rect.setTop(mbTop + mbh); q->setGeometry(rect); #ifndef QT_NO_MENUBAR if (menubar) -- cgit v1.2.3 From 21abfc810128f30101d02792a34db87b4f25d4ce Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Mon, 3 Apr 2017 19:41:55 +0200 Subject: Fix warning for -no-feature-wheelevent Change-Id: Ibf240228100bbc7cd8a85e49abc9dbff026e5433 Reviewed-by: Tasuku Suzuki Reviewed-by: Paul Olav Tvete --- src/gui/kernel/qguiapplication.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index b665750181..a3b2c4c1e4 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2008,6 +2008,8 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh buttons, e->modifiers, e->phase, e->source, e->inverted); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(window, &ev); +#else + Q_UNUSED(e); #endif /* ifndef QT_NO_WHEELEVENT */ } -- cgit v1.2.3 From d285409674915b0eb8c873874e40155ad44ac633 Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Mon, 3 Apr 2017 21:31:42 +0200 Subject: Fix warning for -no-feature-graphicsview Change-Id: I11ab0c664b860014376c725ea162e62740234ea4 Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 28ad56c526..bd67e0be32 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -6774,12 +6774,12 @@ void QWidget::clearFocus() bool QWidget::focusNextPrevChild(bool next) { - Q_D(QWidget); QWidget* p = parentWidget(); bool isSubWindow = (windowType() == Qt::SubWindow); if (!isWindow() && !isSubWindow && p) return p->focusNextPrevChild(next); #ifndef QT_NO_GRAPHICSVIEW + Q_D(QWidget); if (d->extra && d->extra->proxyWidget) return d->extra->proxyWidget->focusNextPrevChild(next); #endif -- cgit v1.2.3 From acc0ad78836cbbf852c097f83717e887b6d4b7b4 Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Mon, 3 Apr 2017 22:55:11 +0200 Subject: Fix warning for -no-feature-texthtmlparser Change-Id: I6dd6e80a546a76ce3717855ebacb188254fe70d6 Reviewed-by: Tasuku Suzuki Reviewed-by: Paul Olav Tvete --- src/gui/text/qtextdocumentfragment.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp index 079b2e01f7..3a78296c57 100644 --- a/src/gui/text/qtextdocumentfragment.cpp +++ b/src/gui/text/qtextdocumentfragment.cpp @@ -408,6 +408,8 @@ QTextDocumentFragment QTextDocumentFragment::fromPlainText(const QString &plainT return res; } +#ifndef QT_NO_TEXTHTMLPARSER + static QTextListFormat::Style nextListStyle(QTextListFormat::Style style) { if (style == QTextListFormat::ListDisc) @@ -417,8 +419,6 @@ static QTextListFormat::Style nextListStyle(QTextListFormat::Style style) return style; } -#ifndef QT_NO_TEXTHTMLPARSER - QTextHtmlImporter::QTextHtmlImporter(QTextDocument *_doc, const QString &_html, ImportMode mode, const QTextDocument *resourceProvider) : indent(0), compressNextWhitespace(PreserveWhiteSpace), doc(_doc), importMode(mode) { -- cgit v1.2.3 From 5678e6214132ab0a7182dbf1970f5df692baf490 Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Mon, 3 Apr 2017 22:57:18 +0200 Subject: Fix warning for -no-feature-textcodec Change-Id: I7775c8611a532db96f9843c311463a69c2e9ef82 Reviewed-by: Tasuku Suzuki Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/xcb/qxcbwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 77291cc4f5..a79696f758 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -284,6 +284,8 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s) free_prop = false; #if QT_CONFIG(textcodec) } +#else + Q_UNUSED(dpy); #endif return &tp; } -- cgit v1.2.3 From dfe0bfff39bf86b2abd9a22fc58dab8ea7da20e7 Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Mon, 3 Apr 2017 23:01:53 +0200 Subject: Fix warnings for -no-feature-settings Change-Id: I79ce0b9c5eb931e238394519ba80bf35e4ff3bf7 Reviewed-by: Tasuku Suzuki Reviewed-by: Paul Olav Tvete --- src/corelib/global/qlibraryinfo.cpp | 2 ++ src/gui/kernel/qplatforminputcontextfactory.cpp | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src') diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 03ee0730db..b4ba0b5b2e 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -663,6 +663,8 @@ QStringList QLibraryInfo::platformPluginArguments(const QString &platformName) + QLatin1String("Arguments"); return settings->value(key).toStringList(); } +#else + Q_UNUSED(platformName); #endif // !QT_BUILD_QMAKE && !QT_NO_SETTINGS return QStringList(); } diff --git a/src/gui/kernel/qplatforminputcontextfactory.cpp b/src/gui/kernel/qplatforminputcontextfactory.cpp index 5f4f8d88fa..c59d89fabe 100644 --- a/src/gui/kernel/qplatforminputcontextfactory.cpp +++ b/src/gui/kernel/qplatforminputcontextfactory.cpp @@ -82,6 +82,8 @@ QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key) delete ic; } +#else + Q_UNUSED(key); #endif return 0; } -- cgit v1.2.3 From 0db0441bb7b7d447cb85cab585f5a89d43e2fd42 Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Mon, 3 Apr 2017 23:19:29 +0200 Subject: Fix warning for -no-feature-temporaryfile Change-Id: Ibb022a1fd043001f628a343dc8ae509083eb4471 Reviewed-by: Tasuku Suzuki Reviewed-by: Paul Olav Tvete --- src/corelib/io/qlockfile_unix.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 5a02741727..ccc607afd5 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -115,6 +115,7 @@ int QLockFilePrivate::checkFcntlWorksAfterFlock(const QString &fn) return 0; return 1; #else + Q_UNUSED(fn); return 0; #endif } -- cgit v1.2.3 From 8146fd5f8ccb144207811cbbc21ec12fc487ec4c Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Tue, 4 Apr 2017 09:46:05 +0200 Subject: Fix several unused warnings for misc disabled features Change-Id: Id42daf684abeeb888155d65eca143150d9c5f5a7 Reviewed-by: Paul Olav Tvete --- src/widgets/styles/qcommonstyle.cpp | 16 ++++++++++++++++ src/widgets/styles/qfusionstyle.cpp | 4 ++++ src/widgets/styles/qpixmapstyle.cpp | 17 +++++++++++++++++ src/widgets/styles/qstylehelper.cpp | 2 ++ src/widgets/styles/qwindowsstyle.cpp | 2 ++ 5 files changed, 41 insertions(+) (limited to 'src') diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index cdb80d7581..fcd8f436fe 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -416,6 +416,8 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q proxy()->drawItemPixmap(p, opt->rect, Qt::AlignCenter, pixmap); break; } +#else + Q_UNUSED(d); #endif // QT_NO_TABBAR case PE_FrameTabWidget: case PE_FrameWindow: @@ -2315,6 +2317,9 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, default: break; } +#if !QT_CONFIG(tabbar) && !QT_CONFIG(itemviews) + Q_UNUSED(d); +#endif } /*! @@ -3058,6 +3063,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, break; } return r; +#if !QT_CONFIG(tabwidget) && !QT_CONFIG(itemviews) + Q_UNUSED(d); +#endif } #ifndef QT_NO_DIAL @@ -4357,6 +4365,9 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex default: qWarning("QCommonStyle::subControlRect: Case %d not handled", cc); } +#if !QT_CONFIG(slider) && !QT_CONFIG(spinbox) && !QT_CONFIG(toolbutton) && !QT_CONFIG(groupbox) + Q_UNUSED(widget); +#endif return ret; } @@ -5275,6 +5286,7 @@ static inline QString clearText16IconPath() } #endif // !QT_NO_IMAGEFORMAT_PNG +#if defined(Q_OS_WIN) || QT_CONFIG(imageformat_png) static QIcon clearTextIcon(bool rtl) { const QString directionalThemeName = rtl @@ -5298,6 +5310,7 @@ static QIcon clearTextIcon(bool rtl) #endif // !QT_NO_IMAGEFORMAT_PNG return icon; } +#endif /*! \reimp */ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, @@ -5642,6 +5655,9 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti } #endif //QT_NO_IMAGEFORMAT_XPM +#if !QT_CONFIG(imageformat_png) && !QT_CONFIG(imageformat_xpm) && !QT_CONFIG(imageformat_png) + Q_UNUSED(rtl); +#endif return QPixmap(); } diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 19b1cc2c57..1fed4f4b9f 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -1954,9 +1954,13 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption Q_D (const QFusionStyle); +#if QT_CONFIG(spinbox) || QT_CONFIG(slider) QColor buttonColor = d->buttonColor(option->palette); +#endif +#if QT_CONFIG(slider) QColor gradientStartColor = buttonColor.lighter(118); QColor gradientStopColor = buttonColor; +#endif QColor outline = d->outline(option->palette); QColor alphaCornerColor; diff --git a/src/widgets/styles/qpixmapstyle.cpp b/src/widgets/styles/qpixmapstyle.cpp index 19f4cc3617..de99b6ce7b 100644 --- a/src/widgets/styles/qpixmapstyle.cpp +++ b/src/widgets/styles/qpixmapstyle.cpp @@ -204,6 +204,9 @@ void QPixmapStyle::polish(QWidget *widget) #if QT_CONFIG(scrollbar) if (qobject_cast(widget)) widget->setAttribute(Qt::WA_OpaquePaintEvent, false); +#endif +#if !QT_CONFIG(progressbar) && !QT_CONFIG(combobox) + Q_UNUSED(d); #endif QCommonStyle::polish(widget); } @@ -929,6 +932,10 @@ void QPixmapStyle::drawSlider(const QStyleOptionComplex *option, painter->drawPixmap(handle, d->pixmaps.value(pix).pixmap); } } +#else + Q_UNUSED(option); + Q_UNUSED(painter); + Q_UNUSED(widget); #endif // QT_CONFIG(slider) } @@ -968,6 +975,10 @@ void QPixmapStyle::drawScrollBar(const QStyleOptionComplex *option, ? SB_Horizontal : SB_Vertical; drawCachedPixmap(control, rect, painter); } +#else + Q_UNUSED(option); + Q_UNUSED(painter); + Q_UNUSED(widget); #endif // QT_CONFIG(slider) } @@ -1044,6 +1055,9 @@ QSize QPixmapStyle::sliderSizeFromContents(const QStyleOption *option, else return QSize(desc.size.width(), result.height()); #else // QT_CONFIG(slider) + Q_UNUSED(option); + Q_UNUSED(contentsSize); + Q_UNUSED(widget); return QSize(); #endif // QT_CONFIG(slider) } @@ -1160,6 +1174,9 @@ QRect QPixmapStyle::scrollBarSubControlRect(const QStyleOptionComplex *option, } } } +#else + Q_UNUSED(option); + Q_UNUSED(sc); #endif // QT_CONFIG(slider) return QRect(); } diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index 9b381c383b..ffb898df57 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -415,6 +415,8 @@ QColor backgroundColor(const QPalette &pal, const QWidget* widget) if (qobject_cast(widget) && widget->parent() && qobject_cast(widget->parent()->parent())) return widget->parentWidget()->parentWidget()->palette().color(QPalette::Base); +#else + Q_UNUSED(widget); #endif return pal.color(QPalette::Base); } diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 0ce8dde74c..b537931f49 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -1734,6 +1734,8 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai step = (animation->animationStep() / 3) % chunkCount; else d->startAnimation(new QProgressStyleAnimation(d->animationFps, opt->styleObject)); +#else + Q_UNUSED(d); #endif int chunksInRow = 5; int myY = pbBits.rect.y(); -- cgit v1.2.3 From 08fc4c4e95d9e0a67eb9af71b282263d355e2532 Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Mon, 3 Apr 2017 22:59:20 +0200 Subject: Fix warning for -no-feature-draganddrop -no-feature-clipboard Change-Id: I974ac692f59622fbb5cf7c6bd60954cf306dabe7 Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/xcb/qxcbconnection.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 8c5f8cae08..7f3567a2f2 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1163,7 +1163,9 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) break; case XCB_SELECTION_REQUEST: { +#if QT_CONFIG(draganddrop) || QT_CONFIG(clipboard) xcb_selection_request_event_t *sr = reinterpret_cast(event); +#endif #ifndef QT_NO_DRAGANDDROP if (sr->selection == atom(QXcbAtom::XdndSelection)) m_drag->handleSelectionRequest(sr); -- cgit v1.2.3 From ecceaec8581886e5215ab10c8f5c702e315cb397 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 3 Apr 2017 20:53:17 +0100 Subject: GCC 7: fix -Werror=implicit-fallthrough More fallthrough-are-errors fixed. Change-Id: I9a6cb6efe988400ed3f9cb95d1e426dac317e6c4 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Marc Mutz --- src/corelib/xml/qxmlstream_p.h | 1 + src/gui/painting/qblendfunctions_p.h | 12 ++++----- src/gui/painting/qdrawhelper_p.h | 42 +++++++++++++++--------------- src/gui/painting/qgrayraster.c | 14 +++++----- src/gui/painting/qtransform.cpp | 6 ++++- src/gui/text/qtextengine.cpp | 7 ++++- src/widgets/styles/qcommonstyle.cpp | 7 +++++ src/widgets/styles/qfusionstyle.cpp | 6 +++++ src/widgets/styles/qstylesheetstyle.cpp | 4 +-- src/widgets/widgets/qabstractspinbox.cpp | 2 ++ src/widgets/widgets/qdatetimeedit.cpp | 1 + src/widgets/widgets/qeffects.cpp | 1 + src/widgets/widgets/qtoolbar.cpp | 2 +- src/widgets/widgets/qwidgetlinecontrol.cpp | 1 + 14 files changed, 68 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h index b62cc9ac39..9ef95c1fbe 100644 --- a/src/corelib/xml/qxmlstream_p.h +++ b/src/corelib/xml/qxmlstream_p.h @@ -1139,6 +1139,7 @@ bool QXmlStreamReaderPrivate::parse() case '\n': ++lineNumber; lastLineStart = characterOffset + readBufferPos; + Q_FALLTHROUGH(); case ' ': case '\t': token = SPACE; diff --git a/src/gui/painting/qblendfunctions_p.h b/src/gui/painting/qblendfunctions_p.h index 7ee04987fe..167f725143 100644 --- a/src/gui/painting/qblendfunctions_p.h +++ b/src/gui/painting/qblendfunctions_p.h @@ -375,12 +375,12 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl, --ii; } switch (i & 7) { - case 7: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; - case 6: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; - case 5: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; - case 4: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; - case 3: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; - case 2: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 7: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH(); + case 6: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH(); + case 5: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH(); + case 4: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH(); + case 3: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH(); + case 2: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; Q_FALLTHROUGH(); case 1: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; } diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 0e46962784..694959909b 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -846,13 +846,13 @@ inline void qt_memfill(T *dest, T value, int count) int n = (count + 7) / 8; switch (count & 0x07) { - case 0: do { *dest++ = value; - case 7: *dest++ = value; - case 6: *dest++ = value; - case 5: *dest++ = value; - case 4: *dest++ = value; - case 3: *dest++ = value; - case 2: *dest++ = value; + case 0: do { *dest++ = value; Q_FALLTHROUGH(); + case 7: *dest++ = value; Q_FALLTHROUGH(); + case 6: *dest++ = value; Q_FALLTHROUGH(); + case 5: *dest++ = value; Q_FALLTHROUGH(); + case 4: *dest++ = value; Q_FALLTHROUGH(); + case 3: *dest++ = value; Q_FALLTHROUGH(); + case 2: *dest++ = value; Q_FALLTHROUGH(); case 1: *dest++ = value; } while (--n > 0); } @@ -888,13 +888,13 @@ do { \ int n = ((length) + 7) / 8; \ switch ((length) & 0x07) \ { \ - case 0: do { *--_d = *--_s; \ - case 7: *--_d = *--_s; \ - case 6: *--_d = *--_s; \ - case 5: *--_d = *--_s; \ - case 4: *--_d = *--_s; \ - case 3: *--_d = *--_s; \ - case 2: *--_d = *--_s; \ + case 0: do { *--_d = *--_s; Q_FALLTHROUGH(); \ + case 7: *--_d = *--_s; Q_FALLTHROUGH(); \ + case 6: *--_d = *--_s; Q_FALLTHROUGH(); \ + case 5: *--_d = *--_s; Q_FALLTHROUGH(); \ + case 4: *--_d = *--_s; Q_FALLTHROUGH(); \ + case 3: *--_d = *--_s; Q_FALLTHROUGH(); \ + case 2: *--_d = *--_s; Q_FALLTHROUGH(); \ case 1: *--_d = *--_s; \ } while (--n > 0); \ } \ @@ -908,13 +908,13 @@ do { \ int n = ((length) + 7) / 8; \ switch ((length) & 0x07) \ { \ - case 0: do { *_d++ = *_s++; \ - case 7: *_d++ = *_s++; \ - case 6: *_d++ = *_s++; \ - case 5: *_d++ = *_s++; \ - case 4: *_d++ = *_s++; \ - case 3: *_d++ = *_s++; \ - case 2: *_d++ = *_s++; \ + case 0: do { *_d++ = *_s++; Q_FALLTHROUGH(); \ + case 7: *_d++ = *_s++; Q_FALLTHROUGH(); \ + case 6: *_d++ = *_s++; Q_FALLTHROUGH(); \ + case 5: *_d++ = *_s++; Q_FALLTHROUGH(); \ + case 4: *_d++ = *_s++; Q_FALLTHROUGH(); \ + case 3: *_d++ = *_s++; Q_FALLTHROUGH(); \ + case 2: *_d++ = *_s++; Q_FALLTHROUGH(); \ case 1: *_d++ = *_s++; \ } while (--n > 0); \ } \ diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c index db3453898f..dae1c06bec 100644 --- a/src/gui/painting/qgrayraster.c +++ b/src/gui/painting/qgrayraster.c @@ -162,6 +162,8 @@ #include #include +#include + #include #include @@ -1147,12 +1149,12 @@ switch ( spans->len ) { - case 7: *q++ = (unsigned char)coverage; - case 6: *q++ = (unsigned char)coverage; - case 5: *q++ = (unsigned char)coverage; - case 4: *q++ = (unsigned char)coverage; - case 3: *q++ = (unsigned char)coverage; - case 2: *q++ = (unsigned char)coverage; + case 7: *q++ = (unsigned char)coverage; Q_FALLTHROUGH(); + case 6: *q++ = (unsigned char)coverage; Q_FALLTHROUGH(); + case 5: *q++ = (unsigned char)coverage; Q_FALLTHROUGH(); + case 4: *q++ = (unsigned char)coverage; Q_FALLTHROUGH(); + case 3: *q++ = (unsigned char)coverage; Q_FALLTHROUGH(); + case 2: *q++ = (unsigned char)coverage; Q_FALLTHROUGH(); case 1: *q = (unsigned char)coverage; default: ; diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 2d841b2953..4e0489b352 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -2094,7 +2094,8 @@ QTransform::TransformationType QTransform::type() const if (!qFuzzyIsNull(m_13) || !qFuzzyIsNull(m_23) || !qFuzzyIsNull(m_33 - 1)) { m_type = TxProject; break; - } + } + Q_FALLTHROUGH(); case TxShear: case TxRotate: if (!qFuzzyIsNull(affine._m12) || !qFuzzyIsNull(affine._m21)) { @@ -2105,16 +2106,19 @@ QTransform::TransformationType QTransform::type() const m_type = TxShear; break; } + Q_FALLTHROUGH(); case TxScale: if (!qFuzzyIsNull(affine._m11 - 1) || !qFuzzyIsNull(affine._m22 - 1)) { m_type = TxScale; break; } + Q_FALLTHROUGH(); case TxTranslate: if (!qFuzzyIsNull(affine._dx) || !qFuzzyIsNull(affine._dy)) { m_type = TxTranslate; break; } + Q_FALLTHROUGH(); case TxNone: m_type = TxNone; break; diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 67cafa53fe..4f052dafd7 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -579,12 +579,14 @@ static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiCon else eor = current; status.eor = QChar::DirEN; - dir = QChar::DirAN; break; + dir = QChar::DirAN; + break; case QChar::DirES: case QChar::DirCS: if(status.eor == QChar::DirEN || dir == QChar::DirAN) { eor = current; break; } + Q_FALLTHROUGH(); case QChar::DirBN: case QChar::DirB: case QChar::DirS: @@ -614,11 +616,13 @@ static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiCon eor = current; status.eor = dirCurrent; } } + break; default: break; } break; } + Q_FALLTHROUGH(); case QChar::DirAN: hasBidi = true; dirCurrent = QChar::DirAN; @@ -642,6 +646,7 @@ static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiCon if(status.eor == QChar::DirAN) { eor = current; break; } + Q_FALLTHROUGH(); case QChar::DirES: case QChar::DirET: case QChar::DirBN: diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 7971bd0b8b..69c9230b4b 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -3008,6 +3008,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, r = subElementRect(SE_CheckBoxIndicator, opt, widget); break; } + Q_FALLTHROUGH(); case SE_ItemViewItemDecoration: case SE_ItemViewItemText: case SE_ItemViewItemFocusRect: @@ -4180,11 +4181,13 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex case SC_TitleBarContextHelpButton: if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) offset += delta; + Q_FALLTHROUGH(); case SC_TitleBarMinButton: if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) offset += delta; else if (sc == SC_TitleBarMinButton) break; + Q_FALLTHROUGH(); case SC_TitleBarNormalButton: if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) offset += delta; @@ -4192,21 +4195,25 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex offset += delta; else if (sc == SC_TitleBarNormalButton) break; + Q_FALLTHROUGH(); case SC_TitleBarMaxButton: if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) offset += delta; else if (sc == SC_TitleBarMaxButton) break; + Q_FALLTHROUGH(); case SC_TitleBarShadeButton: if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) offset += delta; else if (sc == SC_TitleBarShadeButton) break; + Q_FALLTHROUGH(); case SC_TitleBarUnshadeButton: if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) offset += delta; else if (sc == SC_TitleBarUnshadeButton) break; + Q_FALLTHROUGH(); case SC_TitleBarCloseButton: if (tb->titleBarFlags & Qt::WindowSystemMenuHint) offset += delta; diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index f1cd48556c..6f61bff403 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -3556,11 +3556,13 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom case SC_TitleBarContextHelpButton: if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) offset += delta; + Q_FALLTHROUGH(); case SC_TitleBarMinButton: if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) offset += delta; else if (sc == SC_TitleBarMinButton) break; + Q_FALLTHROUGH(); case SC_TitleBarNormalButton: if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) offset += delta; @@ -3568,21 +3570,25 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom offset += delta; else if (sc == SC_TitleBarNormalButton) break; + Q_FALLTHROUGH(); case SC_TitleBarMaxButton: if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) offset += delta; else if (sc == SC_TitleBarMaxButton) break; + Q_FALLTHROUGH(); case SC_TitleBarShadeButton: if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) offset += delta; else if (sc == SC_TitleBarShadeButton) break; + Q_FALLTHROUGH(); case SC_TitleBarUnshadeButton: if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) offset += delta; else if (sc == SC_TitleBarUnshadeButton) break; + Q_FALLTHROUGH(); case SC_TitleBarCloseButton: if (tb->titleBarFlags & Qt::WindowSystemMenuHint) offset += delta; diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 9be19b2679..6b0909ceb1 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -4371,7 +4371,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op break; } #endif - //fall tghought + Q_FALLTHROUGH(); case PE_PanelMenu: case PE_PanelStatusBar: if(rule.hasDrawable()) { @@ -4928,7 +4928,7 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op case CT_ToolButton: if (rule.hasBox() || !rule.hasNativeBorder() || !rule.baseStyleCanDraw()) sz += QSize(3, 3); // ### broken QToolButton - //fall thought + Q_FALLTHROUGH(); case CT_ComboBox: case CT_PushButton: if (rule.hasBox() || !rule.hasNativeBorder()) { diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index 8ccad5c35d..139ca0bc35 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -976,6 +976,7 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event) case Qt::Key_PageDown: steps *= 10; isPgUpOrDown = true; + Q_FALLTHROUGH(); case Qt::Key_Up: case Qt::Key_Down: { #ifdef QT_KEYPAD_NAVIGATION @@ -2111,6 +2112,7 @@ int QAbstractSpinBoxPrivate::variantCompare(const QVariant &arg1, const QVariant case QVariant::Invalid: if (arg2.type() == QVariant::Invalid) return 0; + Q_FALLTHROUGH(); default: Q_ASSERT_X(0, "QAbstractSpinBoxPrivate::variantCompare", qPrintable(QString::fromLatin1("Internal error 3 (%1 %2)"). diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index c5eab55a53..2ca09800de 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -1113,6 +1113,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event) && !(event->modifiers() & ~(Qt::ShiftModifier|Qt::KeypadModifier)); break; } + Q_FALLTHROUGH(); case Qt::Key_Left: case Qt::Key_Right: if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right) { diff --git a/src/widgets/widgets/qeffects.cpp b/src/widgets/widgets/qeffects.cpp index ecd85c2ca7..736f2599fe 100644 --- a/src/widgets/widgets/qeffects.cpp +++ b/src/widgets/widgets/qeffects.cpp @@ -196,6 +196,7 @@ bool QAlphaWidget::eventFilter(QObject *o, QEvent *e) case QEvent::Close: if (o != widget) break; + Q_FALLTHROUGH(); case QEvent::MouseButtonPress: case QEvent::MouseButtonDblClick: showWidget = false; diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp index 2a0912df0a..48fa88b7a0 100644 --- a/src/widgets/widgets/qtoolbar.cpp +++ b/src/widgets/widgets/qtoolbar.cpp @@ -1143,7 +1143,7 @@ bool QToolBar::event(QEvent *event) case QEvent::Hide: if (!isHidden()) break; - // fallthrough intended + Q_FALLTHROUGH(); case QEvent::Show: d->toggleViewAction->setChecked(event->type() == QEvent::Show); #ifdef Q_OS_OSX diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index a862274a3d..363e7157ac 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -1030,6 +1030,7 @@ void QWidgetLineControl::parseInputMask(const QString &maskFields) break; case '\\': escape = true; + Q_FALLTHROUGH(); default: s = true; break; -- cgit v1.2.3 From 2b9ecfe69c01085fbafb6c3c83b7ca4a5f564f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 30 Mar 2017 14:35:26 +0200 Subject: macOS: Split out font engine creation from QCoreTextFontDatabase The Core Text font database can produce both Core Text and FreeType font engines. Refactor the code a bit so that the actual factory methods that differ between the two stand out, and do not require a granular runtime check in each method. Change-Id: Ib70f76f4a9001a8108d87c1101a50699a6ea8f55 Reviewed-by: Simon Hausmann --- .../fontdatabases/mac/qcoretextfontdatabase.mm | 129 +++++++++++---------- .../fontdatabases/mac/qcoretextfontdatabase_p.h | 24 ++-- src/plugins/platforms/cocoa/qcocoaintegration.mm | 12 +- src/plugins/platforms/ios/qiosintegration.mm | 4 +- .../platforms/minimal/qminimalintegration.cpp | 4 +- 5 files changed, 101 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index b8097702ed..fcc94c40b3 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -112,12 +112,8 @@ static NSInteger languageMapSort(id obj1, id obj2, void *context) } #endif -QCoreTextFontDatabase::QCoreTextFontDatabase(bool useFreeType) -#ifndef QT_NO_FREETYPE - : m_useFreeType(useFreeType) -#endif +QCoreTextFontDatabase::QCoreTextFontDatabase() { - Q_UNUSED(useFreeType) #ifdef Q_OS_MACX QSettings appleSettings(QLatin1String("apple.com")); QVariant appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold")); @@ -393,35 +389,24 @@ static QByteArray filenameForCFUrl(CFURLRef url) extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef); -QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr) +template <> +QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QFontDef &fontDef, void *usrPtr) { CTFontDescriptorRef descriptor = static_cast(usrPtr); -#ifndef QT_NO_FREETYPE - if (m_useFreeType) { - QCFType url(static_cast(CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute))); - - QByteArray filename; - if (url) - filename = filenameForCFUrl(url); - - return freeTypeFontEngine(f, filename); - } -#endif - // Since we do not pass in the destination DPI to CoreText when making // the font, we need to pass in a point size which is scaled to include // the DPI. The default DPI for the screen is 72, thus the scale factor // is destinationDpi / 72, but since pixelSize = pointSize / 72 * dpi, // the pixelSize is actually the scaled point size for the destination // DPI, and we can use that directly. - qreal scaledPointSize = f.pixelSize; + qreal scaledPointSize = fontDef.pixelSize; - CGAffineTransform matrix = qt_transform_from_fontdef(f); + CGAffineTransform matrix = qt_transform_from_fontdef(fontDef); CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix); if (font) { - QFontEngine *engine = new QCoreTextFontEngine(font, f); - engine->fontDef = f; + QFontEngine *engine = new QCoreTextFontEngine(font, fontDef); + engine->fontDef = fontDef; CFRelease(font); return engine; } @@ -429,6 +414,24 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr) return NULL; } +#ifndef QT_NO_FREETYPE +template <> +QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QFontDef &fontDef, void *usrPtr) +{ + CTFontDescriptorRef descriptor = static_cast(usrPtr); + + QCFType url(static_cast(CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute))); + + QByteArray filename; + if (url) + filename = filenameForCFUrl(url); + + QFontEngine::FaceId faceId; + faceId.filename = filename; + return QFontEngineFT::create(fontDef, faceId); +} +#endif + static void releaseFontData(void* info, const void* data, size_t size) { Q_UNUSED(data); @@ -436,31 +439,9 @@ static void releaseFontData(void* info, const void* data, size_t size) delete (QByteArray*)info; } -QFontEngine *QCoreTextFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +template <> +QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { -#ifndef QT_NO_FREETYPE - if (m_useFreeType) { - QByteArray *fontDataCopy = new QByteArray(fontData); - QCFType dataProvider = CGDataProviderCreateWithData(fontDataCopy, - fontDataCopy->constData(), fontDataCopy->size(), releaseFontData); - QCFType cgFont(CGFontCreateWithDataProvider(dataProvider)); - - if (!cgFont) { - qWarning("QCoreTextFontDatabase::fontEngine: CGFontCreateWithDataProvider failed"); - return Q_NULLPTR; - } - - QFontDef fontDef; - fontDef.pixelSize = pixelSize; - fontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi(); - fontDef.hintingPreference = hintingPreference; - CGAffineTransform transform = qt_transform_from_fontdef(fontDef); - QCFType ctFont(CTFontCreateWithGraphicsFont(cgFont, fontDef.pixelSize, &transform, Q_NULLPTR)); - QCFType url(static_cast(CTFontCopyAttribute(ctFont, kCTFontURLAttribute))); - return freeTypeFontEngine(fontDef, filenameForCFUrl(url), fontData); - } -#endif - Q_UNUSED(hintingPreference); QByteArray* fontDataCopy = new QByteArray(fontData); @@ -483,6 +464,34 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QByteArray &fontData, qreal return fontEngine; } +#ifndef QT_NO_FREETYPE +template <> +QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +{ + QByteArray *fontDataCopy = new QByteArray(fontData); + QCFType dataProvider = CGDataProviderCreateWithData(fontDataCopy, + fontDataCopy->constData(), fontDataCopy->size(), releaseFontData); + QCFType cgFont(CGFontCreateWithDataProvider(dataProvider)); + + if (!cgFont) { + qWarning("QCoreTextFontDatabase::fontEngine: CGFontCreateWithDataProvider failed"); + return Q_NULLPTR; + } + + QFontDef fontDef; + fontDef.pixelSize = pixelSize; + fontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi(); + fontDef.hintingPreference = hintingPreference; + CGAffineTransform transform = qt_transform_from_fontdef(fontDef); + QCFType ctFont(CTFontCreateWithGraphicsFont(cgFont, fontDef.pixelSize, &transform, Q_NULLPTR)); + QCFType url(static_cast(CTFontCopyAttribute(ctFont, kCTFontURLAttribute))); + + QFontEngine::FaceId faceId; + faceId.filename = filenameForCFUrl(url); + return QFontEngineFT::create(fontDef, faceId, fontData); +} +#endif + QFont::StyleHint styleHintFromNSString(NSString *style) { if ([style isEqual: @"sans-serif"]) @@ -615,17 +624,27 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo return fallbackLists[styleLookupKey.arg(styleHint)]; } -CFArrayRef QCoreTextFontDatabase::createDescriptorArrayForFont(CTFontRef font, const QString &fileName) +template <> +CFArrayRef QCoreTextFontDatabaseEngineFactory::createDescriptorArrayForFont(CTFontRef font, const QString &fileName) { + Q_UNUSED(fileName) CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); QCFType descriptor = CTFontCopyFontDescriptor(font); + CFArrayAppendValue(array, descriptor); + return array; +} - Q_UNUSED(fileName) #ifndef QT_NO_FREETYPE +template <> +CFArrayRef QCoreTextFontDatabaseEngineFactory::createDescriptorArrayForFont(CTFontRef font, const QString &fileName) +{ + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + QCFType descriptor = CTFontCopyFontDescriptor(font); + // The physical font source URL (usually a local file or Qt resource) is only required for // FreeType, when using non-system fonts, and needs some hackery to attach in a format // agreeable to OSX. - if (m_useFreeType && !fileName.isEmpty()) { + if (!fileName.isEmpty()) { QCFType fontURL; if (fileName.startsWith(QLatin1String(":/"))) { @@ -642,11 +661,11 @@ CFArrayRef QCoreTextFontDatabase::createDescriptorArrayForFont(CTFontRef font, c CFDictionaryAddValue(attributes, kCTFontURLAttribute, fontURL); descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, attributes); } -#endif CFArrayAppendValue(array, descriptor); return array; } +#endif QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) { @@ -884,15 +903,5 @@ void QCoreTextFontDatabase::removeApplicationFonts() m_applicationFonts.clear(); } -#ifndef QT_NO_FREETYPE -QFontEngine *QCoreTextFontDatabase::freeTypeFontEngine(const QFontDef &fontDef, const QByteArray &filename, - const QByteArray &fontData) -{ - QFontEngine::FaceId faceId; - faceId.filename = filename; - return QFontEngineFT::create(fontDef, faceId, fontData); -} -#endif - QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index c093d903af..8edf60b5fa 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -72,13 +72,11 @@ QT_BEGIN_NAMESPACE class QCoreTextFontDatabase : public QPlatformFontDatabase { public: - QCoreTextFontDatabase(bool useFreeType = false); + QCoreTextFontDatabase(); ~QCoreTextFontDatabase(); void populateFontDatabase() Q_DECL_OVERRIDE; void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE; QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE; QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) Q_DECL_OVERRIDE; void releaseHandle(void *handle) Q_DECL_OVERRIDE; @@ -93,13 +91,8 @@ public: private: void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString()); - CFArrayRef createDescriptorArrayForFont(CTFontRef font, const QString &fileName); + virtual CFArrayRef createDescriptorArrayForFont(CTFontRef font, const QString &fileName) = 0; -#ifndef QT_NO_FREETYPE - bool m_useFreeType; - QFontEngine *freeTypeFontEngine(const QFontDef &fontDef, const QByteArray &filename, - const QByteArray &fontData = QByteArray()); -#endif mutable QString defaultFontName; void removeApplicationFonts(); @@ -109,6 +102,19 @@ private: mutable QHash m_themeFonts; }; +// Split out into separate template class so that the compiler doesn't have +// to generate code for each override in QCoreTextFontDatabase for each T. + +template +class QCoreTextFontDatabaseEngineFactory : public QCoreTextFontDatabase +{ +public: + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override; + QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override; +protected: + CFArrayRef createDescriptorArrayForFont(CTFontRef font, const QString &fileName) override; +}; + QT_END_NAMESPACE #endif // QCORETEXTFONTDATABASE_H diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 9dfcb82151..d48ec8c6f7 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -69,6 +69,9 @@ static void initResources() QT_BEGIN_NAMESPACE +class QCoreTextFontEngine; +class QFontEngineFT; + QCocoaScreen::QCocoaScreen(int screenIndex) : QPlatformScreen(), m_screenIndex(screenIndex), m_refreshRate(60.0) { @@ -302,7 +305,7 @@ QCocoaIntegration *QCocoaIntegration::mInstance = 0; QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) : mOptions(parseOptions(paramList)) - , mFontDb(new QCoreTextFontDatabase(mOptions.testFlag(UseFreeTypeFontEngine))) + , mFontDb(0) #ifndef QT_NO_ACCESSIBILITY , mAccessibility(new QCocoaAccessibility) #endif @@ -318,6 +321,13 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) qWarning("Creating multiple Cocoa platform integrations is not supported"); mInstance = this; +#ifndef QT_NO_FREETYPE + if (mOptions.testFlag(UseFreeTypeFontEngine)) + mFontDb.reset(new QCoreTextFontDatabaseEngineFactory); + else +#endif + mFontDb.reset(new QCoreTextFontDatabaseEngineFactory); + QString icStr = QPlatformInputContextFactory::requested(); icStr.isNull() ? mInputContext.reset(new QCocoaInputContext) : mInputContext.reset(QPlatformInputContextFactory::create(icStr)); diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index fbf167b514..5c42828885 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -69,13 +69,15 @@ QT_BEGIN_NAMESPACE +class QCoreTextFontEngine; + QIOSIntegration *QIOSIntegration::instance() { return static_cast(QGuiApplicationPrivate::platformIntegration()); } QIOSIntegration::QIOSIntegration() - : m_fontDatabase(new QCoreTextFontDatabase) + : m_fontDatabase(new QCoreTextFontDatabaseEngineFactory) #if !defined(Q_OS_TVOS) && !defined(QT_NO_CLIPBOARD) , m_clipboard(new QIOSClipboard) #endif diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp index 820c4891ca..ca33689cd7 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.cpp +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -69,6 +69,8 @@ QT_BEGIN_NAMESPACE +class QCoreTextFontEngine; + static const char debugBackingStoreEnvironmentVariable[] = "QT_DEBUG_BACKINGSTORE"; static inline unsigned parseOptions(const QStringList ¶mList) @@ -140,7 +142,7 @@ QPlatformFontDatabase *QMinimalIntegration::fontDatabase() const m_fontDatabase = new QWindowsFontDatabase; } #elif defined(Q_OS_DARWIN) - m_fontDatabase = new QCoreTextFontDatabase; + m_fontDatabase = new QCoreTextFontDatabaseEngineFactory; #else m_fontDatabase = QPlatformIntegration::fontDatabase(); #endif -- cgit v1.2.3 From 6c547142d5b80619ca751edade8429f6fddad853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 30 Mar 2017 15:32:12 +0200 Subject: Move FreeType font engine creation for QRawFont into factory function So that the logic can be used without subclassing the FreeType font database. Change-Id: Ib1ac0e1948ce18003b8eda0c1e8fbb3c7e6c8360 Reviewed-by: Simon Hausmann --- .../fontdatabases/freetype/qfontengine_ft.cpp | 50 ++++++++++++++++++++++ .../fontdatabases/freetype/qfontengine_ft_p.h | 1 + .../freetype/qfreetypefontdatabase.cpp | 49 +-------------------- 3 files changed, 52 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp index 98bf91fa9d..3895681507 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #ifndef QT_NO_FREETYPE @@ -706,6 +707,55 @@ QFontEngineFT *QFontEngineFT::create(const QFontDef &fontDef, FaceId faceId, con return engine.take(); } +namespace { + class QFontEngineFTRawData: public QFontEngineFT + { + public: + QFontEngineFTRawData(const QFontDef &fontDef) : QFontEngineFT(fontDef) + { + } + + void updateFamilyNameAndStyle() + { + fontDef.family = QString::fromLatin1(freetype->face->family_name); + + if (freetype->face->style_flags & FT_STYLE_FLAG_ITALIC) + fontDef.style = QFont::StyleItalic; + + if (freetype->face->style_flags & FT_STYLE_FLAG_BOLD) + fontDef.weight = QFont::Bold; + } + + bool initFromData(const QByteArray &fontData) + { + FaceId faceId; + faceId.filename = ""; + faceId.index = 0; + faceId.uuid = QUuid::createUuid().toByteArray(); + + return init(faceId, true, Format_None, fontData); + } + }; +} + +QFontEngineFT *QFontEngineFT::create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +{ + QFontDef fontDef; + fontDef.pixelSize = pixelSize; + fontDef.hintingPreference = hintingPreference; + + QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef); + if (!fe->initFromData(fontData)) { + delete fe; + return 0; + } + + fe->updateFamilyNameAndStyle(); + fe->setQtDefaultHintStyle(static_cast(fontDef.hintingPreference)); + + return fe; +} + QFontEngineFT::QFontEngineFT(const QFontDef &fd) : QFontEngine(Freetype) { diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h index fc923d196b..2993e3b616 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h @@ -294,6 +294,7 @@ private: HintStyle defaultHintStyle() const { return default_hint_style; } static QFontEngineFT *create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData = QByteArray()); + static QFontEngineFT *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); protected: diff --git a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp index 764f2d8868..2caa47658a 100644 --- a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #include #undef QT_NO_FREETYPE @@ -93,56 +92,10 @@ QFontEngine *QFreeTypeFontDatabase::fontEngine(const QFontDef &fontDef, void *us return QFontEngineFT::create(fontDef, faceId); } -namespace { - - class QFontEngineFTRawData: public QFontEngineFT - { - public: - QFontEngineFTRawData(const QFontDef &fontDef) : QFontEngineFT(fontDef) - { - } - - void updateFamilyNameAndStyle() - { - fontDef.family = QString::fromLatin1(freetype->face->family_name); - - if (freetype->face->style_flags & FT_STYLE_FLAG_ITALIC) - fontDef.style = QFont::StyleItalic; - - if (freetype->face->style_flags & FT_STYLE_FLAG_BOLD) - fontDef.weight = QFont::Bold; - } - - bool initFromData(const QByteArray &fontData) - { - FaceId faceId; - faceId.filename = ""; - faceId.index = 0; - faceId.uuid = QUuid::createUuid().toByteArray(); - - return init(faceId, true, Format_None, fontData); - } - }; - -} - QFontEngine *QFreeTypeFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { - QFontDef fontDef; - fontDef.pixelSize = pixelSize; - fontDef.hintingPreference = hintingPreference; - - QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef); - if (!fe->initFromData(fontData)) { - delete fe; - return 0; - } - - fe->updateFamilyNameAndStyle(); - fe->setQtDefaultHintStyle(static_cast(fontDef.hintingPreference)); - - return fe; + return QFontEngineFT::create(fontData, pixelSize, hintingPreference); } QStringList QFreeTypeFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) -- cgit v1.2.3 From a7fe6ab8915d0a52c130a46817a16f89717eee9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 30 Mar 2017 16:25:41 +0200 Subject: macOS: Use shared code path for creating FreeType font engine for QRawFont The round trip via a CGFontRef to a CTFontRef so that we could pull out the kCTFontURLAttribute of the font makes no sense, as the input is just raw font data. None of the tst_QRawFont tests are able to pull out a URL, and none of the other platforms where FreeType is available resolve a filename from raw fonts. Without this change the tst_QRawFont test has 13 failed test cases and spits out 1250 QWARNs. With the patch all tests pass without warnings. Change-Id: I17965e7405d7161958ff0870825ce8190598288f Reviewed-by: Simon Hausmann --- .../fontdatabases/mac/qcoretextfontdatabase.mm | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'src') diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index fcc94c40b3..d40636e7d7 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -468,27 +468,7 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine template <> QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { - QByteArray *fontDataCopy = new QByteArray(fontData); - QCFType dataProvider = CGDataProviderCreateWithData(fontDataCopy, - fontDataCopy->constData(), fontDataCopy->size(), releaseFontData); - QCFType cgFont(CGFontCreateWithDataProvider(dataProvider)); - - if (!cgFont) { - qWarning("QCoreTextFontDatabase::fontEngine: CGFontCreateWithDataProvider failed"); - return Q_NULLPTR; - } - - QFontDef fontDef; - fontDef.pixelSize = pixelSize; - fontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi(); - fontDef.hintingPreference = hintingPreference; - CGAffineTransform transform = qt_transform_from_fontdef(fontDef); - QCFType ctFont(CTFontCreateWithGraphicsFont(cgFont, fontDef.pixelSize, &transform, Q_NULLPTR)); - QCFType url(static_cast(CTFontCopyAttribute(ctFont, kCTFontURLAttribute))); - - QFontEngine::FaceId faceId; - faceId.filename = filenameForCFUrl(url); - return QFontEngineFT::create(fontDef, faceId, fontData); + return QFontEngineFT::create(fontData, pixelSize, hintingPreference); } #endif -- cgit v1.2.3 From 5b41b34958792931b910859fd8ad812d8959d60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 30 Mar 2017 18:48:39 +0200 Subject: macOS: Use NSURL to resolve FreeType font names instead of CoreFoundation Change-Id: I4b397361c483fa07e4e95288f66d7f7ea2df8d9f Reviewed-by: Simon Hausmann --- .../fontdatabases/mac/qcoretextfontdatabase.mm | 37 ++++++---------------- 1 file changed, 9 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index d40636e7d7..ea0aab17a0 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -363,30 +363,6 @@ void QCoreTextFontDatabase::releaseHandle(void *handle) CFRelease(CTFontDescriptorRef(handle)); } -#ifndef QT_NO_FREETYPE -static QByteArray filenameForCFUrl(CFURLRef url) -{ - // The on-stack buffer prevents that a QByteArray allocated for the worst case (MAXPATHLEN) - // stays around for the lifetime of the font. Additionally, it helps to move the char - // signedness cast to an acceptable place. - uchar buffer[MAXPATHLEN]; - QByteArray filename; - - if (!CFURLGetFileSystemRepresentation(url, true, buffer, sizeof(buffer))) { - qWarning("QCoreTextFontDatabase::filenameForCFUrl: could not resolve file for URL %s", - url ? qPrintable(QString::fromCFString(CFURLGetString(url))) : "(null)"); - } else { - QCFType scheme = CFURLCopyScheme(url); - if (QString::fromCFString(scheme) == QLatin1String("qrc")) - filename = ":"; - - filename += reinterpret_cast(buffer); - } - - return filename; -} -#endif - extern CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef); template <> @@ -420,11 +396,16 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine(const { CTFontDescriptorRef descriptor = static_cast(usrPtr); - QCFType url(static_cast(CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute))); - QByteArray filename; - if (url) - filename = filenameForCFUrl(url); + if (NSURL *url = [static_cast(CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute)) autorelease]) { + if ([url.scheme isEqual:@"qrc"]) + filename = ":"; + else if (!url.fileURL) + qWarning() << "QFontDatabase: Unknown scheme" << url.scheme << "in font descriptor URL"; + + filename += QString::fromNSString(url.path).toUtf8(); + } + Q_ASSERT(!filename.isEmpty()); QFontEngine::FaceId faceId; faceId.filename = filename; -- cgit v1.2.3 From 1b2234c4e7d8f1ddb9f22312b4563da2db5ad303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 31 Mar 2017 16:48:43 +0200 Subject: macOS: Remove un-needed fontDef assignment in QCoreTextFontDatabase The QCoreTextFontEngine constructor already sets the member (like it should). Change-Id: I6e59ff36c439857418a636de4056c20d2f65e8d4 Reviewed-by: Simon Hausmann --- src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index ea0aab17a0..ce9b61ba4c 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -382,7 +382,6 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix); if (font) { QFontEngine *engine = new QCoreTextFontEngine(font, fontDef); - engine->fontDef = fontDef; CFRelease(font); return engine; } -- cgit v1.2.3 From 83486f362b02070e29b408be3a9673a0b04dc424 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Tue, 4 Apr 2017 13:12:00 +0200 Subject: Adds a note to QSqlDatabase::~QSqlDatabase documentation When the last QSqlDatabase object is destroyed the destructor implicitly calls close() to release the database connection. Task-number: QTBUG-59919 Change-Id: I04c15c4999cdaaa8800a44a1a1006f977a90d8a6 Reviewed-by: Samuel Gaist Reviewed-by: Andy Shaw --- src/sql/kernel/qsqldatabase.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 0416215870..412658e39c 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -695,6 +695,9 @@ void QSqlDatabasePrivate::init(const QString &type) /*! Destroys the object and frees any allocated resources. + \note When the last connection is destroyed, the destructor + implicitly calls close() to release the database connection. + \sa close() */ -- cgit v1.2.3 From 6b52039866db6629747faa0aa1b57c206ed1cd6f Mon Sep 17 00:00:00 2001 From: Hendrick Melo Date: Tue, 14 Mar 2017 13:45:49 -0400 Subject: qbmphandler fix: use qint64 for caching QIODevice file position Changed the file position and offset types so they can properly handle files larger than the 32bit limit Task-number: QTBUG-59493 Change-Id: I00e1741c7682c4c79f35fef808fe1ea26e67c8b5 Reviewed-by: Marc Mutz Reviewed-by: Eirik Aavitsland Reviewed-by: Hendrick Melo --- src/gui/image/qbmphandler.cpp | 6 +++--- src/gui/image/qbmphandler_p.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 9545abfd21..324fe01414 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -183,14 +183,14 @@ static bool read_dib_infoheader(QDataStream &s, BMP_INFOHDR &bi) return true; } -static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int startpos, QImage &image) +static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset, qint64 startpos, QImage &image) { QIODevice* d = s.device(); if (d->atEnd()) // end of stream/file return false; #if 0 - qDebug("offset...........%d", offset); - qDebug("startpos.........%d", startpos); + qDebug("offset...........%lld", offset); + qDebug("startpos.........%lld", startpos); qDebug("biSize...........%d", bi.biSize); qDebug("biWidth..........%d", bi.biWidth); qDebug("biHeight.........%d", bi.biHeight); diff --git a/src/gui/image/qbmphandler_p.h b/src/gui/image/qbmphandler_p.h index 7d3cbab322..3e1fc3d511 100644 --- a/src/gui/image/qbmphandler_p.h +++ b/src/gui/image/qbmphandler_p.h @@ -121,7 +121,7 @@ private: State state; BMP_FILEHDR fileHeader; BMP_INFOHDR infoHeader; - int startpos; + qint64 startpos; }; QT_END_NAMESPACE -- cgit v1.2.3 From ce2771c71c6679a020ae66ac6602e04621a66a8f Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Tue, 4 Apr 2017 13:58:24 +0200 Subject: QNetworkRequest - do not set ManualRedirectPolicy If QNAM's general policy is 'Manual' and QNetworkRequest has neither policy set not FollowRedirectAttribute - do NOT set this 'Manual' policy - its implicitly implied. This fixes previously unnoticed auto test failure (was blacklisted) and also makes QNetworkRequest::operator == work correctly. Change-Id: If17c9af4baf8a470659f82d1a40488078ea8ede0 Reviewed-by: Edward Welbourne Reviewed-by: Timur Pocheptsov --- src/network/access/qnetworkaccessmanager.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 0a6270d417..018586f9dc 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1280,11 +1280,9 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera Q_D(QNetworkAccessManager); QNetworkRequest req(originalReq); - if (req.attribute(QNetworkRequest::RedirectPolicyAttribute).isNull() + if (redirectPolicy() != QNetworkRequest::ManualRedirectPolicy + && req.attribute(QNetworkRequest::RedirectPolicyAttribute).isNull() && req.attribute(QNetworkRequest::FollowRedirectsAttribute).isNull()) { - // We only apply the general manager's policy if: - // - RedirectPolicyAttribute is not set already on request and - // - no FollowRedirectsAttribute is set. req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, redirectPolicy()); } -- cgit v1.2.3 From 9ae028f507a22bd03c861e9d14c2efc4aa2efeda Mon Sep 17 00:00:00 2001 From: Marco Martin Date: Fri, 10 Feb 2017 15:00:23 +0100 Subject: Environment variable enabling the workaround FBO readback bug On some ARM devices the font glyph generation is broken Add an environment variable to enable workaround_brokenFBOReadBack in QOpenGLContext, to fix font rendering on such devices as Mali and Adreno Change-Id: I9cc99ecb8b71a35bc369ec9dd11b877016b1179e Reviewed-by: Laszlo Agocs --- src/gui/kernel/qopenglcontext.cpp | 34 ++++++++++++++++++++++ .../android/qandroidplatformopenglcontext.cpp | 31 -------------------- .../android/qandroidplatformopenglcontext.h | 1 - 3 files changed, 34 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 8aea593bf0..3dc06ae60e 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -982,6 +982,40 @@ bool QOpenGLContext::makeCurrent(QSurface *surface) QOpenGLContext *previous = QOpenGLContextPrivate::setCurrentContext(this); if (d->platformGLContext->makeCurrent(surface->surfaceHandle())) { + static bool needsWorkaroundSet = false; + static bool needsWorkaround = false; + + if (!needsWorkaroundSet) { + QByteArray env; +#ifdef Q_OS_ANDROID + env = qgetenv(QByteArrayLiteral("QT_ANDROID_DISABLE_GLYPH_CACHE_WORKAROUND")); + needsWorkaround = env.isEmpty() || env == QByteArrayLiteral("0") || env == QByteArrayLiteral("false"); +#endif + env = qgetenv(QByteArrayLiteral("QT_ENABLE_GLYPH_CACHE_WORKAROUND")); + if (env == QByteArrayLiteral("1") || env == QByteArrayLiteral("true")) + needsWorkaround = true; + + if (!needsWorkaround) { + const char *rendererString = reinterpret_cast(functions()->glGetString(GL_RENDERER)); + if (rendererString) + needsWorkaround = + qstrncmp(rendererString, "Mali-4xx", 6) == 0 // Mali-400, Mali-450 + || qstrncmp(rendererString, "Adreno (TM) 2xx", 13) == 0 // Adreno 200, 203, 205 + || qstrncmp(rendererString, "Adreno 2xx", 8) == 0 // Same as above but without the '(TM)' + || qstrncmp(rendererString, "Adreno (TM) 30x", 14) == 0 // Adreno 302, 305 + || qstrncmp(rendererString, "Adreno 30x", 9) == 0 // Same as above but without the '(TM)' + || qstrncmp(rendererString, "Adreno (TM) 4xx", 13) == 0 // Adreno 405, 418, 420, 430 + || qstrncmp(rendererString, "Adreno 4xx", 8) == 0 // Same as above but without the '(TM)' + || qstrcmp(rendererString, "GC800 core") == 0 + || qstrcmp(rendererString, "GC1000 core") == 0 + || qstrcmp(rendererString, "Immersion.16") == 0; + } + needsWorkaroundSet = true; + } + + if (needsWorkaround) + d->workaround_brokenFBOReadBack = true; + d->surface = surface; d->shareGroup->d_func()->deletePendingResources(this); diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp index 4d52085a83..6f979f614c 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp @@ -65,42 +65,11 @@ void QAndroidPlatformOpenGLContext::swapBuffers(QPlatformSurface *surface) QEGLPlatformContext::swapBuffers(surface); } -bool QAndroidPlatformOpenGLContext::needsFBOReadBackWorkaround() -{ - static bool set = false; - static bool needsWorkaround = false; - - if (!set) { - QByteArray env = qgetenv("QT_ANDROID_DISABLE_GLYPH_CACHE_WORKAROUND"); - needsWorkaround = env.isEmpty() || env == "0" || env == "false"; - - if (!needsWorkaround) { - const char *rendererString = reinterpret_cast(glGetString(GL_RENDERER)); - needsWorkaround = - qstrncmp(rendererString, "Mali-4xx", 6) == 0 // Mali-400, Mali-450 - || qstrncmp(rendererString, "Adreno (TM) 2xx", 13) == 0 // Adreno 200, 203, 205 - || qstrncmp(rendererString, "Adreno 2xx", 8) == 0 // Same as above but without the '(TM)' - || qstrncmp(rendererString, "Adreno (TM) 30x", 14) == 0 // Adreno 302, 305 - || qstrncmp(rendererString, "Adreno 30x", 9) == 0 // Same as above but without the '(TM)' - || qstrcmp(rendererString, "GC800 core") == 0 - || qstrcmp(rendererString, "GC1000 core") == 0 - || qstrcmp(rendererString, "Immersion.16") == 0; - } - - set = true; - } - - return needsWorkaround; -} - bool QAndroidPlatformOpenGLContext::makeCurrent(QPlatformSurface *surface) { bool ret = QEGLPlatformContext::makeCurrent(surface); QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context()); - if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) - ctx_d->workaround_brokenFBOReadBack = true; - return ret; } diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.h b/src/plugins/platforms/android/qandroidplatformopenglcontext.h index 3897b3166b..8e65b4cc36 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.h +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.h @@ -55,7 +55,6 @@ public: private: EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override; - static bool needsFBOReadBackWorkaround(); }; QT_END_NAMESPACE -- cgit v1.2.3 From b67b80b71516af71fec28732506c25ad338a84e7 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 4 Apr 2017 17:00:53 +0200 Subject: Fix stretch of QRawFonts Set stretch to always have no transform on raw fonts. Task-number: QTBUG-59799 Change-Id: Ibfacc5c247e0b4a8410572e207f09f6e67b74f9d Reviewed-by: Konstantin Tokarev Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp index 0826b0f2fb..8cf572b1af 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp @@ -152,6 +152,7 @@ QFontEngine *QBasicFontDatabase::fontEngine(const QByteArray &fontData, qreal pi { QFontDef fontDef; fontDef.pixelSize = pixelSize; + fontDef.stretch = QFont::Unstretched; fontDef.hintingPreference = hintingPreference; QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef); -- cgit v1.2.3 From efb84b6189f9e98c6dd29c22f00ad760445196c2 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 27 Mar 2017 15:48:37 +0200 Subject: Copy stretch to multifont fontDef If we do not the fontDef of the multifont will be the default 0. Task-number: QTBUG-59443 Change-Id: Ib223517975b2a57b2371e309d12cd8f918d30825 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/painting/qpdf.cpp | 2 ++ src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src') diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 7b53966f81..644999e00a 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -2556,6 +2556,7 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti) qreal size = ti.fontEngine->fontDef.pixelSize; int synthesized = ti.fontEngine->synthesized(); qreal stretch = synthesized & QFontEngine::SynthesizedStretch ? ti.fontEngine->fontDef.stretch/100. : 1.; + Q_ASSERT(stretch > qreal(0)); QTransform trans; // Build text rendering matrix (Trm). We need it to map the text area to user @@ -2632,6 +2633,7 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti) return; int synthesized = ti.fontEngine->synthesized(); qreal stretch = synthesized & QFontEngine::SynthesizedStretch ? ti.fontEngine->fontDef.stretch/100. : 1.; + Q_ASSERT(stretch > qreal(0)); *currentPage << "BT\n" << "/F" << font->object_id << size << "Tf " diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp index 08ebbc3be0..5af73a6f2b 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp @@ -1293,6 +1293,7 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at) fedw->fontDef.style = fontEngine->fontDef.style; fedw->fontDef.family = fam; fedw->fontDef.hintingPreference = fontEngine->fontDef.hintingPreference; + fedw->fontDef.stretch = fontEngine->fontDef.stretch; return fedw; } else { qErrnoWarning("%s: CreateFontFace failed", __FUNCTION__); @@ -1310,6 +1311,7 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at) fe->fontDef.style = fontEngine->fontDef.style; fe->fontDef.family = fam; fe->fontDef.hintingPreference = fontEngine->fontDef.hintingPreference; + fe->fontDef.stretch = fontEngine->fontDef.stretch; return fe; } -- cgit v1.2.3 From fb38db29e167dacc51892f718453159fcfa4062f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 4 Apr 2017 13:08:11 +0200 Subject: Consider ENXIO (No such device or address) reason to check isatty() Aligns with EPERM (Operation not permitted) and ENOENT (No such file or directory), and is what errno is set to on macOS when opening the /dev/tty device when running inside e.g. Xcode, where isatty() will return true. Change-Id: I09b88eaa3ff611d95ab37f0ff4df9aaaca52747d Reviewed-by: Simon Hausmann Reviewed-by: Thiago Macieira --- src/corelib/global/qlogging.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 6573e0a53e..e525869733 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -197,7 +197,7 @@ static bool willLogToConsole() # elif defined(Q_OS_UNIX) // if /dev/tty exists, we can only open it if we have a controlling TTY int devtty = qt_safe_open("/dev/tty", O_RDONLY); - if (devtty == -1 && (errno == ENOENT || errno == EPERM)) { + if (devtty == -1 && (errno == ENOENT || errno == EPERM || errno == ENXIO)) { // no /dev/tty, fall back to isatty on stderr return isatty(STDERR_FILENO); } else if (devtty != -1) { -- cgit v1.2.3 From 71649e21680ce3d5194a6b7dfc92bd5ac67966ba Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 1 Apr 2017 11:19:22 -0700 Subject: Fix build when SCTP is enabled c0157a9f035a27a3ba20cab0ca3ca1c6e78f0b14 was incomplete. Change-Id: I27b55fdf514247549455fffd14b158f54403663d Reviewed-by: Timur Pocheptsov Reviewed-by: Edward Welbourne --- src/network/socket/qnativesocketengine.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index cf3afe1845..b796934199 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -129,6 +129,10 @@ # include "qtcpserver.h" #endif +#if !defined(QT_NO_SCTP) +# include "qsctpserver.h" +#endif + QT_BEGIN_NAMESPACE //#define QNATIVESOCKETENGINE_DEBUG -- cgit v1.2.3 From b3f474d620f07297c27bf7919a366a5ceb25c20a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 2 Apr 2017 19:35:51 -0700 Subject: QSysInfo: update the ICC warning that needs to be suppressed qsysinfo.h(235): error #1786: enum "QSysInfo::MacVersion" (declared at line 156) was declared deprecated ("Use QOperatingSystemVersion") Take this opportunity to merge the two groups. Change-Id: I27b55fdf514247549455fffd14b1c2a1d8eab869 Reviewed-by: Jake Petroules --- src/corelib/global/qsysinfo.h | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h index 3cbcfd3fc9..ff0a784ace 100644 --- a/src/corelib/global/qsysinfo.h +++ b/src/corelib/global/qsysinfo.h @@ -135,19 +135,6 @@ public: WV_CE_6 = 0x0400, WV_CE_based = 0x0f00 }; -QT_WARNING_PUSH -QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations") -QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations") -QT_WARNING_DISABLE_INTEL(1478) -QT_WARNING_DISABLE_MSVC(4996) -#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) - QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion; - QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion(); -#else - QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion = WV_None; - QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion() { return WV_None; } -#endif -QT_WARNING_POP #define Q_MV_OSX(major, minor) (major == 10 ? minor + 2 : (major == 9 ? 1 : 0)) #define Q_MV_IOS(major, minor) (QSysInfo::MV_IOS | major << 4 | minor) @@ -222,11 +209,19 @@ QT_WARNING_POP MV_WATCHOS_2_2 = Q_MV_WATCHOS(2, 2), MV_WATCHOS_3_0 = Q_MV_WATCHOS(3, 0) }; + QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations") QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations") -QT_WARNING_DISABLE_INTEL(1478) +QT_WARNING_DISABLE_INTEL(1786) QT_WARNING_DISABLE_MSVC(4996) +#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) + QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion; + QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion(); +#else + QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion = WV_None; + QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion() { return WV_None; } +#endif #if defined(Q_OS_MAC) QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const MacVersion MacintoshVersion; QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static MacVersion macVersion(); -- cgit v1.2.3 From 264d814773a15806df497e872e4b19c613c94725 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 2 Apr 2017 09:46:21 -0700 Subject: Fix GCC warning about dereferencing type-punned pointers GCC is wrong. Type-punning is when you read something of a given type as something else. We're not doing that, as it's only read as integer. qnativesocketengine_unix.cpp:1011:79: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing] Too bad my plan for a good C++ solution was foiled by glibc developers. Change-Id: I27b55fdf514247549455fffd14b1a27667745e94 Reviewed-by: Edward Welbourne --- src/network/socket/qnativesocketengine_unix.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 09c06adb1e..3cf65b3553 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -987,7 +987,8 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS if (cmsgptr->cmsg_len == CMSG_LEN(sizeof(int)) && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT) || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) { - header->hopLimit = *reinterpret_cast(CMSG_DATA(cmsgptr)); + Q_STATIC_ASSERT(sizeof(header->hopLimit) == sizeof(int)); + memcpy(&header->hopLimit, CMSG_DATA(cmsgptr), sizeof(header->hopLimit)); } #ifndef QT_NO_SCTP -- cgit v1.2.3 From c817b33b45f2886c89d8a768c61ffffaa46f67a4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 3 Apr 2017 15:41:44 -0700 Subject: f16c: Use the packed intrinsics instead of scalar ones MSVC, Apple's Clang and Clang prior to 3.9 do not recognize _cvtss_sh and _cvtsh_ss. So expand the operation to use directly the packed intrinsics. Change-Id: I27b55fdf514247549455fffd14b2046fd638593d Reviewed-by: Allan Sandfeld Jensen --- src/corelib/global/qfloat16.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 0fa83db93f..654183acd6 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -118,7 +118,9 @@ QT_WARNING_DISABLE_CLANG("-Wc99-extensions") inline qfloat16::qfloat16(float f) Q_DECL_NOTHROW { #if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__) - b16 = _cvtss_sh(f, 0); + __m128 packsingle = _mm_set_ss(f); + __m128i packhalf = _mm_cvtps_ph(packsingle, 0); + b16 = _mm_extract_epi16(packhalf, 0); #elif defined (__ARM_FP16_FORMAT_IEEE) __fp16 f16 = f; memcpy(&b16, &f16, sizeof(quint16)); @@ -134,7 +136,9 @@ QT_WARNING_POP inline qfloat16::operator float() const Q_DECL_NOTHROW { #if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__) - return _cvtsh_ss(b16); + __m128i packhalf = _mm_cvtsi32_si128(b16); + __m128 packsingle = _mm_cvtph_ps(packhalf); + return _mm_cvtss_f32(packsingle); #elif defined (__ARM_FP16_FORMAT_IEEE) __fp16 f16; memcpy(&f16, &b16, sizeof(quint16)); -- cgit v1.2.3 From 280e321e52fd4e86545f3f0d4bd4e047786a897e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 3 Apr 2017 16:05:18 -0700 Subject: Fix detection of F16C for the Intel compiler (again) and Visual Studio Neither the Intel compiler nor Visual C++ have a dedicated switch to enable F16C support, like GCC and Clang do. So we used the AVX switch for that in commit 8241d51f7049d48912ce25fbd49ef4d22c58e340, as it was the closest, lowest denominator. That was incorrect and insufficient. The Intel compiler silently miscompiles the intrinsics with -xAVX, making calls to out-of-line functions like _mm_cvtps_ph, which don't exist. So we actually have to use AVX2 support to generate correct code. That might be a problem later, since Ivy Bridge supports F16C but not AVX2. Visual C++ is able to generate F16C code with just -arch:AVX. Either way, since there's no dedicated command-line switch, there's also no dedicated preprocessor macro. We're using __AVX2__ for both compilers, as that's a sufficient condition to indicate a processor that supports F16C. Change-Id: I27b55fdf514247549455fffd14b205b8d8b86da7 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/global/qfloat16.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 654183acd6..05b88e0e92 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -117,7 +117,7 @@ QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wc99-extensions") inline qfloat16::qfloat16(float f) Q_DECL_NOTHROW { -#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__) +#if defined(QT_COMPILER_SUPPORTS_F16C) && (defined(__F16C__) || defined(__AVX2__)) __m128 packsingle = _mm_set_ss(f); __m128i packhalf = _mm_cvtps_ph(packsingle, 0); b16 = _mm_extract_epi16(packhalf, 0); @@ -135,7 +135,7 @@ QT_WARNING_POP inline qfloat16::operator float() const Q_DECL_NOTHROW { -#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__) +#if defined(QT_COMPILER_SUPPORTS_F16C) && (defined(__F16C__) || defined(__AVX2__)) __m128i packhalf = _mm_cvtsi32_si128(b16); __m128 packsingle = _mm_cvtph_ps(packhalf); return _mm_cvtss_f32(packsingle); -- cgit v1.2.3 From 65a551816fff8fa4ccba5693d59ee2f3fd363176 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 21 Feb 2017 11:16:23 +0100 Subject: Replace last occurrences of LGPL3, LGPL3-COMM headers Change-Id: I0e967120d7bdfa00f110b49e6c65d8c6f9b329aa Reviewed-by: Jani Heikkinen --- src/plugins/platforms/android/extract.cpp | 23 +++++++++++++++------ src/plugins/platforms/vnc/qvncintegration.cpp | 29 +++++++++++++++------------ src/plugins/platforms/winrt/qwinrtdrag.cpp | 27 ++++++++++++++----------- src/plugins/platforms/winrt/qwinrtdrag.h | 27 ++++++++++++++----------- 4 files changed, 63 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/android/extract.cpp b/src/plugins/platforms/android/extract.cpp index 8620aa4fe8..e6636e37d4 100644 --- a/src/plugins/platforms/android/extract.cpp +++ b/src/plugins/platforms/android/extract.cpp @@ -1,26 +1,37 @@ /**************************************************************************** ** ** Copyright (C) 2014 BogDan Vatra -** Contact: http://www.qt.io/licensing/ +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/vnc/qvncintegration.cpp b/src/plugins/platforms/vnc/qvncintegration.cpp index 025112c790..8516e994f5 100644 --- a/src/plugins/platforms/vnc/qvncintegration.cpp +++ b/src/plugins/platforms/vnc/qvncintegration.cpp @@ -1,34 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the FOO module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL3$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp index cf52816b65..15ae024d20 100644 --- a/src/plugins/platforms/winrt/qwinrtdrag.cpp +++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp @@ -1,34 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL3$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtdrag.h b/src/plugins/platforms/winrt/qwinrtdrag.h index dad3e9892d..6cbabfbf41 100644 --- a/src/plugins/platforms/winrt/qwinrtdrag.h +++ b/src/plugins/platforms/winrt/qwinrtdrag.h @@ -1,34 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL3$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** -- cgit v1.2.3 From 4387202f31f7fd546a64b45be382fd05b4539ed2 Mon Sep 17 00:00:00 2001 From: Rainer Keller Date: Wed, 5 Apr 2017 13:06:55 +0200 Subject: eglfs: Show error details when JSON parsing failed Change-Id: I1a92da5b2ed0b8064efa37c43d7894c212073b60 Reviewed-by: Andy Nichols --- .../eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp index 1abc430da6..5e2708e958 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp @@ -97,7 +97,9 @@ void QEglFSEmulatorIntegration::screenInit() } } } else { - qWarning() << "eglfs_emu: Failed to parse display info JSON with error: " << error.errorString(); + qWarning() << "eglfs_emu: Failed to parse display info JSON with error: " << error.errorString() + << " at offset " << error.offset << " : " << displaysInfo; + } } else { qFatal("EGL library doesn't support Emulator extensions"); -- cgit v1.2.3 From 0624085b73ff4d6537e3dd406f6b3701806626d0 Mon Sep 17 00:00:00 2001 From: Sami Nurmenniemi Date: Thu, 30 Mar 2017 11:58:37 +0300 Subject: Don't set margin on offscreen window if it has a parent Offscreen platform had window frame margins set to 2 by default unless Qt::FramelessWindowHint had been set. Margins must not be set to 2 if the window has a parent. This change fixes two tests in tst_QWindowContainer for offscreen platform. Change-Id: Ib1577c301ea3a3b240bfa7c46ff12510dd2bcef0 Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/offscreen/qoffscreenwindow.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp index 892168a1dc..81f262f9ed 100644 --- a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp @@ -157,10 +157,13 @@ QMargins QOffscreenWindow::frameMargins() const void QOffscreenWindow::setFrameMarginsEnabled(bool enabled) { - if (enabled && !(window()->flags() & Qt::FramelessWindowHint)) + if (enabled + && !(window()->flags() & Qt::FramelessWindowHint) + && (parent() == nullptr)) { m_margins = QMargins(2, 2, 2, 2); - else + } else { m_margins = QMargins(0, 0, 0, 0); + } } void QOffscreenWindow::setWindowState(Qt::WindowState state) -- cgit v1.2.3