diff options
Diffstat (limited to 'src/platformsupport')
78 files changed, 3400 insertions, 1333 deletions
diff --git a/src/platformsupport/CMakeLists.txt b/src/platformsupport/CMakeLists.txt index 158ad419a3..fc980f3707 100644 --- a/src/platformsupport/CMakeLists.txt +++ b/src/platformsupport/CMakeLists.txt @@ -5,6 +5,11 @@ add_subdirectory(eventdispatchers) add_subdirectory(devicediscovery) add_subdirectory(fbconvenience) add_subdirectory(themes) +# special case begin +if (QT_FEATURE_dbus) + add_subdirectory(linuxofono) +endif() +# special case end if(APPLE OR QT_FEATURE_freetype OR WIN32) add_subdirectory(fontdatabases) endif() diff --git a/src/platformsupport/accessibility/CMakeLists.txt b/src/platformsupport/accessibility/CMakeLists.txt index 288b1a33e5..4757b123af 100644 --- a/src/platformsupport/accessibility/CMakeLists.txt +++ b/src/platformsupport/accessibility/CMakeLists.txt @@ -4,21 +4,17 @@ ## AccessibilitySupport Module: ##################################################################### -add_qt_module(AccessibilitySupport +qt_add_module(AccessibilitySupport STATIC INTERNAL_MODULE SOURCES qaccessiblebridgeutils.cpp qaccessiblebridgeutils_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui ) #### Keys ignored in scope 1:.:.:accessibility.pro:<TRUE>: # MODULE = "accessibility_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/accessibility/qaccessiblebridgeutils.cpp b/src/platformsupport/accessibility/qaccessiblebridgeutils.cpp index f280e65c29..a15b93e31e 100644 --- a/src/platformsupport/accessibility/qaccessiblebridgeutils.cpp +++ b/src/platformsupport/accessibility/qaccessiblebridgeutils.cpp @@ -93,7 +93,7 @@ bool performEffectiveAction(QAccessibleInterface *iface, const QString &actionNa if (!success) return false; stepSize = (max - min) / 10; // this is pretty arbitrary, we just need to provide something - const int typ = currentVariant.type(); + const int typ = currentVariant.userType(); if (typ != QMetaType::Float && typ != QMetaType::Double) { // currentValue is an integer. Round it up to ensure stepping in case it was below 1 stepSize = qCeil(stepSize); diff --git a/src/platformsupport/clipboard/CMakeLists.txt b/src/platformsupport/clipboard/CMakeLists.txt index 804f3d53c7..52022903aa 100644 --- a/src/platformsupport/clipboard/CMakeLists.txt +++ b/src/platformsupport/clipboard/CMakeLists.txt @@ -4,29 +4,26 @@ ## ClipboardSupport Module: ##################################################################### -add_qt_module(ClipboardSupport +qt_add_module(ClipboardSupport STATIC INTERNAL_MODULE SOURCES qmacmime.mm qmacmime_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES - Qt::CorePrivate PUBLIC_LIBRARIES ${FWImageIO} - Qt::Core + Qt::CorePrivate Qt::Gui ) #### Keys ignored in scope 1:.:.:clipboard.pro:<TRUE>: # MODULE = "clipboard_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(ClipboardSupport CONDITION APPLE_OSX +qt_extend_target(ClipboardSupport CONDITION APPLE_OSX LIBRARIES ${FWAppKit} ) diff --git a/src/platformsupport/devicediscovery/CMakeLists.txt b/src/platformsupport/devicediscovery/CMakeLists.txt index 6253a024c0..8ecabb4a1b 100644 --- a/src/platformsupport/devicediscovery/CMakeLists.txt +++ b/src/platformsupport/devicediscovery/CMakeLists.txt @@ -4,40 +4,37 @@ ## DeviceDiscoverySupport Module: ##################################################################### -add_qt_module(DeviceDiscoverySupport +qt_add_module(DeviceDiscoverySupport STATIC INTERNAL_MODULE SOURCES qdevicediscovery_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES - Qt::CorePrivate PUBLIC_LIBRARIES - Qt::Core + Qt::CorePrivate ) #### Keys ignored in scope 1:.:.:devicediscovery.pro:<TRUE>: # MODULE = "devicediscovery_support" # QT_FOR_CONFIG = "gui-private" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(DeviceDiscoverySupport CONDITION QT_FEATURE_libudev +qt_extend_target(DeviceDiscoverySupport CONDITION QT_FEATURE_libudev SOURCES qdevicediscovery_udev.cpp qdevicediscovery_udev_p.h LIBRARIES PkgConfig::Libudev ) -extend_target(DeviceDiscoverySupport CONDITION QT_FEATURE_evdev AND NOT QT_FEATURE_libudev +qt_extend_target(DeviceDiscoverySupport CONDITION QT_FEATURE_evdev AND NOT QT_FEATURE_libudev SOURCES qdevicediscovery_static.cpp qdevicediscovery_static_p.h ) -extend_target(DeviceDiscoverySupport CONDITION NOT QT_FEATURE_evdev AND NOT QT_FEATURE_libudev +qt_extend_target(DeviceDiscoverySupport CONDITION NOT QT_FEATURE_evdev AND NOT QT_FEATURE_libudev SOURCES qdevicediscovery_dummy.cpp qdevicediscovery_dummy_p.h ) diff --git a/src/platformsupport/edid/CMakeLists.txt b/src/platformsupport/edid/CMakeLists.txt index 2691d27d95..aaea30448e 100644 --- a/src/platformsupport/edid/CMakeLists.txt +++ b/src/platformsupport/edid/CMakeLists.txt @@ -4,21 +4,18 @@ ## EdidSupport Module: ##################################################################### -add_qt_module(EdidSupport +qt_add_module(EdidSupport STATIC INTERNAL_MODULE SOURCES qedidparser.cpp qedidparser_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES - Qt::CorePrivate PUBLIC_LIBRARIES - Qt::Core + Qt::CorePrivate PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:edid.pro:<TRUE>: # MODULE = "edid_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/eglconvenience/.prev_CMakeLists.txt b/src/platformsupport/eglconvenience/.prev_CMakeLists.txt index ea6b9ea902..f8efacd7cb 100644 --- a/src/platformsupport/eglconvenience/.prev_CMakeLists.txt +++ b/src/platformsupport/eglconvenience/.prev_CMakeLists.txt @@ -4,7 +4,7 @@ ## EglSupport Module: ##################################################################### -add_qt_module(EglSupport +qt_add_module(EglSupport STATIC INTERNAL_MODULE SOURCES @@ -13,42 +13,38 @@ add_qt_module(EglSupport qt_egl_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:eglconvenience.pro:<TRUE>: # MODULE = "egl_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(EglSupport CONDITION QT_FEATURE_opengl +qt_extend_target(EglSupport CONDITION QT_FEATURE_opengl SOURCES qeglpbuffer.cpp qeglpbuffer_p.h qeglplatformcontext.cpp qeglplatformcontext_p.h ) -extend_target(EglSupport CONDITION QT_FEATURE_egl_x11 +qt_extend_target(EglSupport CONDITION QT_FEATURE_egl_x11 SOURCES qxlibeglintegration.cpp qxlibeglintegration_p.h LIBRARIES X11::XCB ) -extend_target(EglSupport CONDITION NOT QT_FEATURE_egl_x11 +qt_extend_target(EglSupport CONDITION NOT QT_FEATURE_egl_x11 DEFINES QT_EGL_NO_X11 ) -extend_target(EglSupport CONDITION QT_FEATURE_dlopen +qt_extend_target(EglSupport CONDITION QT_FEATURE_dlopen PUBLIC_LIBRARIES ${CMAKE_DL_LIBS} ) diff --git a/src/platformsupport/eglconvenience/CMakeLists.txt b/src/platformsupport/eglconvenience/CMakeLists.txt index d6d41d1ead..b18a1470ec 100644 --- a/src/platformsupport/eglconvenience/CMakeLists.txt +++ b/src/platformsupport/eglconvenience/CMakeLists.txt @@ -1,10 +1,12 @@ -qt_find_package(EGL) # special case +# Generated from eglconvenience.pro. ##################################################################### ## EglSupport Module: ##################################################################### -add_qt_module(EglSupport +qt_find_package(EGL) # special case + +qt_add_module(EglSupport STATIC INTERNAL_MODULE SOURCES @@ -13,33 +15,39 @@ add_qt_module(EglSupport qt_egl_p.h DEFINES QT_NO_CAST_FROM_ASCII - QT_EGL_NO_X11 - LIBRARIES - ${CMAKE_DL_LIBS} + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate EGL::EGL # special case - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:eglconvenience.pro:<TRUE>: # MODULE = "egl_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(EglSupport CONDITION QT_FEATURE_opengl +qt_extend_target(EglSupport CONDITION QT_FEATURE_opengl SOURCES qeglpbuffer.cpp qeglpbuffer_p.h qeglplatformcontext.cpp qeglplatformcontext_p.h ) -extend_target(EglSupport CONDITION QT_FEATURE_xlib +qt_extend_target(EglSupport CONDITION QT_FEATURE_egl_x11 SOURCES qxlibeglintegration.cpp qxlibeglintegration_p.h + LIBRARIES + X11::XCB +) + +qt_extend_target(EglSupport CONDITION NOT QT_FEATURE_egl_x11 + DEFINES + QT_EGL_NO_X11 +) + +qt_extend_target(EglSupport CONDITION QT_FEATURE_dlopen + PUBLIC_LIBRARIES + ${CMAKE_DL_LIBS} ) diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp index 5ee4773b70..5303d37cee 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience.cpp +++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp @@ -281,11 +281,11 @@ EGLConfig QEglConfigChooser::chooseConfig() } configureAttributes.append(EGL_NONE); - EGLConfig cfg = 0; + EGLConfig cfg = nullptr; do { // Get the number of matching configurations for this set of properties. EGLint matching = 0; - if (!eglChooseConfig(display(), configureAttributes.constData(), 0, 0, &matching) || !matching) + if (!eglChooseConfig(display(), configureAttributes.constData(), nullptr, 0, &matching) || !matching) continue; // Fetch all of the matching configurations and find the @@ -450,7 +450,7 @@ static struct AttrInfo attrs[] = { {EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA"}, {EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL"}, {EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL"}, - {-1, 0}}; + {-1, nullptr}}; void q_printEglConfig(EGLDisplay display, EGLConfig config) { diff --git a/src/platformsupport/eglconvenience/qeglpbuffer_p.h b/src/platformsupport/eglconvenience/qeglpbuffer_p.h index 8ad2eb7248..a137d0d328 100644 --- a/src/platformsupport/eglconvenience/qeglpbuffer_p.h +++ b/src/platformsupport/eglconvenience/qeglpbuffer_p.h @@ -60,7 +60,7 @@ class QEGLPbuffer : public QPlatformOffscreenSurface { public: QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface, - QEGLPlatformContext::Flags flags = nullptr); + QEGLPlatformContext::Flags flags = { }); ~QEGLPbuffer(); QSurfaceFormat format() const override { return m_format; } diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 94def16748..63cf771f32 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -137,7 +137,7 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig, format); // m_format now has the renderableType() resolved (it cannot be Default anymore) // but does not yet contain version, profile, options. - m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0; + m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : nullptr; QVector<EGLint> contextAttrs; contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); @@ -194,8 +194,8 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont eglBindAPI(m_api); m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData()); if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) { - m_shareContext = 0; - m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, 0, contextAttrs.constData()); + m_shareContext = nullptr; + m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, nullptr, contextAttrs.constData()); } if (m_eglContext == EGL_NO_CONTEXT) { @@ -218,7 +218,7 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon qWarning("QEGLPlatformContext: Requires a QEGLNativeContext"); return; } - QEGLNativeContext handle = nativeHandle.value<QEGLNativeContext>(); + QEGLNativeContext handle = qvariant_cast<QEGLNativeContext>(nativeHandle); EGLContext context = handle.context(); if (!context) { qWarning("QEGLPlatformContext: No EGLContext given"); @@ -262,7 +262,7 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon } m_eglContext = context; - m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0; + m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : nullptr; updateFormatFromGL(); } @@ -326,7 +326,7 @@ void QEGLPlatformContext::updateFormatFromGL() EGLBoolean ok = eglMakeCurrent(m_eglDisplay, tempSurface, tempSurface, m_eglContext); if (!ok) { EGLConfig config = q_configFromGLFormat(m_eglDisplay, m_format, false, EGL_PBUFFER_BIT); - tempContext = eglCreateContext(m_eglDisplay, config, 0, m_contextAttrs.constData()); + tempContext = eglCreateContext(m_eglDisplay, config, nullptr, m_contextAttrs.constData()); if (tempContext != EGL_NO_CONTEXT) ok = eglMakeCurrent(m_eglDisplay, tempSurface, tempSurface, tempContext); } diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index ed77c57df5..f0388cd29c 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -69,7 +69,7 @@ public: QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLConfig *config = nullptr, const QVariant &nativeHandle = QVariant(), - Flags flags = nullptr); + Flags flags = { }); ~QEGLPlatformContext(); void initialize() override; diff --git a/src/platformsupport/eventdispatchers/.prev_CMakeLists.txt b/src/platformsupport/eventdispatchers/.prev_CMakeLists.txt index 22b89d3317..2e25d6cfd6 100644 --- a/src/platformsupport/eventdispatchers/.prev_CMakeLists.txt +++ b/src/platformsupport/eventdispatchers/.prev_CMakeLists.txt @@ -4,41 +4,37 @@ ## EventDispatcherSupport Module: ##################################################################### -add_qt_module(EventDispatcherSupport +qt_add_module(EventDispatcherSupport STATIC INTERNAL_MODULE DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:eventdispatchers.pro:<TRUE>: # MODULE = "eventdispatcher_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(EventDispatcherSupport CONDITION UNIX +qt_extend_target(EventDispatcherSupport CONDITION UNIX SOURCES qgenericunixeventdispatcher.cpp qgenericunixeventdispatcher_p.h qunixeventdispatcher.cpp qunixeventdispatcher_qpa_p.h ) -extend_target(EventDispatcherSupport CONDITION WIN32 +qt_extend_target(EventDispatcherSupport CONDITION WIN32 SOURCES qwindowsguieventdispatcher.cpp qwindowsguieventdispatcher_p.h ) -extend_target(EventDispatcherSupport CONDITION QT_FEATURE_glib +qt_extend_target(EventDispatcherSupport CONDITION QT_FEATURE_glib SOURCES qeventdispatcher_glib.cpp qeventdispatcher_glib_p.h LIBRARIES diff --git a/src/platformsupport/eventdispatchers/CMakeLists.txt b/src/platformsupport/eventdispatchers/CMakeLists.txt index fae7bff862..72b873423b 100644 --- a/src/platformsupport/eventdispatchers/CMakeLists.txt +++ b/src/platformsupport/eventdispatchers/CMakeLists.txt @@ -6,41 +6,37 @@ qt_find_package(GLIB2) # special case ## EventDispatcherSupport Module: ##################################################################### -add_qt_module(EventDispatcherSupport +qt_add_module(EventDispatcherSupport STATIC INTERNAL_MODULE DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:eventdispatchers.pro:<TRUE>: # MODULE = "eventdispatcher_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(EventDispatcherSupport CONDITION UNIX +qt_extend_target(EventDispatcherSupport CONDITION UNIX SOURCES qgenericunixeventdispatcher.cpp qgenericunixeventdispatcher_p.h qunixeventdispatcher.cpp qunixeventdispatcher_qpa_p.h ) -extend_target(EventDispatcherSupport CONDITION WIN32 +qt_extend_target(EventDispatcherSupport CONDITION WIN32 SOURCES qwindowsguieventdispatcher.cpp qwindowsguieventdispatcher_p.h ) -extend_target(EventDispatcherSupport CONDITION QT_FEATURE_glib +qt_extend_target(EventDispatcherSupport CONDITION QT_FEATURE_glib SOURCES qeventdispatcher_glib.cpp qeventdispatcher_glib_p.h LIBRARIES diff --git a/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp b/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp index a37547f513..20cfb5155e 100644 --- a/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp +++ b/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE */ QWindowsGuiEventDispatcher::QWindowsGuiEventDispatcher(QObject *parent) : - QEventDispatcherWin32(parent), m_flags(0) + QEventDispatcherWin32(parent) { setObjectName(QStringLiteral("QWindowsGuiEventDispatcher")); createInternalHwnd(); // QTBUG-40881: Do not delay registering timers, etc. for QtMfc. diff --git a/src/platformsupport/fbconvenience/CMakeLists.txt b/src/platformsupport/fbconvenience/CMakeLists.txt index 61d61e4321..804b2c15ec 100644 --- a/src/platformsupport/fbconvenience/CMakeLists.txt +++ b/src/platformsupport/fbconvenience/CMakeLists.txt @@ -4,7 +4,7 @@ ## FbSupport Module: ##################################################################### -add_qt_module(FbSupport +qt_add_module(FbSupport STATIC INTERNAL_MODULE SOURCES @@ -15,16 +15,12 @@ add_qt_module(FbSupport qfbwindow.cpp qfbwindow_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:fbconvenience.pro:<TRUE>: # MODULE = "fb_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp index c42fd879f8..76984dfe5c 100644 --- a/src/platformsupport/fbconvenience/qfbscreen.cpp +++ b/src/platformsupport/fbconvenience/qfbscreen.cpp @@ -255,7 +255,7 @@ QFbWindow *QFbScreen::windowForId(WId wid) const QFbScreen::Flags QFbScreen::flags() const { - return 0; + return { }; } QT_END_NAMESPACE diff --git a/src/platformsupport/fbconvenience/qfbvthandler.cpp b/src/platformsupport/fbconvenience/qfbvthandler.cpp index 7bb9e28ac2..8aab0bada4 100644 --- a/src/platformsupport/fbconvenience/qfbvthandler.cpp +++ b/src/platformsupport/fbconvenience/qfbvthandler.cpp @@ -70,6 +70,10 @@ QT_BEGIN_NAMESPACE #ifdef VTH_ENABLED static void setTTYCursor(bool enable) { + static bool ignore = qEnvironmentVariableIntValue("QT_QPA_PRESERVE_CONSOLE_STATE"); + if (ignore) + return; + const char * const devs[] = { "/dev/tty0", "/dev/tty", "/dev/console", 0 }; int fd = -1; for (const char * const *dev = devs; *dev; ++dev) { diff --git a/src/platformsupport/fontdatabases/.prev_CMakeLists.txt b/src/platformsupport/fontdatabases/.prev_CMakeLists.txt index bd193fbe78..56cf076bd9 100644 --- a/src/platformsupport/fontdatabases/.prev_CMakeLists.txt +++ b/src/platformsupport/fontdatabases/.prev_CMakeLists.txt @@ -4,29 +4,25 @@ ## FontDatabaseSupport Module: ##################################################################### -add_qt_module(FontDatabaseSupport +qt_add_module(FontDatabaseSupport STATIC INTERNAL_MODULE DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:fontdatabases.pro:<TRUE>: # MODULE = "fontdatabase_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(FontDatabaseSupport CONDITION APPLE +qt_extend_target(FontDatabaseSupport CONDITION APPLE SOURCES mac/qcoretextfontdatabase.mm mac/qcoretextfontdatabase_p.h mac/qfontengine_coretext.mm mac/qfontengine_coretext_p.h @@ -37,17 +33,17 @@ extend_target(FontDatabaseSupport CONDITION APPLE ${FWFoundation} ) -extend_target(FontDatabaseSupport CONDITION APPLE_OSX +qt_extend_target(FontDatabaseSupport CONDITION APPLE_OSX LIBRARIES ${FWAppKit} ) -extend_target(FontDatabaseSupport CONDITION APPLE AND NOT APPLE_OSX +qt_extend_target(FontDatabaseSupport CONDITION APPLE AND NOT APPLE_OSX LIBRARIES ${FWUIKit} ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype SOURCES freetype/qfontengine_ft.cpp freetype/qfontengine_ft_p.h freetype/qfreetypefontdatabase.cpp freetype/qfreetypefontdatabase_p.h @@ -55,12 +51,12 @@ extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype WrapFreetype::WrapFreetype ) -extend_target(FontDatabaseSupport CONDITION UNIX +qt_extend_target(FontDatabaseSupport CONDITION UNIX SOURCES genericunix/qgenericunixfontdatabase_p.h ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_fontconfig AND UNIX +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_fontconfig SOURCES fontconfig/qfontconfigdatabase.cpp fontconfig/qfontconfigdatabase_p.h fontconfig/qfontenginemultifontconfig.cpp fontconfig/qfontenginemultifontconfig_p.h @@ -68,64 +64,73 @@ extend_target(FontDatabaseSupport CONDITION QT_FEATURE_fontconfig AND UNIX Fontconfig::Fontconfig ) -extend_target(FontDatabaseSupport CONDITION WIN32 AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION WIN32 AND NOT WINRT SOURCES windows/qwindowsfontdatabase.cpp windows/qwindowsfontdatabase_p.h + windows/qwindowsfontdatabasebase.cpp windows/qwindowsfontdatabasebase_p.h windows/qwindowsfontengine.cpp windows/qwindowsfontengine_p.h windows/qwindowsnativeimage.cpp windows/qwindowsnativeimage_p.h LIBRARIES - Qt::GuiPrivate advapi32 gdi32 ole32 user32 PUBLIC_LIBRARIES - Qt::Gui + Qt::GuiPrivate ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype AND WIN32 AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype AND WIN32 AND NOT WINRT SOURCES windows/qwindowsfontdatabase_ft.cpp windows/qwindowsfontdatabase_ft_p.h ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT WINRT SOURCES windows/qwindowsfontenginedirectwrite.cpp windows/qwindowsfontenginedirectwrite_p.h LIBRARIES d2d1 ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND QT_FEATURE_directwrite2 AND WIN32 AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND QT_FEATURE_directwrite3 AND WIN32 AND NOT WINRT + SOURCES + windows/qwindowsdirectwritefontdatabase.cpp windows/qwindowsdirectwritefontdatabase_p.h + DEFINES + QT_USE_DIRECTWRITE2 + QT_USE_DIRECTWRITE3 + LIBRARIES + dwrite_3 +) + +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND QT_FEATURE_directwrite2 AND WIN32 AND NOT QT_FEATURE_directwrite3 AND NOT WINRT DEFINES QT_USE_DIRECTWRITE2 LIBRARIES dwrite_2 ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT QT_FEATURE_directwrite2 AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT QT_FEATURE_directwrite2 AND NOT QT_FEATURE_directwrite3 AND NOT WINRT LIBRARIES dwrite ) -extend_target(FontDatabaseSupport CONDITION WIN32 AND NOT WINRT AND (NOT QT_FEATURE_direct2d OR NOT QT_FEATURE_directwrite) +qt_extend_target(FontDatabaseSupport CONDITION WIN32 AND NOT WINRT AND (NOT QT_FEATURE_direct2d OR NOT QT_FEATURE_directwrite) DEFINES QT_NO_DIRECTWRITE ) -extend_target(FontDatabaseSupport CONDITION WIN32 AND mingw AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION WIN32 AND mingw AND NOT WINRT LIBRARIES uuid ) -extend_target(FontDatabaseSupport CONDITION WINRT +qt_extend_target(FontDatabaseSupport CONDITION WINRT SOURCES winrt/qwinrtfontdatabase.cpp winrt/qwinrtfontdatabase_p.h DEFINES __WRL_NO_DEFAULT_LIB__ LIBRARIES - Qt::GuiPrivate dwrite_1 ws2_32 PUBLIC_LIBRARIES - Qt::Gui + Qt::GuiPrivate ) diff --git a/src/platformsupport/fontdatabases/CMakeLists.txt b/src/platformsupport/fontdatabases/CMakeLists.txt index 38b0dfb40f..1150ac6bef 100644 --- a/src/platformsupport/fontdatabases/CMakeLists.txt +++ b/src/platformsupport/fontdatabases/CMakeLists.txt @@ -7,29 +7,25 @@ qt_find_package(Fontconfig) # special case ## FontDatabaseSupport Module: ##################################################################### -add_qt_module(FontDatabaseSupport +qt_add_module(FontDatabaseSupport STATIC INTERNAL_MODULE DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:fontdatabases.pro:<TRUE>: # MODULE = "fontdatabase_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(FontDatabaseSupport CONDITION APPLE +qt_extend_target(FontDatabaseSupport CONDITION APPLE SOURCES mac/qcoretextfontdatabase.mm mac/qcoretextfontdatabase_p.h mac/qfontengine_coretext.mm mac/qfontengine_coretext_p.h @@ -40,17 +36,17 @@ extend_target(FontDatabaseSupport CONDITION APPLE ${FWFoundation} ) -extend_target(FontDatabaseSupport CONDITION APPLE_OSX +qt_extend_target(FontDatabaseSupport CONDITION APPLE_OSX LIBRARIES ${FWAppKit} ) -extend_target(FontDatabaseSupport CONDITION APPLE AND NOT APPLE_OSX +qt_extend_target(FontDatabaseSupport CONDITION APPLE AND NOT APPLE_OSX LIBRARIES ${FWUIKit} ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype SOURCES freetype/qfontengine_ft.cpp freetype/qfontengine_ft_p.h freetype/qfreetypefontdatabase.cpp freetype/qfreetypefontdatabase_p.h @@ -58,12 +54,12 @@ extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype WrapFreetype::WrapFreetype ) -extend_target(FontDatabaseSupport CONDITION UNIX +qt_extend_target(FontDatabaseSupport CONDITION UNIX SOURCES genericunix/qgenericunixfontdatabase_p.h ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_fontconfig AND UNIX +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_fontconfig SOURCES fontconfig/qfontconfigdatabase.cpp fontconfig/qfontconfigdatabase_p.h fontconfig/qfontenginemultifontconfig.cpp fontconfig/qfontenginemultifontconfig_p.h @@ -71,64 +67,73 @@ extend_target(FontDatabaseSupport CONDITION QT_FEATURE_fontconfig AND UNIX Fontconfig::Fontconfig ) -extend_target(FontDatabaseSupport CONDITION WIN32 AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION WIN32 AND NOT WINRT SOURCES windows/qwindowsfontdatabase.cpp windows/qwindowsfontdatabase_p.h + windows/qwindowsfontdatabasebase.cpp windows/qwindowsfontdatabasebase_p.h windows/qwindowsfontengine.cpp windows/qwindowsfontengine_p.h windows/qwindowsnativeimage.cpp windows/qwindowsnativeimage_p.h LIBRARIES - Qt::GuiPrivate advapi32 gdi32 ole32 user32 PUBLIC_LIBRARIES - Qt::Gui + Qt::GuiPrivate ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype AND WIN32 AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype AND WIN32 AND NOT WINRT SOURCES windows/qwindowsfontdatabase_ft.cpp windows/qwindowsfontdatabase_ft_p.h ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT WINRT SOURCES windows/qwindowsfontenginedirectwrite.cpp windows/qwindowsfontenginedirectwrite_p.h LIBRARIES d2d1 ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND QT_FEATURE_directwrite2 AND WIN32 AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND QT_FEATURE_directwrite3 AND WIN32 AND NOT WINRT + SOURCES + windows/qwindowsdirectwritefontdatabase.cpp windows/qwindowsdirectwritefontdatabase_p.h + DEFINES + QT_USE_DIRECTWRITE2 + QT_USE_DIRECTWRITE3 + LIBRARIES + dwrite_3 +) + +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND QT_FEATURE_directwrite2 AND WIN32 AND NOT QT_FEATURE_directwrite3 AND NOT WINRT DEFINES QT_USE_DIRECTWRITE2 LIBRARIES dwrite_2 ) -extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT QT_FEATURE_directwrite2 AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT QT_FEATURE_directwrite2 AND NOT QT_FEATURE_directwrite3 AND NOT WINRT LIBRARIES dwrite ) -extend_target(FontDatabaseSupport CONDITION WIN32 AND NOT WINRT AND (NOT QT_FEATURE_direct2d OR NOT QT_FEATURE_directwrite) +qt_extend_target(FontDatabaseSupport CONDITION WIN32 AND NOT WINRT AND (NOT QT_FEATURE_direct2d OR NOT QT_FEATURE_directwrite) DEFINES QT_NO_DIRECTWRITE ) -extend_target(FontDatabaseSupport CONDITION WIN32 AND mingw AND NOT WINRT +qt_extend_target(FontDatabaseSupport CONDITION WIN32 AND mingw AND NOT WINRT LIBRARIES uuid ) -extend_target(FontDatabaseSupport CONDITION WINRT +qt_extend_target(FontDatabaseSupport CONDITION WINRT SOURCES winrt/qwinrtfontdatabase.cpp winrt/qwinrtfontdatabase_p.h DEFINES __WRL_NO_DEFAULT_LIB__ LIBRARIES - Qt::GuiPrivate dwrite_1 ws2_32 PUBLIC_LIBRARIES - Qt::Gui + Qt::GuiPrivate ) diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 7abf295782..af49ad6407 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -56,6 +56,8 @@ #include <QtGui/qguiapplication.h> +#include <QtCore/private/qduplicatetracker_p.h> + #include <fontconfig/fontconfig.h> #if FC_VERSION >= 20402 #include <fontconfig/fcfreetype.h> @@ -260,7 +262,18 @@ static const char specialLanguages[][6] = { "", // MasaramGondi "", // Nushu "", // Soyombo - "" // ZanabazarSquare + "", // ZanabazarSquare + "", // Dogra + "", // GunjalaGondi + "", // HanifiRohingya + "", // Makasar + "", // Medefaidrin + "", // OldSogdian + "", // Sogdian + "", // Elymaic + "", // Nandinagari + "", // NyiakengPuachueHmong + "" // Wancho }; Q_STATIC_ASSERT(sizeof specialLanguages / sizeof *specialLanguages == QChar::ScriptCount); @@ -349,7 +362,7 @@ Q_STATIC_ASSERT(sizeof(capabilityForWritingSystem) / sizeof(*capabilityForWritin static const char *getFcFamilyForStyleHint(const QFont::StyleHint style) { - const char *stylehint = 0; + const char *stylehint = nullptr; switch (style) { case QFont::SansSerif: stylehint = "sans-serif"; @@ -383,7 +396,7 @@ static void populateFromPattern(FcPattern *pattern) { QString familyName; QString familyNameLang; - FcChar8 *value = 0; + FcChar8 *value = nullptr; int weight_value; int slant_value; int spacing_value; @@ -406,7 +419,7 @@ static void populateFromPattern(FcPattern *pattern) slant_value = FC_SLANT_ROMAN; weight_value = FC_WEIGHT_REGULAR; spacing_value = FC_PROPORTIONAL; - file_value = 0; + file_value = nullptr; indexValue = 0; scalable = FcTrue; @@ -420,20 +433,20 @@ static void populateFromPattern(FcPattern *pattern) if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch) spacing_value = FC_PROPORTIONAL; if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch) - file_value = 0; + file_value = nullptr; if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch) indexValue = 0; if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch) scalable = FcTrue; if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) - foundry_value = 0; + foundry_value = nullptr; if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch) - style_value = 0; + style_value = nullptr; if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch) antialias = true; QSupportedWritingSystems writingSystems; - FcLangSet *langset = 0; + FcLangSet *langset = nullptr; FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset); if (res == FcResultMatch) { bool hasLang = false; @@ -450,7 +463,7 @@ static void populateFromPattern(FcPattern *pattern) if (*capabilityForWritingSystem[j] && requiresOpenType(j)) { if (cap == nullptr) capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap); - if (capRes == FcResultMatch && strstr(reinterpret_cast<const char *>(cap), capabilityForWritingSystem[j]) == 0) + if (capRes == FcResultMatch && strstr(reinterpret_cast<const char *>(cap), capabilityForWritingSystem[j]) == nullptr) continue; } #endif @@ -535,14 +548,14 @@ void QFontconfigDatabase::populateFontDatabase() #if FC_VERSION >= 20297 FC_CAPABILITY, #endif - (const char *)0 + (const char *)nullptr }; const char **p = properties; while (*p) { FcObjectSetAdd(os, *p); ++p; } - fonts = FcFontList(0, pattern, os); + fonts = FcFontList(nullptr, pattern, os); FcObjectSetDestroy(os); FcPatternDestroy(pattern); } @@ -561,7 +574,7 @@ void QFontconfigDatabase::populateFontDatabase() { "Serif", "serif", false }, { "Sans Serif", "sans-serif", false }, { "Monospace", "monospace", true }, - { 0, 0, false } + { nullptr, nullptr, false } }; const FcDefaultFont *f = defaults; // aliases only make sense for 'common', not for any of the specials @@ -570,9 +583,9 @@ void QFontconfigDatabase::populateFontDatabase() while (f->qtname) { QString familyQtName = QString::fromLatin1(f->qtname); - registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,0,f->fixed,ws,0); - registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,0,f->fixed,ws,0); - registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,0,f->fixed,ws,0); + registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleNormal,QFont::Unstretched,true,true,0,f->fixed,ws,nullptr); + registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleItalic,QFont::Unstretched,true,true,0,f->fixed,ws,nullptr); + registerFont(familyQtName,QString(),QString(),QFont::Normal,QFont::StyleOblique,QFont::Unstretched,true,true,0,f->fixed,ws,nullptr); ++f; } @@ -588,7 +601,7 @@ void QFontconfigDatabase::populateFontDatabase() void QFontconfigDatabase::invalidate() { // Clear app fonts. - FcConfigAppFontClear(0); + FcConfigAppFontClear(nullptr); } QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) @@ -680,7 +693,7 @@ QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bo QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) { if (!usrPtr) - return 0; + return nullptr; FontFile *fontfile = static_cast<FontFile *> (usrPtr); QFontEngine::FaceId fid; @@ -695,7 +708,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) if (!engine->init(fid, engine->antialias, engine->defaultFormat) || engine->invalid()) { delete engine; - engine = 0; + engine = nullptr; } return engine; @@ -704,8 +717,8 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) QFontEngine *QFontconfigDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { QFontEngineFT *engine = static_cast<QFontEngineFT*>(QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference)); - if (engine == 0) - return 0; + if (engine == nullptr) + return nullptr; setupFontEngine(engine, engine->fontDef); @@ -746,7 +759,7 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont // while a Japanese font should be used for that if LANG=ja) FcPattern *dummy = FcPatternCreate(); FcDefaultSubstitute(dummy); - FcChar8 *lang = 0; + FcChar8 *lang = nullptr; FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang); if (res == FcResultMatch) FcPatternAddString(pattern, FC_LANG, lang); @@ -759,27 +772,26 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); } - FcConfigSubstitute(0, pattern, FcMatchPattern); + FcConfigSubstitute(nullptr, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult result = FcResultMatch; - FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result); + FcFontSet *fontSet = FcFontSort(nullptr,pattern,FcFalse,nullptr,&result); FcPatternDestroy(pattern); if (fontSet) { - QSet<QString> duplicates; + QDuplicateTracker<QString> duplicates; duplicates.reserve(fontSet->nfont + 1); - duplicates.insert(family.toCaseFolded()); + (void)duplicates.hasSeen(family.toCaseFolded()); for (int i = 0; i < fontSet->nfont; i++) { - FcChar8 *value = 0; + FcChar8 *value = nullptr; if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) continue; // capitalize(value); const QString familyName = QString::fromUtf8((const char *)value); const QString familyNameCF = familyName.toCaseFolded(); - if (!duplicates.contains(familyNameCF)) { + if (!duplicates.hasSeen(familyNameCF)) { fallbackFamilies << familyName; - duplicates.insert(familyNameCF); } } FcFontSetDestroy(fontSet); @@ -800,7 +812,7 @@ static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FT_Library lib = qt_getFreetype(); - FcPattern *pattern = 0; + FcPattern *pattern = nullptr; FT_Face face; if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, &face)) { @@ -819,16 +831,16 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, { QStringList families; - FcFontSet *set = FcConfigGetFonts(0, FcSetApplication); + FcFontSet *set = FcConfigGetFonts(nullptr, FcSetApplication); if (!set) { - FcConfigAppFontAddFile(0, (const FcChar8 *)":/non-existent"); - set = FcConfigGetFonts(0, FcSetApplication); // try again + FcConfigAppFontAddFile(nullptr, (const FcChar8 *)":/non-existent"); + set = FcConfigGetFonts(nullptr, FcSetApplication); // try again if (!set) return families; } int id = 0; - FcBlanks *blanks = FcConfigGetBlanks(0); + FcBlanks *blanks = FcConfigGetBlanks(nullptr); int count = 0; FcPattern *pattern; @@ -838,7 +850,7 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, if (!pattern) return families; - FcChar8 *fam = 0; + FcChar8 *fam = nullptr; if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) { QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam)); families << family; @@ -866,10 +878,10 @@ QString QFontconfigDatabase::resolveFontFamilyAlias(const QString &family) const const QByteArray cs = family.toUtf8(); FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) cs.constData()); } - FcConfigSubstitute(0, pattern, FcMatchPattern); + FcConfigSubstitute(nullptr, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); - FcChar8 *familyAfterSubstitution = 0; + FcChar8 *familyAfterSubstitution = nullptr; FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution); resolved = QString::fromUtf8((const char *) familyAfterSubstitution); FcPatternDestroy(pattern); @@ -884,7 +896,7 @@ QFont QFontconfigDatabase::defaultFont() const // or https://bugs.freedesktop.org/show_bug.cgi?id=35482 is fixed FcPattern *dummy = FcPatternCreate(); FcDefaultSubstitute(dummy); - FcChar8 *lang = 0; + FcChar8 *lang = nullptr; FcResult res = FcPatternGetString(dummy, FC_LANG, 0, &lang); FcPattern *pattern = FcPatternCreate(); @@ -893,10 +905,10 @@ QFont QFontconfigDatabase::defaultFont() const // certain FC_LANG based custom rules may happen in FcConfigSubstitute() FcPatternAddString(pattern, FC_LANG, lang); } - FcConfigSubstitute(0, pattern, FcMatchPattern); + FcConfigSubstitute(nullptr, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); - FcChar8 *familyAfterSubstitution = 0; + FcChar8 *familyAfterSubstitution = nullptr; FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution); QString resolved = QString::fromUtf8((const char *) familyAfterSubstitution); FcPatternDestroy(pattern); @@ -953,10 +965,10 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef FcResult result; - FcConfigSubstitute(0, pattern, FcMatchPattern); + FcConfigSubstitute(nullptr, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); - FcPattern *match = FcFontMatch(0, pattern, &result); + FcPattern *match = FcFontMatch(nullptr, pattern, &result); if (match) { engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf)); diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp index 2fbcb6216e..cbf0793d75 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp @@ -60,7 +60,7 @@ bool QFontEngineMultiFontConfig::shouldLoadFontEngineForCharacter(int at, uint u { bool charSetHasChar = true; FcPattern *matchPattern = getMatchPatternForFallback(at - 1); - if (matchPattern != 0) { + if (matchPattern != nullptr) { FcCharSet *charSet; FcPatternGetCharSet(matchPattern, FC_CHARSET, 0, &charSet); charSetHasChar = FcCharSetHasChar(charSet, ucs4); @@ -85,7 +85,7 @@ FcPattern * QFontEngineMultiFontConfig::getMatchPatternForFallback(int fallBackI value.u.s = reinterpret_cast<const FcChar8 *>(cs.data()); FcPatternAdd(requestPattern, FC_FAMILY, value, true); FcResult result; - ret = FcFontMatch(0, requestPattern, &result); + ret = FcFontMatch(nullptr, requestPattern, &result); cachedMatchPatterns.insert(fallBackIndex, ret); FcPatternDestroy(requestPattern); return ret; diff --git a/src/platformsupport/fontdatabases/fontdatabases.pro b/src/platformsupport/fontdatabases/fontdatabases.pro index f2bac9ab94..c3985ed398 100644 --- a/src/platformsupport/fontdatabases/fontdatabases.pro +++ b/src/platformsupport/fontdatabases/fontdatabases.pro @@ -17,9 +17,10 @@ qtConfig(freetype) { unix { include($$PWD/genericunix/genericunix.pri) - qtConfig(fontconfig) { - include($$PWD/fontconfig/fontconfig.pri) - } +} + +qtConfig(fontconfig) { + include($$PWD/fontconfig/fontconfig.pri) } win32:!winrt { diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp index 8c6cc8fbc1..ca78063f08 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp @@ -121,7 +121,7 @@ class QtFreetypeData { public: QtFreetypeData() - : library(0) + : library(nullptr) { } ~QtFreetypeData(); @@ -135,7 +135,7 @@ QtFreetypeData::~QtFreetypeData() iter.value()->cleanup(); faces.clear(); FT_Done_FreeType(library); - library = 0; + library = nullptr; } Q_GLOBAL_STATIC(QThreadStorage<QtFreetypeData *>, theFreetypeData) @@ -215,7 +215,7 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, const QByteArray &fontData) { if (face_id.filename.isEmpty() && fontData.isEmpty()) - return 0; + return nullptr; QtFreetypeData *freetypeData = qt_getFreetypeData(); @@ -238,7 +238,7 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, } else if (!QFileInfo(fileName).isNativePath()) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) { - return 0; + return nullptr; } newFreetype->fontData = file.readAll(); } @@ -247,10 +247,10 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, } 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; + return nullptr; } } else if (FT_New_Face(freetypeData->library, face_id.filename, face_id.index, &face)) { - return 0; + return nullptr; } newFreetype->face = face; @@ -261,8 +261,8 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, newFreetype->matrix.yy = 0x10000; newFreetype->matrix.xy = 0; newFreetype->matrix.yx = 0; - newFreetype->unicode_map = 0; - newFreetype->symbol_map = 0; + newFreetype->unicode_map = nullptr; + newFreetype->symbol_map = nullptr; memset(newFreetype->cmapCache, 0, sizeof(newFreetype->cmapCache)); @@ -307,7 +307,7 @@ void QFreetypeFace::cleanup() { hbFace.reset(); FT_Done_Face(face); - face = 0; + face = nullptr; } void QFreetypeFace::release(const QFontEngine::FaceId &face_id) @@ -324,7 +324,7 @@ void QFreetypeFace::release(const QFontEngine::FaceId &face_id) if (freetypeData->faces.isEmpty()) { FT_Done_FreeType(freetypeData->library); - freetypeData->library = 0; + freetypeData->library = nullptr; } } @@ -659,7 +659,7 @@ QFontEngineFT *QFontEngineFT::create(const QByteArray &fontData, qreal pixelSize QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef); if (!fe->initFromData(fontData)) { delete fe; - return 0; + return nullptr; } fe->updateFamilyNameAndStyle(); @@ -682,7 +682,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd) embolden = false; obliquen = false; antialias = true; - freetype = 0; + freetype = nullptr; default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; default_hint_style = ftInitialDefaultHintStyle; subpixelType = Subpixel_None; @@ -729,7 +729,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, face_id = faceId; - symbol = freetype->symbol_map != 0; + symbol = freetype->symbol_map != nullptr; 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) { @@ -744,12 +744,12 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, 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); + FT_Set_Transform(face, &matrix, nullptr); 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<const TT_OS2 *>(FT_Get_Sfnt_Table(face, ft_sfnt_os2))) { - if (os2->usWeightClass < 750) + if (os2->usWeightClass < 700) embolden = true; } } @@ -953,7 +953,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, format = defaultFormat != Format_None ? defaultFormat : Format_Mono; Q_ASSERT(format != Format_None); - Glyph *g = set ? set->getGlyph(glyph, subPixelPosition) : 0; + Glyph *g = set ? set->getGlyph(glyph, subPixelPosition) : nullptr; if (g && g->format == format && (fetchMetricsOnly || g->data)) return g; @@ -1051,10 +1051,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, // If any of the metrics are too large to fit, don't cache them if (areMetricsTooLarge(info)) - return 0; + return nullptr; g = new Glyph; - g->data = 0; + g->data = nullptr; g->linearAdvance = info.linearAdvance; g->width = info.width; g->height = info.height; @@ -1176,12 +1176,12 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB); } else { qWarning("QFontEngine: Glyph rendered in unknown pixel_mode=%d", slot->bitmap.pixel_mode); - return 0; + return nullptr; } if (!g) { g = new Glyph; - g->data = 0; + g->data = nullptr; } g->linearAdvance = info.linearAdvance; @@ -1354,54 +1354,69 @@ static inline FT_Matrix QTransformToFTMatrix(const QTransform &matrix) return m; } -QFontEngineFT::QGlyphSet *QFontEngineFT::loadGlyphSet(const QTransform &matrix) +QFontEngineFT::QGlyphSet *QFontEngineFT::TransformedGlyphSets::findSet(const QTransform &matrix, const QFontDef &fontDef) { - 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 : 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) { + int i = 0; + for (; i < nSets; ++i) { + QGlyphSet *g = sets[i]; + if (!g) + break; + 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; + moveToFront(i); + return g; } } - 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.determinant()) > QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE; - } - Q_ASSERT(gs != 0); + // don't cache more than nSets transformations + if (i == nSets) + // reuse the last set + --i; + moveToFront(nSets - 1); + if (!sets[0]) + sets[0] = new QGlyphSet; + QGlyphSet *gs = sets[0]; + gs->clear(); + gs->transformationMatrix = m; + gs->outline_drawing = fontDef.pixelSize * fontDef.pixelSize * qAbs(matrix.determinant()) > QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE; + Q_ASSERT(gs != nullptr); return gs; } +void QFontEngineFT::TransformedGlyphSets::moveToFront(int i) +{ + QGlyphSet *g = sets[i]; + while (i > 0) { + sets[i] = sets[i - 1]; + --i; + } + sets[0] = g; +} + + +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 : nullptr; + + return transformedGlyphSets.findSet(matrix, fontDef); +} + void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) { FT_Face face = lockFace(Unscaled); - FT_Set_Transform(face, 0, 0); + FT_Set_Transform(face, nullptr, nullptr); FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP); int left = face->glyph->metrics.horiBearingX; @@ -1424,7 +1439,7 @@ void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_me 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); + FT_Set_Transform(face, &freetype->matrix, nullptr); unlockFace(); } @@ -1622,10 +1637,10 @@ glyph_metrics_t QFontEngineFT::scaledBitmapMetrics(const glyph_metrics_t &m, con void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const { - FT_Face face = 0; + FT_Face face = nullptr; bool design = shouldUseDesignMetrics(flags); for (int i = 0; i < glyphs->numGlyphs; i++) { - Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyphs->glyphs[i]) : 0; + Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyphs->glyphs[i]) : nullptr; // 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) { @@ -1633,7 +1648,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag } else { if (!face) face = lockFace(); - g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs->glyphs[i], 0, Format_None, true); + g = loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr, glyphs->glyphs[i], 0, Format_None, true); if (g) glyphs->advances[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance); else @@ -1657,7 +1672,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) { - FT_Face face = 0; + FT_Face face = nullptr; glyph_metrics_t overall; // initialize with line height, we get the same behaviour on all platforms @@ -1672,11 +1687,11 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) QFixed ymax = 0; QFixed xmax = 0; for (int i = 0; i < glyphs.numGlyphs; i++) { - Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyphs.glyphs[i]) : 0; + Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyphs.glyphs[i]) : nullptr; if (!g) { if (!face) face = lockFace(); - g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs.glyphs[i], 0, Format_None, true); + g = loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr, glyphs.glyphs[i], 0, Format_None, true); } if (g) { QFixed x = overall.xoff + glyphs.offsets[i].x + g->x; @@ -1716,12 +1731,12 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) { - FT_Face face = 0; + FT_Face face = nullptr; glyph_metrics_t overall; - Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyph) : 0; + Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyph) : nullptr; if (!g) { face = lockFace(); - g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, 0, Format_None, true); + g = loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr, glyph, 0, Format_None, true); } if (g) { overall.x = g->x; @@ -1854,10 +1869,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, bool disableOutlineDrawing) { QGlyphSet *glyphSet = loadGlyphSet(t); - if (glyphSet != 0 && glyphSet->outline_drawing && !disableOutlineDrawing && !fetchBoundingBox) - return 0; + if (glyphSet != nullptr && glyphSet->outline_drawing && !disableOutlineDrawing && !fetchBoundingBox) + return nullptr; - Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0; + Glyph *glyph = glyphSet != nullptr ? glyphSet->getGlyph(g, subPixelPosition) : nullptr; if (!glyph || glyph->format != format || (!fetchBoundingBox && !glyph->data)) { QScopedValueRollback<HintStyle> saved_default_hint_style(default_hint_style); if (t.type() >= QTransform::TxScale && !is2dRotation(t)) @@ -1865,7 +1880,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, lockFace(); FT_Matrix m = this->matrix; - FT_Matrix ftMatrix = glyphSet != 0 ? glyphSet->transformationMatrix : QTransformToFTMatrix(t); + FT_Matrix ftMatrix = glyphSet != nullptr ? glyphSet->transformationMatrix : QTransformToFTMatrix(t); FT_Matrix_Multiply(&ftMatrix, &m); freetype->matrix = m; glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false, disableOutlineDrawing); @@ -1978,7 +1993,7 @@ FT_Face QFontEngineFT::lockFace(Scaling scale) const freetype->matrix.xy != matrix.xy || freetype->matrix.yx != matrix.yx) { freetype->matrix = matrix; - FT_Set_Transform(face, &freetype->matrix, 0); + FT_Set_Transform(face, &freetype->matrix, nullptr); } return face; @@ -2017,7 +2032,7 @@ void QFontEngineFT::QGlyphSet::clear() for (int i = 0; i < 256; ++i) { if (fast_glyph_data[i]) { delete fast_glyph_data[i]; - fast_glyph_data[i] = 0; + fast_glyph_data[i] = nullptr; } } fast_glyph_count = 0; @@ -2031,7 +2046,7 @@ void QFontEngineFT::QGlyphSet::removeGlyphFromCache(glyph_t index, QFixed subPix if (useFastGlyphData(index, subPixelPosition)) { if (fast_glyph_data[index]) { delete fast_glyph_data[index]; - fast_glyph_data[index] = 0; + fast_glyph_data[index] = nullptr; if (fast_glyph_count > 0) --fast_glyph_count; } @@ -2056,7 +2071,7 @@ int QFontEngineFT::getPointInOutline(glyph_t glyph, int flags, quint32 point, QF lockFace(); bool hsubpixel = true; int vfactor = 1; - int load_flags = loadFlags(0, Format_A8, flags, hsubpixel, vfactor); + int load_flags = loadFlags(nullptr, Format_A8, flags, hsubpixel, vfactor); int result = freetype->getPointInOutline(glyph, load_flags, point, xpos, ypos, nPoints); unlockFace(); return result; @@ -2091,7 +2106,7 @@ QFontEngine *QFontEngineFT::cloneWithSize(qreal pixelSize) const QFontEngineFT *fe = new QFontEngineFT(fontDef); if (!fe->initFromFontEngine(this)) { delete fe; - return 0; + return nullptr; } else { return fe; } diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h index 2e3aef6979..8019588bf5 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h @@ -63,6 +63,8 @@ #include <qmutex.h> +#include <string.h> + QT_BEGIN_NAMESPACE class QFontEngineFTRawFont; @@ -170,6 +172,7 @@ public: inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); } inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); } private: + Q_DISABLE_COPY(QGlyphSet); mutable QHash<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data mutable QSet<glyph_t> missing_glyphs; mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256 @@ -310,7 +313,18 @@ private: GlyphFormat defaultFormat; FT_Matrix matrix; - QList<QGlyphSet> transformedGlyphSets; + struct TransformedGlyphSets { + enum { nSets = 10 }; + QGlyphSet *sets[nSets]; + + QGlyphSet *findSet(const QTransform &matrix, const QFontDef &fontDef); + TransformedGlyphSets() { std::fill(&sets[0], &sets[nSets], nullptr); } + ~TransformedGlyphSets() { qDeleteAll(&sets[0], &sets[nSets]); } + private: + void moveToFront(int i); + Q_DISABLE_COPY(TransformedGlyphSets); + }; + TransformedGlyphSets transformedGlyphSets; mutable QGlyphSet defaultGlyphSet; QFontEngine::FaceId face_id; @@ -326,6 +340,9 @@ private: QFixed scalableBitmapScaleFactor; }; +Q_DECLARE_TYPEINFO(QFontEngineFT::QGlyphSet, Q_MOVABLE_TYPE); + + inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g) { return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt(); diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index daa3dc94ea..894919a1c8 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -374,17 +374,6 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>::fontEngine QCFType<CTFontDescriptorRef> descriptor = QCFType<CTFontDescriptorRef>::constructFromGet( static_cast<CTFontDescriptorRef>(usrPtr)); - // CoreText will sometimes invalidate information in font descriptors that refer - // to system fonts in certain function calls or application states. While the descriptor - // looks the same from the outside, some internal plumbing is different, causing the results - // of creating CTFonts from those descriptors unreliable. The work-around for this - // is to copy the attributes of those descriptors each time we make a new CTFont - // from them instead of referring to the original, as that may trigger the CoreText bug. - if (m_systemFontDescriptors.contains(descriptor)) { - QCFType<CFDictionaryRef> attributes = CTFontDescriptorCopyAttributes(descriptor); - descriptor = CTFontDescriptorCreateWithAttributes(attributes); - } - // 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 diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 072dd1a28a..30c80ebd86 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -471,7 +471,7 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt const qreal firstY = positions[0].y.toReal(); for (int i = 0; i < glyphs.size(); ++i) { cgPositions[i].x = positions[i].x.toReal() - firstX; - cgPositions[i].y = positions[i].y.toReal() - firstY; + cgPositions[i].y = firstY - positions[i].y.toReal(); cgGlyphs[i] = glyphs[i]; } diff --git a/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase.cpp new file mode 100644 index 0000000000..5a1ff935b8 --- /dev/null +++ b/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase.cpp @@ -0,0 +1,465 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 "qwindowsdirectwritefontdatabase_p.h" +#include "qwindowsfontenginedirectwrite_p.h" + +#include <QtCore/qstringbuilder.h> +#include <QtCore/qvarlengtharray.h> + +#include <dwrite_3.h> +#include <d2d1.h> + +QT_BEGIN_NAMESPACE + +#ifdef QT_USE_DIRECTWRITE3 + +QWindowsDirectWriteFontDatabase::QWindowsDirectWriteFontDatabase() +{ + qCDebug(lcQpaFonts) << "Creating DirectWrite database"; +} + +QWindowsDirectWriteFontDatabase::~QWindowsDirectWriteFontDatabase() +{ + for (auto it = m_populatedFonts.begin(); it != m_populatedFonts.end(); ++it) + it.value()->Release(); +} + +QString QWindowsDirectWriteFontDatabase::localeString(IDWriteLocalizedStrings *names, + wchar_t localeName[]) +{ + uint index; + BOOL exists; + if (SUCCEEDED(names->FindLocaleName(localeName, &index, &exists)) && exists) { + uint length; + if (SUCCEEDED(names->GetStringLength(index, &length)) && length > 0) { + QVarLengthArray<wchar_t> buffer(int(length) + 1); + if (SUCCEEDED(names->GetString(index, buffer.data(), length + 1))) + return QString::fromWCharArray(buffer.data()); + } + } + + return QString(); +} + +static QFont::Stretch fromDirectWriteStretch(DWRITE_FONT_STRETCH stretch) +{ + switch (stretch) { + case DWRITE_FONT_STRETCH_ULTRA_CONDENSED: return QFont::UltraCondensed; + case DWRITE_FONT_STRETCH_EXTRA_CONDENSED: return QFont::ExtraCondensed; + case DWRITE_FONT_STRETCH_CONDENSED: return QFont::Condensed; + case DWRITE_FONT_STRETCH_SEMI_CONDENSED: return QFont::SemiCondensed; + case DWRITE_FONT_STRETCH_NORMAL: return QFont::Unstretched; + case DWRITE_FONT_STRETCH_SEMI_EXPANDED: return QFont::SemiExpanded; + case DWRITE_FONT_STRETCH_EXPANDED: return QFont::Expanded; + case DWRITE_FONT_STRETCH_EXTRA_EXPANDED: return QFont::ExtraExpanded; + case DWRITE_FONT_STRETCH_ULTRA_EXPANDED: return QFont::UltraExpanded; + default: return QFont::AnyStretch; + } +} + +static QFont::Weight fromDirectWriteWeight(DWRITE_FONT_WEIGHT weight) +{ + return QPlatformFontDatabase::weightFromInteger(int(weight)); +} + +static DWRITE_FONT_STYLE toDirectWriteStyle(QFont::Style style) +{ + switch (style) { + case QFont::StyleNormal: return DWRITE_FONT_STYLE_NORMAL; + case QFont::StyleOblique: return DWRITE_FONT_STYLE_OBLIQUE; + case QFont::StyleItalic: return DWRITE_FONT_STYLE_ITALIC; + default: return DWRITE_FONT_STYLE_NORMAL; + } +} + +static QFont::Style fromDirectWriteStyle(DWRITE_FONT_STYLE style) +{ + switch (style) { + case DWRITE_FONT_STYLE_NORMAL: return QFont::StyleNormal; + case DWRITE_FONT_STYLE_OBLIQUE: return QFont::StyleOblique; + case DWRITE_FONT_STYLE_ITALIC: return QFont::StyleItalic; + default: return QFont::StyleNormal; + } +} + +void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName) +{ + auto it = m_populatedFonts.find(familyName); + IDWriteFontFamily *fontFamily = it != m_populatedFonts.end() ? it.value() : nullptr; + if (fontFamily == nullptr) { + qCWarning(lcQpaFonts) << "Cannot find" << familyName << "in list of fonts"; + return; + } + + qCDebug(lcQpaFonts) << "Populate family:" << familyName; + + wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH]; + bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0; + wchar_t englishLocale[] = L"en-us"; + + static const int SMOOTH_SCALABLE = 0xffff; + const QString foundryName; // No such concept. + const bool scalable = true; + const bool antialias = false; + const int size = SMOOTH_SCALABLE; + + IDWriteFontList *matchingFonts; + if (SUCCEEDED(fontFamily->GetMatchingFonts(DWRITE_FONT_WEIGHT_REGULAR, + DWRITE_FONT_STRETCH_NORMAL, + DWRITE_FONT_STYLE_NORMAL, + &matchingFonts))) { + for (uint j = 0; j < matchingFonts->GetFontCount(); ++j) { + IDWriteFont *font; + if (SUCCEEDED(matchingFonts->GetFont(j, &font))) { + IDWriteFont1 *font1 = nullptr; + if (!SUCCEEDED(font->QueryInterface(__uuidof(IDWriteFont1), + reinterpret_cast<void **>(&font1)))) { + qCWarning(lcQpaFonts) << "COM object does not support IDWriteFont1"; + continue; + } + + QString defaultLocaleFamilyName; + QString englishLocaleFamilyName; + + IDWriteFontFamily *fontFamily2; + if (SUCCEEDED(font1->GetFontFamily(&fontFamily2))) { + IDWriteLocalizedStrings *names; + if (SUCCEEDED(fontFamily2->GetFamilyNames(&names))) { + defaultLocaleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); + englishLocaleFamilyName = localeString(names, englishLocale); + + names->Release(); + } + + fontFamily2->Release(); + } + + if (defaultLocaleFamilyName.isEmpty() && englishLocaleFamilyName.isEmpty()) + englishLocaleFamilyName = familyName; + + QVarLengthArray<DWRITE_UNICODE_RANGE, 64> ranges(QFontDatabase::WritingSystemsCount); + + uint count = 0; + if (SUCCEEDED(font1->GetUnicodeRanges(QFontDatabase::WritingSystemsCount, ranges.data(), &count))) { + // ### + } + QSupportedWritingSystems writingSystems; + writingSystems.setSupported(QFontDatabase::Any); + writingSystems.setSupported(QFontDatabase::Latin); + + { + IDWriteLocalizedStrings *names; + if (SUCCEEDED(font1->GetFaceNames(&names))) { + QString defaultLocaleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); + QString englishLocaleStyleName = localeString(names, englishLocale); + + QFont::Stretch stretch = fromDirectWriteStretch(font1->GetStretch()); + QFont::Style style = fromDirectWriteStyle(font1->GetStyle()); + QFont::Weight weight = fromDirectWriteWeight(font1->GetWeight()); + bool fixed = font1->IsMonospacedFont(); + + qCDebug(lcQpaFonts) << "Family" << familyName << "has english variant" << englishLocaleStyleName << ", in default locale:" << defaultLocaleStyleName << stretch << style << weight << fixed; + + IDWriteFontFace *face = nullptr; + if (SUCCEEDED(font->CreateFontFace(&face))) { + if (!englishLocaleStyleName.isEmpty() || defaultLocaleStyleName.isEmpty()) { + QPlatformFontDatabase::registerFont(englishLocaleFamilyName, englishLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face); + face->AddRef(); + } + + if (!defaultLocaleFamilyName.isEmpty() && defaultLocaleFamilyName != englishLocaleFamilyName) { + QPlatformFontDatabase::registerFont(defaultLocaleFamilyName, defaultLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face); + face->AddRef(); + } + + face->Release(); + } + + names->Release(); + } + } + + font1->Release(); + font->Release(); + } + } + + matchingFonts->Release(); + } +} + +QFontEngine *QWindowsDirectWriteFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) +{ + IDWriteFontFace *face = reinterpret_cast<IDWriteFontFace *>(handle); + Q_ASSERT(face != nullptr); + + QWindowsFontEngineDirectWrite *fontEngine = new QWindowsFontEngineDirectWrite(face, fontDef.pixelSize, data()); + fontEngine->initFontInfo(fontDef, defaultVerticalDPI()); + + return fontEngine; +} + +QStringList QWindowsDirectWriteFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const +{ + Q_UNUSED(styleHint); + Q_UNUSED(script); + + wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH]; + bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0; + wchar_t englishLocale[] = L"en-us"; + + QStringList ret; + + auto it = m_populatedFonts.find(family); + IDWriteFontFamily *fontFamily = it != m_populatedFonts.end() ? it.value() : nullptr; + if (fontFamily != nullptr) { + IDWriteFontList *matchingFonts = nullptr; + if (SUCCEEDED(fontFamily->GetMatchingFonts(DWRITE_FONT_WEIGHT_REGULAR, + DWRITE_FONT_STRETCH_NORMAL, + toDirectWriteStyle(style), + &matchingFonts))) { + for (uint j = 0; j < matchingFonts->GetFontCount(); ++j) { + IDWriteFont *font = nullptr; + if (SUCCEEDED(matchingFonts->GetFont(j, &font))) { + IDWriteFontFamily *fontFamily2; + if (SUCCEEDED(font->GetFontFamily(&fontFamily2))) { + IDWriteLocalizedStrings *names; + if (SUCCEEDED(fontFamily2->GetFamilyNames(&names))) { + QString name = localeString(names, englishLocale); + if (name.isEmpty() && hasDefaultLocale) + name = localeString(names, defaultLocale); + + if (!name.isEmpty() && m_populatedFonts.contains(name)) + ret.append(name); + + names->Release(); + } + + fontFamily2->Release(); + } + + font->Release(); + } + } + + matchingFonts->Release(); + } + } + + qDebug(lcQpaFonts) << "fallbacks for" << family << "is" << ret; + + return ret; +} + +QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) +{ + qCDebug(lcQpaFonts) << "Adding application font" << fileName; + + QByteArray loadedData = fontData; + if (loadedData.isEmpty()) { + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) { + qCWarning(lcQpaFonts) << "Cannot open" << fileName << "for reading."; + return QStringList(); + } + loadedData = file.readAll(); + } + + IDWriteFontFace *face = createDirectWriteFace(loadedData); + if (face == nullptr) { + qCWarning(lcQpaFonts) << "Failed to create DirectWrite face from font data. Font may be unsupported."; + return QStringList(); + } + + wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH]; + bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0; + wchar_t englishLocale[] = L"en-us"; + + static const int SMOOTH_SCALABLE = 0xffff; + const QString foundryName; // No such concept. + const bool scalable = true; + const bool antialias = false; + const int size = SMOOTH_SCALABLE; + + QSupportedWritingSystems writingSystems; + writingSystems.setSupported(QFontDatabase::Any); + writingSystems.setSupported(QFontDatabase::Latin); + + QStringList ret; + IDWriteFontFace3 *face3 = nullptr; + if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace3), + reinterpret_cast<void **>(&face3)))) { + QString defaultLocaleFamilyName; + QString englishLocaleFamilyName; + + IDWriteLocalizedStrings *names; + if (SUCCEEDED(face3->GetFamilyNames(&names))) { + defaultLocaleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); + englishLocaleFamilyName = localeString(names, englishLocale); + + names->Release(); + } + + QString defaultLocaleStyleName; + QString englishLocaleStyleName; + if (SUCCEEDED(face3->GetFaceNames(&names))) { + defaultLocaleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); + englishLocaleStyleName = localeString(names, englishLocale); + + names->Release(); + } + + QFont::Stretch stretch = fromDirectWriteStretch(face3->GetStretch()); + QFont::Style style = fromDirectWriteStyle(face3->GetStyle()); + QFont::Weight weight = fromDirectWriteWeight(face3->GetWeight()); + bool fixed = face3->IsMonospacedFont(); + + qCDebug(lcQpaFonts) << "\tFont names:" << englishLocaleFamilyName << ", " << defaultLocaleFamilyName + << ", style names:" << englishLocaleStyleName << ", " << defaultLocaleStyleName + << ", stretch:" << stretch + << ", style:" << style + << ", weight:" << weight + << ", fixed:" << fixed; + + if (!englishLocaleFamilyName.isEmpty()) { + ret.append(englishLocaleFamilyName); + QPlatformFontDatabase::registerFont(englishLocaleFamilyName, englishLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face); + face->AddRef(); + } + + if (!defaultLocaleFamilyName.isEmpty() && defaultLocaleFamilyName != englishLocaleFamilyName) { + ret.append(defaultLocaleFamilyName); + QPlatformFontDatabase::registerFont(defaultLocaleFamilyName, defaultLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face); + face->AddRef(); + } + + face3->Release(); + } else { + qCWarning(lcQpaFonts) << "Unable to query IDWriteFontFace3 interface from font face."; + } + + face->Release(); + + return ret; +} + +void QWindowsDirectWriteFontDatabase::releaseHandle(void *handle) +{ + IDWriteFontFace *face = reinterpret_cast<IDWriteFontFace *>(handle); + face->Release(); +} + +bool QWindowsDirectWriteFontDatabase::fontsAlwaysScalable() const +{ + return true; +} + +bool QWindowsDirectWriteFontDatabase::isPrivateFontFamily(const QString &family) const +{ + Q_UNUSED(family); + return false; +} + +void QWindowsDirectWriteFontDatabase::populateFontDatabase() +{ + wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH]; + bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0; + wchar_t englishLocale[] = L"en-us"; + + QString defaultFontName = defaultFont().family(); + QString systemDefaultFontName = systemDefaultFont().family(); + + IDWriteFontCollection *fontCollection; + if (SUCCEEDED(data()->directWriteFactory->GetSystemFontCollection(&fontCollection))) { + for (uint i = 0; i < fontCollection->GetFontFamilyCount(); ++i) { + IDWriteFontFamily *fontFamily; + if (SUCCEEDED(fontCollection->GetFontFamily(i, &fontFamily))) { + QString defaultLocaleName; + QString englishLocaleName; + + IDWriteLocalizedStrings *names; + if (SUCCEEDED(fontFamily->GetFamilyNames(&names))) { + if (hasDefaultLocale) + defaultLocaleName = localeString(names, defaultLocale); + + englishLocaleName = localeString(names, englishLocale); + } + + qCDebug(lcQpaFonts) << "Registering font, english name = " << englishLocaleName << ", name in current locale = " << defaultLocaleName; + if (!defaultLocaleName.isEmpty()) { + registerFontFamily(defaultLocaleName); + m_populatedFonts.insert(defaultLocaleName, fontFamily); + fontFamily->AddRef(); + + if (defaultLocaleName == defaultFontName && defaultFontName != systemDefaultFontName) { + qDebug(lcQpaFonts) << "Adding default font" << systemDefaultFontName << "as alternative to" << defaultLocaleName; + + m_populatedFonts.insert(systemDefaultFontName, fontFamily); + fontFamily->AddRef(); + } + } + + if (!englishLocaleName.isEmpty() && englishLocaleName != defaultLocaleName) { + registerFontFamily(englishLocaleName); + m_populatedFonts.insert(englishLocaleName, fontFamily); + fontFamily->AddRef(); + + if (englishLocaleName == defaultFontName && defaultFontName != systemDefaultFontName) { + qDebug(lcQpaFonts) << "Adding default font" << systemDefaultFontName << "as alternative to" << englishLocaleName; + + m_populatedFonts.insert(systemDefaultFontName, fontFamily); + fontFamily->AddRef(); + } + } + + fontFamily->Release(); + } + } + } +} + +QFont QWindowsDirectWriteFontDatabase::defaultFont() const +{ + return QFont(QStringLiteral("Segoe UI")); +} + +#endif // QT_USE_DIRECTWRITE3 + +QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase_p.h new file mode 100644 index 0000000000..2110043df6 --- /dev/null +++ b/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 QWINDOWSDIRECTWRITEFONTDATABASE_P_H +#define QWINDOWSDIRECTWRITEFONTDATABASE_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 "qwindowsfontdatabasebase_p.h" + +#include <qpa/qplatformfontdatabase.h> +#include <QtCore/qloggingcategory.h> + +struct IDWriteFactory; +struct IDWriteFont; +struct IDWriteFontFamily; +struct IDWriteLocalizedStrings; + +QT_BEGIN_NAMESPACE + +#ifdef QT_USE_DIRECTWRITE3 + +class QWindowsDirectWriteFontDatabase : public QWindowsFontDatabaseBase +{ + Q_DISABLE_COPY_MOVE(QWindowsDirectWriteFontDatabase) +public: + QWindowsDirectWriteFontDatabase(); + ~QWindowsDirectWriteFontDatabase() override; + + void populateFontDatabase() override; + void populateFamily(const QString &familyName) override; + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override; + QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override; + QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) override; + void releaseHandle(void *handle) override; + QFont defaultFont() const override; + + bool fontsAlwaysScalable() const override; + bool isPrivateFontFamily(const QString &family) const override; + +private: + static QString localeString(IDWriteLocalizedStrings *names, wchar_t localeName[]); + + QHash<QString, IDWriteFontFamily *> m_populatedFonts; +}; + +#endif // QT_USE_DIRECTWRITE3 + +QT_END_NAMESPACE + +#endif // QWINDOWSDIRECTWRITEFONTDATABASE_P_H diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp index 011476cf13..cf5763fdbe 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp @@ -51,7 +51,6 @@ #include <QtCore/QDebug> #include <QtCore/QFile> #include <QtCore/QtEndian> -#include <QtCore/QThreadStorage> #include <QtCore/private/qsystemlibrary_p.h> #include <QtCore/private/qwinregistry_p.h> @@ -64,6 +63,7 @@ # include <dwrite.h> # endif # include <d2d1.h> +# include "qwindowsdirectwritefontdatabase_p.h" #endif QT_BEGIN_NAMESPACE @@ -75,40 +75,6 @@ Q_LOGGING_CATEGORY(lcQpaFonts, "qt.qpa.fonts") typedef HRESULT (WINAPI *DWriteCreateFactoryType)(DWRITE_FACTORY_TYPE, const IID &, IUnknown **); -static inline DWriteCreateFactoryType resolveDWriteCreateFactory() -{ - QSystemLibrary library(QStringLiteral("dwrite")); - QFunctionPointer result = library.resolve("DWriteCreateFactory"); - if (Q_UNLIKELY(!result)) { - qWarning("Unable to load dwrite.dll"); - return nullptr; - } - return reinterpret_cast<DWriteCreateFactoryType>(result); -} - -static void createDirectWriteFactory(IDWriteFactory **factory) -{ - *factory = nullptr; - - static const DWriteCreateFactoryType dWriteCreateFactory = resolveDWriteCreateFactory(); - if (!dWriteCreateFactory) - return; - - IUnknown *result = NULL; -#if defined(QT_USE_DIRECTWRITE2) - dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result); -#endif - - if (result == NULL) { - if (FAILED(dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) { - qErrnoWarning("DWriteCreateFactory failed"); - return; - } - } - - *factory = static_cast<IDWriteFactory *>(result); -} - static inline bool useDirectWrite(QFont::HintingPreference hintingPreference, const QString &familyName = QString(), bool isColorFont = false) @@ -131,459 +97,6 @@ static inline bool useDirectWrite(QFont::HintingPreference hintingPreference, } #endif // !QT_NO_DIRECTWRITE -// Helper classes for creating font engines directly from font data -namespace { - -# pragma pack(1) - - // Common structure for all formats of the "name" table - struct NameTable - { - quint16 format; - quint16 count; - quint16 stringOffset; - }; - - struct NameRecord - { - quint16 platformID; - quint16 encodingID; - quint16 languageID; - quint16 nameID; - quint16 length; - quint16 offset; - }; - - struct OffsetSubTable - { - quint32 scalerType; - quint16 numTables; - quint16 searchRange; - quint16 entrySelector; - quint16 rangeShift; - }; - - struct TableDirectory - { - quint32 identifier; - quint32 checkSum; - quint32 offset; - quint32 length; - }; - - struct OS2Table - { - quint16 version; - qint16 avgCharWidth; - quint16 weightClass; - quint16 widthClass; - quint16 type; - qint16 subscriptXSize; - qint16 subscriptYSize; - qint16 subscriptXOffset; - qint16 subscriptYOffset; - qint16 superscriptXSize; - qint16 superscriptYSize; - qint16 superscriptXOffset; - qint16 superscriptYOffset; - qint16 strikeOutSize; - qint16 strikeOutPosition; - qint16 familyClass; - quint8 panose[10]; - quint32 unicodeRanges[4]; - quint8 vendorID[4]; - quint16 selection; - quint16 firstCharIndex; - quint16 lastCharIndex; - qint16 typoAscender; - qint16 typoDescender; - qint16 typoLineGap; - quint16 winAscent; - quint16 winDescent; - quint32 codepageRanges[2]; - qint16 height; - qint16 capHeight; - quint16 defaultChar; - quint16 breakChar; - quint16 maxContext; - }; - -# pragma pack() - - class EmbeddedFont - { - public: - EmbeddedFont(const QByteArray &fontData) : m_fontData(fontData) {} - - QString changeFamilyName(const QString &newFamilyName); - QByteArray data() const { return m_fontData; } - TableDirectory *tableDirectoryEntry(const QByteArray &tagName); - QString familyName(TableDirectory *nameTableDirectory = 0); - - private: - QByteArray m_fontData; - }; - - TableDirectory *EmbeddedFont::tableDirectoryEntry(const QByteArray &tagName) - { - Q_ASSERT(tagName.size() == 4); - quint32 tagId = *(reinterpret_cast<const quint32 *>(tagName.constData())); - const size_t fontDataSize = m_fontData.size(); - if (Q_UNLIKELY(fontDataSize < sizeof(OffsetSubTable))) - return 0; - - OffsetSubTable *offsetSubTable = reinterpret_cast<OffsetSubTable *>(m_fontData.data()); - TableDirectory *tableDirectory = reinterpret_cast<TableDirectory *>(offsetSubTable + 1); - - const size_t tableCount = qFromBigEndian<quint16>(offsetSubTable->numTables); - if (Q_UNLIKELY(fontDataSize < sizeof(OffsetSubTable) + sizeof(TableDirectory) * tableCount)) - return 0; - - TableDirectory *tableDirectoryEnd = tableDirectory + tableCount; - for (TableDirectory *entry = tableDirectory; entry < tableDirectoryEnd; ++entry) { - if (entry->identifier == tagId) - return entry; - } - - return 0; - } - - QString EmbeddedFont::familyName(TableDirectory *nameTableDirectoryEntry) - { - QString name; - - if (nameTableDirectoryEntry == 0) - nameTableDirectoryEntry = tableDirectoryEntry("name"); - - if (nameTableDirectoryEntry != 0) { - quint32 offset = qFromBigEndian<quint32>(nameTableDirectoryEntry->offset); - if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameTable))) - return QString(); - - NameTable *nameTable = reinterpret_cast<NameTable *>(m_fontData.data() + offset); - NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1); - - quint16 nameTableCount = qFromBigEndian<quint16>(nameTable->count); - if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameRecord) * nameTableCount)) - return QString(); - - for (int i = 0; i < nameTableCount; ++i, ++nameRecord) { - if (qFromBigEndian<quint16>(nameRecord->nameID) == 1 - && qFromBigEndian<quint16>(nameRecord->platformID) == 3 // Windows - && qFromBigEndian<quint16>(nameRecord->languageID) == 0x0409) { // US English - quint16 stringOffset = qFromBigEndian<quint16>(nameTable->stringOffset); - quint16 nameOffset = qFromBigEndian<quint16>(nameRecord->offset); - quint16 nameLength = qFromBigEndian<quint16>(nameRecord->length); - - if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + stringOffset + nameOffset + nameLength)) - return QString(); - - const void *ptr = reinterpret_cast<const quint8 *>(nameTable) - + stringOffset - + nameOffset; - - const quint16 *s = reinterpret_cast<const quint16 *>(ptr); - const quint16 *e = s + nameLength / sizeof(quint16); - while (s != e) - name += QChar( qFromBigEndian<quint16>(*s++)); - break; - } - } - } - - return name; - } - - QString EmbeddedFont::changeFamilyName(const QString &newFamilyName) - { - TableDirectory *nameTableDirectoryEntry = tableDirectoryEntry("name"); - if (nameTableDirectoryEntry == 0) - return QString(); - - QString oldFamilyName = familyName(nameTableDirectoryEntry); - - // Reserve size for name table header, five required name records and string - const int requiredRecordCount = 5; - quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 }; - - int sizeOfHeader = sizeof(NameTable) + sizeof(NameRecord) * requiredRecordCount; - int newFamilyNameSize = newFamilyName.size() * int(sizeof(quint16)); - - const QString regularString = QString::fromLatin1("Regular"); - int regularStringSize = regularString.size() * int(sizeof(quint16)); - - // Align table size of table to 32 bits (pad with 0) - int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4; - - QByteArray newNameTable(fullSize, char(0)); - - { - NameTable *nameTable = reinterpret_cast<NameTable *>(newNameTable.data()); - nameTable->count = qbswap<quint16>(requiredRecordCount); - nameTable->stringOffset = qbswap<quint16>(sizeOfHeader); - - NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1); - for (int i = 0; i < requiredRecordCount; ++i, nameRecord++) { - nameRecord->nameID = qbswap<quint16>(nameIds[i]); - nameRecord->encodingID = qbswap<quint16>(1); - nameRecord->languageID = qbswap<quint16>(0x0409); - nameRecord->platformID = qbswap<quint16>(3); - nameRecord->length = qbswap<quint16>(newFamilyNameSize); - - // Special case for sub-family - if (nameIds[i] == 4) { - nameRecord->offset = qbswap<quint16>(newFamilyNameSize); - nameRecord->length = qbswap<quint16>(regularStringSize); - } - } - - // nameRecord now points to string data - quint16 *stringStorage = reinterpret_cast<quint16 *>(nameRecord); - const quint16 *sourceString = newFamilyName.utf16(); - for (int i = 0; i < newFamilyName.size(); ++i) - stringStorage[i] = qbswap<quint16>(sourceString[i]); - stringStorage += newFamilyName.size(); - - sourceString = regularString.utf16(); - for (int i = 0; i < regularString.size(); ++i) - stringStorage[i] = qbswap<quint16>(sourceString[i]); - } - - quint32 *p = reinterpret_cast<quint32 *>(newNameTable.data()); - quint32 *tableEnd = reinterpret_cast<quint32 *>(newNameTable.data() + fullSize); - - quint32 checkSum = 0; - while (p < tableEnd) - checkSum += qFromBigEndian<quint32>(*(p++)); - - nameTableDirectoryEntry->checkSum = qbswap<quint32>(checkSum); - nameTableDirectoryEntry->offset = qbswap<quint32>(m_fontData.size()); - nameTableDirectoryEntry->length = qbswap<quint32>(fullSize); - - m_fontData.append(newNameTable); - - return oldFamilyName; - } - -#if !defined(QT_NO_DIRECTWRITE) - - class DirectWriteFontFileStream: public IDWriteFontFileStream - { - Q_DISABLE_COPY(DirectWriteFontFileStream) - public: - DirectWriteFontFileStream(const QByteArray &fontData) - : m_fontData(fontData) - , m_referenceCount(0) - { - } - virtual ~DirectWriteFontFileStream() - { - } - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - HRESULT STDMETHODCALLTYPE ReadFileFragment(const void **fragmentStart, UINT64 fileOffset, - UINT64 fragmentSize, OUT void **fragmentContext); - void STDMETHODCALLTYPE ReleaseFileFragment(void *fragmentContext); - HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64 *fileSize); - HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64 *lastWriteTime); - - private: - QByteArray m_fontData; - ULONG m_referenceCount; - }; - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::QueryInterface(REFIID iid, void **object) - { - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) { - *object = this; - AddRef(); - return S_OK; - } else { - *object = NULL; - return E_NOINTERFACE; - } - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::AddRef() - { - return InterlockedIncrement(&m_referenceCount); - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::Release() - { - ULONG newCount = InterlockedDecrement(&m_referenceCount); - if (newCount == 0) - delete this; - return newCount; - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::ReadFileFragment( - const void **fragmentStart, - UINT64 fileOffset, - UINT64 fragmentSize, - OUT void **fragmentContext) - { - *fragmentContext = NULL; - if (fileOffset + fragmentSize <= quint64(m_fontData.size())) { - *fragmentStart = m_fontData.data() + fileOffset; - return S_OK; - } else { - *fragmentStart = NULL; - return E_FAIL; - } - } - - void STDMETHODCALLTYPE DirectWriteFontFileStream::ReleaseFileFragment(void *) - { - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetFileSize(UINT64 *fileSize) - { - *fileSize = m_fontData.size(); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime) - { - *lastWriteTime = 0; - return E_NOTIMPL; - } - - class DirectWriteFontFileLoader: public IDWriteFontFileLoader - { - public: - DirectWriteFontFileLoader() : m_referenceCount(0) {} - virtual ~DirectWriteFontFileLoader() - { - } - - inline void addKey(const void *key, const QByteArray &fontData) - { - Q_ASSERT(!m_fontDatas.contains(key)); - m_fontDatas.insert(key, fontData); - } - - inline void removeKey(const void *key) - { - m_fontDatas.remove(key); - } - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const *fontFileReferenceKey, - UINT32 fontFileReferenceKeySize, - OUT IDWriteFontFileStream **fontFileStream); - - private: - ULONG m_referenceCount; - QHash<const void *, QByteArray> m_fontDatas; - }; - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(const IID &iid, - void **object) - { - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { - *object = this; - AddRef(); - return S_OK; - } else { - *object = NULL; - return E_NOINTERFACE; - } - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef() - { - return InterlockedIncrement(&m_referenceCount); - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::Release() - { - ULONG newCount = InterlockedDecrement(&m_referenceCount); - if (newCount == 0) - delete this; - return newCount; - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey( - void const *fontFileReferenceKey, - UINT32 fontFileReferenceKeySize, - IDWriteFontFileStream **fontFileStream) - { - Q_UNUSED(fontFileReferenceKeySize); - - if (fontFileReferenceKeySize != sizeof(const void *)) { - qWarning("%s: Wrong key size", __FUNCTION__); - return E_FAIL; - } - - const void *key = *reinterpret_cast<void * const *>(fontFileReferenceKey); - *fontFileStream = NULL; - auto it = m_fontDatas.constFind(key); - if (it == m_fontDatas.constEnd()) - return E_FAIL; - - QByteArray fontData = it.value(); - DirectWriteFontFileStream *stream = new DirectWriteFontFileStream(fontData); - stream->AddRef(); - *fontFileStream = stream; - - return S_OK; - } - - class CustomFontFileLoader - { - public: - CustomFontFileLoader() : m_directWriteFontFileLoader(nullptr) - { - createDirectWriteFactory(&m_directWriteFactory); - - if (m_directWriteFactory) { - m_directWriteFontFileLoader = new DirectWriteFontFileLoader(); - m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader); - } - } - - ~CustomFontFileLoader() - { - if (m_directWriteFactory != 0 && m_directWriteFontFileLoader != 0) - m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader); - - if (m_directWriteFactory != 0) - m_directWriteFactory->Release(); - } - - void addKey(const void *key, const QByteArray &fontData) - { - if (m_directWriteFontFileLoader != 0) - m_directWriteFontFileLoader->addKey(key, fontData); - } - - void removeKey(const void *key) - { - if (m_directWriteFontFileLoader != 0) - m_directWriteFontFileLoader->removeKey(key); - } - - IDWriteFontFileLoader *loader() const - { - return m_directWriteFontFileLoader; - } - - private: - IDWriteFactory *m_directWriteFactory; - DirectWriteFontFileLoader *m_directWriteFontFileLoader; - }; - -#endif - -} // Anonymous namespace - /*! \struct QWindowsFontEngineData \brief Static constant data shared by the font engines. @@ -620,18 +133,6 @@ unsigned QWindowsFontDatabase::fontOptions() return m_fontOptions; } -QWindowsFontEngineData::~QWindowsFontEngineData() -{ - if (hdc) - DeleteDC(hdc); -#if !defined(QT_NO_DIRECTWRITE) - if (directWriteGdiInterop) - directWriteGdiInterop->Release(); - if (directWriteFactory) - directWriteFactory->Release(); -#endif -} - qreal QWindowsFontDatabase::fontSmoothingGamma() { int winSmooth; @@ -645,26 +146,6 @@ qreal QWindowsFontDatabase::fontSmoothingGamma() return result; } -#if !defined(QT_NO_DIRECTWRITE) -static inline bool initDirectWrite(QWindowsFontEngineData *d) -{ - if (!d->directWriteFactory) { - createDirectWriteFactory(&d->directWriteFactory); - if (!d->directWriteFactory) - return false; - } - if (!d->directWriteGdiInterop) { - const HRESULT hr = d->directWriteFactory->GetGdiInterop(&d->directWriteGdiInterop); - if (FAILED(hr)) { - qErrnoWarning("%s: GetGdiInterop failed", __FUNCTION__); - return false; - } - } - return true; -} - -#endif // !defined(QT_NO_DIRECTWRITE) - /*! \class QWindowsFontDatabase \brief Font database for Windows @@ -1069,18 +550,16 @@ static bool addFontToDatabase(QString familyName, QString subFamilyName; QString subFamilyStyle; - if (ttf) { - // Look-up names registered in the font - QFontNames canonicalNames = qt_getCanonicalFontNames(logFont); - if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty()) - englishName = canonicalNames.name; - if (!canonicalNames.preferredName.isEmpty()) { - subFamilyName = familyName; - subFamilyStyle = styleName; - faceName = familyName; // Remember the original name for later lookups - familyName = canonicalNames.preferredName; - styleName = canonicalNames.preferredStyle; - } + // Look-up names registered in the font + QFontNames canonicalNames = qt_getCanonicalFontNames(logFont); + if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty()) + englishName = canonicalNames.name; + if (!canonicalNames.preferredName.isEmpty()) { + subFamilyName = familyName; + subFamilyStyle = styleName; + faceName = familyName; // Remember the original name for later lookups + familyName = canonicalNames.preferredName; + styleName = canonicalNames.preferredStyle; } QSupportedWritingSystems writingSystems; @@ -1241,20 +720,6 @@ void QWindowsFontDatabase::populateFontDatabase() addDefaultEUDCFont(); } -typedef QSharedPointer<QWindowsFontEngineData> QWindowsFontEngineDataPtr; - -typedef QThreadStorage<QWindowsFontEngineDataPtr> FontEngineThreadLocalData; - -Q_GLOBAL_STATIC(FontEngineThreadLocalData, fontEngineThreadLocalData) - -QSharedPointer<QWindowsFontEngineData> sharedFontData() -{ - FontEngineThreadLocalData *data = fontEngineThreadLocalData(); - if (!data->hasLocalData()) - data->setLocalData(QSharedPointer<QWindowsFontEngineData>::create()); - return data->localData(); -} - QWindowsFontDatabase::QWindowsFontDatabase() { // Properties accessed by QWin32PrintEngine (Qt Print Support) @@ -1264,9 +729,9 @@ QWindowsFontDatabase::QWindowsFontDatabase() Q_UNUSED(logFontMetaTypeId) if (lcQpaFonts().isDebugEnabled()) { - const QWindowsFontEngineDataPtr data = sharedFontData(); + QSharedPointer<QWindowsFontEngineData> d = data(); qCDebug(lcQpaFonts) << __FUNCTION__ << "Clear type: " - << data->clearTypeEnabled << "gamma: " << data->fontSmoothingGamma; + << d->clearTypeEnabled << "gamma: " << d->fontSmoothingGamma; } } @@ -1280,7 +745,7 @@ QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, void *ha const QString faceName(static_cast<const QChar*>(handle)); QFontEngine *fe = QWindowsFontDatabase::createEngine(fontDef, faceName, defaultVerticalDPI(), - sharedFontData()); + data()); qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef << fe << handle; return fe; } @@ -1334,7 +799,7 @@ QT_WARNING_POP fontEngine = QWindowsFontDatabase::createEngine(request, QString(), defaultVerticalDPI(), - sharedFontData()); + data()); if (fontEngine) { if (request.family != fontEngine->fontDef.family) { @@ -1373,87 +838,17 @@ QT_WARNING_POP RemoveFontMemResourceEx(fontHandle); } } + + // Get style and weight info + if (fontEngine != nullptr) + font.updateFromOS2Table(fontEngine); } #if !defined(QT_NO_DIRECTWRITE) else { - CustomFontFileLoader fontFileLoader; - fontFileLoader.addKey(this, fontData); - - QSharedPointer<QWindowsFontEngineData> fontEngineData = sharedFontData(); - if (!initDirectWrite(fontEngineData.data())) - return 0; - - IDWriteFontFile *fontFile = 0; - void *key = this; - - HRESULT hres = fontEngineData->directWriteFactory->CreateCustomFontFileReference(&key, - sizeof(void *), - fontFileLoader.loader(), - &fontFile); - if (FAILED(hres)) { - qErrnoWarning(hres, "%s: CreateCustomFontFileReference failed", __FUNCTION__); - return 0; - } - - BOOL isSupportedFontType; - DWRITE_FONT_FILE_TYPE fontFileType; - DWRITE_FONT_FACE_TYPE fontFaceType; - UINT32 numberOfFaces; - fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces); - if (!isSupportedFontType) { - fontFile->Release(); - return 0; - } - - IDWriteFontFace *directWriteFontFace = 0; - hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType, - 1, - &fontFile, - 0, - DWRITE_FONT_SIMULATIONS_NONE, - &directWriteFontFace); - if (FAILED(hres)) { - qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__); - fontFile->Release(); - return 0; - } - - fontFile->Release(); - - fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace, - pixelSize, - fontEngineData); - - // Get font family from font data - fontEngine->fontDef.family = font.familyName(); - fontEngine->fontDef.hintingPreference = hintingPreference; - - directWriteFontFace->Release(); + fontEngine = QWindowsFontDatabaseBase::fontEngine(fontData, pixelSize, hintingPreference); } #endif - // Get style and weight info - if (fontEngine != 0) { - TableDirectory *os2TableEntry = font.tableDirectoryEntry("OS/2"); - if (os2TableEntry != 0) { - const OS2Table *os2Table = - reinterpret_cast<const OS2Table *>(fontData.constData() - + qFromBigEndian<quint32>(os2TableEntry->offset)); - - bool italic = qFromBigEndian<quint16>(os2Table->selection) & (1 << 0); - bool oblique = qFromBigEndian<quint16>(os2Table->selection) & (1 << 9); - - if (italic) - fontEngine->fontDef.style = QFont::StyleItalic; - else if (oblique) - fontEngine->fontDef.style = QFont::StyleOblique; - else - fontEngine->fontDef.style = QFont::StyleNormal; - - fontEngine->fontDef.weight = QPlatformFontDatabase::weightFromInteger(qFromBigEndian<quint16>(os2Table->weightClass)); - } - } - qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDATA" << fontData << pixelSize << hintingPreference << fontEngine; return fontEngine; } @@ -1685,14 +1080,6 @@ void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont) m_uniqueFontData[uniqueFont].refCount.ref(); } -// ### fixme Qt 6 (QTBUG-58610): See comment at QWindowsFontDatabase::systemDefaultFont() -HFONT QWindowsFontDatabase::systemFont() -{ - static const auto stock_sysfont = - reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT)); - return stock_sysfont; -} - // Creation functions static const char *other_tryFonts[] = { @@ -1747,101 +1134,6 @@ static const char *kr_tryFonts[] = { static const char **tryFonts = 0; -LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request, const QString &faceName) -{ - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - - lf.lfHeight = -qRound(request.pixelSize); - lf.lfWidth = 0; - lf.lfEscapement = 0; - lf.lfOrientation = 0; - if (request.weight == 50) - lf.lfWeight = FW_DONTCARE; - else - lf.lfWeight = (request.weight*900)/99; - lf.lfItalic = request.style != QFont::StyleNormal; - lf.lfCharSet = DEFAULT_CHARSET; - - int strat = OUT_DEFAULT_PRECIS; - if (request.styleStrategy & QFont::PreferBitmap) { - strat = OUT_RASTER_PRECIS; - } else if (request.styleStrategy & QFont::PreferDevice) { - strat = OUT_DEVICE_PRECIS; - } else if (request.styleStrategy & QFont::PreferOutline) { - strat = OUT_OUTLINE_PRECIS; - } else if (request.styleStrategy & QFont::ForceOutline) { - strat = OUT_TT_ONLY_PRECIS; - } - - lf.lfOutPrecision = strat; - - int qual = DEFAULT_QUALITY; - - if (request.styleStrategy & QFont::PreferMatch) - qual = DRAFT_QUALITY; - else if (request.styleStrategy & QFont::PreferQuality) - qual = PROOF_QUALITY; - - if (request.styleStrategy & QFont::PreferAntialias) { - qual = (request.styleStrategy & QFont::NoSubpixelAntialias) == 0 - ? CLEARTYPE_QUALITY : ANTIALIASED_QUALITY; - } else if (request.styleStrategy & QFont::NoAntialias) { - qual = NONANTIALIASED_QUALITY; - } else if ((request.styleStrategy & QFont::NoSubpixelAntialias) && sharedFontData()->clearTypeEnabled) { - qual = ANTIALIASED_QUALITY; - } - - lf.lfQuality = qual; - - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - - int hint = FF_DONTCARE; - switch (request.styleHint) { - case QFont::Helvetica: - hint = FF_SWISS; - break; - case QFont::Times: - hint = FF_ROMAN; - break; - case QFont::Courier: - hint = FF_MODERN; - break; - case QFont::OldEnglish: - hint = FF_DECORATIVE; - break; - case QFont::System: - hint = FF_MODERN; - break; - default: - break; - } - - lf.lfPitchAndFamily = DEFAULT_PITCH | hint; - - QString fam = faceName; - if (fam.isEmpty()) - fam = request.families.size() > 0 ? request.families.at(0) : request.family; - if (Q_UNLIKELY(fam.size() >= LF_FACESIZE)) { - qCritical("%s: Family name '%s' is too long.", __FUNCTION__, qPrintable(fam)); - fam.truncate(LF_FACESIZE - 1); - } - - if (fam.isEmpty()) - fam = QStringLiteral("MS Sans Serif"); - - if (fam == QLatin1String("MS Sans Serif") - && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) { - fam = QStringLiteral("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale - } - if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap)) - fam = QStringLiteral("Courier New"); - - memcpy(lf.lfFaceName, fam.utf16(), fam.size() * sizeof(wchar_t)); - - return lf; -} - QStringList QWindowsFontDatabase::extraTryFontsForFamily(const QString &family) { QStringList result; @@ -1949,7 +1241,7 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q } #if !defined(QT_NO_DIRECTWRITE) - if (initDirectWrite(data.data())) { + if (data->directWriteFactory != nullptr) { const QString fam = QString::fromWCharArray(lf.lfFaceName); const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam); if (nameSubstitute != fam) { @@ -2025,62 +1317,6 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q return fe; } -QFont QWindowsFontDatabase::systemDefaultFont() -{ -#if QT_VERSION >= 0x060000 - // Qt 6: Obtain default GUI font (typically "Segoe UI, 9pt", see QTBUG-58610) - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); - const QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont); -#else - LOGFONT lf; - GetObject(QWindowsFontDatabase::systemFont(), sizeof(lf), &lf); - QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(lf); - // "MS Shell Dlg 2" is the correct system font >= Win2k - if (systemFont.family() == QLatin1String("MS Shell Dlg")) - systemFont.setFamily(QStringLiteral("MS Shell Dlg 2")); - // Qt 5 by (Qt 4) legacy uses GetStockObject(DEFAULT_GUI_FONT) to - // obtain the default GUI font (typically "MS Shell Dlg 2, 8pt"). This has been - // long deprecated; the message font of the NONCLIENTMETRICS structure obtained by - // SystemParametersInfo(SPI_GETNONCLIENTMETRICS) should be used instead (see - // QWindowsTheme::refreshFonts(), typically "Segoe UI, 9pt"), which is larger. -#endif // Qt 5 - qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont; - return systemFont; -} - -QFont QWindowsFontDatabase::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In) -{ - if (verticalDPI_In <= 0) - verticalDPI_In = defaultVerticalDPI(); - QFont qFont(QString::fromWCharArray(logFont.lfFaceName)); - qFont.setItalic(logFont.lfItalic); - if (logFont.lfWeight != FW_DONTCARE) - qFont.setWeight(QPlatformFontDatabase::weightFromInteger(logFont.lfWeight)); - const qreal logFontHeight = qAbs(logFont.lfHeight); - qFont.setPointSizeF(logFontHeight * 72.0 / qreal(verticalDPI_In)); - qFont.setUnderline(logFont.lfUnderline); - qFont.setOverline(false); - qFont.setStrikeOut(logFont.lfStrikeOut); - return qFont; -} - -int QWindowsFontDatabase::defaultVerticalDPI() -{ - static int vDPI = -1; - if (vDPI == -1) { - if (HDC defaultDC = GetDC(0)) { - vDPI = GetDeviceCaps(defaultDC, LOGPIXELSY); - ReleaseDC(0, defaultDC); - } else { - // FIXME: Resolve now or return 96 and keep unresolved? - vDPI = 96; - } - } - return vDPI; -} - bool QWindowsFontDatabase::isPrivateFontFamily(const QString &family) const { return m_eudcFonts.contains(family) || QPlatformFontDatabase::isPrivateFontFamily(family); diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp index a6b7fcf31e..5c2742d295 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp @@ -215,17 +215,15 @@ static bool addFontToDatabase(QString familyName, QString subFamilyName; QString subFamilyStyle; - if (ttf) { - // Look-up names registered in the font - QFontNames canonicalNames = qt_getCanonicalFontNames(logFont); - if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty()) - englishName = canonicalNames.name; - if (!canonicalNames.preferredName.isEmpty()) { - subFamilyName = familyName; - subFamilyStyle = styleName; - familyName = canonicalNames.preferredName; - styleName = canonicalNames.preferredStyle; - } + // Look-up names registered in the font + QFontNames canonicalNames = qt_getCanonicalFontNames(logFont); + if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty()) + englishName = canonicalNames.name; + if (!canonicalNames.preferredName.isEmpty()) { + subFamilyName = familyName; + subFamilyStyle = styleName; + familyName = canonicalNames.preferredName; + styleName = canonicalNames.preferredStyle; } QSupportedWritingSystems writingSystems; diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h index f132e69d4d..a76fdc0810 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h @@ -51,39 +51,16 @@ // We mean it. // +#include "qwindowsfontdatabasebase_p.h" + #include <qpa/qplatformfontdatabase.h> #include <QtCore/QSharedPointer> #include <QtCore/QLoggingCategory> #include <QtCore/qt_windows.h> -#if !defined(QT_NO_DIRECTWRITE) - struct IDWriteFactory; - struct IDWriteGdiInterop; -#endif - QT_BEGIN_NAMESPACE -Q_DECLARE_LOGGING_CATEGORY(lcQpaFonts) - -class QWindowsFontEngineData -{ - Q_DISABLE_COPY_MOVE(QWindowsFontEngineData) -public: - QWindowsFontEngineData(); - ~QWindowsFontEngineData(); - - uint pow_gamma[256]; - - bool clearTypeEnabled = false; - qreal fontSmoothingGamma; - HDC hdc = 0; -#if !defined(QT_NO_DIRECTWRITE) - IDWriteFactory *directWriteFactory = nullptr; - IDWriteGdiInterop *directWriteGdiInterop = nullptr; -#endif -}; - -class QWindowsFontDatabase : public QPlatformFontDatabase +class QWindowsFontDatabase : public QWindowsFontDatabaseBase { Q_DISABLE_COPY_MOVE(QWindowsFontDatabase) public: @@ -113,23 +90,15 @@ public: void refUniqueFont(const QString &uniqueFont); bool isPrivateFontFamily(const QString &family) const override; - static QFont systemDefaultFont(); - static QFontEngine *createEngine(const QFontDef &request, const QString &faceName, int dpi, const QSharedPointer<QWindowsFontEngineData> &data); - static HFONT systemFont(); - static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0); - static qreal fontSmoothingGamma(); - static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef, const QString &faceName); static QStringList extraTryFontsForFamily(const QString &family); static QString familyForStyleHint(QFont::StyleHint styleHint); - static int defaultVerticalDPI(); - static void setFontOptions(unsigned options); static unsigned fontOptions(); diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase.cpp new file mode 100644 index 0000000000..5b8707cdec --- /dev/null +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase.cpp @@ -0,0 +1,869 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 "qwindowsfontdatabasebase_p.h" +#include "qwindowsfontdatabase_p.h" + +#include <QtCore/private/qsystemlibrary_p.h> +#include <QtCore/QThreadStorage> +#include <QtCore/QtEndian> + +#if !defined(QT_NO_DIRECTWRITE) +# if defined(QT_USE_DIRECTWRITE3) +# include <dwrite_3.h> +# elif defined(QT_USE_DIRECTWRITE2) +# include <dwrite_2.h> +# else +# include <dwrite.h> +# endif +# include <d2d1.h> +# include "qwindowsfontenginedirectwrite_p.h" +#endif + +QT_BEGIN_NAMESPACE + +// Helper classes for creating font engines directly from font data +namespace { + +# pragma pack(1) + + // Common structure for all formats of the "name" table + struct NameTable + { + quint16 format; + quint16 count; + quint16 stringOffset; + }; + + struct NameRecord + { + quint16 platformID; + quint16 encodingID; + quint16 languageID; + quint16 nameID; + quint16 length; + quint16 offset; + }; + + struct OffsetSubTable + { + quint32 scalerType; + quint16 numTables; + quint16 searchRange; + quint16 entrySelector; + quint16 rangeShift; + }; + + struct TableDirectory : public QWindowsFontDatabaseBase::FontTable + { + quint32 identifier; + quint32 checkSum; + quint32 offset; + quint32 length; + }; + + struct OS2Table + { + quint16 version; + qint16 avgCharWidth; + quint16 weightClass; + quint16 widthClass; + quint16 type; + qint16 subscriptXSize; + qint16 subscriptYSize; + qint16 subscriptXOffset; + qint16 subscriptYOffset; + qint16 superscriptXSize; + qint16 superscriptYSize; + qint16 superscriptXOffset; + qint16 superscriptYOffset; + qint16 strikeOutSize; + qint16 strikeOutPosition; + qint16 familyClass; + quint8 panose[10]; + quint32 unicodeRanges[4]; + quint8 vendorID[4]; + quint16 selection; + quint16 firstCharIndex; + quint16 lastCharIndex; + qint16 typoAscender; + qint16 typoDescender; + qint16 typoLineGap; + quint16 winAscent; + quint16 winDescent; + quint32 codepageRanges[2]; + qint16 height; + qint16 capHeight; + quint16 defaultChar; + quint16 breakChar; + quint16 maxContext; + }; + +# pragma pack() + +} // Anonymous namespace + +QWindowsFontDatabaseBase::FontTable *QWindowsFontDatabaseBase::EmbeddedFont::tableDirectoryEntry(const QByteArray &tagName) +{ + Q_ASSERT(tagName.size() == 4); + quint32 tagId = *(reinterpret_cast<const quint32 *>(tagName.constData())); + const size_t fontDataSize = m_fontData.size(); + if (Q_UNLIKELY(fontDataSize < sizeof(OffsetSubTable))) + return nullptr; + + OffsetSubTable *offsetSubTable = reinterpret_cast<OffsetSubTable *>(m_fontData.data()); + TableDirectory *tableDirectory = reinterpret_cast<TableDirectory *>(offsetSubTable + 1); + + const size_t tableCount = qFromBigEndian<quint16>(offsetSubTable->numTables); + if (Q_UNLIKELY(fontDataSize < sizeof(OffsetSubTable) + sizeof(TableDirectory) * tableCount)) + return nullptr; + + TableDirectory *tableDirectoryEnd = tableDirectory + tableCount; + for (TableDirectory *entry = tableDirectory; entry < tableDirectoryEnd; ++entry) { + if (entry->identifier == tagId) + return entry; + } + + return nullptr; +} + +QString QWindowsFontDatabaseBase::EmbeddedFont::familyName(QWindowsFontDatabaseBase::FontTable *directoryEntry) +{ + QString name; + + TableDirectory *nameTableDirectoryEntry = static_cast<TableDirectory *>(directoryEntry); + if (nameTableDirectoryEntry == nullptr) + nameTableDirectoryEntry = static_cast<TableDirectory *>(tableDirectoryEntry("name")); + + if (nameTableDirectoryEntry != nullptr) { + quint32 offset = qFromBigEndian<quint32>(nameTableDirectoryEntry->offset); + if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameTable))) + return QString(); + + NameTable *nameTable = reinterpret_cast<NameTable *>(m_fontData.data() + offset); + NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1); + + quint16 nameTableCount = qFromBigEndian<quint16>(nameTable->count); + if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameRecord) * nameTableCount)) + return QString(); + + for (int i = 0; i < nameTableCount; ++i, ++nameRecord) { + if (qFromBigEndian<quint16>(nameRecord->nameID) == 1 + && qFromBigEndian<quint16>(nameRecord->platformID) == 3 // Windows + && qFromBigEndian<quint16>(nameRecord->languageID) == 0x0409) { // US English + quint16 stringOffset = qFromBigEndian<quint16>(nameTable->stringOffset); + quint16 nameOffset = qFromBigEndian<quint16>(nameRecord->offset); + quint16 nameLength = qFromBigEndian<quint16>(nameRecord->length); + + if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + stringOffset + nameOffset + nameLength)) + return QString(); + + const void *ptr = reinterpret_cast<const quint8 *>(nameTable) + + stringOffset + + nameOffset; + + const quint16 *s = reinterpret_cast<const quint16 *>(ptr); + const quint16 *e = s + nameLength / sizeof(quint16); + while (s != e) + name += QChar( qFromBigEndian<quint16>(*s++)); + break; + } + } + } + + return name; +} + +void QWindowsFontDatabaseBase::EmbeddedFont::updateFromOS2Table(QFontEngine *fontEngine) +{ + TableDirectory *os2TableEntry = static_cast<TableDirectory *>(tableDirectoryEntry("OS/2")); + if (os2TableEntry != nullptr) { + const OS2Table *os2Table = + reinterpret_cast<const OS2Table *>(m_fontData.constData() + + qFromBigEndian<quint32>(os2TableEntry->offset)); + + bool italic = qFromBigEndian<quint16>(os2Table->selection) & (1 << 0); + bool oblique = qFromBigEndian<quint16>(os2Table->selection) & (1 << 9); + + if (italic) + fontEngine->fontDef.style = QFont::StyleItalic; + else if (oblique) + fontEngine->fontDef.style = QFont::StyleOblique; + else + fontEngine->fontDef.style = QFont::StyleNormal; + + fontEngine->fontDef.weight = QPlatformFontDatabase::weightFromInteger(qFromBigEndian<quint16>(os2Table->weightClass)); + } +} + +QString QWindowsFontDatabaseBase::EmbeddedFont::changeFamilyName(const QString &newFamilyName) +{ + TableDirectory *nameTableDirectoryEntry = static_cast<TableDirectory *>(tableDirectoryEntry("name")); + if (nameTableDirectoryEntry == nullptr) + return QString(); + + QString oldFamilyName = familyName(nameTableDirectoryEntry); + + // Reserve size for name table header, five required name records and string + const int requiredRecordCount = 5; + quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 }; + + int sizeOfHeader = sizeof(NameTable) + sizeof(NameRecord) * requiredRecordCount; + int newFamilyNameSize = newFamilyName.size() * int(sizeof(quint16)); + + const QString regularString = QString::fromLatin1("Regular"); + int regularStringSize = regularString.size() * int(sizeof(quint16)); + + // Align table size of table to 32 bits (pad with 0) + int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4; + + QByteArray newNameTable(fullSize, char(0)); + + { + NameTable *nameTable = reinterpret_cast<NameTable *>(newNameTable.data()); + nameTable->count = qbswap<quint16>(requiredRecordCount); + nameTable->stringOffset = qbswap<quint16>(sizeOfHeader); + + NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1); + for (int i = 0; i < requiredRecordCount; ++i, nameRecord++) { + nameRecord->nameID = qbswap<quint16>(nameIds[i]); + nameRecord->encodingID = qbswap<quint16>(1); + nameRecord->languageID = qbswap<quint16>(0x0409); + nameRecord->platformID = qbswap<quint16>(3); + nameRecord->length = qbswap<quint16>(newFamilyNameSize); + + // Special case for sub-family + if (nameIds[i] == 4) { + nameRecord->offset = qbswap<quint16>(newFamilyNameSize); + nameRecord->length = qbswap<quint16>(regularStringSize); + } + } + + // nameRecord now points to string data + quint16 *stringStorage = reinterpret_cast<quint16 *>(nameRecord); + const quint16 *sourceString = newFamilyName.utf16(); + for (int i = 0; i < newFamilyName.size(); ++i) + stringStorage[i] = qbswap<quint16>(sourceString[i]); + stringStorage += newFamilyName.size(); + + sourceString = regularString.utf16(); + for (int i = 0; i < regularString.size(); ++i) + stringStorage[i] = qbswap<quint16>(sourceString[i]); + } + + quint32 *p = reinterpret_cast<quint32 *>(newNameTable.data()); + quint32 *tableEnd = reinterpret_cast<quint32 *>(newNameTable.data() + fullSize); + + quint32 checkSum = 0; + while (p < tableEnd) + checkSum += qFromBigEndian<quint32>(*(p++)); + + nameTableDirectoryEntry->checkSum = qbswap<quint32>(checkSum); + nameTableDirectoryEntry->offset = qbswap<quint32>(m_fontData.size()); + nameTableDirectoryEntry->length = qbswap<quint32>(fullSize); + + m_fontData.append(newNameTable); + + return oldFamilyName; +} + +#if !defined(QT_NO_DIRECTWRITE) + +namespace { + class DirectWriteFontFileStream: public IDWriteFontFileStream + { + Q_DISABLE_COPY(DirectWriteFontFileStream) + public: + DirectWriteFontFileStream(const QByteArray &fontData) + : m_fontData(fontData) + , m_referenceCount(0) + { + } + virtual ~DirectWriteFontFileStream() + { + } + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE ReadFileFragment(const void **fragmentStart, UINT64 fileOffset, + UINT64 fragmentSize, OUT void **fragmentContext); + void STDMETHODCALLTYPE ReleaseFileFragment(void *fragmentContext); + HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64 *fileSize); + HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64 *lastWriteTime); + + private: + QByteArray m_fontData; + ULONG m_referenceCount; + }; + + HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::QueryInterface(REFIID iid, void **object) + { + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) { + *object = this; + AddRef(); + return S_OK; + } else { + *object = NULL; + return E_NOINTERFACE; + } + } + + ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::AddRef() + { + return InterlockedIncrement(&m_referenceCount); + } + + ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::Release() + { + ULONG newCount = InterlockedDecrement(&m_referenceCount); + if (newCount == 0) + delete this; + return newCount; + } + + HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::ReadFileFragment( + const void **fragmentStart, + UINT64 fileOffset, + UINT64 fragmentSize, + OUT void **fragmentContext) + { + *fragmentContext = NULL; + if (fileOffset + fragmentSize <= quint64(m_fontData.size())) { + *fragmentStart = m_fontData.data() + fileOffset; + return S_OK; + } else { + *fragmentStart = NULL; + return E_FAIL; + } + } + + void STDMETHODCALLTYPE DirectWriteFontFileStream::ReleaseFileFragment(void *) + { + } + + HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetFileSize(UINT64 *fileSize) + { + *fileSize = m_fontData.size(); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime) + { + *lastWriteTime = 0; + return E_NOTIMPL; + } + + class DirectWriteFontFileLoader: public IDWriteFontFileLoader + { + public: + DirectWriteFontFileLoader() : m_referenceCount(0) {} + virtual ~DirectWriteFontFileLoader() + { + } + + inline void addKey(const void *key, const QByteArray &fontData) + { + Q_ASSERT(!m_fontDatas.contains(key)); + m_fontDatas.insert(key, fontData); + } + + inline void removeKey(const void *key) + { + m_fontDatas.remove(key); + } + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const *fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + OUT IDWriteFontFileStream **fontFileStream); + + private: + ULONG m_referenceCount; + QHash<const void *, QByteArray> m_fontDatas; + }; + + HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(const IID &iid, + void **object) + { + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { + *object = this; + AddRef(); + return S_OK; + } else { + *object = NULL; + return E_NOINTERFACE; + } + } + + ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef() + { + return InterlockedIncrement(&m_referenceCount); + } + + ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::Release() + { + ULONG newCount = InterlockedDecrement(&m_referenceCount); + if (newCount == 0) + delete this; + return newCount; + } + + HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey( + void const *fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + IDWriteFontFileStream **fontFileStream) + { + Q_UNUSED(fontFileReferenceKeySize); + + if (fontFileReferenceKeySize != sizeof(const void *)) { + qWarning("%s: Wrong key size", __FUNCTION__); + return E_FAIL; + } + + const void *key = *reinterpret_cast<void * const *>(fontFileReferenceKey); + *fontFileStream = NULL; + auto it = m_fontDatas.constFind(key); + if (it == m_fontDatas.constEnd()) + return E_FAIL; + + QByteArray fontData = it.value(); + DirectWriteFontFileStream *stream = new DirectWriteFontFileStream(fontData); + stream->AddRef(); + *fontFileStream = stream; + + return S_OK; + } + + class CustomFontFileLoader + { + public: + CustomFontFileLoader(IDWriteFactory *factory) + { + m_directWriteFactory = factory; + + if (m_directWriteFactory) { + m_directWriteFactory->AddRef(); + + m_directWriteFontFileLoader = new DirectWriteFontFileLoader(); + m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader); + } + } + + ~CustomFontFileLoader() + { + if (m_directWriteFactory != nullptr && m_directWriteFontFileLoader != nullptr) + m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader); + + if (m_directWriteFactory != nullptr) + m_directWriteFactory->Release(); + } + + void addKey(const void *key, const QByteArray &fontData) + { + if (m_directWriteFontFileLoader != nullptr) + m_directWriteFontFileLoader->addKey(key, fontData); + } + + void removeKey(const void *key) + { + if (m_directWriteFontFileLoader != nullptr) + m_directWriteFontFileLoader->removeKey(key); + } + + IDWriteFontFileLoader *loader() const + { + return m_directWriteFontFileLoader; + } + + private: + IDWriteFactory *m_directWriteFactory = nullptr; + DirectWriteFontFileLoader *m_directWriteFontFileLoader = nullptr; + }; +} // Anonymous namespace + +#endif // !defined(QT_NO_DIRECTWRITE) + + +QWindowsFontEngineData::~QWindowsFontEngineData() +{ + if (hdc) + DeleteDC(hdc); + +#if !defined(QT_NO_DIRECTWRITE) + if (directWriteGdiInterop) + directWriteGdiInterop->Release(); + if (directWriteFactory) + directWriteFactory->Release(); +#endif +} + +QWindowsFontDatabaseBase::QWindowsFontDatabaseBase() +{ +} + +QWindowsFontDatabaseBase::~QWindowsFontDatabaseBase() +{ +} + +typedef QSharedPointer<QWindowsFontEngineData> QWindowsFontEngineDataPtr; +typedef QThreadStorage<QWindowsFontEngineDataPtr> FontEngineThreadLocalData; +Q_GLOBAL_STATIC(FontEngineThreadLocalData, fontEngineThreadLocalData) + +QSharedPointer<QWindowsFontEngineData> QWindowsFontDatabaseBase::data() +{ + FontEngineThreadLocalData *data = fontEngineThreadLocalData(); + if (!data->hasLocalData()) + data->setLocalData(QSharedPointer<QWindowsFontEngineData>::create()); + + if (!init(data->localData())) + qCWarning(lcQpaFonts) << "Cannot initialize common font database data"; + + return data->localData(); +} + +bool QWindowsFontDatabaseBase::init(QSharedPointer<QWindowsFontEngineData> d) +{ +#if !defined(QT_NO_DIRECTWRITE) + if (!d->directWriteFactory) { + createDirectWriteFactory(&d->directWriteFactory); + if (!d->directWriteFactory) + return false; + } + if (!d->directWriteGdiInterop) { + const HRESULT hr = d->directWriteFactory->GetGdiInterop(&d->directWriteGdiInterop); + if (FAILED(hr)) { + qErrnoWarning("%s: GetGdiInterop failed", __FUNCTION__); + return false; + } + } +#endif + return true; +} + +#if !defined(QT_NO_DIRECTWRITE) +// ### Qt 6: Link directly to dwrite instead +typedef HRESULT (WINAPI *DWriteCreateFactoryType)(DWRITE_FACTORY_TYPE, const IID &, IUnknown **); +static inline DWriteCreateFactoryType resolveDWriteCreateFactory() +{ + QSystemLibrary library(QStringLiteral("dwrite")); + QFunctionPointer result = library.resolve("DWriteCreateFactory"); + if (Q_UNLIKELY(!result)) { + qWarning("Unable to load dwrite.dll"); + return nullptr; + } + return reinterpret_cast<DWriteCreateFactoryType>(result); +} + +void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **factory) +{ + *factory = nullptr; + + static const DWriteCreateFactoryType dWriteCreateFactory = resolveDWriteCreateFactory(); + if (!dWriteCreateFactory) + return; + + IUnknown *result = nullptr; +# if defined(QT_USE_DIRECTWRITE3) + dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &result); +# endif + +# if defined(QT_USE_DIRECTWRITE2) + if (result == nullptr) + dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result); +# endif + + if (result == nullptr) { + if (FAILED(dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) { + qErrnoWarning("DWriteCreateFactory failed"); + return; + } + } + + *factory = static_cast<IDWriteFactory *>(result); +} +#endif // !defined(QT_NO_DIRECTWRITE) + +int QWindowsFontDatabaseBase::defaultVerticalDPI() +{ + static int vDPI = -1; + if (vDPI == -1) { + if (HDC defaultDC = GetDC(0)) { + vDPI = GetDeviceCaps(defaultDC, LOGPIXELSY); + ReleaseDC(0, defaultDC); + } else { + // FIXME: Resolve now or return 96 and keep unresolved? + vDPI = 96; + } + } + return vDPI; +} + +LOGFONT QWindowsFontDatabaseBase::fontDefToLOGFONT(const QFontDef &request, const QString &faceName) +{ + LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); + + lf.lfHeight = -qRound(request.pixelSize); + lf.lfWidth = 0; + lf.lfEscapement = 0; + lf.lfOrientation = 0; + if (request.weight == 50) + lf.lfWeight = FW_DONTCARE; + else + lf.lfWeight = (request.weight*900)/99; + lf.lfItalic = request.style != QFont::StyleNormal; + lf.lfCharSet = DEFAULT_CHARSET; + + int strat = OUT_DEFAULT_PRECIS; + if (request.styleStrategy & QFont::PreferBitmap) { + strat = OUT_RASTER_PRECIS; + } else if (request.styleStrategy & QFont::PreferDevice) { + strat = OUT_DEVICE_PRECIS; + } else if (request.styleStrategy & QFont::PreferOutline) { + strat = OUT_OUTLINE_PRECIS; + } else if (request.styleStrategy & QFont::ForceOutline) { + strat = OUT_TT_ONLY_PRECIS; + } + + lf.lfOutPrecision = strat; + + int qual = DEFAULT_QUALITY; + + if (request.styleStrategy & QFont::PreferMatch) + qual = DRAFT_QUALITY; + else if (request.styleStrategy & QFont::PreferQuality) + qual = PROOF_QUALITY; + + if (request.styleStrategy & QFont::PreferAntialias) { + qual = (request.styleStrategy & QFont::NoSubpixelAntialias) == 0 + ? CLEARTYPE_QUALITY : ANTIALIASED_QUALITY; + } else if (request.styleStrategy & QFont::NoAntialias) { + qual = NONANTIALIASED_QUALITY; + } else if ((request.styleStrategy & QFont::NoSubpixelAntialias) && data()->clearTypeEnabled) { + qual = ANTIALIASED_QUALITY; + } + + lf.lfQuality = qual; + + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + + int hint = FF_DONTCARE; + switch (request.styleHint) { + case QFont::Helvetica: + hint = FF_SWISS; + break; + case QFont::Times: + hint = FF_ROMAN; + break; + case QFont::Courier: + hint = FF_MODERN; + break; + case QFont::OldEnglish: + hint = FF_DECORATIVE; + break; + case QFont::System: + hint = FF_MODERN; + break; + default: + break; + } + + lf.lfPitchAndFamily = DEFAULT_PITCH | hint; + + QString fam = faceName; + if (fam.isEmpty()) + fam = request.families.size() > 0 ? request.families.at(0) : request.family; + if (Q_UNLIKELY(fam.size() >= LF_FACESIZE)) { + qCritical("%s: Family name '%s' is too long.", __FUNCTION__, qPrintable(fam)); + fam.truncate(LF_FACESIZE - 1); + } + + if (fam.isEmpty()) + fam = QStringLiteral("MS Sans Serif"); + + if (fam == QLatin1String("MS Sans Serif") + && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) { + fam = QStringLiteral("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale + } + if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap)) + fam = QStringLiteral("Courier New"); + + memcpy(lf.lfFaceName, fam.utf16(), fam.size() * sizeof(wchar_t)); + + return lf; +} + +QFont QWindowsFontDatabaseBase::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In) +{ + if (verticalDPI_In <= 0) + verticalDPI_In = defaultVerticalDPI(); + QFont qFont(QString::fromWCharArray(logFont.lfFaceName)); + qFont.setItalic(logFont.lfItalic); + if (logFont.lfWeight != FW_DONTCARE) + qFont.setWeight(QPlatformFontDatabase::weightFromInteger(logFont.lfWeight)); + const qreal logFontHeight = qAbs(logFont.lfHeight); + qFont.setPointSizeF(logFontHeight * 72.0 / qreal(verticalDPI_In)); + qFont.setUnderline(logFont.lfUnderline); + qFont.setOverline(false); + qFont.setStrikeOut(logFont.lfStrikeOut); + return qFont; +} + +// ### fixme Qt 6 (QTBUG-58610): See comment at QWindowsFontDatabase::systemDefaultFont() +HFONT QWindowsFontDatabaseBase::systemFont() +{ + static const auto stock_sysfont = + reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT)); + return stock_sysfont; +} + +QFont QWindowsFontDatabaseBase::systemDefaultFont() +{ +#if QT_VERSION >= 0x060000 + // Qt 6: Obtain default GUI font (typically "Segoe UI, 9pt", see QTBUG-58610) + NONCLIENTMETRICS ncm; + ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); + const QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont); +#else + LOGFONT lf; + GetObject(systemFont(), sizeof(lf), &lf); + QFont systemFont = LOGFONT_to_QFont(lf); + // "MS Shell Dlg 2" is the correct system font >= Win2k + if (systemFont.family() == QLatin1String("MS Shell Dlg")) + systemFont.setFamily(QStringLiteral("MS Shell Dlg 2")); + // Qt 5 by (Qt 4) legacy uses GetStockObject(DEFAULT_GUI_FONT) to + // obtain the default GUI font (typically "MS Shell Dlg 2, 8pt"). This has been + // long deprecated; the message font of the NONCLIENTMETRICS structure obtained by + // SystemParametersInfo(SPI_GETNONCLIENTMETRICS) should be used instead (see + // QWindowsTheme::refreshFonts(), typically "Segoe UI, 9pt"), which is larger. +#endif // Qt 5 + qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont; + return systemFont; +} + +#if !defined(QT_NO_DIRECTWRITE) +IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArray &fontData) const +{ + QSharedPointer<QWindowsFontEngineData> fontEngineData = data(); + if (fontEngineData->directWriteFactory == nullptr) { + qCWarning(lcQpaFonts) << "DirectWrite factory not created in QWindowsFontDatabaseBase::createDirectWriteFace()"; + return nullptr; + } + + CustomFontFileLoader fontFileLoader(fontEngineData->directWriteFactory); + fontFileLoader.addKey(this, fontData); + + IDWriteFontFile *fontFile = nullptr; + const void *key = this; + + HRESULT hres = fontEngineData->directWriteFactory->CreateCustomFontFileReference(&key, + sizeof(void *), + fontFileLoader.loader(), + &fontFile); + if (FAILED(hres)) { + qErrnoWarning(hres, "%s: CreateCustomFontFileReference failed", __FUNCTION__); + return nullptr; + } + + BOOL isSupportedFontType; + DWRITE_FONT_FILE_TYPE fontFileType; + DWRITE_FONT_FACE_TYPE fontFaceType; + UINT32 numberOfFaces; + fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces); + if (!isSupportedFontType) { + fontFile->Release(); + return nullptr; + } + + // ### Currently no support for .ttc, but we could easily return a list here. + IDWriteFontFace *directWriteFontFace = nullptr; + hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType, + 1, + &fontFile, + 0, + DWRITE_FONT_SIMULATIONS_NONE, + &directWriteFontFace); + if (FAILED(hres)) { + qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__); + fontFile->Release(); + return nullptr; + } + + fontFile->Release(); + return directWriteFontFace; +} +#endif // !defined(QT_NO_DIRECTWRITE) + +QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) +{ + QFontEngine *fontEngine = nullptr; + +#if !defined(QT_NO_DIRECTWRITE) + QSharedPointer<QWindowsFontEngineData> fontEngineData = data(); + if (fontEngineData->directWriteFactory == nullptr) + return nullptr; + + IDWriteFontFace *directWriteFontFace = createDirectWriteFace(fontData); + fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace, + pixelSize, + fontEngineData); + + // Get font family from font data + EmbeddedFont font(fontData); + font.updateFromOS2Table(fontEngine); + fontEngine->fontDef.family = font.familyName(); + fontEngine->fontDef.hintingPreference = hintingPreference; + + directWriteFontFace->Release(); +#else // !defined(QT_NO_DIRECTWRITE) + Q_UNUSED(fontData); + Q_UNUSED(pixelSize); + Q_UNUSED(hintingPreference); +#endif + + return fontEngine; +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase_p.h new file mode 100644 index 0000000000..fbaa98b663 --- /dev/null +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase_p.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 QWINDOWSFONTDATABASEBASE_P_H +#define QWINDOWSFONTDATABASEBASE_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 <qpa/qplatformfontdatabase.h> +#include <QtCore/QSharedPointer> +#include <QtCore/QLoggingCategory> +#include <QtCore/qt_windows.h> + +#if !defined(QT_NO_DIRECTWRITE) + struct IDWriteFactory; + struct IDWriteGdiInterop; + struct IDWriteFontFace; +#endif + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcQpaFonts); + +class QWindowsFontEngineData +{ + Q_DISABLE_COPY_MOVE(QWindowsFontEngineData) +public: + QWindowsFontEngineData(); + ~QWindowsFontEngineData(); + + uint pow_gamma[256]; + + bool clearTypeEnabled = false; + qreal fontSmoothingGamma; + HDC hdc = 0; +#if !defined(QT_NO_DIRECTWRITE) + IDWriteFactory *directWriteFactory = nullptr; + IDWriteGdiInterop *directWriteGdiInterop = nullptr; +#endif +}; + +class QWindowsFontDatabaseBase : public QPlatformFontDatabase +{ +public: + QWindowsFontDatabaseBase(); + ~QWindowsFontDatabaseBase() override; + + QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override; + + static int defaultVerticalDPI(); + static QSharedPointer<QWindowsFontEngineData> data(); +#if !defined(QT_NO_DIRECTWRITE) + static void createDirectWriteFactory(IDWriteFactory **factory); +#endif + static QFont systemDefaultFont(); + static HFONT systemFont(); + static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef, const QString &faceName); + static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0); + + class FontTable{}; + class EmbeddedFont + { + public: + EmbeddedFont(const QByteArray &fontData) : m_fontData(fontData) {} + + QString changeFamilyName(const QString &newFamilyName); + QByteArray data() const { return m_fontData; } + void updateFromOS2Table(QFontEngine *fontEngine); + FontTable *tableDirectoryEntry(const QByteArray &tagName); + QString familyName(FontTable *nameTableDirectory = nullptr); + + private: + QByteArray m_fontData; + }; + +protected: + +#if !defined(QT_NO_DIRECTWRITE) + IDWriteFontFace *createDirectWriteFace(const QByteArray &fontData) const; +#endif + +private: + static bool init(QSharedPointer<QWindowsFontEngineData> data); +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSFONTDATABASEBASE_P_H diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp index e796c18e79..45ce396d5e 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp @@ -62,6 +62,9 @@ QT_BEGIN_NAMESPACE +// Clang does not consider __declspec(nothrow) as nothrow +QT_WARNING_DISABLE_CLANG("-Wmicrosoft-exception-spec") + // Convert from design units to logical pixels #define DESIGN_TO_LOGICAL(DESIGN_UNIT_VALUE) \ QFixed::fromReal((qreal(DESIGN_UNIT_VALUE) / qreal(m_unitsPerEm)) * fontDef.pixelSize) @@ -184,6 +187,18 @@ namespace { } +static DWRITE_MEASURING_MODE renderModeToMeasureMode(DWRITE_RENDERING_MODE renderMode) +{ + switch (renderMode) { + case DWRITE_RENDERING_MODE_GDI_CLASSIC: + return DWRITE_MEASURING_MODE_GDI_CLASSIC; + case DWRITE_RENDERING_MODE_GDI_NATURAL: + return DWRITE_MEASURING_MODE_GDI_NATURAL; + default: + return DWRITE_MEASURING_MODE_NATURAL; + } +} + static DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(QFont::HintingPreference hintingPreference) { if (QHighDpiScaling::isActive() && hintingPreference == QFont::PreferDefaultHinting) @@ -206,13 +221,10 @@ static DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(QFont::HintingPref \ingroup qt-lighthouse-win Font engine for subpixel positioned text on Windows Vista - (with platform update) and Windows 7. If selected during + (with platform update) and later. If selected during configuration, the engine will be selected only when the hinting - preference of a font is set to None or Vertical hinting. The font - database uses most of the same logic but creates a direct write - font based on the LOGFONT rather than a GDI handle. - - Will probably be superseded by a common Free Type font engine in Qt 5.X. + preference of a font is set to None or Vertical hinting, or + when fontengine=directwrite is selected as platform option. */ QWindowsFontEngineDirectWrite::QWindowsFontEngineDirectWrite(IDWriteFontFace *directWriteFontFace, @@ -458,7 +470,7 @@ bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGly glyphs->numGlyphs = actualLength; if (!(flags & GlyphIndicesOnly)) - recalcAdvances(glyphs, 0); + recalcAdvances(glyphs, {}); return true; } @@ -477,9 +489,22 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn glyphIndices[i] = UINT16(glyphs->glyphs[i]); QVarLengthArray<DWRITE_GLYPH_METRICS> glyphMetrics(glyphIndices.size()); - HRESULT hr = m_directWriteFontFace->GetDesignGlyphMetrics(glyphIndices.data(), - glyphIndices.size(), - glyphMetrics.data()); + + HRESULT hr; + DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(QFont::HintingPreference(fontDef.hintingPreference)); + if (renderMode == DWRITE_RENDERING_MODE_GDI_CLASSIC || renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL) { + hr = m_directWriteFontFace->GetGdiCompatibleGlyphMetrics(float(fontDef.pixelSize), + 1.0f, + NULL, + TRUE, + glyphIndices.data(), + glyphIndices.size(), + glyphMetrics.data()); + } else { + hr = m_directWriteFontFace->GetDesignGlyphMetrics(glyphIndices.data(), + glyphIndices.size(), + glyphMetrics.data()); + } if (SUCCEEDED(hr)) { qreal stretch = fontDef.stretch != QFont::AnyStretch ? fontDef.stretch / 100.0 : 1.0; for (int i = 0; i < glyphs->numGlyphs; ++i) @@ -685,6 +710,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(QFont::HintingPreference(fontDef.hintingPreference)); + DWRITE_MEASURING_MODE measureMode = + renderModeToMeasureMode(renderMode); IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( @@ -692,7 +719,7 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, 1.0f, &transform, renderMode, - DWRITE_MEASURING_MODE_NATURAL, + measureMode, 0.0, 0.0, &glyphAnalysis ); @@ -722,7 +749,7 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, 0.0f, &glyphRun, NULL, - DWRITE_MEASURING_MODE_NATURAL, + measureMode, NULL, 0, &enumerator); @@ -753,7 +780,7 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, 1.0f, &transform, renderMode, - DWRITE_MEASURING_MODE_NATURAL, + measureMode, 0.0, 0.0, &colorGlyphsAnalysis ); @@ -993,6 +1020,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(QFont::HintingPreference(fontDef.hintingPreference)); + DWRITE_MEASURING_MODE measureMode = renderModeToMeasureMode(renderMode); IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( @@ -1000,7 +1028,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph 1.0f, &transform, renderMode, - DWRITE_MEASURING_MODE_NATURAL, + measureMode, 0.0, 0.0, &glyphAnalysis ); @@ -1012,8 +1040,8 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph int margin = glyphMargin(QFontEngine::Format_A32); - return glyph_metrics_t(rect.left, - rect.top, + return glyph_metrics_t(rect.left - margin, + rect.top - margin, rect.right - rect.left + margin * 2, rect.bottom - rect.top + margin * 2, bbox.xoff, bbox.yoff); diff --git a/src/platformsupport/fontdatabases/windows/windows.pri b/src/platformsupport/fontdatabases/windows/windows.pri index 7ddfb2c281..fbe6d490f9 100644 --- a/src/platformsupport/fontdatabases/windows/windows.pri +++ b/src/platformsupport/fontdatabases/windows/windows.pri @@ -2,11 +2,13 @@ QT *= gui-private SOURCES += \ $$PWD/qwindowsfontdatabase.cpp \ + $$PWD/qwindowsfontdatabasebase.cpp \ $$PWD/qwindowsfontengine.cpp \ $$PWD/qwindowsnativeimage.cpp HEADERS += \ $$PWD/qwindowsfontdatabase_p.h \ + $$PWD/qwindowsfontdatabasebase_p.h \ $$PWD/qwindowsfontengine_p.h \ $$PWD/qwindowsnativeimage_p.h @@ -16,7 +18,13 @@ qtConfig(freetype) { } qtConfig(directwrite):qtConfig(direct2d) { - qtConfig(directwrite2) { + qtConfig(directwrite3) { + QMAKE_USE_PRIVATE += dwrite_3 + DEFINES *= QT_USE_DIRECTWRITE3 QT_USE_DIRECTWRITE2 + + SOURCES += $$PWD/qwindowsdirectwritefontdatabase.cpp + HEADERS += $$PWD/qwindowsdirectwritefontdatabase_p.h + } else: qtConfig(directwrite2) { QMAKE_USE_PRIVATE += dwrite_2 DEFINES *= QT_USE_DIRECTWRITE2 } else { diff --git a/src/platformsupport/glxconvenience/.prev_CMakeLists.txt b/src/platformsupport/glxconvenience/.prev_CMakeLists.txt index ecee19fc8b..f9a2fed5b2 100644 --- a/src/platformsupport/glxconvenience/.prev_CMakeLists.txt +++ b/src/platformsupport/glxconvenience/.prev_CMakeLists.txt @@ -4,22 +4,18 @@ ## GlxSupport Module: ##################################################################### -add_qt_module(GlxSupport +qt_add_module(GlxSupport STATIC INTERNAL_MODULE SOURCES qglxconvenience.cpp qglxconvenience_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui X11::XCB ) #### Keys ignored in scope 1:.:.:glxconvenience.pro:<TRUE>: # MODULE = "glx_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/glxconvenience/CMakeLists.txt b/src/platformsupport/glxconvenience/CMakeLists.txt index ff2357d52c..00bc78d429 100644 --- a/src/platformsupport/glxconvenience/CMakeLists.txt +++ b/src/platformsupport/glxconvenience/CMakeLists.txt @@ -6,22 +6,18 @@ qt_find_package(X11) # special case ## GlxSupport Module: ##################################################################### -add_qt_module(GlxSupport +qt_add_module(GlxSupport STATIC INTERNAL_MODULE SOURCES qglxconvenience.cpp qglxconvenience_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate X11::X11 # special case - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui ) #### Keys ignored in scope 1:.:.:glxconvenience.pro:<TRUE>: # MODULE = "glx_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp index 81bccb1c25..5387214e8c 100644 --- a/src/platformsupport/glxconvenience/qglxconvenience.cpp +++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp @@ -193,7 +193,7 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format { QXcbSoftwareOpenGLEnforcer softwareOpenGLEnforcer; - GLXFBConfig config = 0; + GLXFBConfig config = nullptr; do { const QVector<int> spec = qglx_buildSpec(format, drawableBit, flags); @@ -273,7 +273,7 @@ XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *f { Q_ASSERT(format); - XVisualInfo *visualInfo = 0; + XVisualInfo *visualInfo = nullptr; GLXFBConfig config = qglx_findConfig(display, screen, *format, false, drawableBit, flags); if (config) diff --git a/src/platformsupport/graphics/CMakeLists.txt b/src/platformsupport/graphics/CMakeLists.txt index f342fd0c08..e9f0245dbe 100644 --- a/src/platformsupport/graphics/CMakeLists.txt +++ b/src/platformsupport/graphics/CMakeLists.txt @@ -4,21 +4,17 @@ ## GraphicsSupport Module: ##################################################################### -add_qt_module(GraphicsSupport +qt_add_module(GraphicsSupport STATIC INTERNAL_MODULE SOURCES qrasterbackingstore.cpp qrasterbackingstore_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui ) #### Keys ignored in scope 1:.:.:graphics.pro:<TRUE>: # MODULE = "graphics_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/input/.prev_CMakeLists.txt b/src/platformsupport/input/.prev_CMakeLists.txt index 1d5270f234..f8c05e9f97 100644 --- a/src/platformsupport/input/.prev_CMakeLists.txt +++ b/src/platformsupport/input/.prev_CMakeLists.txt @@ -4,31 +4,26 @@ ## InputSupport Module: ##################################################################### -add_qt_module(InputSupport +qt_add_module(InputSupport STATIC INTERNAL_MODULE DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::DeviceDiscoverySupportPrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::DeviceDiscoverySupport - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 3:.:.:input-support.pro:<TRUE>: # MODULE = "input_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(InputSupport CONDITION QT_FEATURE_evdev +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev SOURCES evdevkeyboard/qevdevkeyboard_defaultmap_p.h evdevkeyboard/qevdevkeyboardhandler.cpp evdevkeyboard/qevdevkeyboardhandler_p.h @@ -41,35 +36,35 @@ extend_target(InputSupport CONDITION QT_FEATURE_evdev evdevtouch/../shared ) -extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_tabletevent +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_tabletevent SOURCES evdevtablet/qevdevtablethandler.cpp evdevtablet/qevdevtablethandler_p.h evdevtablet/qevdevtabletmanager.cpp evdevtablet/qevdevtabletmanager_p.h ) -extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_libudev AND QT_FEATURE_tabletevent +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_libudev AND QT_FEATURE_tabletevent LIBRARIES PkgConfig::Libudev ) -extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_libudev +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_libudev LIBRARIES PkgConfig::Libudev ) -extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_mtdev +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_mtdev LIBRARIES PkgConfig::Mtdev ) -extend_target(InputSupport CONDITION QT_FEATURE_tslib +qt_extend_target(InputSupport CONDITION QT_FEATURE_tslib SOURCES tslib/qtslib.cpp tslib/qtslib_p.h PUBLIC_LIBRARIES PkgConfig::Tslib ) -extend_target(InputSupport CONDITION QT_FEATURE_libinput +qt_extend_target(InputSupport CONDITION QT_FEATURE_libinput SOURCES libinput/qlibinputhandler.cpp libinput/qlibinputhandler_p.h libinput/qlibinputkeyboard.cpp libinput/qlibinputkeyboard_p.h @@ -82,22 +77,21 @@ extend_target(InputSupport CONDITION QT_FEATURE_libinput PkgConfig::Libudev ) -extend_target(InputSupport CONDITION QT_FEATURE_libinput AND QT_FEATURE_xkbcommon +qt_extend_target(InputSupport CONDITION QT_FEATURE_libinput AND QT_FEATURE_xkbcommon LIBRARIES - Qt::XkbCommonSupportPrivate XKB::XKB PUBLIC_LIBRARIES - Qt::XkbCommonSupport + Qt::XkbCommonSupportPrivate ) -extend_target(InputSupport CONDITION QT_FEATURE_evdev OR QT_FEATURE_libinput +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev OR QT_FEATURE_libinput SOURCES shared/devicehandlerlist_p.h shared/qevdevutil.cpp shared/qevdevutil_p.h shared/qtouchoutputmapping.cpp shared/qtouchoutputmapping_p.h ) -extend_target(InputSupport CONDITION QT_FEATURE_integrityhid +qt_extend_target(InputSupport CONDITION QT_FEATURE_integrityhid SOURCES integrityhid/qintegrityhidmanager.cpp integrityhid/qintegrityhidmanager.h LIBRARIES diff --git a/src/platformsupport/input/CMakeLists.txt b/src/platformsupport/input/CMakeLists.txt index 3c5cbaa4ce..7ab93df062 100644 --- a/src/platformsupport/input/CMakeLists.txt +++ b/src/platformsupport/input/CMakeLists.txt @@ -9,31 +9,26 @@ qt_find_package(Mtdev) # special case ## InputSupport Module: ##################################################################### -add_qt_module(InputSupport +qt_add_module(InputSupport STATIC INTERNAL_MODULE DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::DeviceDiscoverySupportPrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::DeviceDiscoverySupport - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 3:.:.:input-support.pro:<TRUE>: # MODULE = "input_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(InputSupport CONDITION QT_FEATURE_evdev +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev SOURCES evdevkeyboard/qevdevkeyboard_defaultmap_p.h evdevkeyboard/qevdevkeyboardhandler.cpp evdevkeyboard/qevdevkeyboardhandler_p.h @@ -46,35 +41,35 @@ extend_target(InputSupport CONDITION QT_FEATURE_evdev evdevtouch/../shared ) -extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_tabletevent +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_tabletevent SOURCES evdevtablet/qevdevtablethandler.cpp evdevtablet/qevdevtablethandler_p.h evdevtablet/qevdevtabletmanager.cpp evdevtablet/qevdevtabletmanager_p.h ) -extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_libudev AND QT_FEATURE_tabletevent +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_libudev AND QT_FEATURE_tabletevent LIBRARIES PkgConfig::Libudev ) -extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_libudev +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_libudev LIBRARIES PkgConfig::Libudev ) -extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_mtdev +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev AND QT_FEATURE_mtdev LIBRARIES PkgConfig::Mtdev ) -extend_target(InputSupport CONDITION QT_FEATURE_tslib +qt_extend_target(InputSupport CONDITION QT_FEATURE_tslib SOURCES tslib/qtslib.cpp tslib/qtslib_p.h PUBLIC_LIBRARIES PkgConfig::Tslib ) -extend_target(InputSupport CONDITION QT_FEATURE_libinput +qt_extend_target(InputSupport CONDITION QT_FEATURE_libinput SOURCES libinput/qlibinputhandler.cpp libinput/qlibinputhandler_p.h libinput/qlibinputkeyboard.cpp libinput/qlibinputkeyboard_p.h @@ -87,22 +82,21 @@ extend_target(InputSupport CONDITION QT_FEATURE_libinput PkgConfig::Libudev ) -extend_target(InputSupport CONDITION QT_FEATURE_libinput AND QT_FEATURE_xkbcommon +qt_extend_target(InputSupport CONDITION QT_FEATURE_libinput AND QT_FEATURE_xkbcommon LIBRARIES - Qt::XkbCommonSupportPrivate XKB::XKB PUBLIC_LIBRARIES - Qt::XkbCommonSupport + Qt::XkbCommonSupportPrivate ) -extend_target(InputSupport CONDITION QT_FEATURE_evdev OR QT_FEATURE_libinput +qt_extend_target(InputSupport CONDITION QT_FEATURE_evdev OR QT_FEATURE_libinput SOURCES shared/devicehandlerlist_p.h shared/qevdevutil.cpp shared/qevdevutil_p.h shared/qtouchoutputmapping.cpp shared/qtouchoutputmapping_p.h ) -extend_target(InputSupport CONDITION QT_FEATURE_integrityhid +qt_extend_target(InputSupport CONDITION QT_FEATURE_integrityhid SOURCES integrityhid/qintegrityhidmanager.cpp integrityhid/qintegrityhidmanager.h LIBRARIES diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp index 6a53ad2088..a729eeb851 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp @@ -99,8 +99,7 @@ std::unique_ptr<QEvdevMouseHandler> QEvdevMouseHandler::create(const QString &de } QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool abs, bool compression, int jitterLimit) - : m_device(device), m_fd(fd), m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0), - m_abs(abs), m_compression(compression), m_buttons(0), m_prevInvalid(true) + : m_device(device), m_fd(fd), m_abs(abs), m_compression(compression) { setObjectName(QLatin1String("Evdev Mouse Handler")); diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h index 727f1a02f9..93314e885f 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h @@ -84,16 +84,16 @@ private: QString m_device; int m_fd; - QSocketNotifier *m_notify; - int m_x, m_y; - int m_prevx, m_prevy; + QSocketNotifier *m_notify = nullptr; + int m_x = 0, m_y = 0; + int m_prevx = 0, m_prevy = 0; bool m_abs; bool m_compression; Qt::MouseButtons m_buttons; Qt::MouseButton m_button; QEvent::Type m_eventType; int m_jitterLimitSquared; - bool m_prevInvalid; + bool m_prevInvalid = true; int m_hardwareWidth; int m_hardwareHeight; qreal m_hardwareScalerY; diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp index c51db59e1f..78728ef4ce 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp @@ -113,16 +113,13 @@ public: QList<QWindowSystemInterface::TouchPoint> m_lastTouchPoints; struct Contact { - int trackingId; - int x; - int y; - int maj; - int pressure; - Qt::TouchPointState state; + int trackingId = -1; + int x = 0; + int y = 0; + int maj = -1; + int pressure = 0; + Qt::TouchPointState state = Qt::TouchPointPressed; QTouchEvent::TouchPoint::InfoFlags flags; - Contact() : trackingId(-1), - x(0), y(0), maj(-1), pressure(0), - state(Qt::TouchPointPressed), flags(0) { } }; QHash<int, Contact> m_contacts; // The key is a tracking id for type A, slot number for type B. QHash<int, Contact> m_lastContacts; diff --git a/src/platformsupport/input/integrityhid/qintegrityhidmanager.h b/src/platformsupport/input/integrityhid/qintegrityhidmanager.h index 36d7587457..fde5fd7dbb 100644 --- a/src/platformsupport/input/integrityhid/qintegrityhidmanager.h +++ b/src/platformsupport/input/integrityhid/qintegrityhidmanager.h @@ -52,7 +52,7 @@ class QIntegrityHIDManager : public QThread { Q_OBJECT public: - QIntegrityHIDManager(const QString &key, const QString &specification, QObject *parent = 0); + QIntegrityHIDManager(const QString &key, const QString &specification, QObject *parent = nullptr); ~QIntegrityHIDManager(); void run(void); diff --git a/src/platformsupport/input/libinput/qlibinputtouch.cpp b/src/platformsupport/input/libinput/qlibinputtouch.cpp index a65bc91c39..446218e4b3 100644 --- a/src/platformsupport/input/libinput/qlibinputtouch.cpp +++ b/src/platformsupport/input/libinput/qlibinputtouch.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qlibinputtouch_p.h" +#include "qtouchoutputmapping_p.h" #include <libinput.h> #include <QtGui/QGuiApplication> #include <QtGui/QScreen> @@ -45,6 +46,8 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(qLcLibInput) + QWindowSystemInterface::TouchPoint *QLibInputTouch::DeviceState::point(int32_t slot) { const int id = qMax(0, slot); @@ -62,12 +65,23 @@ QLibInputTouch::DeviceState *QLibInputTouch::deviceState(libinput_event_touch *e return &m_devState[dev]; } -static inline QPointF getPos(libinput_event_touch *e) +QPointF QLibInputTouch::getPos(libinput_event_touch *e) { - // TODO Map to correct screen using QTouchOutputMapping. - // Perhaps investigate libinput_device_get_output_name as well. - // For now just use the primary screen. + DeviceState *state = deviceState(e); QScreen *screen = QGuiApplication::primaryScreen(); + if (!state->m_screenName.isEmpty()) { + if (!m_screen) { + const QList<QScreen *> screens = QGuiApplication::screens(); + for (QScreen *s : screens) { + if (s->name() == state->m_screenName) { + m_screen = s; + break; + } + } + } + if (m_screen) + screen = m_screen; + } const QRect geom = QHighDpi::toNativePixels(screen->geometry(), screen); const double x = libinput_event_touch_get_x_transformed(e, geom.width()); const double y = libinput_event_touch_get_y_transformed(e, geom.height()); @@ -76,9 +90,25 @@ static inline QPointF getPos(libinput_event_touch *e) void QLibInputTouch::registerDevice(libinput_device *dev) { + struct udev_device *udev_device; + udev_device = libinput_device_get_udev_device(dev); + QString devNode = QString::fromUtf8(udev_device_get_devnode(udev_device)); + QString devName = QString::fromUtf8(libinput_device_get_name(dev)); + + qCDebug(qLcLibInput, "libinput: registerDevice %s - %s", + qPrintable(devNode), qPrintable(devName)); + + QTouchOutputMapping mapping; + if (mapping.load()) { + m_devState[dev].m_screenName = mapping.screenNameForDeviceNode(devNode); + if (!m_devState[dev].m_screenName.isEmpty()) + qCDebug(qLcLibInput, "libinput: Mapping device %s to screen %s", + qPrintable(devNode), qPrintable(m_devState[dev].m_screenName)); + } + QTouchDevice *&td = m_devState[dev].m_touchDevice; td = new QTouchDevice; - td->setName(QString::fromUtf8(libinput_device_get_name(dev))); + td->setName(devName); td->setType(QTouchDevice::TouchScreen); td->setCapabilities(QTouchDevice::Position | QTouchDevice::Area); QWindowSystemInterface::registerTouchDevice(td); @@ -113,16 +143,16 @@ void QLibInputTouch::processTouchMotion(libinput_event_touch *e) DeviceState *state = deviceState(e); QWindowSystemInterface::TouchPoint *tp = state->point(slot); if (tp) { + Qt::TouchPointState tmpState = Qt::TouchPointMoved; const QPointF p = getPos(e); - if (tp->area.center() != p) { + if (tp->area.center() == p) + tmpState = Qt::TouchPointStationary; + else tp->area.moveCenter(p); - // 'down' may be followed by 'motion' within the same "frame". - // Handle this by compressing and keeping the Pressed state until the 'frame'. - if (tp->state != Qt::TouchPointPressed) - tp->state = Qt::TouchPointMoved; - } else { - tp->state = Qt::TouchPointStationary; - } + // 'down' may be followed by 'motion' within the same "frame". + // Handle this by compressing and keeping the Pressed state until the 'frame'. + if (tp->state != Qt::TouchPointPressed && tp->state != Qt::TouchPointReleased) + tp->state = tmpState; } else { qWarning("Inconsistent touch state (got 'motion' without 'down')"); } @@ -136,7 +166,7 @@ void QLibInputTouch::processTouchUp(libinput_event_touch *e) if (tp) { tp->state = Qt::TouchPointReleased; // There may not be a Frame event after the last Up. Work this around. - Qt::TouchPointStates s = 0; + Qt::TouchPointStates s; for (int i = 0; i < state->m_points.count(); ++i) s |= state->m_points.at(i).state; if (s == Qt::TouchPointReleased) diff --git a/src/platformsupport/input/libinput/qlibinputtouch_p.h b/src/platformsupport/input/libinput/qlibinputtouch_p.h index 51304e6a21..2682b83b26 100644 --- a/src/platformsupport/input/libinput/qlibinputtouch_p.h +++ b/src/platformsupport/input/libinput/qlibinputtouch_p.h @@ -42,6 +42,7 @@ #include <QtCore/QHash> #include <QtCore/QList> +#include <QtCore/QPointer> #include <qpa/qwindowsysteminterface.h> // @@ -60,6 +61,7 @@ struct libinput_device; QT_BEGIN_NAMESPACE +class QScreen; class QLibInputTouch { public: @@ -73,15 +75,18 @@ public: private: struct DeviceState { - DeviceState() : m_touchDevice(nullptr) { } + DeviceState() : m_touchDevice(nullptr), m_screenName() { } QWindowSystemInterface::TouchPoint *point(int32_t slot); QList<QWindowSystemInterface::TouchPoint> m_points; QTouchDevice *m_touchDevice; + QString m_screenName; }; DeviceState *deviceState(libinput_event_touch *e); + QPointF getPos(libinput_event_touch *e); QHash<libinput_device *, DeviceState> m_devState; + mutable QPointer<QScreen> m_screen; }; QT_END_NAMESPACE diff --git a/src/platformsupport/input/xkbcommon/CMakeLists.txt b/src/platformsupport/input/xkbcommon/CMakeLists.txt index 958e00fd06..86d132d912 100644 --- a/src/platformsupport/input/xkbcommon/CMakeLists.txt +++ b/src/platformsupport/input/xkbcommon/CMakeLists.txt @@ -4,7 +4,7 @@ ## XkbCommonSupport Module: ##################################################################### -add_qt_module(XkbCommonSupport +qt_add_module(XkbCommonSupport STATIC INTERNAL_MODULE SOURCES @@ -12,12 +12,9 @@ add_qt_module(XkbCommonSupport qxkbcommon_3rdparty.cpp DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui XKB::XKB PRECOMPILED_HEADER "../../../corelib/global/qt_pch.h" @@ -25,12 +22,11 @@ add_qt_module(XkbCommonSupport #### Keys ignored in scope 1:.:.:xkbcommon.pro:<TRUE>: # MODULE = "xkbcommon_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(XkbCommonSupport CONDITION CLANG AND NOT ICC +qt_extend_target(XkbCommonSupport CONDITION CLANG AND NOT ICC COMPILE_OPTIONS -ftemplate-depth=1024 ) diff --git a/src/platformsupport/kmsconvenience/.prev_CMakeLists.txt b/src/platformsupport/kmsconvenience/.prev_CMakeLists.txt index a595aa40c8..5b0fd00566 100644 --- a/src/platformsupport/kmsconvenience/.prev_CMakeLists.txt +++ b/src/platformsupport/kmsconvenience/.prev_CMakeLists.txt @@ -4,22 +4,18 @@ ## KmsSupport Module: ##################################################################### -add_qt_module(KmsSupport +qt_add_module(KmsSupport STATIC INTERNAL_MODULE SOURCES qkmsdevice.cpp qkmsdevice_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES - Qt::CorePrivate - Qt::GuiPrivate PUBLIC_LIBRARIES Libdrm::Libdrm - Qt::Core - Qt::Gui + Qt::CorePrivate + Qt::GuiPrivate ) #### Keys ignored in scope 1:.:.:kmsconvenience.pro:<TRUE>: # MODULE = "kms_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/kmsconvenience/CMakeLists.txt b/src/platformsupport/kmsconvenience/CMakeLists.txt index 9ea4842e52..8001ee27de 100644 --- a/src/platformsupport/kmsconvenience/CMakeLists.txt +++ b/src/platformsupport/kmsconvenience/CMakeLists.txt @@ -6,22 +6,18 @@ qt_find_package(Libdrm) # special case ## KmsSupport Module: ##################################################################### -add_qt_module(KmsSupport +qt_add_module(KmsSupport STATIC INTERNAL_MODULE SOURCES qkmsdevice.cpp qkmsdevice_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES - Qt::CorePrivate - Qt::GuiPrivate PUBLIC_LIBRARIES Libdrm::Libdrm - Qt::Core - Qt::Gui + Qt::CorePrivate + Qt::GuiPrivate ) #### Keys ignored in scope 1:.:.:kmsconvenience.pro:<TRUE>: # MODULE = "kms_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp index 06d1251a65..8cd7f9b368 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp +++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp @@ -176,6 +176,15 @@ static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode) return true; } +static inline void assignPlane(QKmsOutput *output, QKmsPlane *plane) +{ + if (output->eglfs_plane) + output->eglfs_plane->activeCrtcId = 0; + + plane->activeCrtcId = output->crtc_id; + output->eglfs_plane = plane; +} + QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, ScreenInfo *vinfo) @@ -253,7 +262,7 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, // Get the current mode on the current crtc drmModeModeInfo crtc_mode; memset(&crtc_mode, 0, sizeof crtc_mode); - if (drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->connector_id)) { + if (drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoder_id)) { drmModeCrtcPtr crtc = drmModeGetCrtc(m_dri_fd, encoder->crtc_id); drmModeFreeEncoder(encoder); @@ -449,13 +458,16 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, #endif QString planeListStr; - for (const QKmsPlane &plane : qAsConst(m_planes)) { + for (QKmsPlane &plane : m_planes) { if (plane.possibleCrtcs & (1 << output.crtc_index)) { output.available_planes.append(plane); planeListStr.append(QString::number(plane.id)); planeListStr.append(QLatin1Char(' ')); - if (plane.type == QKmsPlane::PrimaryPlane) - output.eglfs_plane = (QKmsPlane*)&plane; + + // Choose the first primary plane that is not already assigned to + // another screen's associated crtc. + if (!output.eglfs_plane && plane.type == QKmsPlane::PrimaryPlane && !plane.activeCrtcId) + assignPlane(&output, &plane); } } qCDebug(qLcKmsDebug, "Output %s can use %d planes: %s", @@ -477,9 +489,11 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, qCDebug(qLcKmsDebug, "Forcing plane index %d, plane id %u (belongs to crtc id %u)", idx, plane->plane_id, plane->crtc_id); - for (const QKmsPlane &kmsplane : qAsConst(m_planes)) { - if (kmsplane.id == output.forced_plane_id) - output.eglfs_plane = (QKmsPlane*)&kmsplane; + for (QKmsPlane &kmsplane : m_planes) { + if (kmsplane.id == output.forced_plane_id) { + assignPlane(&output, &kmsplane); + break; + } } drmModeFreePlane(plane); @@ -490,8 +504,37 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, } } - if (output.eglfs_plane) - qCDebug(qLcKmsDebug, "Output eglfs plane is: %d", output.eglfs_plane->id); + // A more useful version: allows specifying "crtc_id,plane_id:crtc_id,plane_id:..." + // in order to allow overriding the plane used for a given crtc. + if (qEnvironmentVariableIsSet("QT_QPA_EGLFS_KMS_PLANES_FOR_CRTCS")) { + const QString val = qEnvironmentVariable("QT_QPA_EGLFS_KMS_PLANES_FOR_CRTCS"); + qCDebug(qLcKmsDebug, "crtc_id:plane_id override list: %s", qPrintable(val)); + const QStringList crtcPlanePairs = val.split(QLatin1Char(':')); + for (const QString &crtcPlanePair : crtcPlanePairs) { + const QStringList values = crtcPlanePair.split(QLatin1Char(',')); + if (values.count() == 2 && uint(values[0].toInt()) == output.crtc_id) { + uint planeId = values[1].toInt(); + for (QKmsPlane &kmsplane : m_planes) { + if (kmsplane.id == planeId) { + assignPlane(&output, &kmsplane); + break; + } + } + } + } + } + + if (output.eglfs_plane) { + qCDebug(qLcKmsDebug, "Chose plane %u for output %s (crtc id %u) (may not be applicable)", + output.eglfs_plane->id, connectorName.constData(), output.crtc_id); + } + +#if QT_CONFIG(drm_atomic) + if (hasAtomicSupport() && !output.eglfs_plane) { + qCDebug(qLcKmsDebug, "No plane associated with output %s (crtc id %u) and atomic modesetting is enabled. This is bad.", + connectorName.constData(), output.crtc_id); + } +#endif m_crtc_allocator |= (1 << output.crtc_index); @@ -538,10 +581,6 @@ QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path) , m_path(path) , m_dri_fd(-1) , m_has_atomic_support(false) -#if QT_CONFIG(drm_atomic) - , m_atomic_request(nullptr) - , m_previous_request(nullptr) -#endif , m_crtc_allocator(0) { if (m_path.isEmpty()) { @@ -557,7 +596,7 @@ QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path) QKmsDevice::~QKmsDevice() { #if QT_CONFIG(drm_atomic) - atomicReset(); + threadLocalAtomicReset(); #endif } @@ -834,7 +873,7 @@ void QKmsDevice::discoverPlanes() plane.type = QKmsPlane::Type(value); } else if (!strcmp(prop->name, "rotation")) { plane.initialRotation = QKmsPlane::Rotations(int(value)); - plane.availableRotations = 0; + plane.availableRotations = { }; if (propTypeIs(prop, DRM_MODE_PROP_BITMASK)) { for (int i = 0; i < prop->count_enums; ++i) plane.availableRotations |= QKmsPlane::Rotation(1 << prop->enums[i].value); @@ -897,39 +936,51 @@ bool QKmsDevice::hasAtomicSupport() } #if QT_CONFIG(drm_atomic) -drmModeAtomicReq * QKmsDevice::atomic_request() +drmModeAtomicReq *QKmsDevice::threadLocalAtomicRequest() { - if (!m_atomic_request && m_has_atomic_support) - m_atomic_request = drmModeAtomicAlloc(); + if (!m_has_atomic_support) + return nullptr; + + AtomicReqs &a(m_atomicReqs.localData()); + if (!a.request) + a.request = drmModeAtomicAlloc(); - return m_atomic_request; + return a.request; } -bool QKmsDevice::atomicCommit(void *user_data) +bool QKmsDevice::threadLocalAtomicCommit(void *user_data) { - if (m_atomic_request) { - int ret = drmModeAtomicCommit(m_dri_fd, m_atomic_request, - DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET, user_data); + if (!m_has_atomic_support) + return false; - if (ret) { - qWarning("Failed to commit atomic request (code=%d)", ret); - return false; - } + AtomicReqs &a(m_atomicReqs.localData()); + if (!a.request) + return false; - m_previous_request = m_atomic_request; - m_atomic_request = nullptr; + int ret = drmModeAtomicCommit(m_dri_fd, a.request, + DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET, + user_data); - return true; + if (ret) { + qWarning("Failed to commit atomic request (code=%d)", ret); + return false; } - return false; + a.previous_request = a.request; + a.request = nullptr; + + return true; } -void QKmsDevice::atomicReset() +void QKmsDevice::threadLocalAtomicReset() { - if (m_previous_request) { - drmModeAtomicFree(m_previous_request); - m_previous_request = nullptr; + if (!m_has_atomic_support) + return; + + AtomicReqs &a(m_atomicReqs.localData()); + if (a.previous_request) { + drmModeAtomicFree(a.previous_request); + a.previous_request = nullptr; } } #endif diff --git a/src/platformsupport/kmsconvenience/qkmsdevice_p.h b/src/platformsupport/kmsconvenience/qkmsdevice_p.h index b1150e2875..55a590cfce 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice_p.h +++ b/src/platformsupport/kmsconvenience/qkmsdevice_p.h @@ -57,6 +57,7 @@ #include <qpa/qplatformscreen.h> #include <QtCore/QMap> #include <QtCore/QVariant> +#include <QtCore/QThreadStorage> #include <xf86drm.h> #include <xf86drmMode.h> @@ -179,6 +180,8 @@ struct QKmsPlane uint32_t crtcheightPropertyId = 0; uint32_t zposPropertyId = 0; uint32_t blendOpPropertyId = 0; + + uint32_t activeCrtcId = 0; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QKmsPlane::Rotations) @@ -239,10 +242,9 @@ public: bool hasAtomicSupport(); #if QT_CONFIG(drm_atomic) - bool atomicCommit(void *user_data); - void atomicReset(); - - drmModeAtomicReq *atomic_request(); + drmModeAtomicReq *threadLocalAtomicRequest(); + bool threadLocalAtomicCommit(void *user_data); + void threadLocalAtomicReset(); #endif void createScreens(); @@ -282,8 +284,11 @@ protected: bool m_has_atomic_support; #if QT_CONFIG(drm_atomic) - drmModeAtomicReq *m_atomic_request; - drmModeAtomicReq *m_previous_request; + struct AtomicReqs { + drmModeAtomicReq *request = nullptr; + drmModeAtomicReq *previous_request = nullptr; + }; + QThreadStorage<AtomicReqs> m_atomicReqs; #endif quint32 m_crtc_allocator; diff --git a/src/platformsupport/linuxaccessibility/.prev_CMakeLists.txt b/src/platformsupport/linuxaccessibility/.prev_CMakeLists.txt index c6f7aba91b..38d3d2831f 100644 --- a/src/platformsupport/linuxaccessibility/.prev_CMakeLists.txt +++ b/src/platformsupport/linuxaccessibility/.prev_CMakeLists.txt @@ -4,7 +4,7 @@ ## LinuxAccessibilitySupport Module: ##################################################################### -add_qt_module(LinuxAccessibilitySupport +qt_add_module(LinuxAccessibilitySupport STATIC INTERNAL_MODULE SOURCES @@ -27,20 +27,15 @@ add_qt_module(LinuxAccessibilitySupport "-i" "struct_marshallers_p.h" DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES - Qt::AccessibilitySupportPrivate - Qt::CorePrivate - Qt::GuiPrivate PUBLIC_LIBRARIES PkgConfig::ATSPI2_nolink - Qt::AccessibilitySupport - Qt::Core + Qt::AccessibilitySupportPrivate + Qt::CorePrivate Qt::DBus - Qt::Gui + Qt::GuiPrivate PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:linuxaccessibility.pro:<TRUE>: # MODULE = "linuxaccessibility_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/linuxaccessibility/CMakeLists.txt b/src/platformsupport/linuxaccessibility/CMakeLists.txt index 22681afa60..35bfdabf5f 100644 --- a/src/platformsupport/linuxaccessibility/CMakeLists.txt +++ b/src/platformsupport/linuxaccessibility/CMakeLists.txt @@ -6,7 +6,7 @@ qt_find_package(ATSPI2) # special case ## LinuxAccessibilitySupport Module: ##################################################################### -add_qt_module(LinuxAccessibilitySupport +qt_add_module(LinuxAccessibilitySupport STATIC INTERNAL_MODULE SOURCES @@ -29,20 +29,15 @@ add_qt_module(LinuxAccessibilitySupport "-i" "struct_marshallers_p.h" DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES - Qt::AccessibilitySupportPrivate - Qt::CorePrivate - Qt::GuiPrivate PUBLIC_LIBRARIES PkgConfig::ATSPI2_nolink - Qt::AccessibilitySupport - Qt::Core + Qt::AccessibilitySupportPrivate + Qt::CorePrivate Qt::DBus - Qt::Gui + Qt::GuiPrivate PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:linuxaccessibility.pro:<TRUE>: # MODULE = "linuxaccessibility_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp index 8a825f8284..012edc82e4 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp @@ -958,7 +958,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) textRemoved = textEvent->textRemoved(); changePosition = textEvent->changePosition(); cursorPosition = textEvent->cursorPosition(); - } else if (event->type() == QAccessible::TextInserted) { + } else if (event->type() == QAccessible::TextUpdated) { QAccessibleTextUpdateEvent *textEvent = static_cast<QAccessibleTextUpdateEvent*>(event); textInserted = textEvent->textInserted(); textRemoved = textEvent->textRemoved(); @@ -2230,7 +2230,7 @@ bool AtSpiAdaptor::valueInterface(QAccessibleInterface *interface, const QString return false; if (function == QLatin1String("SetCurrentValue")) { - QDBusVariant v = message.arguments().at(2).value<QDBusVariant>(); + QDBusVariant v = qvariant_cast<QDBusVariant>(message.arguments().at(2)); double value = v.variant().toDouble(); //Temporary fix //See https://bugzilla.gnome.org/show_bug.cgi?id=652596 @@ -2250,7 +2250,7 @@ bool AtSpiAdaptor::valueInterface(QAccessibleInterface *interface, const QString qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::valueInterface does not implement " << function << message.path(); return false; } - if (!value.canConvert(QVariant::Double)) { + if (!value.canConvert(QMetaType::Double)) { qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::valueInterface: Could not convert to double: " << function; } diff --git a/src/platformsupport/linuxofono/CMakeLists.txt b/src/platformsupport/linuxofono/CMakeLists.txt new file mode 100644 index 0000000000..ba8bc97dd6 --- /dev/null +++ b/src/platformsupport/linuxofono/CMakeLists.txt @@ -0,0 +1,20 @@ +# Generated from linuxofono.pro. + +##################################################################### +## LinuxOfonoSupport Module: +##################################################################### + +add_qt_module(LinuxOfonoSupport + STATIC + INTERNAL_MODULE + SOURCES + qofonoservice_linux.cpp qofonoservice_linux_p.h + DEFINES + QT_NO_CAST_FROM_ASCII + PUBLIC_LIBRARIES + Qt::Core + Qt::DBus +) + +#### Keys ignored in scope 1:.:.:linuxofono.pro:<TRUE>: +# MODULE = "linuxofono_support" diff --git a/src/platformsupport/linuxofono/linuxofono.pro b/src/platformsupport/linuxofono/linuxofono.pro new file mode 100644 index 0000000000..1bc5b10225 --- /dev/null +++ b/src/platformsupport/linuxofono/linuxofono.pro @@ -0,0 +1,15 @@ +TARGET = QtLinuxOfonoSupport +MODULE = linuxofono_support + +QT = core dbus +CONFIG += static internal_module + +DEFINES += QT_NO_CAST_FROM_ASCII + +HEADERS += \ + qofonoservice_linux_p.h + +SOURCES += \ + qofonoservice_linux.cpp + +load(qt_module) diff --git a/src/platformsupport/linuxofono/qofonoservice_linux.cpp b/src/platformsupport/linuxofono/qofonoservice_linux.cpp new file mode 100644 index 0000000000..792c703966 --- /dev/null +++ b/src/platformsupport/linuxofono/qofonoservice_linux.cpp @@ -0,0 +1,384 @@ +/**************************************************************************** +** +** 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 <QObject> +#include <QList> +#include <QtDBus/QtDBus> +#include <QtDBus/QDBusConnection> +#include <QtDBus/QDBusError> +#include <QtDBus/QDBusInterface> +#include <QtDBus/QDBusMessage> +#include <QtDBus/QDBusReply> +#include <QtDBus/QDBusPendingCallWatcher> +#include <QtDBus/QDBusObjectPath> +#include <QtDBus/QDBusPendingCall> + +#include "qofonoservice_linux_p.h" + +#ifndef QT_NO_DBUS + +QDBusArgument &operator<<(QDBusArgument &argument, const ObjectPathProperties &item) +{ + argument.beginStructure(); + argument << item.path << item.properties; + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, ObjectPathProperties &item) +{ + argument.beginStructure(); + argument >> item.path >> item.properties; + argument.endStructure(); + return argument; +} + +QT_BEGIN_NAMESPACE + +QOfonoManagerInterface::QOfonoManagerInterface( QObject *parent) + : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE), + QLatin1String(OFONO_MANAGER_PATH), + OFONO_MANAGER_INTERFACE, + QDBusConnection::systemBus(), parent) +{ + qDBusRegisterMetaType<ObjectPathProperties>(); + qDBusRegisterMetaType<PathPropertiesList>(); + + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), + QLatin1String(OFONO_MANAGER_PATH), + QLatin1String(OFONO_MANAGER_INTERFACE), + QLatin1String("ModemAdded"), + this,SLOT(modemAdded(QDBusObjectPath,QVariantMap))); + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), + QLatin1String(OFONO_MANAGER_PATH), + QLatin1String(OFONO_MANAGER_INTERFACE), + QLatin1String("ModemRemoved"), + this,SLOT(modemRemoved(QDBusObjectPath))); +} + +QOfonoManagerInterface::~QOfonoManagerInterface() +{ +} + +QStringList QOfonoManagerInterface::getModems() +{ + if (modemList.isEmpty()) { + QDBusPendingReply<PathPropertiesList> reply = call(QDBus::Block, QLatin1String("GetModems")); + reply.waitForFinished(); + if (!reply.isError()) { + const auto modems = reply.value(); + for (const ObjectPathProperties &modem : modems) + modemList << modem.path.path(); + } + } + + return modemList; +} + +QString QOfonoManagerInterface::currentModem() +{ + const QStringList modems = getModems(); + for (const QString &modem : modems) { + QOfonoModemInterface device(modem); + if (device.isPowered() && device.isOnline() + && device.interfaces().contains(QLatin1String("org.ofono.NetworkRegistration"))) + return modem; + } + return QString(); +} + +void QOfonoManagerInterface::modemAdded(const QDBusObjectPath &path, const QVariantMap &/*var*/) +{ + if (!modemList.contains(path.path())) { + modemList << path.path(); + Q_EMIT modemChanged(); + } +} + +void QOfonoManagerInterface::modemRemoved(const QDBusObjectPath &path) +{ + if (modemList.contains(path.path())) { + modemList.removeOne(path.path()); + Q_EMIT modemChanged(); + } +} + + +QOfonoModemInterface::QOfonoModemInterface(const QString &dbusPathName, QObject *parent) + : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE), + dbusPathName, + OFONO_MODEM_INTERFACE, + QDBusConnection::systemBus(), parent) +{ + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), + path(), + QLatin1String(OFONO_MODEM_INTERFACE), + QLatin1String("PropertyChanged"), + this,SLOT(propertyChanged(QString,QDBusVariant))); +} + +QOfonoModemInterface::~QOfonoModemInterface() +{ +} + +void QOfonoModemInterface::propertyChanged(const QString &name,const QDBusVariant &value) +{ + propertiesMap[name] = value.variant(); +} + +bool QOfonoModemInterface::isPowered() +{ + QVariant var = getProperty(QStringLiteral("Powered")); + return qdbus_cast<bool>(var); +} + +bool QOfonoModemInterface::isOnline() +{ + QVariant var = getProperty(QStringLiteral("Online")); + return qdbus_cast<bool>(var); +} + +QStringList QOfonoModemInterface::interfaces() +{ + const QVariant var = getProperty(QStringLiteral("Interfaces")); + return var.toStringList(); +} + +QVariantMap QOfonoModemInterface::getProperties() +{ + if (propertiesMap.isEmpty()) { + QDBusPendingReply<QVariantMap> reply = call(QDBus::Block, QLatin1String("GetProperties")); + if (!reply.isError()) { + propertiesMap = reply.value(); + } + } + return propertiesMap; +} + +QVariant QOfonoModemInterface::getProperty(const QString &property) +{ + QVariant var; + QVariantMap map = getProperties(); + if (map.contains(property)) + var = map.value(property); + return var; +} + + +QOfonoNetworkRegistrationInterface::QOfonoNetworkRegistrationInterface(const QString &dbusPathName, QObject *parent) + : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE), + dbusPathName, + OFONO_NETWORK_REGISTRATION_INTERFACE, + QDBusConnection::systemBus(), parent) +{ +} + +QOfonoNetworkRegistrationInterface::~QOfonoNetworkRegistrationInterface() +{ +} + +QString QOfonoNetworkRegistrationInterface::getTechnology() +{ + QVariant var = getProperty(QStringLiteral("Technology")); + return qdbus_cast<QString>(var); +} + +QVariant QOfonoNetworkRegistrationInterface::getProperty(const QString &property) +{ + QVariant var; + QVariantMap map = getProperties(); + if (map.contains(property)) + var = map.value(property); + return var; +} + +QVariantMap QOfonoNetworkRegistrationInterface::getProperties() +{ + if (propertiesMap.isEmpty()) { + QDBusPendingReply<QVariantMap> reply = call(QDBus::Block, QLatin1String("GetProperties")); + reply.waitForFinished(); + if (!reply.isError()) { + propertiesMap = reply.value(); + } + } + return propertiesMap; +} + +QOfonoDataConnectionManagerInterface::QOfonoDataConnectionManagerInterface(const QString &dbusPathName, QObject *parent) + : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE), + dbusPathName, + OFONO_DATA_CONNECTION_MANAGER_INTERFACE, + QDBusConnection::systemBus(), parent) +{ + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), + path(), + QLatin1String(OFONO_MODEM_INTERFACE), + QLatin1String("PropertyChanged"), + this,SLOT(propertyChanged(QString,QDBusVariant))); +} + +QOfonoDataConnectionManagerInterface::~QOfonoDataConnectionManagerInterface() +{ +} + +QStringList QOfonoDataConnectionManagerInterface::contexts() +{ + if (contextList.isEmpty()) { + QDBusPendingReply<PathPropertiesList > reply = call(QLatin1String("GetContexts")); + reply.waitForFinished(); + if (!reply.isError()) { + const auto contexts = reply.value(); + for (const ObjectPathProperties &context : contexts) + contextList << context.path.path(); + } + } + return contextList; +} + +PathPropertiesList QOfonoDataConnectionManagerInterface::contextsWithProperties() +{ + if (contextListProperties.isEmpty()) { + QDBusPendingReply<PathPropertiesList > reply = call(QLatin1String("GetContexts")); + reply.waitForFinished(); + if (!reply.isError()) { + contextListProperties = reply.value(); + } + } + return contextListProperties; +} + +bool QOfonoDataConnectionManagerInterface::roamingAllowed() +{ + QVariant var = getProperty(QStringLiteral("RoamingAllowed")); + return qdbus_cast<bool>(var); +} + +QString QOfonoDataConnectionManagerInterface::bearer() +{ + QVariant var = getProperty(QStringLiteral("Bearer")); + return qdbus_cast<QString>(var); +} + +QVariant QOfonoDataConnectionManagerInterface::getProperty(const QString &property) +{ + return getProperties().value(property); +} + +QVariantMap &QOfonoDataConnectionManagerInterface::getProperties() +{ + if (propertiesMap.isEmpty()) { + QDBusPendingReply<QVariantMap> reply = call(QDBus::Block, QLatin1String("GetProperties")); + if (!reply.isError()) { + propertiesMap = reply.value(); + } + } + return propertiesMap; +} + +void QOfonoDataConnectionManagerInterface::propertyChanged(const QString &name, const QDBusVariant &value) +{ + propertiesMap[name] = value.variant(); + if (name == QLatin1String("RoamingAllowed")) + Q_EMIT roamingAllowedChanged(value.variant().toBool()); +} + + +QOfonoConnectionContextInterface::QOfonoConnectionContextInterface(const QString &dbusPathName, QObject *parent) + : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE), + dbusPathName, + OFONO_CONNECTION_CONTEXT_INTERFACE, + QDBusConnection::systemBus(), parent) +{ + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), + path(), + QLatin1String(OFONO_MODEM_INTERFACE), + QLatin1String("PropertyChanged"), + this,SLOT(propertyChanged(QString,QDBusVariant))); +} + +QOfonoConnectionContextInterface::~QOfonoConnectionContextInterface() +{ +} + +QVariantMap QOfonoConnectionContextInterface::getProperties() +{ + if (propertiesMap.isEmpty()) { + QDBusPendingReply<QVariantMap> reply = call(QDBus::Block, QLatin1String("GetProperties")); + if (!reply.isError()) { + propertiesMap = reply.value(); + } + } + return propertiesMap; +} + +void QOfonoConnectionContextInterface::propertyChanged(const QString &name, const QDBusVariant &value) +{ + propertiesMap[name] = value.variant(); +} + +QVariant QOfonoConnectionContextInterface::getProperty(const QString &property) +{ + QVariant var; + QVariantMap map = getProperties(); + if (map.contains(property)) + var = map.value(property); + return var; +} + +bool QOfonoConnectionContextInterface::active() +{ + QVariant var = getProperty(QStringLiteral("Active")); + return qdbus_cast<bool>(var); +} + +QString QOfonoConnectionContextInterface::accessPointName() +{ + QVariant var = getProperty(QStringLiteral("AccessPointName")); + return qdbus_cast<QString>(var); +} + +QString QOfonoConnectionContextInterface::name() +{ + QVariant var = getProperty(QStringLiteral("Name")); + return qdbus_cast<QString>(var); +} + +QT_END_NAMESPACE + +#endif // QT_NO_DBUS diff --git a/src/platformsupport/linuxofono/qofonoservice_linux_p.h b/src/platformsupport/linuxofono/qofonoservice_linux_p.h new file mode 100644 index 0000000000..62df5d4fa7 --- /dev/null +++ b/src/platformsupport/linuxofono/qofonoservice_linux_p.h @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** 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 QOFONOSERVICE_H +#define QOFONOSERVICE_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 <QtDBus/QtDBus> +#include <QtDBus/QDBusConnection> +#include <QtDBus/QDBusError> +#include <QtDBus/QDBusInterface> +#include <QtDBus/QDBusMessage> +#include <QtDBus/QDBusReply> + +#include <QtDBus/QDBusPendingCallWatcher> +#include <QtDBus/QDBusObjectPath> +#include <QtDBus/QDBusContext> +#include <QMap> + +#ifndef QT_NO_DBUS + +#define OFONO_SERVICE "org.ofono" +#define OFONO_MANAGER_INTERFACE "org.ofono.Manager" +#define OFONO_MANAGER_PATH "/" + +#define OFONO_MODEM_INTERFACE "org.ofono.Modem" +#define OFONO_NETWORK_REGISTRATION_INTERFACE "org.ofono.NetworkRegistration" +#define OFONO_DATA_CONNECTION_MANAGER_INTERFACE "org.ofono.ConnectionManager" +#define OFONO_CONNECTION_CONTEXT_INTERFACE "org.ofono.ConnectionContext" + +QT_BEGIN_NAMESPACE + +QT_END_NAMESPACE + +struct ObjectPathProperties +{ + QDBusObjectPath path; + QVariantMap properties; +}; +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(ObjectPathProperties, Q_MOVABLE_TYPE); // QDBusObjectPath is movable, but cannot be + // marked as such until Qt 6 +QT_END_NAMESPACE + +typedef QVector<ObjectPathProperties> PathPropertiesList; +Q_DECLARE_METATYPE(ObjectPathProperties) +Q_DECLARE_METATYPE (PathPropertiesList) + +QT_BEGIN_NAMESPACE + +class QOfonoManagerInterface : public QDBusAbstractInterface +{ + Q_OBJECT + +public: + + QOfonoManagerInterface( QObject *parent = nullptr); + ~QOfonoManagerInterface(); + + QStringList getModems(); + QString currentModem(); +signals: + void modemChanged(); +private: + QStringList modemList; +private slots: + void modemAdded(const QDBusObjectPath &path, const QVariantMap &var); + void modemRemoved(const QDBusObjectPath &path); +}; + +class QOfonoModemInterface : public QDBusAbstractInterface +{ + Q_OBJECT + +public: + + explicit QOfonoModemInterface(const QString &dbusModemPathName, QObject *parent = nullptr); + ~QOfonoModemInterface(); + + bool isPowered(); + bool isOnline(); + QStringList interfaces(); +private: + QVariantMap getProperties(); + QVariantMap propertiesMap; + QVariant getProperty(const QString &); + void propertyChanged(const QString &, const QDBusVariant &value); +}; + + +class QOfonoNetworkRegistrationInterface : public QDBusAbstractInterface +{ + Q_OBJECT + +public: + + explicit QOfonoNetworkRegistrationInterface(const QString &dbusModemPathName, QObject *parent = nullptr); + ~QOfonoNetworkRegistrationInterface(); + + QString getTechnology(); + +private: + QVariantMap getProperties(); + QVariant getProperty(const QString &); + QVariantMap propertiesMap; +Q_SIGNALS: + void propertyChanged(const QString &, const QDBusVariant &value); +}; + +class QOfonoDataConnectionManagerInterface : public QDBusAbstractInterface +{ + Q_OBJECT + +public: + + explicit QOfonoDataConnectionManagerInterface(const QString &dbusPathName, QObject *parent = nullptr); + ~QOfonoDataConnectionManagerInterface(); + + QStringList contexts(); + PathPropertiesList contextsWithProperties(); + bool roamingAllowed(); + QVariant getProperty(const QString &); + QString bearer(); +Q_SIGNALS: + void roamingAllowedChanged(bool); +private: + QVariantMap &getProperties(); + QVariantMap propertiesMap; + QStringList contextList; + PathPropertiesList contextListProperties; +private Q_SLOTS: + void propertyChanged(const QString &, const QDBusVariant &value); +}; + +class QOfonoConnectionContextInterface : public QDBusAbstractInterface +{ + Q_OBJECT + +public: + + explicit QOfonoConnectionContextInterface(const QString &dbusPathName, QObject *parent = nullptr); + ~QOfonoConnectionContextInterface(); + + QVariant getProperty(const QString &); + bool active(); + QString accessPointName(); + QString name(); + +Q_SIGNALS: +private: + QVariantMap getProperties(); + QVariantMap propertiesMap; +private slots: + void propertyChanged(const QString &, const QDBusVariant &value); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_DBUS + +#endif //QOFONOSERVICE_H diff --git a/src/platformsupport/platformcompositor/CMakeLists.txt b/src/platformsupport/platformcompositor/CMakeLists.txt index 0d3bc597c0..1ddc9e719d 100644 --- a/src/platformsupport/platformcompositor/CMakeLists.txt +++ b/src/platformsupport/platformcompositor/CMakeLists.txt @@ -4,22 +4,20 @@ ## PlatformCompositorSupport Module: ##################################################################### -add_qt_module(PlatformCompositorSupport +qt_add_module(PlatformCompositorSupport STATIC INTERNAL_MODULE SOURCES qopenglcompositor.cpp qopenglcompositor_p.h qopenglcompositorbackingstore.cpp qopenglcompositorbackingstore_p.h + qplatformbackingstoreopenglsupport.cpp qplatformbackingstoreopenglsupport.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui + Qt::OpenGL ) #### Keys ignored in scope 1:.:.:platformcompositor.pro:<TRUE>: # MODULE = "platformcompositor_support" -# _LOADED = "qt_module" diff --git a/src/platformsupport/platformcompositor/platformcompositor.pro b/src/platformsupport/platformcompositor/platformcompositor.pro index 81c31571d0..89386ab3ef 100644 --- a/src/platformsupport/platformcompositor/platformcompositor.pro +++ b/src/platformsupport/platformcompositor/platformcompositor.pro @@ -1,16 +1,18 @@ TARGET = QtPlatformCompositorSupport MODULE = platformcompositor_support -QT = core-private gui-private +QT = core-private gui-private opengl CONFIG += static internal_module DEFINES += QT_NO_CAST_FROM_ASCII SOURCES += \ + qplatformbackingstoreopenglsupport.cpp \ qopenglcompositor.cpp \ qopenglcompositorbackingstore.cpp HEADERS += \ + qplatformbackingstoreopenglsupport.h \ qopenglcompositor_p.h \ qopenglcompositorbackingstore_p.h diff --git a/src/platformsupport/platformcompositor/qopenglcompositor_p.h b/src/platformsupport/platformcompositor/qopenglcompositor_p.h index 41a3288240..c9414c82c6 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositor_p.h +++ b/src/platformsupport/platformcompositor/qopenglcompositor_p.h @@ -52,7 +52,7 @@ // #include <QtCore/QTimer> -#include <QtGui/QOpenGLTextureBlitter> +#include <QtOpenGL/QOpenGLTextureBlitter> #include <QtGui/QMatrix4x4> QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/platformcompositor/qplatformbackingstoreopenglsupport.cpp b/src/platformsupport/platformcompositor/qplatformbackingstoreopenglsupport.cpp new file mode 100644 index 0000000000..ca50910114 --- /dev/null +++ b/src/platformsupport/platformcompositor/qplatformbackingstoreopenglsupport.cpp @@ -0,0 +1,455 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 QT_NO_OPENGL + +#include "qplatformbackingstoreopenglsupport.h" + +#include <QtGui/private/qwindow_p.h> + +#include <qpa/qplatformgraphicsbuffer.h> +#include <qpa/qplatformgraphicsbufferhelper.h> + +#include <QtOpenGL/QOpenGLTextureBlitter> +#include <QtGui/qopengl.h> +#include <QtGui/QOpenGLFunctions> +#include <QtGui/QOpenGLContext> +#include <QtGui/QOffscreenSurface> + +#ifndef GL_TEXTURE_BASE_LEVEL +#define GL_TEXTURE_BASE_LEVEL 0x813C +#endif +#ifndef GL_TEXTURE_MAX_LEVEL +#define GL_TEXTURE_MAX_LEVEL 0x813D +#endif +#ifndef GL_UNPACK_ROW_LENGTH +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#endif +#ifndef GL_RGB10_A2 +#define GL_RGB10_A2 0x8059 +#endif +#ifndef GL_UNSIGNED_INT_2_10_10_10_REV +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#endif + +#ifndef GL_FRAMEBUFFER_SRGB +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#endif +#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE +#define GL_FRAMEBUFFER_SRGB_CAPABLE 0x8DBA +#endif + +QT_BEGIN_NAMESPACE + +static inline QRect deviceRect(const QRect &rect, QWindow *window) +{ + QRect deviceRect(rect.topLeft() * window->devicePixelRatio(), + rect.size() * window->devicePixelRatio()); + return deviceRect; +} + +static inline QPoint deviceOffset(const QPoint &pt, QWindow *window) +{ + return pt * window->devicePixelRatio(); +} + +static QRegion deviceRegion(const QRegion ®ion, QWindow *window, const QPoint &offset) +{ + if (offset.isNull() && window->devicePixelRatio() <= 1) + return region; + + QVector<QRect> rects; + rects.reserve(region.rectCount()); + for (const QRect &rect : region) + rects.append(deviceRect(rect.translated(offset), window)); + + QRegion deviceRegion; + deviceRegion.setRects(rects.constData(), rects.count()); + return deviceRegion; +} + +static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight) +{ + return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1, + topLeftRect.width(), topLeftRect.height()); +} + +static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect, + QOpenGLTextureBlitter *blitter, const QPoint &offset, bool canUseSrgb) +{ + const QRect clipRect = textures->clipRect(idx); + if (clipRect.isEmpty()) + return; + + QRect rectInWindow = textures->geometry(idx); + // relative to the TLW, not necessarily our window (if the flush is for a native child widget), have to adjust + rectInWindow.translate(-offset); + + const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft()); + const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height()); + + const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(deviceRect(clippedRectInWindow, window), + deviceWindowRect); + + const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(deviceRect(srcRect, window), + deviceRect(rectInWindow, window).size(), + QOpenGLTextureBlitter::OriginBottomLeft); + + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + const bool srgb = textures->flags(idx).testFlag(QPlatformTextureList::TextureIsSrgb); + if (srgb && canUseSrgb) + funcs->glEnable(GL_FRAMEBUFFER_SRGB); + + blitter->blit(textures->textureId(idx), target, source); + + if (srgb && canUseSrgb) + funcs->glDisable(GL_FRAMEBUFFER_SRGB); +} + +QPlatformBackingStoreOpenGLSupport::~QPlatformBackingStoreOpenGLSupport() { + if (context) { + QOffscreenSurface offscreenSurface; + offscreenSurface.setFormat(context->format()); + offscreenSurface.create(); + context->makeCurrent(&offscreenSurface); + if (textureId) + context->functions()->glDeleteTextures(1, &textureId); + if (blitter) + blitter->destroy(); + } + delete blitter; +} + +void QPlatformBackingStoreOpenGLSupport::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, bool translucentBackground) +{ + if (!qt_window_private(window)->receivedExpose) + return; + + if (!context) { + context.reset(new QOpenGLContext); + context->setFormat(window->requestedFormat()); + context->setScreen(window->screen()); + context->setShareContext(qt_window_private(window)->shareContext()); + if (!context->create()) { + qCWarning(lcQpaBackingStore, "composeAndFlush: QOpenGLContext creation failed"); + return; + } + } + + bool current = context->makeCurrent(window); + + if (!current && context->isValid()) { + delete blitter; + blitter = nullptr; + textureId = 0; + current = context->create() && context->makeCurrent(window); + } + + if (!current) { + qCWarning(lcQpaBackingStore, "composeAndFlush: makeCurrent() failed"); + return; + } + + qCDebug(lcQpaBackingStore) << "Composing and flushing" << region << "of" << window + << "at offset" << offset << "with" << textures->count() << "texture(s) in" << textures; + + QWindowPrivate::get(window)->lastComposeTime.start(); + + QOpenGLFunctions *funcs = context->functions(); + funcs->glViewport(0, 0, qRound(window->width() * window->devicePixelRatio()), qRound(window->height() * window->devicePixelRatio())); + funcs->glClearColor(0, 0, 0, translucentBackground ? 0 : 1); + funcs->glClear(GL_COLOR_BUFFER_BIT); + + if (!blitter) { + blitter = new QOpenGLTextureBlitter; + blitter->create(); + } + + blitter->bind(); + + const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window); + const QPoint deviceWindowOffset = deviceOffset(offset, window); + + bool canUseSrgb = false; + // If there are any sRGB textures in the list, check if the destination + // framebuffer is sRGB capable. + for (int i = 0; i < textures->count(); ++i) { + if (textures->flags(i).testFlag(QPlatformTextureList::TextureIsSrgb)) { + GLint cap = 0; + funcs->glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE, &cap); + if (cap) + canUseSrgb = true; + break; + } + } + + // Textures for renderToTexture widgets. + for (int i = 0; i < textures->count(); ++i) { + if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) + blitTextureForWidget(textures, i, window, deviceWindowRect, blitter, offset, canUseSrgb); + } + + // Backingstore texture with the normal widgets. + GLuint textureId = 0; + QOpenGLTextureBlitter::Origin origin = QOpenGLTextureBlitter::OriginTopLeft; + if (QPlatformGraphicsBuffer *graphicsBuffer = backingStore->graphicsBuffer()) { + if (graphicsBuffer->size() != textureSize) { + if (this->textureId) + funcs->glDeleteTextures(1, &this->textureId); + funcs->glGenTextures(1, &this->textureId); + funcs->glBindTexture(GL_TEXTURE_2D, this->textureId); + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + } + funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + if (QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &needsSwizzle, &premultiplied)) { + textureSize = graphicsBuffer->size(); + } else { + textureSize = QSize(0,0); + } + + graphicsBuffer->unlock(); + } else if (!region.isEmpty()){ + funcs->glBindTexture(GL_TEXTURE_2D, this->textureId); + QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &needsSwizzle, &premultiplied); + graphicsBuffer->unlock(); + } + + if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft) + origin = QOpenGLTextureBlitter::OriginBottomLeft; + textureId = this->textureId; + } else { + QPlatformBackingStore::TextureFlags flags; + textureId = backingStore->toTexture(deviceRegion(region, window, offset), &textureSize, &flags); + needsSwizzle = (flags & QPlatformBackingStore::TextureSwizzle) != 0; + premultiplied = (flags & QPlatformBackingStore::TexturePremultiplied) != 0; + if (flags & QPlatformBackingStore::TextureFlip) + origin = QOpenGLTextureBlitter::OriginBottomLeft; + } + + funcs->glEnable(GL_BLEND); + if (premultiplied) + funcs->glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + else + funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + + if (textureId) { + if (needsSwizzle) + blitter->setRedBlueSwizzle(true); + // The backingstore is for the entire tlw. + // In case of native children offset tells the position relative to the tlw. + const QRect srcRect = toBottomLeftRect(deviceWindowRect.translated(deviceWindowOffset), textureSize.height()); + const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(srcRect, + textureSize, + origin); + blitter->blit(textureId, QMatrix4x4(), source); + if (needsSwizzle) + blitter->setRedBlueSwizzle(false); + } + + // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set. + bool blendIsPremultiplied = premultiplied; + for (int i = 0; i < textures->count(); ++i) { + const QPlatformTextureList::Flags flags = textures->flags(i); + if (flags.testFlag(QPlatformTextureList::NeedsPremultipliedAlphaBlending)) { + if (!blendIsPremultiplied) { + funcs->glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + blendIsPremultiplied = true; + } + } else { + if (blendIsPremultiplied) { + funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + blendIsPremultiplied = false; + } + } + if (flags.testFlag(QPlatformTextureList::StacksOnTop)) + blitTextureForWidget(textures, i, window, deviceWindowRect, blitter, offset, canUseSrgb); + } + + funcs->glDisable(GL_BLEND); + blitter->release(); + + context->swapBuffers(window); +} + +GLuint QPlatformBackingStoreOpenGLSupport::toTexture(const QRegion &dirtyRegion, QSize *textureSize, QPlatformBackingStore::TextureFlags *flags) const +{ + Q_ASSERT(textureSize); + Q_ASSERT(flags); + + QImage image = backingStore->toImage(); + QSize imageSize = image.size(); + + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + GLenum internalFormat = GL_RGBA; + GLuint pixelType = GL_UNSIGNED_BYTE; + + bool needsConversion = false; + *flags = { }; + switch (image.format()) { + case QImage::Format_ARGB32_Premultiplied: + *flags |= QPlatformBackingStore::TexturePremultiplied; + Q_FALLTHROUGH(); + case QImage::Format_RGB32: + case QImage::Format_ARGB32: + *flags |= QPlatformBackingStore::TextureSwizzle; + break; + case QImage::Format_RGBA8888_Premultiplied: + *flags |= QPlatformBackingStore::TexturePremultiplied; + Q_FALLTHROUGH(); + case QImage::Format_RGBX8888: + case QImage::Format_RGBA8888: + break; + case QImage::Format_BGR30: + case QImage::Format_A2BGR30_Premultiplied: + if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { + pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; + internalFormat = GL_RGB10_A2; + *flags |= QPlatformBackingStore::TexturePremultiplied; + } else { + needsConversion = true; + } + break; + case QImage::Format_RGB30: + case QImage::Format_A2RGB30_Premultiplied: + if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { + pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; + internalFormat = GL_RGB10_A2; + *flags |= QPlatformBackingStore::TextureSwizzle | QPlatformBackingStore::TexturePremultiplied; + } else { + needsConversion = true; + } + break; + default: + needsConversion = true; + break; + } + if (imageSize.isEmpty()) { + *textureSize = imageSize; + return 0; + } + + // Must rely on the input only, not d_ptr. + // With the default composeAndFlush() textureSize is &d_ptr->textureSize. + bool resized = *textureSize != imageSize; + if (dirtyRegion.isEmpty() && !resized) + return textureId; + + *textureSize = imageSize; + + if (needsConversion) + image = image.convertToFormat(QImage::Format_RGBA8888); + + // The image provided by the backingstore may have a stride larger than width * 4, for + // instance on platforms that manually implement client-side decorations. + static const int bytesPerPixel = 4; + const int strideInPixels = image.bytesPerLine() / bytesPerPixel; + const bool hasUnpackRowLength = !ctx->isOpenGLES() || ctx->format().majorVersion() >= 3; + + QOpenGLFunctions *funcs = ctx->functions(); + + if (hasUnpackRowLength) { + funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, strideInPixels); + } else if (strideInPixels != image.width()) { + // No UNPACK_ROW_LENGTH on ES 2.0 and yet we would need it. This case is typically + // hit with QtWayland which is rarely used in combination with a ES2.0-only GL + // implementation. Therefore, accept the performance hit and do a copy. + image = image.copy(); + } + + if (resized) { + if (textureId) + funcs->glDeleteTextures(1, &textureId); + funcs->glGenTextures(1, &textureId); + funcs->glBindTexture(GL_TEXTURE_2D, textureId); + if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + } + funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, imageSize.width(), imageSize.height(), 0, GL_RGBA, pixelType, + const_cast<uchar*>(image.constBits())); + } else { + funcs->glBindTexture(GL_TEXTURE_2D, textureId); + QRect imageRect = image.rect(); + QRect rect = dirtyRegion.boundingRect() & imageRect; + + if (hasUnpackRowLength) { + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, + image.constScanLine(rect.y()) + rect.x() * bytesPerPixel); + } else { + // if the rect is wide enough it's cheaper to just + // extend it instead of doing an image copy + if (rect.width() >= imageRect.width() / 2) { + rect.setX(0); + rect.setWidth(imageRect.width()); + } + + // if the sub-rect is full-width we can pass the image data directly to + // OpenGL instead of copying, since there's no gap between scanlines + + if (rect.width() == imageRect.width()) { + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, + image.constScanLine(rect.y())); + } else { + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, + image.copy(rect).constBits()); + } + } + } + + if (hasUnpackRowLength) + funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + + return textureId; +} + +#endif // QT_NO_OPENGL + +QT_END_NAMESPACE diff --git a/src/platformsupport/platformcompositor/qplatformbackingstoreopenglsupport.h b/src/platformsupport/platformcompositor/qplatformbackingstoreopenglsupport.h new file mode 100644 index 0000000000..5523b18f76 --- /dev/null +++ b/src/platformsupport/platformcompositor/qplatformbackingstoreopenglsupport.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 QPLATFORMBACKINGSTOREOPENGLSUPPORT_H +#define QPLATFORMBACKINGSTOREOPENGLSUPPORT_H + +// +// W A R N I N G +// ------------- +// +// This file is part of the QPA API and is not meant to be used +// in applications. Usage of this API may make your code +// source and binary incompatible with future versions of Qt. +// + +#ifndef QT_NO_OPENGL + +#include <QtGui/qtguiglobal.h> +#include <qpa/qplatformbackingstore.h> + +#include <QtGui/QOpenGLContext> + +QT_BEGIN_NAMESPACE + +class QOpenGLTextureBlitter; +class QOpenGLBackingStore; + +class QPlatformBackingStoreOpenGLSupport : public QPlatformBackingStoreOpenGLSupportBase +{ +public: + explicit QPlatformBackingStoreOpenGLSupport(QPlatformBackingStore *backingStore) : backingStore(backingStore) {} + ~QPlatformBackingStoreOpenGLSupport() override; + void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, + QPlatformTextureList *textures, bool translucentBackground) override; + GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, QPlatformBackingStore::TextureFlags *flags) const override; + +private: + QPlatformBackingStore *backingStore = nullptr; + QScopedPointer<QOpenGLContext> context; + mutable GLuint textureId = 0; + mutable QSize textureSize; + mutable bool needsSwizzle = false; + mutable bool premultiplied = false; + QOpenGLTextureBlitter *blitter = nullptr; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_OPENGL + +#endif // QPLATFORMBACKINGSTOREOPENGLSUPPORT_H diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro index 6d4f1b93bd..4b41b29c12 100644 --- a/src/platformsupport/platformsupport.pro +++ b/src/platformsupport/platformsupport.pro @@ -11,7 +11,7 @@ SUBDIRS = \ qtConfig(freetype)|darwin|win32: \ SUBDIRS += fontdatabases -qtConfig(evdev)|qtConfig(tslib)|qtConfig(libinput)|qtConfig(integrityhid) { +qtConfig(evdev)|qtConfig(tslib)|qtConfig(libinput)|qtConfig(integrityhid)|qtConfig(xkbcommon) { SUBDIRS += input input.depends += devicediscovery } @@ -45,3 +45,7 @@ darwin { qtConfig(vulkan): \ SUBDIRS += vkconvenience + +!android:linux*:qtHaveModule(dbus) \ + SUBDIRS += linuxofono + diff --git a/src/platformsupport/services/CMakeLists.txt b/src/platformsupport/services/CMakeLists.txt index 59e10a84a4..602dd40305 100644 --- a/src/platformsupport/services/CMakeLists.txt +++ b/src/platformsupport/services/CMakeLists.txt @@ -4,31 +4,27 @@ ## ServiceSupport Module: ##################################################################### -add_qt_module(ServiceSupport +qt_add_module(ServiceSupport STATIC INTERNAL_MODULE SOURCES genericunix/qgenericunixservices.cpp genericunix/qgenericunixservices_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:services.pro:<TRUE>: # MODULE = "service_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(ServiceSupport CONDITION QT_FEATURE_dbus +qt_extend_target(ServiceSupport CONDITION QT_FEATURE_dbus PUBLIC_LIBRARIES Qt::DBus ) diff --git a/src/platformsupport/themes/CMakeLists.txt b/src/platformsupport/themes/CMakeLists.txt index 0000a9092d..a7be78d0e0 100644 --- a/src/platformsupport/themes/CMakeLists.txt +++ b/src/platformsupport/themes/CMakeLists.txt @@ -4,34 +4,30 @@ ## ThemeSupport Module: ##################################################################### -add_qt_module(ThemeSupport +qt_add_module(ThemeSupport STATIC INTERNAL_MODULE SOURCES qabstractfileiconengine.cpp qabstractfileiconengine_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui ) #### Keys ignored in scope 1:.:.:themes.pro:<TRUE>: # MODULE = "theme_support" -# _LOADED = "qt_module" ## Scopes: ##################################################################### -extend_target(ThemeSupport CONDITION QT_FEATURE_xcb OR (UNIX AND NOT APPLE_UIKIT) +qt_extend_target(ThemeSupport CONDITION QT_FEATURE_xcb OR (UNIX AND NOT APPLE_UIKIT) SOURCES genericunix/qgenericunixthemes.cpp genericunix/qgenericunixthemes_p.h ) -extend_target(ThemeSupport CONDITION QT_FEATURE_dbus AND (QT_FEATURE_xcb OR UNIX) AND (QT_FEATURE_xcb OR NOT APPLE_UIKIT) +qt_extend_target(ThemeSupport CONDITION QT_FEATURE_dbus AND (QT_FEATURE_xcb OR UNIX) AND (QT_FEATURE_xcb OR NOT APPLE_UIKIT) SOURCES genericunix/dbusmenu/qdbusmenuadaptor.cpp genericunix/dbusmenu/qdbusmenuadaptor_p.h genericunix/dbusmenu/qdbusmenubar.cpp genericunix/dbusmenu/qdbusmenubar_p.h @@ -45,7 +41,7 @@ extend_target(ThemeSupport CONDITION QT_FEATURE_dbus AND (QT_FEATURE_xcb OR UNIX Qt::DBus ) -extend_target(ThemeSupport CONDITION QT_FEATURE_dbus AND QT_FEATURE_systemtrayicon AND (QT_FEATURE_xcb OR UNIX) AND (QT_FEATURE_xcb OR NOT APPLE_UIKIT) +qt_extend_target(ThemeSupport CONDITION QT_FEATURE_dbus AND QT_FEATURE_systemtrayicon AND (QT_FEATURE_xcb OR UNIX) AND (QT_FEATURE_xcb OR NOT APPLE_UIKIT) SOURCES genericunix/dbustray/qdbustrayicon.cpp genericunix/dbustray/qdbustrayicon_p.h genericunix/dbustray/qdbustraytypes.cpp genericunix/dbustray/qdbustraytypes_p.h diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes.cpp b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes.cpp index 82a13d2fa0..6fadea5d28 100644 --- a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes.cpp +++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes.cpp @@ -48,7 +48,9 @@ #include <QDebug> #include <QtEndian> #include <QBuffer> -#include <private/qkeysequence_p.h> +#if QT_CONFIG(shortcut) +# include <private/qkeysequence_p.h> +#endif #include <qpa/qplatformmenu.h> #include "qdbusplatformmenu_p.h" @@ -152,7 +154,7 @@ const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuLayoutItem &i while (!arg.atEnd()) { QDBusVariant dbusVariant; arg >> dbusVariant; - QDBusArgument childArgument = dbusVariant.variant().value<QDBusArgument>(); + QDBusArgument childArgument = qvariant_cast<QDBusArgument>(dbusVariant.variant()); QDBusMenuLayoutItem child; childArgument >> child; diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h index 8a31f82fb0..aa0f303416 100644 --- a/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h +++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h @@ -96,7 +96,7 @@ public: void setChecked(bool isChecked) override; bool hasExclusiveGroup() const { return m_hasExclusiveGroup; } void setHasExclusiveGroup(bool hasExclusiveGroup) override; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) QKeySequence shortcut() const { return m_shortcut; } void setShortcut(const QKeySequence& shortcut) override; #endif @@ -123,7 +123,9 @@ private: bool m_hasExclusiveGroup : 1; short /*unused*/ : 6; short m_dbusID : 16; +#if QT_CONFIG(shortcut) QKeySequence m_shortcut; +#endif }; class QDBusPlatformMenu : public QPlatformMenu diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp index 70d5616075..36d9e4e065 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp @@ -517,7 +517,7 @@ QFont *QKdeThemePrivate::kdeFont(const QVariant &fontValue) // causing recursion. QString fontDescription; QString fontFamily; - if (fontValue.type() == QVariant::StringList) { + if (fontValue.userType() == QMetaType::QStringList) { const QStringList list = fontValue.toStringList(); if (!list.isEmpty()) { fontFamily = list.first(); diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h index c0da9d8370..f6acf00f39 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h @@ -109,7 +109,7 @@ public: QVariant themeHint(ThemeHint hint) const override; QIcon fileIcon(const QFileInfo &fileInfo, - QPlatformTheme::IconOptions iconOptions = nullptr) const override; + QPlatformTheme::IconOptions iconOptions = { }) const override; const QPalette *palette(Palette type = SystemPalette) const override; @@ -134,7 +134,7 @@ public: QGnomeTheme(); QVariant themeHint(ThemeHint hint) const override; QIcon fileIcon(const QFileInfo &fileInfo, - QPlatformTheme::IconOptions = nullptr) const override; + QPlatformTheme::IconOptions = { }) const override; const QFont *font(Font type) const override; QString standardButtonText(int button) const override; diff --git a/src/platformsupport/vkconvenience/.prev_CMakeLists.txt b/src/platformsupport/vkconvenience/.prev_CMakeLists.txt index 4de17b99c0..6f17cfa306 100644 --- a/src/platformsupport/vkconvenience/.prev_CMakeLists.txt +++ b/src/platformsupport/vkconvenience/.prev_CMakeLists.txt @@ -4,7 +4,7 @@ ## VulkanSupport Module: ##################################################################### -add_qt_module(VulkanSupport +qt_add_module(VulkanSupport STATIC INTERNAL_MODULE SOURCES @@ -12,16 +12,20 @@ add_qt_module(VulkanSupport qvkconvenience.cpp qvkconvenience_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:vkconvenience.pro:<TRUE>: # MODULE = "vulkan_support" -# _LOADED = "qt_module" + +## Scopes: +##################################################################### + +qt_extend_target(VulkanSupport CONDITION QT_FEATURE_opengl + PUBLIC_LIBRARIES + Qt::OpenGL +) diff --git a/src/platformsupport/vkconvenience/CMakeLists.txt b/src/platformsupport/vkconvenience/CMakeLists.txt index ee7e1c560c..6ec2574375 100644 --- a/src/platformsupport/vkconvenience/CMakeLists.txt +++ b/src/platformsupport/vkconvenience/CMakeLists.txt @@ -6,7 +6,7 @@ qt_find_package(Vulkan) # special case ## VulkanSupport Module: ##################################################################### -add_qt_module(VulkanSupport +qt_add_module(VulkanSupport STATIC INTERNAL_MODULE SOURCES @@ -14,16 +14,20 @@ add_qt_module(VulkanSupport qvkconvenience.cpp qvkconvenience_p.h DEFINES QT_NO_CAST_FROM_ASCII - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui PRECOMPILED_HEADER "../../corelib/global/qt_pch.h" ) #### Keys ignored in scope 1:.:.:vkconvenience.pro:<TRUE>: # MODULE = "vulkan_support" -# _LOADED = "qt_module" + +## Scopes: +##################################################################### + +qt_extend_target(VulkanSupport CONDITION QT_FEATURE_opengl + PUBLIC_LIBRARIES + Qt::OpenGL +) diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp index 68340a3173..6f6ba58319 100644 --- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp +++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp @@ -214,6 +214,22 @@ void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const for (const QByteArray &ext : extraExts) m_enabledExtensions.append(ext); + QByteArray envExts = qgetenv("QT_VULKAN_INSTANCE_EXTENSIONS"); + if (!envExts.isEmpty()) { + QByteArrayList envExtList = envExts.split(';'); + for (auto ext : m_enabledExtensions) + envExtList.removeAll(ext); + m_enabledExtensions.append(envExtList); + } + + QByteArray envLayers = qgetenv("QT_VULKAN_INSTANCE_LAYERS"); + if (!envLayers.isEmpty()) { + QByteArrayList envLayerList = envLayers.split(';'); + for (auto ext : m_enabledLayers) + envLayerList.removeAll(ext); + m_enabledLayers.append(envLayerList); + } + // No clever stuff with QSet and friends: the order for layers matters // and the user-provided order must be kept. for (int i = 0; i < m_enabledLayers.count(); ++i) { diff --git a/src/platformsupport/vkconvenience/qvkconvenience.cpp b/src/platformsupport/vkconvenience/qvkconvenience.cpp index acde1d1bda..59de335333 100644 --- a/src/platformsupport/vkconvenience/qvkconvenience.cpp +++ b/src/platformsupport/vkconvenience/qvkconvenience.cpp @@ -39,7 +39,9 @@ #include "qvkconvenience_p.h" -#include <QOpenGLTexture> +#if QT_CONFIG(opengl) +#include <QtOpenGL/QOpenGLTexture> +#endif QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/vkconvenience/vkconvenience.pro b/src/platformsupport/vkconvenience/vkconvenience.pro index ee540024cf..f3ada5768a 100644 --- a/src/platformsupport/vkconvenience/vkconvenience.pro +++ b/src/platformsupport/vkconvenience/vkconvenience.pro @@ -2,6 +2,8 @@ TARGET = QtVulkanSupport MODULE = vulkan_support QT = core-private gui-private +qtConfig(opengl): QT += opengl + CONFIG += static internal_module DEFINES += QT_NO_CAST_FROM_ASCII diff --git a/src/platformsupport/windowsuiautomation/CMakeLists.txt b/src/platformsupport/windowsuiautomation/CMakeLists.txt index 2a182feaea..c610b97fd6 100644 --- a/src/platformsupport/windowsuiautomation/CMakeLists.txt +++ b/src/platformsupport/windowsuiautomation/CMakeLists.txt @@ -4,7 +4,7 @@ ## WindowsUIAutomationSupport Module: ##################################################################### -add_qt_module(WindowsUIAutomationSupport +qt_add_module(WindowsUIAutomationSupport STATIC INTERNAL_MODULE SOURCES @@ -19,14 +19,10 @@ add_qt_module(WindowsUIAutomationSupport uiapropertyids_p.h uiaserverinterfaces_p.h uiatypes_p.h - LIBRARIES + PUBLIC_LIBRARIES Qt::CorePrivate Qt::GuiPrivate - PUBLIC_LIBRARIES - Qt::Core - Qt::Gui ) #### Keys ignored in scope 1:.:.:windowsuiautomation.pro:<TRUE>: # MODULE = "windowsuiautomation_support" -# _LOADED = "qt_module" |