diff --git a/bin/syncqt.pl b/bin/syncqt.pl index b531dce3748..0435aead0af 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -200,9 +200,11 @@ sub shouldMasterInclude { } ###################################################################### -# Syntax: classNames(iheader, clean) +# Syntax: classNames(iheader, clean, requires) # Params: iheader, string, filename to parse for classname "symlinks" # (out) clean, boolean, will be set to false if the header isn't clean +# (out) requires, string, will be set to non-empty if the header +# requires a feature # # Purpose: Scans through iheader to find all classnames that should be # synced into library's include structure. @@ -210,8 +212,9 @@ sub shouldMasterInclude { ###################################################################### sub classNames { my @ret; - my ($iheader, $clean) = @_; + my ($iheader, $clean, $requires) = @_; $$clean = 1; + $$requires = ""; my $ihdrbase = basename($iheader); my $classname = $classnames{$ihdrbase}; @@ -236,6 +239,7 @@ sub classNames { $line .= ";" if($line =~ m/^QT_(BEGIN|END)_NAMESPACE(_[A-Z]+)*[\r\n]*$/); #qt macro $line .= ";" if($line =~ m/^QT_MODULE\(.*\)[\r\n]*$/); # QT_MODULE macro $line .= ";" if($line =~ m/^QT_WARNING_(PUSH|POP|DISABLE_\w+\(.*\))[\r\n]*$/); # qt macros + $$requires = $1 if ($line =~ m/^QT_REQUIRE_CONFIG\((.*)\);[\r\n]*$/); $parsable .= " " . $line; } } @@ -706,6 +710,21 @@ sub isQpaHeader return 0; } +sub globosort($$) { + my ($a, $b) = @_; + if ($a =~ /^q(.*)global\.h$/) { + my $sa = $1; + if ($b =~ /^q(.*)global\.h$/) { + my $sb = $1; + # Compare stems so qglobal.h (empty stem) is first: + return $sa cmp $sb; + } + return -1; # $a is global, so before $b + } + return +1 if $b =~ /^q.*global\.h$/; # $a not global, so after $b + return $a cmp $b; +} + # check if this is an in-source build, and if so use that as the basedir too $basedir = locateSyncProfile($out_basedir); if ($basedir) { @@ -914,10 +933,7 @@ foreach my $lib (@modules_to_sync) { my $pri_clean_files = ""; my $libcapitals = uc($lib); - my $master_contents = - "#ifndef QT_".$libcapitals."_MODULE_H\n" . - "#define QT_".$libcapitals."_MODULE_H\n" . - "#include <$lib/${lib}Depends>\n"; + my %master_contents = (); #remove the old files if($remove_stale) { @@ -1017,6 +1033,7 @@ foreach my $lib (@modules_to_sync) { } my $clean_header; + my $requires; my $iheader = $subdir . "/" . $header; $iheader =~ s/^\Q$basedir\E/$out_basedir/ if ($shadow); if ($check_includes) { @@ -1025,7 +1042,7 @@ foreach my $lib (@modules_to_sync) { && $header =~ /_p\.h$/ && $subdir !~ /3rdparty/; check_header($lib, $header, $iheader, $public_header, $private_header); } - my @classes = $public_header && (!$minimal && $is_qt) ? classNames($iheader, \$clean_header) : (); + my @classes = $public_header && (!$minimal && $is_qt) ? classNames($iheader, \$clean_header, \$requires) : (); if($showonly) { print "$header [$lib]\n"; foreach(@classes) { @@ -1059,7 +1076,7 @@ foreach my $lib (@modules_to_sync) { my $injection = ""; if($public_header) { #put it into the master file - $master_contents .= "#include \"$public_header\"\n" if (!$shadow && shouldMasterInclude($iheader)); + $master_contents{$public_header} = $requires if (!$shadow && shouldMasterInclude($iheader)); #deal with the install directives foreach my $class (@classes) { @@ -1074,7 +1091,7 @@ foreach my $lib (@modules_to_sync) { $injection .= ":$class"; } $pri_install_files.= "$pri_install_iheader ";; - $pri_clean_files .= "$pri_install_iheader " if ($clean_header); + $pri_clean_files .= "$pri_install_iheader".($requires ? ":".$requires : "")." " if ($clean_header); } elsif ($qpa_header) { $pri_install_qpafiles.= "$pri_install_iheader ";; @@ -1113,8 +1130,17 @@ foreach my $lib (@modules_to_sync) { } } - # close the master include: - $master_contents .= + # populate the master include: + my $master_contents = + "#ifndef QT_".$libcapitals."_MODULE_H\n" . + "#define QT_".$libcapitals."_MODULE_H\n" . + "#include <$lib/${lib}Depends>\n" . + join("", map { + my $rq = $master_contents{$_}; + ($rq ? "#if QT_CONFIG($rq)\n" : "") . + "#include \"$_\"\n" . + ($rq ? "#endif\n" : "") + } sort globosort keys %master_contents) . "#include \"".lc($lib)."version.h\"\n" . "#endif\n"; diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index 229760068ea..5a450078204 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -243,16 +243,23 @@ headersclean:!internal_module { } !isEmpty(hcleanCOMMAND):if(!qtConfig(debug_and_release)|CONFIG(release, debug|release)) { + CLEAN_HEADERS = + for (h, SYNCQT.CLEAN_HEADER_FILES) { + hh = $$split(h, :) + hr = $$member(hh, 1) + isEmpty(hr)|qtConfig($$hr): \ + CLEAN_HEADERS += $$member(hh, 0) + } + CLEAN_HEADERS -= $$HEADERSCLEAN_EXCLUDE header_check.dependency_type = TYPE_C header_check.CONFIG += no_link header_check.output = ${QMAKE_VAR_OBJECTS_DIR}header_${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - header_check.input = SYNCQT.CLEAN_HEADER_FILES + header_check.input = CLEAN_HEADERS header_check.variable_out = PRE_TARGETDEPS header_check.name = headercheck ${QMAKE_FILE_IN} header_check.commands = $$hcleanCOMMAND silent:header_check.commands = @echo compiling[header] ${QMAKE_FILE_IN} && $$hcleanCOMMAND QMAKE_EXTRA_COMPILERS += header_check - SYNCQT.CLEAN_HEADER_FILES -= $$HEADERSCLEAN_EXCLUDE } unset(hcleanCOMMAND) unset(hcleanFLAGS) diff --git a/src/3rdparty/freetype/freetype.pro b/src/3rdparty/freetype/freetype.pro index 1e12dadc5d2..6d630d4190c 100644 --- a/src/3rdparty/freetype/freetype.pro +++ b/src/3rdparty/freetype/freetype.pro @@ -69,7 +69,7 @@ DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB include(../zlib_dependency.pri) QT_FOR_CONFIG += gui-private -include(../../gui/qtgui-config.pri) +include($$OUT_PWD/../../gui/qtgui-config.pri) DEFINES += FT_CONFIG_OPTION_USE_PNG include($$PWD/../png_dependency.pri) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index b602cabd27f..bfdbaed43fc 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -1455,4 +1455,9 @@ public class QtActivityDelegate } return false; } + + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) + { + QtNative.sendRequestPermissionsResult(requestCode, permissions, grantResults); + } } diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 4df2cb88c9b..af4f20679c2 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -455,20 +455,25 @@ public class QtNative } } - public static int checkSelfPermission(final String permission) + public static Context getContext() { + if (m_activity != null) + return m_activity; + return m_service; + } + + public static int checkSelfPermission(String permission) { int perm = PackageManager.PERMISSION_DENIED; synchronized (m_mainActivityMutex) { - if (m_activity == null) - return perm; + Context context = getContext(); try { if (Build.VERSION.SDK_INT >= 23) { if (m_checkSelfPermissionMethod == null) m_checkSelfPermissionMethod = Context.class.getMethod("checkSelfPermission", String.class); - perm = (Integer)m_checkSelfPermissionMethod.invoke(m_activity, permission); + perm = (Integer)m_checkSelfPermissionMethod.invoke(context, permission); } else { - final PackageManager pm = m_activity.getPackageManager(); - perm = pm.checkPermission(permission, m_activity.getPackageName()); + final PackageManager pm = context.getPackageManager(); + perm = pm.checkPermission(permission, context.getApplicationContext().getPackageName()); } } catch (Exception e) { e.printStackTrace(); @@ -831,6 +836,8 @@ public class QtNative public static native void runPendingCppRunnables(); + public static native void sendRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults); + private static native void setNativeActivity(Activity activity); private static native void setNativeService(Service service); } diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java index 573a28e44b2..22ff1738c8c 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -981,4 +981,11 @@ public class QtActivity extends Activity //--------------------------------------------------------------------------- //@ANDROID-12 + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) + { + if (QtApplication.m_delegateObject != null && QtApplication.onRequestPermissionsResult != null) { + QtApplication.invokeDelegateMethod(QtApplication.onRequestPermissionsResult, requestCode , permissions, grantResults); + return; + } + } } diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java index 1078060d7f7..afc0432bdda 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java @@ -64,6 +64,7 @@ public class QtApplication extends Application public static Method onKeyShortcut = null; public static Method dispatchGenericMotionEvent = null; public static Method onGenericMotionEvent = null; + public static Method onRequestPermissionsResult = null; private static String activityClassName; public static void setQtContextDelegate(Class clazz, Object listener) { diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro index c13cf7ba8da..9d0728a72d8 100644 --- a/src/angle/src/compiler/preprocessor/preprocessor.pro +++ b/src/angle/src/compiler/preprocessor/preprocessor.pro @@ -1,5 +1,5 @@ CONFIG += static -include(../../../../gui/qtgui-config.pri) +include($$OUT_PWD/../../../../gui/qtgui-config.pri) qtConfig(dynamicgl): CONFIG += not_installed include(../../config.pri) diff --git a/src/angle/src/compiler/translator.pro b/src/angle/src/compiler/translator.pro index 4c0a05e45c9..2e5adaee961 100644 --- a/src/angle/src/compiler/translator.pro +++ b/src/angle/src/compiler/translator.pro @@ -1,5 +1,5 @@ CONFIG += static -include(../../../gui/qtgui-config.pri) +include($$OUT_PWD/../../../gui/qtgui-config.pri) qtConfig(dynamicgl): CONFIG += not_installed include(../config.pri) diff --git a/src/concurrent/concurrent.pro b/src/concurrent/concurrent.pro index 337f4042bd7..017153c74d5 100644 --- a/src/concurrent/concurrent.pro +++ b/src/concurrent/concurrent.pro @@ -37,8 +37,4 @@ HEADERS += \ # private headers HEADERS += \ -qtConfig(clock-gettime) { - linux-*|hpux-*|solaris-*: LIBS_PRIVATE *= -lrt -} - load(qt_module) diff --git a/src/concurrent/qtconcurrentiteratekernel.cpp b/src/concurrent/qtconcurrentiteratekernel.cpp index 4b6ccc2810c..52218f794bb 100644 --- a/src/concurrent/qtconcurrentiteratekernel.cpp +++ b/src/concurrent/qtconcurrentiteratekernel.cpp @@ -39,20 +39,7 @@ #include "qtconcurrentiteratekernel.h" -#if defined(Q_OS_MAC) -#include -#include -#include -#elif defined(Q_OS_UNIX) -#if defined(Q_OS_HURD) -#include -#endif -#include -#include -#elif defined(Q_OS_WIN) -#include -#endif - +#include #include "private/qfunctions_p.h" @@ -65,69 +52,11 @@ enum { MedianSize = 7 }; -#if defined(Q_OS_MAC) - static qint64 getticks() { - return mach_absolute_time(); + return QDeadlineTimer::current(Qt::PreciseTimer).deadlineNSecs(); } -#elif defined(Q_OS_UNIX) - - -static qint64 getticks() -{ -#if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)) || defined(Q_OS_OPENBSD) - clockid_t clockId; - -#ifndef _POSIX_THREAD_CPUTIME - clockId = CLOCK_REALTIME; -#elif (_POSIX_THREAD_CPUTIME-0 <= 0) - // if we don't have CLOCK_THREAD_CPUTIME_ID, we have to just use elapsed realtime instead - clockId = CLOCK_REALTIME; - -# if (_POSIX_THREAD_CPUTIME-0 == 0) - // detect availablility of CLOCK_THREAD_CPUTIME_ID - static QBasicAtomicInt sUseThreadCpuTime = Q_BASIC_ATOMIC_INITIALIZER(-2); - int useThreadCpuTime = sUseThreadCpuTime.load(); - if (useThreadCpuTime == -2) { - // sysconf() will return either -1L or _POSIX_VERSION - // (don't care about sysconf's exact return value) - useThreadCpuTime = sysconf(_SC_THREAD_CPUTIME) == -1L ? -1 : 0 ; - sUseThreadCpuTime.store(useThreadCpuTime); // might happen multiple times, but doesn't matter - } - if (useThreadCpuTime != -1) - clockId = CLOCK_THREAD_CPUTIME_ID; -# endif -#else - clockId = CLOCK_THREAD_CPUTIME_ID; -#endif - - struct timespec ts; - if (clock_gettime(clockId, &ts) == -1) - return 0; - return (ts.tv_sec * 1000000000) + ts.tv_nsec; -#else - - // no clock_gettime(), fall back to wall time - struct timeval tv; - gettimeofday(&tv, 0); - return (tv.tv_sec * 1000000) + tv.tv_usec; -#endif -} - -#elif defined(Q_OS_WIN) - -static qint64 getticks() -{ - LARGE_INTEGER x; - if (!QueryPerformanceCounter(&x)) - return 0; - return x.QuadPart; -} - -#endif - static double elapsed(qint64 after, qint64 before) { return double(after - before); diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index a48548bc907..a3d816f0c3b 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1031,7 +1031,8 @@ // critical definitions. (Reported as Intel Issue ID 6000117277) # define __USE_CONSTEXPR 1 # define __USE_NOEXCEPT 1 -# elif defined(Q_CC_MSVC) && (defined(Q_CC_CLANG) || defined(Q_CC_INTEL)) +# endif +# if defined(Q_CC_MSVC) && defined(Q_CC_CLANG) // Clang and the Intel compiler support more C++ features than the Microsoft compiler // so make sure we don't enable them if the MS headers aren't properly adapted. # ifndef _HAS_CONSTEXPR @@ -1058,7 +1059,8 @@ # ifndef _HAS_VARIADIC_TEMPLATES # undef Q_COMPILER_VARIADIC_TEMPLATES # endif -# elif defined(_LIBCPP_VERSION) +# endif +# if defined(_LIBCPP_VERSION) // libc++ uses __has_feature(cxx_atomic), so disable the feature if the compiler // doesn't support it. That's required for the Intel compiler 14.x or earlier on OS X, for example. # if !__has_feature(cxx_atomic) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index e8b86411915..c78e6f2482b 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1179,6 +1179,12 @@ bool qSharedBuild() Q_DECL_NOTHROW \value WV_None Operating system other than Windows. + \omitvalue WV_CE + \omitvalue WV_CENET + \omitvalue WV_CE_5 + \omitvalue WV_CE_6 + \omitvalue WV_CE_based + \sa MacVersion */ @@ -1255,7 +1261,7 @@ bool qSharedBuild() Q_DECL_NOTHROW \macro Q_OS_DARWIN \relates - Defined on Darwin-based operating systems such as \macOS, iOS, watchOS, and tvOS. + Defined on Darwin-based operating systems such as \macos, iOS, watchOS, and tvOS. */ /*! diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index f11ec127e04..dd8b6110b31 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -78,6 +78,7 @@ 1: The feature is available */ #define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1) +#define QT_REQUIRE_CONFIG(feature) Q_STATIC_ASSERT_X(QT_FEATURE_##feature == 1, "Required feature " #feature " for file " __FILE__ " not vailable.") #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) # define QT_NO_UNSHARABLE_CONTAINERS diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h index 5cf8d786cda..cdc186cdcd5 100644 --- a/src/corelib/global/qsysinfo.h +++ b/src/corelib/global/qsysinfo.h @@ -110,7 +110,13 @@ public: WV_6_1 = WV_WINDOWS7, WV_6_2 = WV_WINDOWS8, WV_6_3 = WV_WINDOWS8_1, - WV_10_0 = WV_WINDOWS10 + WV_10_0 = WV_WINDOWS10, + + WV_CE = 0x0100, + WV_CENET = 0x0200, + WV_CE_5 = 0x0300, + WV_CE_6 = 0x0400, + WV_CE_based = 0x0f00 }; #if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion; diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index 102b8350892..6a46f7dd114 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -38,14 +38,17 @@ ****************************************************************************/ #include "qjnihelpers_p.h" +#include "qjni_p.h" #include "qmutex.h" #include "qlist.h" #include "qsemaphore.h" #include "qsharedpointer.h" #include "qvector.h" +#include "qthread.h" #include #include +#include QT_BEGIN_NAMESPACE @@ -60,6 +63,22 @@ static jmethodID g_hideSplashScreenMethodID = Q_NULLPTR; Q_GLOBAL_STATIC(std::deque, g_pendingRunnables); Q_GLOBAL_STATIC(QMutex, g_pendingRunnablesMutex); +class PermissionsResultClass : public QObject +{ + Q_OBJECT +public: + PermissionsResultClass(const QtAndroidPrivate::PermissionsResultFunc &func) : m_func(func) {} + Q_INVOKABLE void sendResult(const QtAndroidPrivate::PermissionsHash &result) { m_func(result); } + +private: + QtAndroidPrivate::PermissionsResultFunc m_func; +}; + +typedef QHash> PendingPermissionRequestsHash; +Q_GLOBAL_STATIC(PendingPermissionRequestsHash, g_pendingPermissionRequests); +Q_GLOBAL_STATIC(QMutex, g_pendingPermissionRequestsMutex); +Q_GLOBAL_STATIC(QAtomicInt, g_requestPermissionsRequestCode); + // function called from Java from Android UI thread static void runPendingCppRunnables(JNIEnv */*env*/, jobject /*obj*/) { @@ -81,9 +100,43 @@ namespace { QMutex mutex; QVector listeners; }; + + enum { + PERMISSION_GRANTED = 0 + }; } Q_GLOBAL_STATIC(GenericMotionEventListeners, g_genericMotionEventListeners) +static void sendRequestPermissionsResult(JNIEnv *env, jobject /*obj*/, jint requestCode, + jobjectArray permissions, jintArray grantResults) +{ + g_pendingPermissionRequestsMutex->lock(); + auto it = g_pendingPermissionRequests->find(requestCode); + if (it == g_pendingPermissionRequests->end()) { + g_pendingPermissionRequestsMutex->unlock(); + // show an error or something ? + return; + } + g_pendingPermissionRequestsMutex->unlock(); + + Qt::ConnectionType connection = QThread::currentThread() == it.value()->thread() ? Qt::DirectConnection : Qt::BlockingQueuedConnection; + QtAndroidPrivate::PermissionsHash hash; + const int size = env->GetArrayLength(permissions); + std::unique_ptr results(new jint[size]); + env->GetIntArrayRegion(grantResults, 0, size, results.get()); + for (int i = 0 ; i < size; ++i) { + const auto &permission = QJNIObjectPrivate(env->GetObjectArrayElement(permissions, i)).toString(); + auto value = results[i] == PERMISSION_GRANTED ? + QtAndroidPrivate::PermissionsResult::Granted : + QtAndroidPrivate::PermissionsResult::Denied; + hash[permission] = value; + } + QMetaObject::invokeMethod(it.value().data(), "sendResult", connection, Q_ARG(QtAndroidPrivate::PermissionsHash, hash)); + g_pendingPermissionRequestsMutex->lock(); + g_pendingPermissionRequests->erase(it); + g_pendingPermissionRequestsMutex->unlock(); +} + static jboolean dispatchGenericMotionEvent(JNIEnv *, jclass, jobject event) { jboolean ret = JNI_FALSE; @@ -328,7 +381,8 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) {"dispatchGenericMotionEvent", "(Landroid/view/MotionEvent;)Z", reinterpret_cast(dispatchGenericMotionEvent)}, {"dispatchKeyEvent", "(Landroid/view/KeyEvent;)Z", reinterpret_cast(dispatchKeyEvent)}, {"setNativeActivity", "(Landroid/app/Activity;)V", reinterpret_cast(setNativeActivity)}, - {"setNativeService", "(Landroid/app/Service;)V", reinterpret_cast(setNativeService)} + {"setNativeService", "(Landroid/app/Service;)V", reinterpret_cast(setNativeService)}, + {"sendRequestPermissionsResult", "(I[Ljava/lang/String;[I)V", reinterpret_cast(sendRequestPermissionsResult)}, }; const bool regOk = (env->RegisterNatives(jQtNative, methods, sizeof(methods) / sizeof(methods[0])) == JNI_OK); @@ -411,6 +465,70 @@ void QtAndroidPrivate::runOnAndroidThreadSync(const QtAndroidPrivate::Runnable & sem->tryAcquire(1, timeoutMs); } +void QtAndroidPrivate::requestPermissions(JNIEnv *env, const QStringList &permissions, const QtAndroidPrivate::PermissionsResultFunc &callbackFunc, bool directCall) +{ + if (androidSdkVersion() < 23 || !activity()) { + QHash res; + for (const auto &perm : permissions) + res[perm] = checkPermission(perm); + callbackFunc(res); + return; + } + // Check API 23+ permissions + const int requestCode = (*g_requestPermissionsRequestCode)++; + if (!directCall) { + g_pendingPermissionRequestsMutex->lock(); + (*g_pendingPermissionRequests)[requestCode] = QSharedPointer::create(callbackFunc); + g_pendingPermissionRequestsMutex->unlock(); + } + + runOnAndroidThread([permissions, callbackFunc, requestCode, directCall] { + if (directCall) { + g_pendingPermissionRequestsMutex->lock(); + (*g_pendingPermissionRequests)[requestCode] = QSharedPointer::create(callbackFunc); + g_pendingPermissionRequestsMutex->unlock(); + } + + QJNIEnvironmentPrivate env; + auto array = env->NewObjectArray(permissions.size(), env->FindClass("java/lang/String"), nullptr); + int index = 0; + for (const auto &perm : permissions) + env->SetObjectArrayElement(array, index++, QJNIObjectPrivate::fromString(perm).object()); + QJNIObjectPrivate(activity()).callMethod("requestPermissions", "([Ljava/lang/String;I)V", array, requestCode); + env->DeleteLocalRef(array); + }, env); +} + +QHash QtAndroidPrivate::requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs) +{ + QSharedPointer> res(new QHash()); + QSharedPointer sem(new QSemaphore); + requestPermissions(env, permissions, [sem, res](const QHash &result){ + *res = result; + sem->release(); + }, true); + sem->tryAcquire(1, timeoutMs); + return *res; +} + +QtAndroidPrivate::PermissionsResult QtAndroidPrivate::checkPermission(const QString &permission) +{ + const auto res = QJNIObjectPrivate::callStaticMethod("org/qtproject/qt5/android/QtNative", + "checkSelfPermission", + "(Ljava/lang/String;)I", + QJNIObjectPrivate::fromString(permission).object()); + return res == PERMISSION_GRANTED ? PermissionsResult::Granted : PermissionsResult::Denied; +} + +bool QtAndroidPrivate::shouldShowRequestPermissionRationale(const QString &permission) +{ + if (androidSdkVersion() < 23 || !activity()) + return false; + + return QJNIObjectPrivate(activity()).callMethod("shouldShowRequestPermissionRationale", "(Ljava/lang/String;)Z", + QJNIObjectPrivate::fromString(permission).object()); +} + void QtAndroidPrivate::registerGenericMotionEventListener(QtAndroidPrivate::GenericMotionEventListener *listener) { QMutexLocker locker(&g_genericMotionEventListeners()->mutex); @@ -441,3 +559,5 @@ void QtAndroidPrivate::hideSplashScreen(JNIEnv *env) } QT_END_NAMESPACE + +#include "qjnihelpers.moc" diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h index 43e2f3af201..478f62a5c77 100644 --- a/src/corelib/kernel/qjnihelpers_p.h +++ b/src/corelib/kernel/qjnihelpers_p.h @@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE class QRunnable; +class QStringList; namespace QtAndroidPrivate { @@ -97,7 +98,13 @@ namespace QtAndroidPrivate virtual bool handleKeyEvent(jobject event) = 0; }; + enum class PermissionsResult { + Granted, + Denied + }; + typedef QHash PermissionsHash; typedef std::function Runnable; + typedef std::function PermissionsResultFunc; Q_CORE_EXPORT jobject activity(); Q_CORE_EXPORT jobject service(); @@ -109,6 +116,10 @@ namespace QtAndroidPrivate Q_CORE_EXPORT void runOnAndroidThread(const Runnable &runnable, JNIEnv *env); Q_CORE_EXPORT void runOnAndroidThreadSync(const Runnable &runnable, JNIEnv *env, int timeoutMs = INT_MAX); Q_CORE_EXPORT void runOnUiThread(QRunnable *runnable, JNIEnv *env); + Q_CORE_EXPORT void requestPermissions(JNIEnv *env, const QStringList &permissions, const PermissionsResultFunc &callbackFunc, bool directCall = false); + Q_CORE_EXPORT QHash requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs = INT_MAX); + Q_CORE_EXPORT PermissionsResult checkPermission(const QString &permission); + Q_CORE_EXPORT bool shouldShowRequestPermissionRationale(const QString &permission); Q_CORE_EXPORT void handleActivityResult(jint requestCode, jint resultCode, jobject data); Q_CORE_EXPORT void registerActivityResultListener(ActivityResultListener *listener); diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index e25eb4272de..a798d9eff6b 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -572,10 +572,9 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) const QString file = data.name + QLatin1String(".xml"); // shared-mime-info since 1.3 lowercases the xml files - QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file.toLower()); - if (mimeFiles.isEmpty()) { - mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file); // pre-1.3 - } + QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/") + file.toLower()); + if (mimeFiles.isEmpty()) + mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/") + file); // pre-1.3 if (mimeFiles.isEmpty()) { qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist.\n" "Either it was just removed, or the directory doesn't have executable permission..." @@ -807,7 +806,7 @@ bool QMimeXMLProvider::load(const QString &fileName, QString *errorMessage) QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (errorMessage) - *errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(fileName, file.errorString()); + *errorMessage = QLatin1String("Cannot open ") + fileName + QLatin1String(": ") + file.errorString(); return false; } diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index da8d1704b0e..3a0e22e3bd9 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -135,8 +135,8 @@ public: template bool try_lock_for(std::chrono::duration duration) { - // § 30.4.1.3.5 [thread.timedmutex.requirements] specifies that a - // duration less than or equal to duration.zero() shall result in a + // N4606 § 30.4.1.3 [thread.timedmutex.requirements]/5 specifies that + // a duration less than or equal to duration.zero() shall result in a // try_lock, unlike QMutex's tryLock with a negative duration which // results in a lock. @@ -150,7 +150,7 @@ public: bool try_lock_until(std::chrono::time_point timePoint) { // Implemented in terms of try_lock_for to honor the similar - // requirement in § 30.4.1.3.12 [thread.timedmutex.requirements] + // requirement in N4606 § 30.4.1.3 [thread.timedmutex.requirements]/12. return try_lock_for(timePoint - Clock::now()); } diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 9d8695c0f60..2fd4be00a57 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -468,6 +468,9 @@ static inline quint64 qCpuFeatures() #define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \ for (; i < static_cast(qMin(static_cast(length), ((4 - ((reinterpret_cast(ptr) >> 2) & 0x3)) & 0x3))); ++i) +#define ALIGNMENT_PROLOGUE_32BYTES(ptr, i, length) \ + for (; i < static_cast(qMin(static_cast(length), ((8 - ((reinterpret_cast(ptr) >> 2) & 0x7)) & 0x7))); ++i) + QT_END_NAMESPACE #endif // QSIMD_P_H diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index a110c129def..53a28d92787 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1440,7 +1440,8 @@ public: QStringRef mid(int pos, int n = -1) const Q_REQUIRED_RESULT; void truncate(int pos) Q_DECL_NOTHROW { m_size = qBound(0, pos, m_size); } - void chop(int n) Q_DECL_NOTHROW { + void chop(int n) Q_DECL_NOTHROW + { if (n >= m_size) m_size = 0; else if (n > 0) diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index eae9e0e5d9a..a0b65ea5549 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -447,6 +447,17 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularEx #endif // QT_NO_REGULAREXPRESSION #endif // QT_BOOTSTRAPPED +static int accumulatedSize(const QStringList &list, int seplen) +{ + int result = 0; + if (!list.isEmpty()) { + for (const auto &e : list) + result += e.size() + seplen; + result -= seplen; + } + return result; +} + /*! \fn QString QStringList::join(const QString &separator) const @@ -464,15 +475,9 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularEx */ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, int seplen) { - int totalLength = 0; + const int totalLength = accumulatedSize(*that, seplen); const int size = that->size(); - for (int i = 0; i < size; ++i) - totalLength += that->at(i).size(); - - if(size > 0) - totalLength += seplen * (size - 1); - QString res; if (totalLength == 0) return res; @@ -485,6 +490,27 @@ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, i return res; } +/*! + \fn QString QStringList::join(QLatin1String separator) const + \since 5.8 + \overload join() +*/ +QString QtPrivate::QStringList_join(const QStringList &list, QLatin1String sep) +{ + QString result; + if (!list.isEmpty()) { + result.reserve(accumulatedSize(list, sep.size())); + const auto end = list.end(); + auto it = list.begin(); + result += *it; + while (++it != end) { + result += sep; + result += *it; + } + } + return result; +} + /*! \fn QStringList QStringList::operator+(const QStringList &other) const diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 87f15528bf0..720d7d7419b 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -73,6 +73,7 @@ public: inline int removeDuplicates(); inline QString join(const QString &sep) const; + inline QString join(QLatin1String sep) const; inline QString join(QChar sep) const; inline QStringList filter(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -159,6 +160,7 @@ namespace QtPrivate { void Q_CORE_EXPORT QStringList_sort(QStringList *that, Qt::CaseSensitivity cs); int Q_CORE_EXPORT QStringList_removeDuplicates(QStringList *that); QString Q_CORE_EXPORT QStringList_join(const QStringList *that, const QChar *sep, int seplen); + Q_CORE_EXPORT QString QStringList_join(const QStringList &list, QLatin1String sep); QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QString &str, Qt::CaseSensitivity cs); @@ -200,6 +202,11 @@ inline QString QListSpecialMethods::join(const QString &sep) const return QtPrivate::QStringList_join(self(), sep.constData(), sep.length()); } +QString QListSpecialMethods::join(QLatin1String sep) const +{ + return QtPrivate::QStringList_join(*self(), sep); +} + inline QString QListSpecialMethods::join(QChar sep) const { return QtPrivate::QStringList_join(self(), &sep, 1); diff --git a/src/dbus/qdbusinternalfilters.cpp b/src/dbus/qdbusinternalfilters.cpp index ad6b06da231..03e04bb2f58 100644 --- a/src/dbus/qdbusinternalfilters.cpp +++ b/src/dbus/qdbusinternalfilters.cpp @@ -116,8 +116,7 @@ static QString generateSubObjectXml(QObject *object) for ( ; it != end; ++it) { QString name = (*it)->objectName(); if (!name.isEmpty() && QDBusUtil::isValidPartOfObjectPath(name)) - retval += QString::fromLatin1(" \n") - .arg(name); + retval += QLatin1String(" \n"); } return retval; } @@ -192,8 +191,7 @@ QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node node.children.constEnd(); for ( ; it != end; ++it) if (it->obj || !it->children.isEmpty()) - xml_data += QString::fromLatin1(" \n") - .arg(it->name); + xml_data += QLatin1String(" name + QLatin1String("\"/>\n"); } xml_data += QLatin1String("\n"); diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 442492d198a..9bd098b7b17 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -134,7 +134,8 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio Q_ASSERT(dest->format > QImage::Format_Indexed8); Q_ASSERT(src->format > QImage::Format_Indexed8); const int buffer_size = 2048; - uint buffer[buffer_size]; + uint buf[buffer_size]; + uint *buffer = buf; const QPixelLayout *srcLayout = &qPixelLayouts[src->format]; const QPixelLayout *destLayout = &qPixelLayouts[dest->format]; const uchar *srcData = src->data; @@ -169,11 +170,16 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio int x = 0; while (x < src->width) { dither.x = x; - int l = qMin(src->width - x, buffer_size); + int l = src->width - x; + if (destLayout->bpp == QPixelLayout::BPP32) + buffer = reinterpret_cast(destData) + x; + else + l = qMin(l, buffer_size); const uint *ptr = fetch(buffer, srcData, x, l); ptr = convertToARGB32PM(buffer, ptr, l, 0, ditherPtr); ptr = convertFromARGB32PM(buffer, ptr, l, 0, ditherPtr); - store(destData, ptr, x, l); + if (ptr != reinterpret_cast(destData)) + store(destData, ptr, x, l); x += l; } srcData += src->bytes_per_line; diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 0320d032b0a..4390e46fde0 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -569,7 +569,7 @@ bool QImageReaderPrivate::initHandler() do { file->setFileName(fileName + QLatin1Char('.') - + QString::fromLatin1(extensions.at(currentExtension++).constData())); + + QLatin1String(extensions.at(currentExtension++).constData())); file->open(QIODevice::ReadOnly); } while (!file->isOpen() && currentExtension < extensions.size()); diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 93374b2299d..a062331bd82 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -52,7 +52,7 @@ #include #include // ### Qt 6: Remove #include -#include // ### Qt 6: Replace by and forward declare QFile +#include // ### Qt 6: Replace by and forward declare QFile #include #include // ### Qt 6: Replace by forward declaration diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 9a75f4bc831..d59bd63caff 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -1211,9 +1211,13 @@ QString QKeySequence::encodeString(int key) static inline void addKey(QString &str, const QString &theKey, QKeySequence::SequenceFormat format) { - if (!str.isEmpty()) - str += (format == QKeySequence::NativeText) ? QCoreApplication::translate("QShortcut", "+") - : QString::fromLatin1("+"); + if (!str.isEmpty()) { + if (format == QKeySequence::NativeText) + str += QCoreApplication::translate("QShortcut", "+"); + else + str += QLatin1Char('+'); + } + str += theKey; } diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index bc4a25a65f3..1dd8fb5e670 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -667,6 +667,10 @@ void QScreenPrivate::updatePrimaryOrientation() that are not part of the application, window system frames, and so on. + \warning Grabbing windows that are not part of the application is + not supported on systems such as iOS, where sandboxing/security + prevents reading pixels of windows not owned by the application. + The grabWindow() function grabs pixels from the screen, not from the window, i.e. if there is another window partially or entirely over the one you grab, you get pixels from the overlying window, diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index c47060a2ad5..a61865a0b60 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -99,6 +99,11 @@ SOURCES += \ painting/qplatformbackingstore.cpp \ painting/qpathsimplifier.cpp +darwin { + HEADERS += painting/qcoregraphics_p.h + SOURCES += painting/qcoregraphics.mm +} + SSE2_SOURCES += painting/qdrawhelper_sse2.cpp SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \ diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm new file mode 100644 index 00000000000..a29d60ca6ef --- /dev/null +++ b/src/gui/painting/qcoregraphics.mm @@ -0,0 +1,566 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcoregraphics_p.h" + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// ---------------------- Images ---------------------- + +CGImageRef qt_mac_toCGImage(const QImage &inImage) +{ + CGImageRef cgImage = inImage.toCGImage(); + if (cgImage) + return cgImage; + + // Convert image data to a known-good format if the fast conversion fails. + return inImage.convertToFormat(QImage::Format_ARGB32_Premultiplied).toCGImage(); +} + +CGImageRef qt_mac_toCGImageMask(const QImage &image) +{ + static const auto deleter = [](void *image, const void *, size_t) { delete static_cast(image); }; + QCFType dataProvider = + CGDataProviderCreateWithData(new QImage(image), image.bits(), + image.byteCount(), deleter); + + return CGImageMaskCreate(image.width(), image.height(), 8, image.depth(), + image.bytesPerLine(), dataProvider, NULL, false); +} + +OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage) +{ + // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev) + OSStatus err = noErr; + +#ifdef Q_OS_MACOS + require_action(inContext != NULL, InvalidContext, err = paramErr); + require_action(inBounds != NULL, InvalidBounds, err = paramErr); + require_action(inImage != NULL, InvalidImage, err = paramErr); +#endif + + CGContextSaveGState( inContext ); + CGContextTranslateCTM (inContext, 0, inBounds->origin.y + CGRectGetMaxY(*inBounds)); + CGContextScaleCTM(inContext, 1, -1); + + CGContextDrawImage(inContext, *inBounds, inImage); + + CGContextRestoreGState(inContext); + +#ifdef Q_OS_MACOS +InvalidImage: +InvalidBounds: +InvalidContext: +#endif + return err; +} + +QImage qt_mac_toQImage(CGImageRef image) +{ + const size_t w = CGImageGetWidth(image), + h = CGImageGetHeight(image); + QImage ret(w, h, QImage::Format_ARGB32_Premultiplied); + ret.fill(Qt::transparent); + CGRect rect = CGRectMake(0, 0, w, h); + QMacCGContext ctx(&ret); + qt_mac_drawCGImage(ctx, &rect, image); + return ret; +} + +#ifdef Q_OS_MACOS + +QT_END_NAMESPACE + +@interface NSGraphicsContext (QtAdditions) + ++ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState; + +@end + +@implementation NSGraphicsContext (QtAdditions) + ++ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState +{ +#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_NA) + if (QT_PREPEND_NAMESPACE(QOperatingSystemVersion::current()) >= QT_PREPEND_NAMESPACE(QOperatingSystemVersion::OSXYosemite)) + return [self graphicsContextWithCGContext:graphicsPort flipped:initialFlippedState]; +#endif + return [self graphicsContextWithGraphicsPort:graphicsPort flipped:initialFlippedState]; +} + +@end + +QT_BEGIN_NAMESPACE + +static NSImage *qt_mac_cgimage_to_nsimage(CGImageRef image) +{ + NSImage *newImage = [[NSImage alloc] initWithCGImage:image size:NSZeroSize]; + return newImage; +} + +NSImage *qt_mac_create_nsimage(const QPixmap &pm) +{ + if (pm.isNull()) + return 0; + QImage image = pm.toImage(); + CGImageRef cgImage = qt_mac_toCGImage(image); + NSImage *nsImage = qt_mac_cgimage_to_nsimage(cgImage); + CGImageRelease(cgImage); + return nsImage; +} + +NSImage *qt_mac_create_nsimage(const QIcon &icon) +{ + if (icon.isNull()) + return nil; + + NSImage *nsImage = [[NSImage alloc] init]; + foreach (QSize size, icon.availableSizes()) { + QPixmap pm = icon.pixmap(size); + QImage image = pm.toImage(); + CGImageRef cgImage = qt_mac_toCGImage(image); + NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage]; + [nsImage addRepresentation:imageRep]; + [imageRep release]; + CGImageRelease(cgImage); + } + return nsImage; +} + +QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size) +{ + const NSSize pixmapSize = NSMakeSize(size.width(), size.height()); + QPixmap pixmap(pixmapSize.width, pixmapSize.height); + pixmap.fill(Qt::transparent); + [image setSize:pixmapSize]; + const NSRect iconRect = NSMakeRect(0, 0, pixmapSize.width, pixmapSize.height); + QMacCGContext ctx(&pixmap); + if (!ctx) + return QPixmap(); + NSGraphicsContext *gc = [NSGraphicsContext qt_graphicsContextWithCGContext:ctx flipped:YES]; + if (!gc) + return QPixmap(); + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:gc]; + [image drawInRect:iconRect fromRect:iconRect operation:NSCompositeSourceOver fraction:1.0 respectFlipped:YES hints:nil]; + [NSGraphicsContext restoreGraphicsState]; + return pixmap; +} + +#endif // Q_OS_MACOS + +// ---------------------- Colors and Brushes ---------------------- + +QColor qt_mac_toQColor(CGColorRef color) +{ + QColor qtColor; + CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(color)); + const CGFloat *components = CGColorGetComponents(color); + if (model == kCGColorSpaceModelRGB) { + qtColor.setRgbF(components[0], components[1], components[2], components[3]); + } else if (model == kCGColorSpaceModelCMYK) { + qtColor.setCmykF(components[0], components[1], components[2], components[3]); + } else if (model == kCGColorSpaceModelMonochrome) { + qtColor.setRgbF(components[0], components[0], components[0], components[1]); + } else { + // Colorspace we can't deal with. + qWarning("Qt: qt_mac_toQColor: cannot convert from colorspace model: %d", model); + Q_ASSERT(false); + } + return qtColor; +} + +#ifdef Q_OS_MACOS +QColor qt_mac_toQColor(const NSColor *color) +{ + QColor qtColor; + NSString *colorSpace = [color colorSpaceName]; + if (colorSpace == NSDeviceCMYKColorSpace) { + CGFloat cyan, magenta, yellow, black, alpha; + [color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha]; + qtColor.setCmykF(cyan, magenta, yellow, black, alpha); + } else { + NSColor *tmpColor; + tmpColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; + CGFloat red, green, blue, alpha; + [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha]; + qtColor.setRgbF(red, green, blue, alpha); + } + return qtColor; +} +#endif + +QBrush qt_mac_toQBrush(CGColorRef color) +{ + QBrush qtBrush; + CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(color)); + if (model == kCGColorSpaceModelPattern) { + // Colorspace we can't deal with; the color is drawn directly using a callback. + qWarning("Qt: qt_mac_toQBrush: cannot convert from colorspace model: %d", model); + Q_ASSERT(false); + } else { + qtBrush.setStyle(Qt::SolidPattern); + qtBrush.setColor(qt_mac_toQColor(color)); + } + return qtBrush; +} + +#ifdef Q_OS_MACOS +static bool qt_mac_isSystemColorOrInstance(const NSColor *color, NSString *colorNameComponent, NSString *className) +{ + // We specifically do not want isKindOfClass: here + if ([color.className isEqualToString:className]) // NSPatternColorSpace + return true; + if ([color.catalogNameComponent isEqualToString:@"System"] && + [color.colorNameComponent isEqualToString:colorNameComponent] && + [color.colorSpaceName isEqualToString:NSNamedColorSpace]) + return true; + return false; +} + +QBrush qt_mac_toQBrush(const NSColor *color, QPalette::ColorGroup colorGroup) +{ + QBrush qtBrush; + + // QTBUG-49773: This calls NSDrawMenuItemBackground to render a 1 by n gradient; could use HITheme + if ([color.className isEqualToString:@"NSMenuItemHighlightColor"]) { + qWarning("Qt: qt_mac_toQBrush: cannot convert from NSMenuItemHighlightColor"); + return qtBrush; + } + + // Not a catalog color or a manifestation of System.windowBackgroundColor; + // only retrieved from NSWindow.backgroundColor directly + if ([color.className isEqualToString:@"NSMetalPatternColor"]) { + // NSTexturedBackgroundWindowMask, could theoretically handle this without private API by + // creating a window with the appropriate properties and then calling NSWindow.backgroundColor.patternImage, + // which returns a texture sized 1 by (window height, including frame), backed by a CGPattern + // which follows the window key state... probably need to allow QBrush to store a function pointer + // like CGPattern does + qWarning("Qt: qt_mac_toQBrush: cannot convert from NSMetalPatternColor"); + return qtBrush; + } + + // No public API to get these colors/stops; + // both accurately obtained through runtime object inspection on OS X 10.11 + // (the NSColor object has NSGradient i-vars for both color groups) + if (qt_mac_isSystemColorOrInstance(color, @"_sourceListBackgroundColor", @"NSSourceListBackgroundColor")) { + QLinearGradient gradient; + if (colorGroup == QPalette::Active) { + gradient.setColorAt(0, QColor(233, 237, 242)); + gradient.setColorAt(0.5, QColor(225, 229, 235)); + gradient.setColorAt(1, QColor(209, 216, 224)); + } else { + gradient.setColorAt(0, QColor(248, 248, 248)); + gradient.setColorAt(0.5, QColor(240, 240, 240)); + gradient.setColorAt(1, QColor(235, 235, 235)); + } + return QBrush(gradient); + } + + // A couple colors are special... they are actually instances of NSGradientPatternColor, which + // override set/setFill/setStroke to instead initialize an internal color + // ([NSColor colorWithCalibratedWhite:0.909804 alpha:1.000000]) while still returning the + // ruled lines pattern image (from OS X 10.4) to the user from -[NSColor patternImage] + // (and providing no public API to get the underlying color without this insanity) + if (qt_mac_isSystemColorOrInstance(color, @"controlColor", @"NSGradientPatternColor") || + qt_mac_isSystemColorOrInstance(color, @"windowBackgroundColor", @"NSGradientPatternColor")) { + qtBrush.setStyle(Qt::SolidPattern); + qtBrush.setColor(qt_mac_toQColor(color.CGColor)); + return qtBrush; + } + + if (NSColor *patternColor = [color colorUsingColorSpaceName:NSPatternColorSpace]) { + NSImage *patternImage = patternColor.patternImage; + const QSizeF sz(patternImage.size.width, patternImage.size.height); + // FIXME: QBrush is not resolution independent (QTBUG-49774) + qtBrush.setTexture(qt_mac_toQPixmap(patternImage, sz)); + } else { + qtBrush.setStyle(Qt::SolidPattern); + qtBrush.setColor(qt_mac_toQColor(color)); + } + return qtBrush; +} +#endif + +// ---------------------- Color Management ---------------------- + +static CGColorSpaceRef m_genericColorSpace = 0; +static QHash m_displayColorSpaceHash; +static bool m_postRoutineRegistered = false; + +static void qt_mac_cleanUpMacColorSpaces() +{ + if (m_genericColorSpace) { + CFRelease(m_genericColorSpace); + m_genericColorSpace = 0; + } + QHash::const_iterator it = m_displayColorSpaceHash.constBegin(); + while (it != m_displayColorSpaceHash.constEnd()) { + if (it.value()) + CFRelease(it.value()); + ++it; + } + m_displayColorSpaceHash.clear(); +} + +static CGColorSpaceRef qt_mac_displayColorSpace(const QWindow *window) +{ + CGColorSpaceRef colorSpace = 0; + uint32_t displayID = 0; + +#ifdef Q_OS_MACOS + if (window == 0) { + displayID = CGMainDisplayID(); + } else { + displayID = CGMainDisplayID(); + /* + ### get correct display + const QRect &qrect = window->geometry(); + CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height()); + CGDisplayCount throwAway; + CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway); + if (dErr != kCGErrorSuccess) + return macDisplayColorSpace(0); // fall back on main display + */ + } + if ((colorSpace = m_displayColorSpaceHash.value(displayID))) + return colorSpace; + + colorSpace = CGDisplayCopyColorSpace(displayID); +#else + Q_UNUSED(window); +#endif + + if (colorSpace == 0) + colorSpace = CGColorSpaceCreateDeviceRGB(); + + m_displayColorSpaceHash.insert(displayID, colorSpace); + if (!m_postRoutineRegistered) { + m_postRoutineRegistered = true; + qAddPostRoutine(qt_mac_cleanUpMacColorSpaces); + } + return colorSpace; +} + +CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice) +{ + Q_UNUSED(paintDevice); + + // FIXME: Move logic into each paint device once Qt has support for color spaces + return qt_mac_displayColorSpace(0); + + // The following code seems to take care of QWidget, but in reality doesn't, as + // qt_mac_displayColorSpace ignores the argument and always uses the main display. +#if 0 + bool isWidget = (paintDevice->devType() == QInternal::Widget); + return qt_mac_displayColorSpace(isWidget ? static_cast(paintDevice)->window() : 0); +#endif +} + +CGColorSpaceRef qt_mac_genericColorSpace() +{ +#if 0 + if (!m_genericColorSpace) { + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { + m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + } else + { + m_genericColorSpace = CGColorSpaceCreateDeviceRGB(); + } + if (!m_postRoutineRegistered) { + m_postRoutineRegistered = true; + qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); + } + } + return m_genericColorSpace; +#else + // Just return the main display colorspace for the moment. + return qt_mac_displayColorSpace(0); +#endif +} + +// ---------------------- Geometry Helpers ---------------------- + +void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform) +{ + CGAffineTransform old_xform = CGAffineTransformIdentity; + if (orig_xform) { //setup xforms + old_xform = CGContextGetCTM(hd); + CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform)); + CGContextConcatCTM(hd, *orig_xform); + } + + //do the clipping + CGContextBeginPath(hd); + if (rgn.isEmpty()) { + CGContextAddRect(hd, CGRectMake(0, 0, 0, 0)); + } else { + for (const QRect &r : rgn) { + CGRect mac_r = CGRectMake(r.x(), r.y(), r.width(), r.height()); + CGContextAddRect(hd, mac_r); + } + } + CGContextClip(hd); + + if (orig_xform) {//reset xforms + CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); + CGContextConcatCTM(hd, old_xform); + } +} + +// move to QRegion? +void qt_mac_scale_region(QRegion *region, qreal scaleFactor) +{ + if (!region || !region->rectCount()) + return; + + QVector scaledRects; + scaledRects.reserve(region->rectCount()); + + for (const QRect &rect : *region) + scaledRects.append(QRect(rect.topLeft() * scaleFactor, rect.size() * scaleFactor)); + + region->setRects(&scaledRects[0], scaledRects.count()); +} + +// ---------------------- QMacCGContext ---------------------- + +QMacCGContext::QMacCGContext(QPaintDevice *paintDevice) : context(0) +{ + // In Qt 5, QWidget and QPixmap (and QImage) paint devices are all QImages under the hood. + QImage *image = 0; + if (paintDevice->devType() == QInternal::Image) { + image = static_cast(paintDevice); + } else if (paintDevice->devType() == QInternal::Pixmap) { + + const QPixmap *pm = static_cast(paintDevice); + QPlatformPixmap *data = const_cast(pm)->data_ptr().data(); + if (data && data->classId() == QPlatformPixmap::RasterClass) { + image = data->buffer(); + } else { + qDebug("QMacCGContext: Unsupported pixmap class"); + } + } else if (paintDevice->devType() == QInternal::Widget) { + // TODO test: image = static_cast(static_cast(paintDevice)->backingStore()->paintDevice()); + qDebug("QMacCGContext: not implemented: Widget class"); + } + + if (!image) + return; // Context type not supported. + + CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(paintDevice); + uint flags = kCGImageAlphaPremultipliedFirst; + flags |= kCGBitmapByteOrder32Host; + + context = CGBitmapContextCreate(image->bits(), image->width(), image->height(), + 8, image->bytesPerLine(), colorspace, flags); + CGContextTranslateCTM(context, 0, image->height()); + CGContextScaleCTM(context, 1, -1); +} + +QMacCGContext::QMacCGContext(QPainter *painter) : context(0) +{ + QPaintEngine *paintEngine = painter->paintEngine(); + + // Handle the case of QMacPrintEngine, which has an internal QCoreGraphicsPaintEngine + while (QPaintEngine *aggregateEngine = QPaintEnginePrivate::get(paintEngine)->aggregateEngine()) + paintEngine = aggregateEngine; + + paintEngine->syncState(); + + if (Qt::HANDLE handle = QPaintEnginePrivate::get(paintEngine)->nativeHandle()) { + context = static_cast(handle); + return; + } + + int devType = painter->device()->devType(); + if (paintEngine->type() == QPaintEngine::Raster + && (devType == QInternal::Widget || + devType == QInternal::Pixmap || + devType == QInternal::Image)) { + + CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(paintEngine->paintDevice()); + uint flags = kCGImageAlphaPremultipliedFirst; +#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version + flags |= kCGBitmapByteOrder32Host; +#endif + const QImage *image = static_cast(paintEngine->paintDevice()); + + context = CGBitmapContextCreate((void *)image->bits(), image->width(), image->height(), + 8, image->bytesPerLine(), colorspace, flags); + + // Invert y axis + CGContextTranslateCTM(context, 0, image->height()); + CGContextScaleCTM(context, 1, -1); + + const qreal devicePixelRatio = image->devicePixelRatio(); + + if (devType == QInternal::Widget) { + // Set the clip rect which is an intersection of the system clip + // and the painter clip. To make matters more interesting these + // are in device pixels and device-independent pixels, respectively. + QRegion clip = painter->paintEngine()->systemClip(); // get system clip in device pixels + QTransform native = painter->deviceTransform(); // get device transform. dx/dy is in device pixels + + if (painter->hasClipping()) { + QRegion r = painter->clipRegion(); // get painter clip, which is in device-independent pixels + qt_mac_scale_region(&r, devicePixelRatio); // scale painter clip to device pixels + r.translate(native.dx(), native.dy()); + if (clip.isEmpty()) + clip = r; + else + clip &= r; + } + qt_mac_clip_cg(context, clip, 0); // clip in device pixels + + // Scale the context so that painting happens in device-independent pixels + CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio); + CGContextTranslateCTM(context, native.dx() / devicePixelRatio, native.dy() / devicePixelRatio); + } else { + // Scale to paint in device-independent pixels + CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio); + } + } else { + qDebug() << "QMacCGContext:: Unsupported painter devtype type" << devType; + } +} + +QT_END_NAMESPACE diff --git a/src/gui/painting/qcoregraphics_p.h b/src/gui/painting/qcoregraphics_p.h new file mode 100644 index 00000000000..ab2579387e6 --- /dev/null +++ b/src/gui/painting/qcoregraphics_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOREGRAPHICS_P_H +#define QCOREGRAPHICS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include +#ifdef Q_OS_MACOS +#include +#endif + +QT_BEGIN_NAMESPACE + +#ifdef Q_OS_MACOS +Q_GUI_EXPORT NSImage *qt_mac_create_nsimage(const QPixmap &pm); +Q_GUI_EXPORT NSImage *qt_mac_create_nsimage(const QIcon &icon); +Q_GUI_EXPORT QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size); +#endif +Q_GUI_EXPORT CGImageRef qt_mac_toCGImage(const QImage &qImage); +Q_GUI_EXPORT CGImageRef qt_mac_toCGImageMask(const QImage &qImage); +Q_GUI_EXPORT QImage qt_mac_toQImage(CGImageRef image); + +Q_GUI_EXPORT OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage); + +Q_GUI_EXPORT CGColorSpaceRef qt_mac_genericColorSpace(); +Q_GUI_EXPORT CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice); + +Q_GUI_EXPORT void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform); + +#ifdef Q_OS_MACOS +Q_GUI_EXPORT QColor qt_mac_toQColor(const NSColor *color); +Q_GUI_EXPORT QBrush qt_mac_toQBrush(const NSColor *color, QPalette::ColorGroup colorGroup = QPalette::Normal); +#endif +Q_GUI_EXPORT QColor qt_mac_toQColor(CGColorRef color); +Q_GUI_EXPORT QBrush qt_mac_toQBrush(CGColorRef color); + +class Q_GUI_EXPORT QMacCGContext +{ +public: + inline QMacCGContext() { context = 0; } + QMacCGContext(QPaintDevice *pdev); + QMacCGContext(QPainter *p); + inline QMacCGContext(CGContextRef cg, bool takeOwnership = false) { + context = cg; + if (!takeOwnership) + CGContextRetain(context); + } + inline QMacCGContext(const QMacCGContext ©) : context(0) { *this = copy; } + inline ~QMacCGContext() { + if (context) + CGContextRelease(context); + } + inline bool isNull() const { return context; } + inline operator CGContextRef() { return context; } + inline QMacCGContext &operator=(const QMacCGContext ©) { + if (context) + CGContextRelease(context); + context = copy.context; + CGContextRetain(context); + return *this; + } + inline QMacCGContext &operator=(CGContextRef cg) { + if (context) + CGContextRelease(context); + context = cg; + CGContextRetain(context); //we do not take ownership + return *this; + } + +private: + CGContextRef context; +}; + +QT_END_NAMESPACE + +#endif // QCOREGRAPHICS_P_H diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index c697aceaf38..c1a49b7d9a1 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -3263,342 +3263,72 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co return buffer; } -static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { - // Untransformed - { - 0, // Invalid - fetchUntransformed, // Mono - fetchUntransformed, // MonoLsb - fetchUntransformed, // Indexed8 - fetchUntransformedARGB32PM, // RGB32 - fetchUntransformed, // ARGB32 - fetchUntransformedARGB32PM, // ARGB32_Premultiplied - fetchUntransformedRGB16, // RGB16 - fetchUntransformed, // ARGB8565_Premultiplied - fetchUntransformed, // RGB666 - fetchUntransformed, // ARGB6666_Premultiplied - fetchUntransformed, // RGB555 - fetchUntransformed, // ARGB8555_Premultiplied - fetchUntransformed, // RGB888 - fetchUntransformed, // RGB444 - fetchUntransformed, // ARGB4444_Premultiplied - fetchUntransformed, // RGBX8888 - fetchUntransformed, // RGBA8888 - fetchUntransformed, // RGBA8888_Premultiplied - fetchUntransformed, // Format_BGR30 - fetchUntransformed, // Format_A2BGR30_Premultiplied - fetchUntransformed, // Format_RGB30 - fetchUntransformed, // Format_A2RGB30_Premultiplied - fetchUntransformed, // Alpha8 - fetchUntransformed, // Grayscale8 - }, - // Tiled - { - 0, // Invalid - fetchUntransformed, // Mono - fetchUntransformed, // MonoLsb - fetchUntransformed, // Indexed8 - fetchUntransformedARGB32PM, // RGB32 - fetchUntransformed, // ARGB32 - fetchUntransformedARGB32PM, // ARGB32_Premultiplied - fetchUntransformedRGB16, // RGB16 - fetchUntransformed, // ARGB8565_Premultiplied - fetchUntransformed, // RGB666 - fetchUntransformed, // ARGB6666_Premultiplied - fetchUntransformed, // RGB555 - fetchUntransformed, // ARGB8555_Premultiplied - fetchUntransformed, // RGB888 - fetchUntransformed, // RGB444 - fetchUntransformed, // ARGB4444_Premultiplied - fetchUntransformed, // RGBX8888 - fetchUntransformed, // RGBA8888 - fetchUntransformed, // RGBA8888_Premultiplied - fetchUntransformed, // BGR30 - fetchUntransformed, // A2BGR30_Premultiplied - fetchUntransformed, // RGB30 - fetchUntransformed, // A2RGB30_Premultiplied - fetchUntransformed, // Alpha8 - fetchUntransformed, // Grayscale8 - }, - // Transformed - { - 0, // Invalid - fetchTransformed, // Mono - fetchTransformed, // MonoLsb - fetchTransformed, // Indexed8 - fetchTransformedARGB32PM, // RGB32 - fetchTransformed, // ARGB32 - fetchTransformedARGB32PM, // ARGB32_Premultiplied - fetchTransformed, // RGB16 - fetchTransformed, // ARGB8565_Premultiplied - fetchTransformed, // RGB666 - fetchTransformed, // ARGB6666_Premultiplied - fetchTransformed, // RGB555 - fetchTransformed, // ARGB8555_Premultiplied - fetchTransformed, // RGB888 - fetchTransformed, // RGB444 - fetchTransformed, // ARGB4444_Premultiplied - fetchTransformed, // RGBX8888 - fetchTransformed, // RGBA8888 - fetchTransformed, // RGBA8888_Premultiplied - fetchTransformed, // BGR30 - fetchTransformed, // A2BGR30_Premultiplied - fetchTransformed, // RGB30 - fetchTransformed, // A2RGB30_Premultiplied - fetchTransformed, // Alpah8 - fetchTransformed, // Grayscale8 - }, - { - 0, // TransformedTiled - fetchTransformed, // Mono - fetchTransformed, // MonoLsb - fetchTransformed, // Indexed8 - fetchTransformedARGB32PM, // RGB32 - fetchTransformed, // ARGB32 - fetchTransformedARGB32PM, // ARGB32_Premultiplied - fetchTransformed, // RGB16 - fetchTransformed, // ARGB8565_Premultiplied - fetchTransformed, // RGB666 - fetchTransformed, // ARGB6666_Premultiplied - fetchTransformed, // RGB555 - fetchTransformed, // ARGB8555_Premultiplied - fetchTransformed, // RGB888 - fetchTransformed, // RGB444 - fetchTransformed, // ARGB4444_Premultiplied - fetchTransformed, // RGBX8888 - fetchTransformed, // RGBA8888 - fetchTransformed, // RGBA8888_Premultiplied - fetchTransformed, // BGR30 - fetchTransformed, // A2BGR30_Premultiplied - fetchTransformed, // RGB30 - fetchTransformed, // A2RGB30_Premultiplied - fetchTransformed, // Alpha8 - fetchTransformed, // Grayscale8 - }, - { - 0, // Bilinear - fetchTransformedBilinear, // Mono - fetchTransformedBilinear, // MonoLsb - fetchTransformedBilinear, // Indexed8 - fetchTransformedBilinearARGB32PM, // RGB32 - fetchTransformedBilinear, // ARGB32 - fetchTransformedBilinearARGB32PM, // ARGB32_Premultiplied - fetchTransformedBilinear, // RGB16 - fetchTransformedBilinear, // ARGB8565_Premultiplied - fetchTransformedBilinear, // RGB666 - fetchTransformedBilinear, // ARGB6666_Premultiplied - fetchTransformedBilinear, // RGB555 - fetchTransformedBilinear, // ARGB8555_Premultiplied - fetchTransformedBilinear, // RGB888 - fetchTransformedBilinear, // RGB444 - fetchTransformedBilinear, // ARGB4444_Premultiplied - fetchTransformedBilinear, // RGBX8888 - fetchTransformedBilinear, // RGBA8888 - fetchTransformedBilinear, // RGBA8888_Premultiplied - fetchTransformedBilinear, // BGR30 - fetchTransformedBilinear, // A2BGR30_Premultiplied - fetchTransformedBilinear, // RGB30 - fetchTransformedBilinear, // A2RGB30_Premultiplied - fetchTransformedBilinear, // Alpha8 - fetchTransformedBilinear, // Grayscale8 - }, - { - 0, // BilinearTiled - fetchTransformedBilinear, // Mono - fetchTransformedBilinear, // MonoLsb - fetchTransformedBilinear, // Indexed8 - fetchTransformedBilinearARGB32PM, // RGB32 - fetchTransformedBilinear, // ARGB32 - fetchTransformedBilinearARGB32PM, // ARGB32_Premultiplied - fetchTransformedBilinear, // RGB16 - fetchTransformedBilinear, // ARGB8565_Premultiplied - fetchTransformedBilinear, // RGB666 - fetchTransformedBilinear, // ARGB6666_Premultiplied - fetchTransformedBilinear, // RGB555 - fetchTransformedBilinear, // ARGB8555_Premultiplied - fetchTransformedBilinear, // RGB888 - fetchTransformedBilinear, // RGB444 - fetchTransformedBilinear, // ARGB4444_Premultiplied - fetchTransformedBilinear, // RGBX8888 - fetchTransformedBilinear, // RGBA8888 - fetchTransformedBilinear, // RGBA8888_Premultiplied - fetchTransformedBilinear, // BGR30 - fetchTransformedBilinear, // A2BGR30_Premultiplied - fetchTransformedBilinear, // RGB30 - fetchTransformedBilinear, // A2RGB30_Premultiplied - fetchTransformedBilinear, // Alpha8 - fetchTransformedBilinear, // Grayscale8 - }, +// FetchUntransformed can have more specialized methods added depending on SIMD features. +static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = { + 0, // Invalid + fetchUntransformed, // Mono + fetchUntransformed, // MonoLsb + fetchUntransformed, // Indexed8 + fetchUntransformedARGB32PM, // RGB32 + fetchUntransformed, // ARGB32 + fetchUntransformedARGB32PM, // ARGB32_Premultiplied + fetchUntransformedRGB16, // RGB16 + fetchUntransformed, // ARGB8565_Premultiplied + fetchUntransformed, // RGB666 + fetchUntransformed, // ARGB6666_Premultiplied + fetchUntransformed, // RGB555 + fetchUntransformed, // ARGB8555_Premultiplied + fetchUntransformed, // RGB888 + fetchUntransformed, // RGB444 + fetchUntransformed, // ARGB4444_Premultiplied + fetchUntransformed, // RGBX8888 + fetchUntransformed, // RGBA8888 + fetchUntransformed, // RGBA8888_Premultiplied + fetchUntransformed, // Format_BGR30 + fetchUntransformed, // Format_A2BGR30_Premultiplied + fetchUntransformed, // Format_RGB30 + fetchUntransformed, // Format_A2RGB30_Premultiplied + fetchUntransformed, // Alpha8 + fetchUntransformed, // Grayscale8 }; -static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = { - // Untransformed - { - 0, // Invalid - fetchUntransformed64, // Mono - fetchUntransformed64, // MonoLsb - fetchUntransformed64, // Indexed8 - fetchUntransformed64, // RGB32 - fetchUntransformed64, // ARGB32 - fetchUntransformed64, // ARGB32_Premultiplied - fetchUntransformed64, // RGB16 - fetchUntransformed64, // ARGB8565_Premultiplied - fetchUntransformed64, // RGB666 - fetchUntransformed64, // ARGB6666_Premultiplied - fetchUntransformed64, // RGB555 - fetchUntransformed64, // ARGB8555_Premultiplied - fetchUntransformed64, // RGB888 - fetchUntransformed64, // RGB444 - fetchUntransformed64, // ARGB4444_Premultiplied - fetchUntransformed64, // RGBX8888 - fetchUntransformed64, // RGBA8888 - fetchUntransformed64, // RGBA8888_Premultiplied - fetchUntransformed64, // Format_BGR30 - fetchUntransformed64, // Format_A2BGR30_Premultiplied - fetchUntransformed64, // Format_RGB30 - fetchUntransformed64, // Format_A2RGB30_Premultiplied - fetchUntransformed64, // Alpha8 - fetchUntransformed64, // Grayscale8 - }, - // Tiled - { - 0, // Invalid - fetchUntransformed64, // Mono - fetchUntransformed64, // MonoLsb - fetchUntransformed64, // Indexed8 - fetchUntransformed64, // RGB32 - fetchUntransformed64, // ARGB32 - fetchUntransformed64, // ARGB32_Premultiplied - fetchUntransformed64, // RGB16 - fetchUntransformed64, // ARGB8565_Premultiplied - fetchUntransformed64, // RGB666 - fetchUntransformed64, // ARGB6666_Premultiplied - fetchUntransformed64, // RGB555 - fetchUntransformed64, // ARGB8555_Premultiplied - fetchUntransformed64, // RGB888 - fetchUntransformed64, // RGB444 - fetchUntransformed64, // ARGB4444_Premultiplied - fetchUntransformed64, // RGBX8888 - fetchUntransformed64, // RGBA8888 - fetchUntransformed64, // RGBA8888_Premultiplied - fetchUntransformed64, // BGR30 - fetchUntransformed64, // A2BGR30_Premultiplied - fetchUntransformed64, // RGB30 - fetchUntransformed64, // A2RGB30_Premultiplied - fetchUntransformed64, // Alpha8 - fetchUntransformed64, // Grayscale8 - }, - // Transformed - { - 0, // Invalid - fetchTransformed64, // Mono - fetchTransformed64, // MonoLsb - fetchTransformed64, // Indexed8 - fetchTransformed64, // RGB32 - fetchTransformed64, // ARGB32 - fetchTransformed64, // ARGB32_Premultiplied - fetchTransformed64, // RGB16 - fetchTransformed64, // ARGB8565_Premultiplied - fetchTransformed64, // RGB666 - fetchTransformed64, // ARGB6666_Premultiplied - fetchTransformed64, // RGB555 - fetchTransformed64, // ARGB8555_Premultiplied - fetchTransformed64, // RGB888 - fetchTransformed64, // RGB444 - fetchTransformed64, // ARGB4444_Premultiplied - fetchTransformed64, // RGBX8888 - fetchTransformed64, // RGBA8888 - fetchTransformed64, // RGBA8888_Premultiplied - fetchTransformed64, // BGR30 - fetchTransformed64, // A2BGR30_Premultiplied - fetchTransformed64, // RGB30 - fetchTransformed64, // A2RGB30_Premultiplied - fetchTransformed64, // Alpah8 - fetchTransformed64, // Grayscale8 - }, - { - 0, // TransformedTiled - fetchTransformed64, // Mono - fetchTransformed64, // MonoLsb - fetchTransformed64, // Indexed8 - fetchTransformed64, // RGB32 - fetchTransformed64, // ARGB32 - fetchTransformed64, // ARGB32_Premultiplied - fetchTransformed64, // RGB16 - fetchTransformed64, // ARGB8565_Premultiplied - fetchTransformed64, // RGB666 - fetchTransformed64, // ARGB6666_Premultiplied - fetchTransformed64, // RGB555 - fetchTransformed64, // ARGB8555_Premultiplied - fetchTransformed64, // RGB888 - fetchTransformed64, // RGB444 - fetchTransformed64, // ARGB4444_Premultiplied - fetchTransformed64, // RGBX8888 - fetchTransformed64, // RGBA8888 - fetchTransformed64, // RGBA8888_Premultiplied - fetchTransformed64, // BGR30 - fetchTransformed64, // A2BGR30_Premultiplied - fetchTransformed64, // RGB30 - fetchTransformed64, // A2RGB30_Premultiplied - fetchTransformed64, // Alpha8 - fetchTransformed64, // Grayscale8 - }, - { - 0, // Bilinear - fetchTransformedBilinear64, // Mono - fetchTransformedBilinear64, // MonoLsb - fetchTransformedBilinear64, // Indexed8 - fetchTransformedBilinear64, // RGB32 - fetchTransformedBilinear64, // ARGB32 - fetchTransformedBilinear64, // ARGB32_Premultiplied - fetchTransformedBilinear64, // RGB16 - fetchTransformedBilinear64, // ARGB8565_Premultiplied - fetchTransformedBilinear64, // RGB666 - fetchTransformedBilinear64, // ARGB6666_Premultiplied - fetchTransformedBilinear64, // RGB555 - fetchTransformedBilinear64, // ARGB8555_Premultiplied - fetchTransformedBilinear64, // RGB888 - fetchTransformedBilinear64, // RGB444 - fetchTransformedBilinear64, // ARGB4444_Premultiplied - fetchTransformedBilinear64, // RGBX8888 - fetchTransformedBilinear64, // RGBA8888 - fetchTransformedBilinear64, // RGBA8888_Premultiplied - fetchTransformedBilinear64, // BGR30 - fetchTransformedBilinear64, // A2BGR30_Premultiplied - fetchTransformedBilinear64, // RGB30 - fetchTransformedBilinear64, // A2RGB30_Premultiplied - fetchTransformedBilinear64, // Alpha8 - fetchTransformedBilinear64, // Grayscale8 - }, - { - 0, // BilinearTiled - fetchTransformedBilinear64, // Mono - fetchTransformedBilinear64, // MonoLsb - fetchTransformedBilinear64, // Indexed8 - fetchTransformedBilinear64, // RGB32 - fetchTransformedBilinear64, // ARGB32 - fetchTransformedBilinear64, // ARGB32_Premultiplied - fetchTransformedBilinear64, // RGB16 - fetchTransformedBilinear64, // ARGB8565_Premultiplied - fetchTransformedBilinear64, // RGB666 - fetchTransformedBilinear64, // ARGB6666_Premultiplied - fetchTransformedBilinear64, // RGB555 - fetchTransformedBilinear64, // ARGB8555_Premultiplied - fetchTransformedBilinear64, // RGB888 - fetchTransformedBilinear64, // RGB444 - fetchTransformedBilinear64, // ARGB4444_Premultiplied - fetchTransformedBilinear64, // RGBX8888 - fetchTransformedBilinear64, // RGBA8888 - fetchTransformedBilinear64, // RGBA8888_Premultiplied - fetchTransformedBilinear64, // BGR30 - fetchTransformedBilinear64, // A2BGR30_Premultiplied - fetchTransformedBilinear64, // RGB30 - fetchTransformedBilinear64, // A2RGB30_Premultiplied - fetchTransformedBilinear64, // Alpha8 - fetchTransformedBilinear64, // Grayscale8 - }, +static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = { + fetchUntransformed, // Untransformed + fetchUntransformed, // Tiled + fetchTransformed, // Transformed + fetchTransformed, // TransformedTiled + fetchTransformedBilinear, // Bilinear + fetchTransformedBilinear // BilinearTiled }; +static SourceFetchProc sourceFetchARGB32PM[NBlendTypes] = { + fetchUntransformedARGB32PM, // Untransformed + fetchUntransformedARGB32PM, // Tiled + fetchTransformedARGB32PM, // Transformed + fetchTransformedARGB32PM, // TransformedTiled + fetchTransformedBilinearARGB32PM, // Bilinear + fetchTransformedBilinearARGB32PM // BilinearTiled +}; + +static const SourceFetchProc64 sourceFetchGeneric64[NBlendTypes] = { + fetchUntransformed64, // Untransformed + fetchUntransformed64, // Tiled + fetchTransformed64, // Transformed + fetchTransformed64, // TransformedTiled + fetchTransformedBilinear64, // Bilinear + fetchTransformedBilinear64 // BilinearTiled +}; + +static inline SourceFetchProc getSourceFetch(TextureBlendType blendType, QImage::Format format) +{ + if (format == QImage::Format_RGB32 || format == QImage::Format_ARGB32_Premultiplied) + return sourceFetchARGB32PM[blendType]; + if (blendType == BlendUntransformed || blendType == BlendTiled) + return sourceFetchUntransformed[format]; + return sourceFetchGeneric[blendType]; +} + + #define FIXPT_BITS 8 #define FIXPT_SIZE (1<texture.hasAlpha; - op.srcFetch = sourceFetch[getBlendType(data)][data->texture.format]; - op.srcFetch64 = sourceFetch64[getBlendType(data)][data->texture.format]; + op.srcFetch = getSourceFetch(getBlendType(data), data->texture.format); + op.srcFetch64 = sourceFetchGeneric64[getBlendType(data)]; break; default: Q_UNREACHABLE(); @@ -5483,181 +5213,67 @@ static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, void * /* Image formats here are target formats */ -static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats] = { - // Untransformed - { - 0, // Invalid - blend_untransformed_generic, // Mono - blend_untransformed_generic, // MonoLsb - blend_untransformed_generic, // Indexed8 - blend_untransformed_generic, // RGB32 - blend_untransformed_generic, // ARGB32 - blend_untransformed_argb, // ARGB32_Premultiplied - blend_untransformed_rgb565, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic_rgb64, - blend_untransformed_generic_rgb64, - blend_untransformed_generic_rgb64, - blend_untransformed_generic_rgb64, - blend_untransformed_generic, - blend_untransformed_generic, - }, - // Tiled - { - 0, // Invalid - blend_tiled_generic, // Mono - blend_tiled_generic, // MonoLsb - blend_tiled_generic, // Indexed8 - blend_tiled_generic, // RGB32 - blend_tiled_generic, // ARGB32 - blend_tiled_argb, // ARGB32_Premultiplied - blend_tiled_rgb565, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic_rgb64, - blend_tiled_generic_rgb64, - blend_tiled_generic_rgb64, - blend_tiled_generic_rgb64, - blend_tiled_generic, - blend_tiled_generic, - }, - // Transformed - { - 0, // Invalid - blend_src_generic, // Mono - blend_src_generic, // MonoLsb - blend_src_generic, // Indexed8 - blend_src_generic, // RGB32 - blend_src_generic, // ARGB32 - blend_transformed_argb, // ARGB32_Premultiplied - blend_transformed_rgb565, - blend_src_generic, // ARGB8565_Premultiplied - blend_src_generic, // RGB666 - blend_src_generic, // ARGB6666_Premultiplied - blend_src_generic, // RGB555 - blend_src_generic, // ARGB8555_Premultiplied - blend_src_generic, // RGB888 - blend_src_generic, // RGB444 - blend_src_generic, // ARGB4444_Premultiplied - blend_src_generic, // RGBX8888 - blend_src_generic, // RGBA8888 - blend_src_generic, // RGBA8888_Premultiplied - blend_src_generic_rgb64, - blend_src_generic_rgb64, - blend_src_generic_rgb64, - blend_src_generic_rgb64, - blend_src_generic, - blend_src_generic, - }, - // TransformedTiled - { - 0, - blend_src_generic, // Mono - blend_src_generic, // MonoLsb - blend_src_generic, // Indexed8 - blend_src_generic, // RGB32 - blend_src_generic, // ARGB32 - blend_transformed_tiled_argb, // ARGB32_Premultiplied - blend_transformed_tiled_rgb565, - blend_src_generic, // ARGB8565_Premultiplied - blend_src_generic, // RGB666 - blend_src_generic, // ARGB6666_Premultiplied - blend_src_generic, // RGB555 - blend_src_generic, // ARGB8555_Premultiplied - blend_src_generic, // RGB888 - blend_src_generic, // RGB444 - blend_src_generic, // ARGB4444_Premultiplied - blend_src_generic, // RGBX8888 - blend_src_generic, // RGBA8888 - blend_src_generic, // RGBA8888_Premultiplied - blend_src_generic_rgb64, - blend_src_generic_rgb64, - blend_src_generic_rgb64, - blend_src_generic_rgb64, - blend_src_generic, - blend_src_generic, - }, - // Bilinear - { - 0, - blend_src_generic, // Mono - blend_src_generic, // MonoLsb - blend_src_generic, // Indexed8 - blend_src_generic, // RGB32 - blend_src_generic, // ARGB32 - blend_src_generic, // ARGB32_Premultiplied - blend_transformed_bilinear_rgb565, - blend_src_generic, // ARGB8565_Premultiplied - blend_src_generic, // RGB666 - blend_src_generic, // ARGB6666_Premultiplied - blend_src_generic, // RGB555 - blend_src_generic, // ARGB8555_Premultiplied - blend_src_generic, // RGB888 - blend_src_generic, // RGB444 - blend_src_generic, // ARGB4444_Premultiplied - blend_src_generic, // RGBX8888 - blend_src_generic, // RGBA8888 - blend_src_generic, // RGBA8888_Premultiplied - blend_src_generic_rgb64, - blend_src_generic_rgb64, - blend_src_generic_rgb64, - blend_src_generic_rgb64, - blend_src_generic, - blend_src_generic, - }, - // BilinearTiled - { - 0, - blend_src_generic, // Mono - blend_src_generic, // MonoLsb - blend_src_generic, // Indexed8 - blend_src_generic, // RGB32 - blend_src_generic, // ARGB32 - blend_src_generic, // ARGB32_Premultiplied - blend_src_generic, // RGB16 - blend_src_generic, // ARGB8565_Premultiplied - blend_src_generic, // RGB666 - blend_src_generic, // ARGB6666_Premultiplied - blend_src_generic, // RGB555 - blend_src_generic, // ARGB8555_Premultiplied - blend_src_generic, // RGB888 - blend_src_generic, // RGB444 - blend_src_generic, // ARGB4444_Premultiplied - blend_src_generic, // RGBX8888 - blend_src_generic, // RGBA8888 - blend_src_generic, // RGBA8888_Premultiplied - blend_src_generic_rgb64, // BGR30 - blend_src_generic_rgb64, // A2BGR30_Premultiplied - blend_src_generic_rgb64, // RGB30 - blend_src_generic_rgb64, // A2RGB30_Premultiplied - blend_src_generic, // Alpha8 - blend_src_generic, // Grayscale8 - } +static const ProcessSpans processTextureSpansARGB32PM[NBlendTypes] = { + blend_untransformed_argb, // Untransformed + blend_tiled_argb, // Tiled + blend_transformed_argb, // Transformed + blend_transformed_tiled_argb, // TransformedTiled + blend_src_generic, // TransformedBilinear + blend_src_generic // TransformedBilinearTiled +}; + +static const ProcessSpans processTextureSpansRGB16[NBlendTypes] = { + blend_untransformed_rgb565, // Untransformed + blend_tiled_rgb565, // Tiled + blend_transformed_rgb565, // Transformed + blend_transformed_tiled_rgb565, // TransformedTiled + blend_transformed_bilinear_rgb565, // TransformedBilinear + blend_src_generic // TransformedBilinearTiled +}; + +static const ProcessSpans processTextureSpansGeneric[NBlendTypes] = { + blend_untransformed_generic, // Untransformed + blend_tiled_generic, // Tiled + blend_src_generic, // Transformed + blend_src_generic, // TransformedTiled + blend_src_generic, // TransformedBilinear + blend_src_generic // TransformedBilinearTiled +}; + +static const ProcessSpans processTextureSpansGeneric64[NBlendTypes] = { + blend_untransformed_generic_rgb64, // Untransformed + blend_tiled_generic_rgb64, // Tiled + blend_src_generic_rgb64, // Transformed + blend_src_generic_rgb64, // TransformedTiled + blend_src_generic_rgb64, // TransformedBilinear + blend_src_generic_rgb64 // TransformedBilinearTiled }; void qBlendTexture(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast(userData); - ProcessSpans proc = processTextureSpans[getBlendType(data)][data->rasterBuffer->format]; + TextureBlendType blendType = getBlendType(data); + ProcessSpans proc; + switch (data->rasterBuffer->format) { + case QImage::Format_ARGB32_Premultiplied: + proc = processTextureSpansARGB32PM[blendType]; + break; + case QImage::Format_RGB16: + proc = processTextureSpansRGB16[blendType]; + break; + case QImage::Format_BGR30: + case QImage::Format_A2BGR30_Premultiplied: + case QImage::Format_RGB30: + case QImage::Format_A2RGB30_Premultiplied: + proc = processTextureSpansGeneric64[blendType]; + break; + case QImage::Format_Invalid: + Q_UNREACHABLE(); + return; + default: + proc = processTextureSpansGeneric[blendType]; + break; + } proc(count, spans, userData); } @@ -6548,6 +6164,15 @@ static void qInitDrawhelperFunctions() qt_fetch_radial_gradient = qt_fetch_radial_gradient_sse2; + extern void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); + extern void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha); + extern void QT_FASTCALL comp_func_Source_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); + extern void QT_FASTCALL comp_func_Plus_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); + qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_sse2; + qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_sse2; + qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_sse2; + qt_functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_sse2; + #ifdef QT_COMPILER_SUPPORTS_SSSE3 if (qCpuHasFeature(SSSE3)) { extern void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl, @@ -6563,8 +6188,7 @@ static void qInitDrawhelperFunctions() qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; qStorePixels[QPixelLayout::BPP24] = storePixelsBPP24_ssse3; - sourceFetch[BlendUntransformed][QImage::Format_RGB888] = qt_fetchUntransformed_888_ssse3; - sourceFetch[BlendTiled][QImage::Format_RGB888] = qt_fetchUntransformed_888_ssse3; + sourceFetchUntransformed[QImage::Format_RGB888] = qt_fetchUntransformed_888_ssse3; } #endif // SSSE3 @@ -6592,24 +6216,39 @@ static void qInitDrawhelperFunctions() } #endif -#if defined(QT_COMPILER_SUPPORTS_AVX2) && !defined(__AVX2__) +#if defined(QT_COMPILER_SUPPORTS_AVX2) if (qCpuHasFeature(AVX2)) { +#if !defined(__AVX2__) extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QVector *, QDitherInfo *); extern const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QVector *, QDitherInfo *); qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_avx2; qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_avx2; +#endif + extern void qt_blend_rgb32_on_rgb32_avx2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, int const_alpha); + extern void qt_blend_argb32_on_argb32_avx2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, int const_alpha); + qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_avx2; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_avx2; + qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_avx2; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_avx2; + qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_avx2; + qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_avx2; + qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_avx2; + qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_avx2; + + extern void QT_FASTCALL comp_func_SourceOver_avx2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); + extern void QT_FASTCALL comp_func_solid_SourceOver_avx2(uint *destPixels, int length, uint color, uint const_alpha); + extern void QT_FASTCALL comp_func_Source_avx2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); + qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_avx2; + qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_avx2; + qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_avx2; } #endif - extern void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); - extern void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha); - extern void QT_FASTCALL comp_func_Source_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); - extern void QT_FASTCALL comp_func_Plus_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); - qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_sse2; - qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_sse2; - qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_sse2; - qt_functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_sse2; #endif // SSE2 @@ -6634,8 +6273,7 @@ static void qInitDrawhelperFunctions() qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon; - sourceFetch[BlendUntransformed][QImage::Format_RGB888] = qt_fetchUntransformed_888_neon; - sourceFetch[BlendTiled][QImage::Format_RGB888] = qt_fetchUntransformed_888_neon; + sourceFetchUntransformed[QImage::Format_RGB888] = qt_fetchUntransformed_888_neon; #if defined(ENABLE_PIXMAN_DRAWHELPERS) // The RGB16 helpers are using Arm32 assemblythat has not been ported to AArch64 @@ -6696,14 +6334,9 @@ static void qInitDrawhelperFunctions() destStoreProc[QImage::Format_ARGB32] = qt_destStoreARGB32_mips_dsp; - sourceFetch[BlendUntransformed][QImage::Format_RGB888] = qt_fetchUntransformed_888_mips_dsp; - sourceFetch[BlendTiled][QImage::Format_RGB888] = qt_fetchUntransformed_888_mips_dsp; - - sourceFetch[BlendUntransformed][QImage::Format_RGB444] = qt_fetchUntransformed_444_mips_dsp; - sourceFetch[BlendTiled][QImage::Format_RGB444] = qt_fetchUntransformed_444_mips_dsp; - - sourceFetch[BlendUntransformed][QImage::Format_ARGB8565_Premultiplied] = qt_fetchUntransformed_argb8565_premultiplied_mips_dsp; - sourceFetch[BlendTiled][QImage::Format_ARGB8565_Premultiplied] = qt_fetchUntransformed_argb8565_premultiplied_mips_dsp; + sourceFetchUntransformed[QImage::Format_RGB888] = qt_fetchUntransformed_888_mips_dsp; + sourceFetchUntransformed[QImage::Format_RGB444] = qt_fetchUntransformed_444_mips_dsp; + sourceFetchUntransformed[QImage::Format_ARGB8565_Premultiplied] = qt_fetchUntransformed_argb8565_premultiplied_mips_dsp; #if defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2) qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_mips_dspr2; diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp index 35a975c972c..01ffd549180 100644 --- a/src/gui/painting/qdrawhelper_avx2.cpp +++ b/src/gui/painting/qdrawhelper_avx2.cpp @@ -37,12 +37,14 @@ ** ****************************************************************************/ -#include +#include "qdrawhelper_p.h" +#include "qdrawingprimitive_sse2_p.h" #if defined(QT_COMPILER_SUPPORTS_AVX2) QT_BEGIN_NAMESPACE +// Autovectorized premultiply functions: const uint *QT_FASTCALL convertARGB32ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QVector *, QDitherInfo *) { @@ -55,6 +57,307 @@ const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_avx2(uint *buffer, const uint return qt_convertRGBA8888ToARGB32PM(buffer, src, count); } +// Vectorized blend functions: + +// See BYTE_MUL_SSE2 for details. +inline static void BYTE_MUL_AVX2(__m256i &pixelVector, const __m256i &alphaChannel, const __m256i &colorMask, const __m256i &half) +{ + __m256i pixelVectorAG = _mm256_srli_epi16(pixelVector, 8); + __m256i pixelVectorRB = _mm256_and_si256(pixelVector, colorMask); + + pixelVectorAG = _mm256_mullo_epi16(pixelVectorAG, alphaChannel); + pixelVectorRB = _mm256_mullo_epi16(pixelVectorRB, alphaChannel); + + pixelVectorRB = _mm256_add_epi16(pixelVectorRB, _mm256_srli_epi16(pixelVectorRB, 8)); + pixelVectorAG = _mm256_add_epi16(pixelVectorAG, _mm256_srli_epi16(pixelVectorAG, 8)); + pixelVectorRB = _mm256_add_epi16(pixelVectorRB, half); + pixelVectorAG = _mm256_add_epi16(pixelVectorAG, half); + + pixelVectorRB = _mm256_srli_epi16(pixelVectorRB, 8); + pixelVectorAG = _mm256_andnot_si256(colorMask, pixelVectorAG); + + pixelVector = _mm256_or_si256(pixelVectorAG, pixelVectorRB); +} + +// See INTERPOLATE_PIXEL_255_SSE2 for details. +inline static void INTERPOLATE_PIXEL_255_AVX2(const __m256i &srcVector, __m256i &dstVector, const __m256i &alphaChannel, const __m256i &oneMinusAlphaChannel, const __m256i &colorMask, const __m256i &half) +{ + const __m256i srcVectorAG = _mm256_srli_epi16(srcVector, 8); + const __m256i dstVectorAG = _mm256_srli_epi16(dstVector, 8); + const __m256i srcVectorRB = _mm256_and_si256(srcVector, colorMask); + const __m256i dstVectorRB = _mm256_and_si256(dstVector, colorMask); + const __m256i srcVectorAGalpha = _mm256_mullo_epi16(srcVectorAG, alphaChannel); + const __m256i srcVectorRBalpha = _mm256_mullo_epi16(srcVectorRB, alphaChannel); + const __m256i dstVectorAGoneMinusAlpha = _mm256_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); + const __m256i dstVectorRBoneMinusAlpha = _mm256_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); + __m256i finalAG = _mm256_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlpha); + __m256i finalRB = _mm256_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlpha); + finalAG = _mm256_add_epi16(finalAG, _mm256_srli_epi16(finalAG, 8)); + finalRB = _mm256_add_epi16(finalRB, _mm256_srli_epi16(finalRB, 8)); + finalAG = _mm256_add_epi16(finalAG, half); + finalRB = _mm256_add_epi16(finalRB, half); + finalAG = _mm256_andnot_si256(colorMask, finalAG); + finalRB = _mm256_srli_epi16(finalRB, 8); + + dstVector = _mm256_or_si256(finalAG, finalRB); +} + +// See BLEND_SOURCE_OVER_ARGB32_SSE2 for details. +inline static void BLEND_SOURCE_OVER_ARGB32_AVX2(quint32 *dst, const quint32 *src, const int length) +{ + const __m256i half = _mm256_set1_epi16(0x80); + const __m256i one = _mm256_set1_epi16(0xff); + const __m256i colorMask = _mm256_set1_epi32(0x00ff00ff); + const __m256i alphaMask = _mm256_set1_epi32(0xff000000); + const __m256i offsetMask = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7); + const __m256i alphaShuffleMask = _mm256_set_epi8(char(0xff),15,char(0xff),15,char(0xff),11,char(0xff),11,char(0xff),7,char(0xff),7,char(0xff),3,char(0xff),3, + char(0xff),15,char(0xff),15,char(0xff),11,char(0xff),11,char(0xff),7,char(0xff),7,char(0xff),3,char(0xff),3); + + const int minusOffsetToAlignDstOn32Bytes = (reinterpret_cast(dst) >> 2) & 0x7; + + int x = 0; + // Prologue to handle all pixels until dst is 32-byte aligned in one step. + if (minusOffsetToAlignDstOn32Bytes != 0 && x < (length - 7)) { + const __m256i prologueMask = _mm256_sub_epi32(_mm256_set1_epi32(minusOffsetToAlignDstOn32Bytes - 1), offsetMask); + const __m256i srcVector = _mm256_maskload_epi32((const int *)&src[x - minusOffsetToAlignDstOn32Bytes], prologueMask); + const __m256i prologueAlphaMask = _mm256_blendv_epi8(_mm256_setzero_si256(), alphaMask, prologueMask); + if (!_mm256_testz_si256(srcVector, prologueAlphaMask)) { + if (_mm256_testc_si256(srcVector, prologueAlphaMask)) { + _mm256_maskstore_epi32((int *)&dst[x - minusOffsetToAlignDstOn32Bytes], prologueMask, srcVector); + } else { + __m256i alphaChannel = _mm256_shuffle_epi8(srcVector, alphaShuffleMask); + alphaChannel = _mm256_sub_epi16(one, alphaChannel); + __m256i dstVector = _mm256_maskload_epi32((int *)&dst[x - minusOffsetToAlignDstOn32Bytes], prologueMask); + BYTE_MUL_AVX2(dstVector, alphaChannel, colorMask, half); + dstVector = _mm256_add_epi8(dstVector, srcVector); + _mm256_maskstore_epi32((int *)&dst[x - minusOffsetToAlignDstOn32Bytes], prologueMask, dstVector); + } + } + x += (8 - minusOffsetToAlignDstOn32Bytes); + } + + for (; x < (length - 7); x += 8) { + const __m256i srcVector = _mm256_lddqu_si256((const __m256i *)&src[x]); + if (!_mm256_testz_si256(srcVector, alphaMask)) { + if (_mm256_testc_si256(srcVector, alphaMask)) { + _mm256_store_si256((__m256i *)&dst[x], srcVector); + } else { + __m256i alphaChannel = _mm256_shuffle_epi8(srcVector, alphaShuffleMask); + alphaChannel = _mm256_sub_epi16(one, alphaChannel); + __m256i dstVector = _mm256_load_si256((__m256i *)&dst[x]); + BYTE_MUL_AVX2(dstVector, alphaChannel, colorMask, half); + dstVector = _mm256_add_epi8(dstVector, srcVector); + _mm256_store_si256((__m256i *)&dst[x], dstVector); + } + } + } + + // Epilogue to handle all remaining pixels in one step. + if (x < length) { + const __m256i epilogueMask = _mm256_add_epi32(offsetMask, _mm256_set1_epi32(x - length)); + const __m256i srcVector = _mm256_maskload_epi32((const int *)&src[x], epilogueMask); + const __m256i epilogueAlphaMask = _mm256_blendv_epi8(_mm256_setzero_si256(), alphaMask, epilogueMask); + if (!_mm256_testz_si256(srcVector, epilogueAlphaMask)) { + if (_mm256_testc_si256(srcVector, epilogueAlphaMask)) { + _mm256_maskstore_epi32((int *)&dst[x], epilogueMask, srcVector); + } else { + __m256i alphaChannel = _mm256_shuffle_epi8(srcVector, alphaShuffleMask); + alphaChannel = _mm256_sub_epi16(one, alphaChannel); + __m256i dstVector = _mm256_maskload_epi32((int *)&dst[x], epilogueMask); + BYTE_MUL_AVX2(dstVector, alphaChannel, colorMask, half); + dstVector = _mm256_add_epi8(dstVector, srcVector); + _mm256_maskstore_epi32((int *)&dst[x], epilogueMask, dstVector); + } + } + } +} + + +// See BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2 for details. +inline static void BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_AVX2(quint32 *dst, const quint32 *src, const int length, const int const_alpha) +{ + int x = 0; + + ALIGNMENT_PROLOGUE_32BYTES(dst, x, length) + blend_pixel(dst[x], src[x], const_alpha); + + const __m256i half = _mm256_set1_epi16(0x80); + const __m256i one = _mm256_set1_epi16(0xff); + const __m256i colorMask = _mm256_set1_epi32(0x00ff00ff); + const __m256i alphaMask = _mm256_set1_epi32(0xff000000); + const __m256i alphaShuffleMask = _mm256_set_epi8(char(0xff),15,char(0xff),15,char(0xff),11,char(0xff),11,char(0xff),7,char(0xff),7,char(0xff),3,char(0xff),3, + char(0xff),15,char(0xff),15,char(0xff),11,char(0xff),11,char(0xff),7,char(0xff),7,char(0xff),3,char(0xff),3); + const __m256i constAlphaVector = _mm256_set1_epi16(const_alpha); + for (; x < (length - 7); x += 8) { + __m256i srcVector = _mm256_lddqu_si256((const __m256i *)&src[x]); + if (!_mm256_testz_si256(srcVector, alphaMask)) { + BYTE_MUL_AVX2(srcVector, constAlphaVector, colorMask, half); + + __m256i alphaChannel = _mm256_shuffle_epi8(srcVector, alphaShuffleMask); + alphaChannel = _mm256_sub_epi16(one, alphaChannel); + __m256i dstVector = _mm256_load_si256((__m256i *)&dst[x]); + BYTE_MUL_AVX2(dstVector, alphaChannel, colorMask, half); + dstVector = _mm256_add_epi8(dstVector, srcVector); + _mm256_store_si256((__m256i *)&dst[x], dstVector); + } + } + for (; x < length; ++x) + blend_pixel(dst[x], src[x], const_alpha); +} + +void qt_blend_argb32_on_argb32_avx2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha) +{ + if (const_alpha == 256) { + for (int y = 0; y < h; ++y) { + const quint32 *src = reinterpret_cast(srcPixels); + quint32 *dst = reinterpret_cast(destPixels); + BLEND_SOURCE_OVER_ARGB32_AVX2(dst, src, w); + destPixels += dbpl; + srcPixels += sbpl; + } + } else if (const_alpha != 0) { + const_alpha = (const_alpha * 255) >> 8; + for (int y = 0; y < h; ++y) { + const quint32 *src = reinterpret_cast(srcPixels); + quint32 *dst = reinterpret_cast(destPixels); + BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_AVX2(dst, src, w, const_alpha); + destPixels += dbpl; + srcPixels += sbpl; + } + } +} + +void qt_blend_rgb32_on_rgb32_avx2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha) +{ + if (const_alpha == 256) { + for (int y = 0; y < h; ++y) { + const quint32 *src = reinterpret_cast(srcPixels); + quint32 *dst = reinterpret_cast(destPixels); + ::memcpy(dst, src, w * sizeof(uint)); + srcPixels += sbpl; + destPixels += dbpl; + } + return; + } + if (const_alpha == 0) + return; + + const __m256i half = _mm256_set1_epi16(0x80); + const __m256i colorMask = _mm256_set1_epi32(0x00ff00ff); + + const_alpha = (const_alpha * 255) >> 8; + int one_minus_const_alpha = 255 - const_alpha; + const __m256i constAlphaVector = _mm256_set1_epi16(const_alpha); + const __m256i oneMinusConstAlpha = _mm256_set1_epi16(one_minus_const_alpha); + for (int y = 0; y < h; ++y) { + const quint32 *src = reinterpret_cast(srcPixels); + quint32 *dst = reinterpret_cast(destPixels); + int x = 0; + + // First, align dest to 32 bytes: + ALIGNMENT_PROLOGUE_32BYTES(dst, x, w) + dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha); + + // 2) interpolate pixels with AVX2 + for (; x < (w - 7); x += 8) { + const __m256i srcVector = _mm256_lddqu_si256((const __m256i *)&src[x]); + if (!_mm256_testc_si256(srcVector, _mm256_setzero_si256())) { + __m256i dstVector = _mm256_load_si256((__m256i *)&dst[x]); + INTERPOLATE_PIXEL_255_AVX2(srcVector, dstVector, constAlphaVector, oneMinusConstAlpha, colorMask, half); + _mm256_store_si256((__m256i *)&dst[x], dstVector); + } + } + + // 3) Epilogue + for (; x < w; ++x) + dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha); + + srcPixels += sbpl; + destPixels += dbpl; + } +} + +void QT_FASTCALL comp_func_SourceOver_avx2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha) +{ + Q_ASSERT(const_alpha < 256); + + const quint32 *src = (const quint32 *) srcPixels; + quint32 *dst = (quint32 *) destPixels; + + if (const_alpha == 255) + BLEND_SOURCE_OVER_ARGB32_AVX2(dst, src, length); + else + BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_AVX2(dst, src, length, const_alpha); +} + +void QT_FASTCALL comp_func_Source_avx2(uint *dst, const uint *src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + ::memcpy(dst, src, length * sizeof(uint)); + } else { + const int ialpha = 255 - const_alpha; + + int x = 0; + + // 1) prologue, align on 32 bytes + ALIGNMENT_PROLOGUE_32BYTES(dst, x, length) + dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], ialpha); + + // 2) interpolate pixels with AVX2 + const __m256i half = _mm256_set1_epi16(0x80); + const __m256i colorMask = _mm256_set1_epi32(0x00ff00ff); + const __m256i constAlphaVector = _mm256_set1_epi16(const_alpha); + const __m256i oneMinusConstAlpha = _mm256_set1_epi16(ialpha); + for (; x < length - 7; x += 8) { + const __m256i srcVector = _mm256_lddqu_si256((const __m256i *)&src[x]); + __m256i dstVector = _mm256_load_si256((__m256i *)&dst[x]); + INTERPOLATE_PIXEL_255_AVX2(srcVector, dstVector, constAlphaVector, oneMinusConstAlpha, colorMask, half); + _mm256_store_si256((__m256i *)&dst[x], dstVector); + } + + // 3) Epilogue + for (; x < length; ++x) + dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], ialpha); + } +} + +void QT_FASTCALL comp_func_solid_SourceOver_avx2(uint *destPixels, int length, uint color, uint const_alpha) +{ + if ((const_alpha & qAlpha(color)) == 255) { + qt_memfill32(destPixels, color, length); + } else { + if (const_alpha != 255) + color = BYTE_MUL(color, const_alpha); + + const quint32 minusAlphaOfColor = qAlpha(~color); + int x = 0; + + quint32 *dst = (quint32 *) destPixels; + const __m256i colorVector = _mm256_set1_epi32(color); + const __m256i colorMask = _mm256_set1_epi32(0x00ff00ff); + const __m256i half = _mm256_set1_epi16(0x80); + const __m256i minusAlphaOfColorVector = _mm256_set1_epi16(minusAlphaOfColor); + + ALIGNMENT_PROLOGUE_32BYTES(dst, x, length) + destPixels[x] = color + BYTE_MUL(destPixels[x], minusAlphaOfColor); + + for (; x < length - 7; x += 8) { + __m256i dstVector = _mm256_load_si256((__m256i *)&dst[x]); + BYTE_MUL_AVX2(dstVector, minusAlphaOfColorVector, colorMask, half); + dstVector = _mm256_add_epi8(colorVector, dstVector); + _mm256_store_si256((__m256i *)&dst[x], dstVector); + } + for (; x < length; ++x) + destPixels[x] = color + BYTE_MUL(destPixels[x], minusAlphaOfColor); + } +} + QT_END_NAMESPACE #endif diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h index 1a1df547bb3..9d511f9badf 100644 --- a/src/gui/painting/qpaintengine_p.h +++ b/src/gui/painting/qpaintengine_p.h @@ -118,6 +118,11 @@ public: virtual void systemStateChanged() { } void drawBoxTextItem(const QPointF &p, const QTextItemInt &ti); + + static QPaintEnginePrivate *get(QPaintEngine *paintEngine) { return paintEngine->d_func(); } + + virtual QPaintEngine *aggregateEngine() { return 0; } + virtual Qt::HANDLE nativeHandle() { return 0; } }; QT_END_NAMESPACE diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index a3a3f20b181..7fcac9b9f2f 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -2439,7 +2439,7 @@ int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString & } if (font.fileName.isEmpty() && !fontData.isEmpty()) - font.fileName = QString::fromLatin1(":qmemoryfonts/") + QString::number(i); + font.fileName = QLatin1String(":qmemoryfonts/") + QString::number(i); registerFont(&font); if (font.families.isEmpty()) diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index 73d2e545ba4..e228b3c8400 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE static QString pixelToPoint(qreal pixels) { // we hardcode 96 DPI, we do the same in the ODF importer to have a perfect roundtrip. - return QString::number(pixels * 72 / 96) + QString::fromLatin1("pt"); + return QString::number(pixels * 72 / 96) + QLatin1String("pt"); } // strategies diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 74fc23957cf..8e5cfd94971 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -319,9 +319,9 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair) if (systemLocale == QLatin1String("C")) acceptLanguage = QString::fromLatin1("en,*"); else if (systemLocale.startsWith(QLatin1String("en-"))) - acceptLanguage = QString::fromLatin1("%1,*").arg(systemLocale); + acceptLanguage = systemLocale + QLatin1String(",*"); else - acceptLanguage = QString::fromLatin1("%1,en,*").arg(systemLocale); + acceptLanguage = systemLocale + QLatin1String(",en,*"); request.setHeaderField("Accept-Language", acceptLanguage.toLatin1()); } diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index b8bcdc4bfb8..9a3a7f0fb5b 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -87,10 +87,10 @@ public: BackgroundRequestAttribute, SpdyAllowedAttribute, SpdyWasUsedAttribute, - HTTP2AllowedAttribute, - HTTP2WasUsedAttribute, EmitAllUploadProgressSignalsAttribute, FollowRedirectsAttribute, + HTTP2AllowedAttribute, + HTTP2WasUsedAttribute, OriginalContentLengthAttribute, User = 1000, diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index da53ccfe70d..2fa98c0e071 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -488,7 +488,7 @@ static QList interfaceListing() interfaces = createInterfaces(interfaceListing); for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) { // Find the interface - QString name = QString::fromLatin1(ptr->ifa_name); + QLatin1String name(ptr->ifa_name); QNetworkInterfacePrivate *iface = 0; QList::Iterator if_it = interfaces.begin(); for ( ; if_it != interfaces.end(); ++if_it) diff --git a/src/network/kernel/qnetworkproxy_generic.cpp b/src/network/kernel/qnetworkproxy_generic.cpp index e69870a98cc..3ff0cc51682 100644 --- a/src/network/kernel/qnetworkproxy_generic.cpp +++ b/src/network/kernel/qnetworkproxy_generic.cpp @@ -79,7 +79,7 @@ static bool ignoreProxyFor(const QNetworkProxyQuery &query) if (!peerHostName.startsWith('.')) peerHostName.prepend('.'); - if (peerHostName.endsWith(QString::fromLatin1(token))) + if (peerHostName.endsWith(QLatin1String(token))) return true; } diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp index 83a9343a6aa..5c72dbe7e24 100644 --- a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp +++ b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp @@ -135,7 +135,7 @@ bool QDeviceDiscoveryStatic::checkDeviceType(const QString &device) qCDebug(lcDD) << "doing static device discovery for " << device; - if ((m_types & Device_DRM) && device.contains(QString::fromLatin1(QT_DRM_DEVICE_PREFIX))) { + if ((m_types & Device_DRM) && device.contains(QLatin1String(QT_DRM_DEVICE_PREFIX))) { QT_CLOSE(fd); return true; } diff --git a/src/platformsupport/graphics/qrasterbackingstore.cpp b/src/platformsupport/graphics/qrasterbackingstore.cpp index 58e811dff1a..325c98b93d1 100644 --- a/src/platformsupport/graphics/qrasterbackingstore.cpp +++ b/src/platformsupport/graphics/qrasterbackingstore.cpp @@ -62,13 +62,20 @@ void QRasterBackingStore::resize(const QSize &size, const QRegion &staticContent if (m_image.size() == effectiveBufferSize) return; - QImage::Format format = window()->format().hasAlpha() ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; - m_image = QImage(effectiveBufferSize, format); + m_image = QImage(effectiveBufferSize, format()); m_image.setDevicePixelRatio(windowDevicePixelRatio); - if (format == QImage::Format_ARGB32_Premultiplied) + if (m_image.format() == QImage::Format_ARGB32_Premultiplied) m_image.fill(Qt::transparent); } +QImage::Format QRasterBackingStore::format() const +{ + if (window()->format().hasAlpha()) + return QImage::Format_ARGB32_Premultiplied; + else + return QImage::Format_RGB32; +} + QPaintDevice *QRasterBackingStore::paintDevice() { return &m_image; diff --git a/src/platformsupport/graphics/qrasterbackingstore_p.h b/src/platformsupport/graphics/qrasterbackingstore_p.h index de96c99b5ae..55976d2ceb0 100644 --- a/src/platformsupport/graphics/qrasterbackingstore_p.h +++ b/src/platformsupport/graphics/qrasterbackingstore_p.h @@ -62,13 +62,16 @@ public: QRasterBackingStore(QWindow *window); ~QRasterBackingStore(); - QPaintDevice *paintDevice() Q_DECL_OVERRIDE; - QImage toImage() const Q_DECL_OVERRIDE; - void resize (const QSize &size, const QRegion &) Q_DECL_OVERRIDE; + void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE; void beginPaint(const QRegion ®ion) Q_DECL_OVERRIDE; + QPaintDevice *paintDevice() Q_DECL_OVERRIDE; + QImage toImage() const Q_DECL_OVERRIDE; + protected: + virtual QImage::Format format() const; + QImage m_image; }; diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro index 15bbaf94c99..19efa60f480 100644 --- a/src/platformsupport/platformsupport.pro +++ b/src/platformsupport/platformsupport.pro @@ -29,6 +29,6 @@ unix:!darwin:qtConfig(dbus) { include(dbusmenu/dbusmenu.pri) include(dbustray/dbustray.pri) } -uikit: include(graphics/graphics.pri) +darwin: include(graphics/graphics.pri) load(qt_module) diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index 52a3e756b96..562be2be8f8 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -40,33 +40,20 @@ #ifndef QBACKINGSTORE_COCOA_H #define QBACKINGSTORE_COCOA_H -#include - -#include "qcocoawindow.h" -#include "qnsview.h" - -#include +#include QT_BEGIN_NAMESPACE -class QCocoaBackingStore : public QPlatformBackingStore +class QCocoaBackingStore : public QRasterBackingStore { public: QCocoaBackingStore(QWindow *window); ~QCocoaBackingStore(); - QPaintDevice *paintDevice() Q_DECL_OVERRIDE; - void flush(QWindow *widget, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; - QImage toImage() const Q_DECL_OVERRIDE; - - void resize (const QSize &size, const QRegion &) Q_DECL_OVERRIDE; - bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE; - void beginPaint(const QRegion ®ion) Q_DECL_OVERRIDE; - qreal getBackingStoreDevicePixelRatio(); + void flush(QWindow *, const QRegion &, const QPoint &) Q_DECL_OVERRIDE; private: - QImage m_qImage; - QSize m_requestedSize; + QImage::Format format() const Q_DECL_OVERRIDE; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 20233518b30..af5418315c1 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -38,13 +38,13 @@ ****************************************************************************/ #include "qcocoabackingstore.h" -#include -#include "qcocoahelpers.h" + +#include "qcocoawindow.h" QT_BEGIN_NAMESPACE QCocoaBackingStore::QCocoaBackingStore(QWindow *window) - : QPlatformBackingStore(window) + : QRasterBackingStore(window) { } @@ -54,69 +54,21 @@ QCocoaBackingStore::~QCocoaBackingStore() [cocoaWindow->m_qtView clearBackingStore:this]; } -QPaintDevice *QCocoaBackingStore::paintDevice() +QImage::Format QCocoaBackingStore::format() const { - QCocoaWindow *cocoaWindow = static_cast(window()->handle()); - int windowDevicePixelRatio = int(cocoaWindow->devicePixelRatio()); + if (static_cast(window()->handle())->m_drawContentBorderGradient) + return QImage::Format_ARGB32_Premultiplied; - // Receate the backing store buffer if the effective buffer size has changed, - // either due to a window resize or devicePixelRatio change. - QSize effectiveBufferSize = m_requestedSize * windowDevicePixelRatio; - if (m_qImage.size() != effectiveBufferSize) { - QImage::Format format = (window()->format().hasAlpha() || cocoaWindow->m_drawContentBorderGradient) - ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; - m_qImage = QImage(effectiveBufferSize, format); - m_qImage.setDevicePixelRatio(windowDevicePixelRatio); - if (format == QImage::Format_ARGB32_Premultiplied) - m_qImage.fill(Qt::transparent); - } - return &m_qImage; + return QRasterBackingStore::format(); } -void QCocoaBackingStore::flush(QWindow *win, const QRegion ®ion, const QPoint &offset) +void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { - if (!m_qImage.isNull()) { - if (QCocoaWindow *cocoaWindow = static_cast(win->handle())) - [cocoaWindow->m_qtView flushBackingStore:this region:region offset:offset]; - } -} + if (m_image.isNull()) + return; -QImage QCocoaBackingStore::toImage() const -{ - return m_qImage; -} - -void QCocoaBackingStore::resize(const QSize &size, const QRegion &) -{ - m_requestedSize = size; -} - -bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy) -{ - extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); - const qreal devicePixelRatio = m_qImage.devicePixelRatio(); - QPoint qpoint(dx * devicePixelRatio, dy * devicePixelRatio); - for (const QRect &rect : area) { - const QRect qrect(rect.topLeft() * devicePixelRatio, rect.size() * devicePixelRatio); - qt_scrollRectInImage(m_qImage, qrect, qpoint); - } - return true; -} - -void QCocoaBackingStore::beginPaint(const QRegion ®ion) -{ - if (m_qImage.hasAlphaChannel()) { - QPainter p(&m_qImage); - p.setCompositionMode(QPainter::CompositionMode_Source); - const QColor blank = Qt::transparent; - for (const QRect &rect : region) - p.fillRect(rect, blank); - } -} - -qreal QCocoaBackingStore::getBackingStoreDevicePixelRatio() -{ - return m_qImage.devicePixelRatio(); + if (QCocoaWindow *cocoaWindow = static_cast(window->handle())) + [cocoaWindow->m_qtView flushBackingStore:this region:region offset:offset]; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index 04330844361..8e523dfbbf3 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -40,6 +40,7 @@ #include "qcocoacursor.h" #include "qcocoawindow.h" #include "qcocoahelpers.h" +#include #include diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index 13ae0382ab7..7d11023b78d 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.mm +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -43,6 +43,7 @@ #ifndef QT_NO_WIDGETS #include #endif +#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 9b061bbae8a..536a2d2d58c 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -69,25 +69,6 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list); inline NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &qstrlist) { return reinterpret_cast(qt_mac_QStringListToNSMutableArrayVoid(qstrlist)); } -NSImage *qt_mac_cgimage_to_nsimage(CGImageRef iamge); -NSImage *qt_mac_create_nsimage(const QPixmap &pm); -NSImage *qt_mac_create_nsimage(const QIcon &icon); -CGImageRef qt_mac_toCGImage(const QImage &qImage); -CGImageRef qt_mac_toCGImageMask(const QImage &qImage); -QImage qt_mac_toQImage(CGImageRef image); -QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size); - -QColor qt_mac_toQColor(const NSColor *color); -QColor qt_mac_toQColor(CGColorRef color); - -QBrush qt_mac_toQBrush(CGColorRef color); -QBrush qt_mac_toQBrush(const NSColor *color, QPalette::ColorGroup colorGroup = QPalette::Normal); - -// Creates a mutable shape, it's the caller's responsibility to release. -HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion ®ion); - -OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage); - NSDragOperation qt_mac_mapDropAction(Qt::DropAction action); NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions); Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions); @@ -95,9 +76,6 @@ Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions); // Misc void qt_mac_transformProccessToForegroundApplication(); -CGColorSpaceRef qt_mac_genericColorSpace(); -CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget); -CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice); QString qt_mac_applicationName(); int qt_mac_flipYCoordinate(int y); @@ -143,8 +121,6 @@ public: } }; -CGContextRef qt_mac_cg_context(QPaintDevice *pdev); - template T qt_mac_resolveOption(const T &fallback, const QByteArray &environment) { diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 542c046d421..0c7c30579e8 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -47,6 +47,7 @@ #include #include #include +#include #ifndef QT_NO_WIDGETS #include @@ -56,25 +57,6 @@ #include -@interface NSGraphicsContext (QtAdditions) - -+ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState; - -@end - -@implementation NSGraphicsContext (QtAdditions) - -+ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState -{ -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_NA) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite) - return [self graphicsContextWithCGContext:graphicsPort flipped:initialFlippedState]; -#endif - return [self graphicsContextWithGraphicsPort:graphicsPort flipped:initialFlippedState]; -} - -@end - QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaCocoaWindow, "qt.qpa.cocoa.window"); @@ -101,198 +83,6 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list) return result; } -CGImageRef qt_mac_toCGImage(const QImage &inImage) -{ - CGImageRef cgImage = inImage.toCGImage(); - if (cgImage) - return cgImage; - - // Convert image data to a known-good format if the fast conversion fails. - return inImage.convertToFormat(QImage::Format_ARGB32_Premultiplied).toCGImage(); -} - -CGImageRef qt_mac_toCGImageMask(const QImage &image) -{ - static const auto deleter = [](void *image, const void *, size_t) { delete static_cast(image); }; - QCFType dataProvider = - CGDataProviderCreateWithData(new QImage(image), image.bits(), - image.byteCount(), deleter); - - return CGImageMaskCreate(image.width(), image.height(), 8, image.depth(), - image.bytesPerLine(), dataProvider, NULL, false); -} - -NSImage *qt_mac_cgimage_to_nsimage(CGImageRef image) -{ - NSImage *newImage = [[NSImage alloc] initWithCGImage:image size:NSZeroSize]; - return newImage; -} - -NSImage *qt_mac_create_nsimage(const QPixmap &pm) -{ - if (pm.isNull()) - return 0; - QImage image = pm.toImage(); - CGImageRef cgImage = qt_mac_toCGImage(image); - NSImage *nsImage = qt_mac_cgimage_to_nsimage(cgImage); - CGImageRelease(cgImage); - return nsImage; -} - -NSImage *qt_mac_create_nsimage(const QIcon &icon) -{ - if (icon.isNull()) - return nil; - - NSImage *nsImage = [[NSImage alloc] init]; - foreach (QSize size, icon.availableSizes()) { - QPixmap pm = icon.pixmap(size); - QImage image = pm.toImage(); - CGImageRef cgImage = qt_mac_toCGImage(image); - NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage]; - [nsImage addRepresentation:imageRep]; - [imageRep release]; - CGImageRelease(cgImage); - } - return nsImage; -} - -HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion ®ion) -{ - HIMutableShapeRef shape = HIShapeCreateMutable(); - for (const QRect &rect : region) { - CGRect cgRect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); - HIShapeUnionWithRect(shape, &cgRect); - } - return shape; -} - -QColor qt_mac_toQColor(const NSColor *color) -{ - QColor qtColor; - NSString *colorSpace = [color colorSpaceName]; - if (colorSpace == NSDeviceCMYKColorSpace) { - CGFloat cyan, magenta, yellow, black, alpha; - [color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha]; - qtColor.setCmykF(cyan, magenta, yellow, black, alpha); - } else { - NSColor *tmpColor; - tmpColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - CGFloat red, green, blue, alpha; - [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha]; - qtColor.setRgbF(red, green, blue, alpha); - } - return qtColor; -} - -QColor qt_mac_toQColor(CGColorRef color) -{ - QColor qtColor; - CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(color)); - const CGFloat *components = CGColorGetComponents(color); - if (model == kCGColorSpaceModelRGB) { - qtColor.setRgbF(components[0], components[1], components[2], components[3]); - } else if (model == kCGColorSpaceModelCMYK) { - qtColor.setCmykF(components[0], components[1], components[2], components[3]); - } else if (model == kCGColorSpaceModelMonochrome) { - qtColor.setRgbF(components[0], components[0], components[0], components[1]); - } else { - // Colorspace we can't deal with. - qWarning("Qt: qt_mac_toQColor: cannot convert from colorspace model: %d", model); - Q_ASSERT(false); - } - return qtColor; -} - -QBrush qt_mac_toQBrush(CGColorRef color) -{ - QBrush qtBrush; - CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(color)); - if (model == kCGColorSpaceModelPattern) { - // Colorspace we can't deal with; the color is drawn directly using a callback. - qWarning("Qt: qt_mac_toQBrush: cannot convert from colorspace model: %d", model); - Q_ASSERT(false); - } else { - qtBrush.setStyle(Qt::SolidPattern); - qtBrush.setColor(qt_mac_toQColor(color)); - } - return qtBrush; -} - -static bool qt_mac_isSystemColorOrInstance(const NSColor *color, NSString *colorNameComponent, NSString *className) -{ - // We specifically do not want isKindOfClass: here - if ([color.className isEqualToString:className]) // NSPatternColorSpace - return true; - if ([color.catalogNameComponent isEqualToString:@"System"] && - [color.colorNameComponent isEqualToString:colorNameComponent] && - [color.colorSpaceName isEqualToString:NSNamedColorSpace]) - return true; - return false; -} - -QBrush qt_mac_toQBrush(const NSColor *color, QPalette::ColorGroup colorGroup) -{ - QBrush qtBrush; - - // QTBUG-49773: This calls NSDrawMenuItemBackground to render a 1 by n gradient; could use HITheme - if ([color.className isEqualToString:@"NSMenuItemHighlightColor"]) { - qWarning("Qt: qt_mac_toQBrush: cannot convert from NSMenuItemHighlightColor"); - return qtBrush; - } - - // Not a catalog color or a manifestation of System.windowBackgroundColor; - // only retrieved from NSWindow.backgroundColor directly - if ([color.className isEqualToString:@"NSMetalPatternColor"]) { - // NSTexturedBackgroundWindowMask, could theoretically handle this without private API by - // creating a window with the appropriate properties and then calling NSWindow.backgroundColor.patternImage, - // which returns a texture sized 1 by (window height, including frame), backed by a CGPattern - // which follows the window key state... probably need to allow QBrush to store a function pointer - // like CGPattern does - qWarning("Qt: qt_mac_toQBrush: cannot convert from NSMetalPatternColor"); - return qtBrush; - } - - // No public API to get these colors/stops; - // both accurately obtained through runtime object inspection on OS X 10.11 - // (the NSColor object has NSGradient i-vars for both color groups) - if (qt_mac_isSystemColorOrInstance(color, @"_sourceListBackgroundColor", @"NSSourceListBackgroundColor")) { - QLinearGradient gradient; - if (colorGroup == QPalette::Active) { - gradient.setColorAt(0, QColor(233, 237, 242)); - gradient.setColorAt(0.5, QColor(225, 229, 235)); - gradient.setColorAt(1, QColor(209, 216, 224)); - } else { - gradient.setColorAt(0, QColor(248, 248, 248)); - gradient.setColorAt(0.5, QColor(240, 240, 240)); - gradient.setColorAt(1, QColor(235, 235, 235)); - } - return QBrush(gradient); - } - - // A couple colors are special... they are actually instances of NSGradientPatternColor, which - // override set/setFill/setStroke to instead initialize an internal color - // ([NSColor colorWithCalibratedWhite:0.909804 alpha:1.000000]) while still returning the - // ruled lines pattern image (from OS X 10.4) to the user from -[NSColor patternImage] - // (and providing no public API to get the underlying color without this insanity) - if (qt_mac_isSystemColorOrInstance(color, @"controlColor", @"NSGradientPatternColor") || - qt_mac_isSystemColorOrInstance(color, @"windowBackgroundColor", @"NSGradientPatternColor")) { - qtBrush.setStyle(Qt::SolidPattern); - qtBrush.setColor(qt_mac_toQColor(color.CGColor)); - return qtBrush; - } - - if (NSColor *patternColor = [color colorUsingColorSpaceName:NSPatternColorSpace]) { - NSImage *patternImage = patternColor.patternImage; - const QSizeF sz(patternImage.size.width, patternImage.size.height); - qtBrush.setTexture(qt_mac_toQPixmap(patternImage, sz)); // QTBUG-49774 - } else { - qtBrush.setStyle(Qt::SolidPattern); - qtBrush.setColor(qt_mac_toQColor(color)); - } - return qtBrush; -} - struct dndenum_mapper { NSDragOperation mac_code; @@ -402,97 +192,6 @@ void qt_mac_transformProccessToForegroundApplication() [[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular]; } } -static CGColorSpaceRef m_genericColorSpace = 0; -static QHash m_displayColorSpaceHash; -static bool m_postRoutineRegistered = false; - -CGColorSpaceRef qt_mac_genericColorSpace() -{ -#if 0 - if (!m_genericColorSpace) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - } else - { - m_genericColorSpace = CGColorSpaceCreateDeviceRGB(); - } - if (!m_postRoutineRegistered) { - m_postRoutineRegistered = true; - qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); - } - } - return m_genericColorSpace; -#else - // Just return the main display colorspace for the moment. - return qt_mac_displayColorSpace(0); -#endif -} - -/* - Ideally, we should pass the widget in here, and use CGGetDisplaysWithRect() etc. - to support multiple displays correctly. -*/ -CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget) -{ - CGColorSpaceRef colorSpace; - - CGDirectDisplayID displayID; - if (widget == 0) { - displayID = CGMainDisplayID(); - } else { - displayID = CGMainDisplayID(); - /* - ### get correct display - const QRect &qrect = widget->window()->geometry(); - CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height()); - CGDisplayCount throwAway; - CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway); - if (dErr != kCGErrorSuccess) - return macDisplayColorSpace(0); // fall back on main display - */ - } - if ((colorSpace = m_displayColorSpaceHash.value(displayID))) - return colorSpace; - - colorSpace = CGDisplayCopyColorSpace(displayID); - if (colorSpace == 0) - colorSpace = CGColorSpaceCreateDeviceRGB(); - - m_displayColorSpaceHash.insert(displayID, colorSpace); - if (!m_postRoutineRegistered) { - m_postRoutineRegistered = true; - void qt_mac_cleanUpMacColorSpaces(); - qAddPostRoutine(qt_mac_cleanUpMacColorSpaces); - } - return colorSpace; -} - -void qt_mac_cleanUpMacColorSpaces() -{ - if (m_genericColorSpace) { - CFRelease(m_genericColorSpace); - m_genericColorSpace = 0; - } - QHash::const_iterator it = m_displayColorSpaceHash.constBegin(); - while (it != m_displayColorSpaceHash.constEnd()) { - if (it.value()) - CFRelease(it.value()); - ++it; - } - m_displayColorSpaceHash.clear(); -} - -CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice) -{ -#ifdef QT_NO_WIDGETS - Q_UNUSED(paintDevice) - return qt_mac_displayColorSpace(0); -#else - bool isWidget = (paintDevice->devType() == QInternal::Widget); - return qt_mac_displayColorSpace(isWidget ? static_cast(paintDevice): 0); -#endif - -} QString qt_mac_applicationName() { @@ -557,28 +256,6 @@ NSRect qt_mac_flipRect(const QRect &rect) return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height()); } -OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage) -{ - // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev) - OSStatus err = noErr; - - require_action(inContext != NULL, InvalidContext, err = paramErr); - require_action(inBounds != NULL, InvalidBounds, err = paramErr); - require_action(inImage != NULL, InvalidImage, err = paramErr); - - CGContextSaveGState( inContext ); - CGContextTranslateCTM (inContext, 0, inBounds->origin.y + CGRectGetMaxY(*inBounds)); - CGContextScaleCTM(inContext, 1, -1); - - CGContextDrawImage(inContext, *inBounds, inImage); - - CGContextRestoreGState(inContext); -InvalidImage: -InvalidBounds: -InvalidContext: - return err; -} - Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) { if (buttonNum == 0) @@ -599,81 +276,4 @@ QString qt_mac_removeAmpersandEscapes(QString s) return QPlatformTheme::removeMnemonics(s).trimmed(); } -/*! \internal - - Returns the CoreGraphics CGContextRef of the paint device. 0 is - returned if it can't be obtained. It is the caller's responsibility to - CGContextRelease the context when finished using it. - - \warning This function is only available on \macos. - \warning This function is duplicated in qmacstyle_mac.mm - */ -CGContextRef qt_mac_cg_context(QPaintDevice *pdev) -{ - // In Qt 5, QWidget and QPixmap (and QImage) paint devices are all QImages under the hood. - QImage *image = 0; - if (pdev->devType() == QInternal::Image) { - image = static_cast(pdev); - } else if (pdev->devType() == QInternal::Pixmap) { - - const QPixmap *pm = static_cast(pdev); - QPlatformPixmap *data = const_cast(pm)->data_ptr().data(); - if (data && data->classId() == QPlatformPixmap::RasterClass) { - image = data->buffer(); - } else { - qDebug("qt_mac_cg_context: Unsupported pixmap class"); - } - } else if (pdev->devType() == QInternal::Widget) { - // TODO test: image = static_cast(static_cast(pdev)->backingStore()->paintDevice()); - qDebug("qt_mac_cg_context: not implemented: Widget class"); - } - - if (!image) - return 0; // Context type not supported. - - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); - uint flags = kCGImageAlphaPremultipliedFirst; - flags |= kCGBitmapByteOrder32Host; - CGContextRef ret = 0; - ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(), - 8, image->bytesPerLine(), colorspace, flags); - CGContextTranslateCTM(ret, 0, image->height()); - CGContextScaleCTM(ret, 1, -1); - return ret; -} - -QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size) -{ - const NSSize pixmapSize = NSMakeSize(size.width(), size.height()); - QPixmap pixmap(pixmapSize.width, pixmapSize.height); - pixmap.fill(Qt::transparent); - [image setSize:pixmapSize]; - const NSRect iconRect = NSMakeRect(0, 0, pixmapSize.width, pixmapSize.height); - QMacCGContext ctx(&pixmap); - if (!ctx) - return QPixmap(); - NSGraphicsContext *gc = [NSGraphicsContext qt_graphicsContextWithCGContext:ctx flipped:YES]; - if (!gc) - return QPixmap(); - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:gc]; - [image drawInRect:iconRect fromRect:iconRect operation:NSCompositeSourceOver fraction:1.0 respectFlipped:YES hints:nil]; - [NSGraphicsContext restoreGraphicsState]; - return pixmap; -} - -QImage qt_mac_toQImage(CGImageRef image) -{ - const size_t w = CGImageGetWidth(image), - h = CGImageGetHeight(image); - QImage ret(w, h, QImage::Format_ARGB32_Premultiplied); - ret.fill(Qt::transparent); - CGRect rect = CGRectMake(0, 0, w, h); - CGContextRef ctx = qt_mac_cg_context(&ret); - qt_mac_drawCGImage(ctx, &rect, image); - CGContextRelease(ctx); - return ret; -} - - QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 1793bd404e4..f3f720654e5 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -58,6 +58,8 @@ #include #include +#include + #include static void initResources() @@ -199,8 +201,6 @@ QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const return window; } -extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); - QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const { // TODO window should be handled @@ -251,9 +251,8 @@ QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height QPixmap pix(w, h); pix.fill(Qt::transparent); CGRect rect = CGRectMake(0, 0, w, h); - CGContextRef ctx = qt_mac_cg_context(&pix); + QMacCGContext ctx(&pix); qt_mac_drawCGImage(ctx, &rect, image); - CGContextRelease(ctx); QPainter painter(&windowPixmap); painter.drawPixmap(0, 0, pix); diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index cac166a4096..ea094c86eef 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -48,6 +48,7 @@ #include "qt_mac_p.h" #include "qcocoaapplication.h" // for custom application category #include "qcocoamenuloader.h" +#include #include diff --git a/src/plugins/platforms/cocoa/qcocoamimetypes.mm b/src/plugins/platforms/cocoa/qcocoamimetypes.mm index e7a3aab845d..c109eb7bf4c 100644 --- a/src/plugins/platforms/cocoa/qcocoamimetypes.mm +++ b/src/plugins/platforms/cocoa/qcocoamimetypes.mm @@ -40,6 +40,7 @@ #include "qcocoamimetypes.h" #include #include "qcocoahelpers.h" +#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 8562246817f..3ff37a84637 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -64,6 +64,8 @@ #include #endif +#include + #include #include diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index be5fa61b8be..9ddad7fc7af 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -43,6 +43,7 @@ #include #include +#include #include diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index 0640faeb8a3..9a543e893e8 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -86,6 +86,7 @@ #include "qt_mac_p.h" #include "qcocoahelpers.h" +#include #import diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 95175871a40..d0879ed4579 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -56,6 +56,7 @@ #include #include +#include #include #include #include @@ -197,7 +198,7 @@ QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) CGRect rect = CGRectMake(0, 0, width, height); - CGContextRef ctx = qt_mac_cg_context(&ret); + QMacCGContext ctx(&ret); CGAffineTransform old_xform = CGContextGetCTM(ctx); CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform)); CGContextConcatCTM(ctx, CGAffineTransformIdentity); @@ -205,7 +206,6 @@ QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) ::RGBColor b; b.blue = b.green = b.red = 255*255; PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon); - CGContextRelease(ctx); return ret; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 7fb695630b2..b2fd0580bc3 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -52,6 +52,7 @@ #include #include #include +#include #include diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 70eaea63cb1..e5c0bb4771c 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -52,6 +52,7 @@ #include #include #include +#include #include "qcocoabackingstore.h" #ifndef QT_NO_OPENGL #include "qcocoaglcontext.h" @@ -494,7 +495,7 @@ static bool _q_dontOverrideCtrlLMB = false; qCDebug(lcQpaCocoaWindow) << "[QNSView flushBackingStore:]" << m_window << region.rectCount() << region.boundingRect() << offset; m_backingStore = backingStore; - m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio(); + m_backingStoreOffset = offset * m_backingStore->paintDevice()->devicePixelRatio(); for (const QRect &rect : region) [self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; } @@ -576,7 +577,7 @@ static bool _q_dontOverrideCtrlLMB = false; // The backing store source rect will be larger on retina displays. // Scale dirtyRect by the device pixel ratio: - const qreal devicePixelRatio = m_backingStore->getBackingStoreDevicePixelRatio(); + const qreal devicePixelRatio = m_backingStore->paintDevice()->devicePixelRatio(); CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio, dirtyRect.origin.y * devicePixelRatio, dirtyRect.size.width * devicePixelRatio, diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index 759c4d26a5f..7e241e3ae68 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -63,6 +63,7 @@ #include #include #include +#include #include "qcocoahelpers.h" @@ -74,84 +75,6 @@ QT_BEGIN_NAMESPACE QCoreGraphicsPaintEngine utility functions *****************************************************************************/ -static void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform) -{ - CGAffineTransform old_xform = CGAffineTransformIdentity; - if (orig_xform) { //setup xforms - old_xform = CGContextGetCTM(hd); - CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform)); - CGContextConcatCTM(hd, *orig_xform); - } - - //do the clipping - CGContextBeginPath(hd); - if (rgn.isEmpty()) { - CGContextAddRect(hd, CGRectMake(0, 0, 0, 0)); - } else { - for (const QRect &r : rgn) { - CGRect mac_r = CGRectMake(r.x(), r.y(), r.width(), r.height()); - CGContextAddRect(hd, mac_r); - } - } - CGContextClip(hd); - - if (orig_xform) {//reset xforms - CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); - CGContextConcatCTM(hd, old_xform); - } -} - -// Implemented for qt_mac_p.h -QMacCGContext::QMacCGContext(QPainter *p) -{ - QPaintEngine *pe = p->paintEngine(); -#ifndef QT_NO_PRINTER - if (pe->type() == QPaintEngine::MacPrinter) - pe = static_cast(pe)->paintEngine(); -#endif - pe->syncState(); - context = 0; - if (pe->type() == QPaintEngine::CoreGraphics) - context = static_cast(pe)->handle(); - - int devType = p->device()->devType(); - if (pe->type() == QPaintEngine::Raster - && (devType == QInternal::Widget || devType == QInternal::Pixmap || devType == QInternal::Image)) { - - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pe->paintDevice()); - uint flags = kCGImageAlphaPremultipliedFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - flags |= kCGBitmapByteOrder32Host; -#endif - const QImage *image = (const QImage *) pe->paintDevice(); - - context = CGBitmapContextCreate((void *) image->bits(), image->width(), image->height(), - 8, image->bytesPerLine(), colorspace, flags); - - CGContextTranslateCTM(context, 0, image->height()); - CGContextScaleCTM(context, 1, -1); - - if (devType == QInternal::Widget) { - QRegion clip = p->paintEngine()->systemClip(); - QTransform native = p->deviceTransform(); - - if (p->hasClipping()) { - QRegion r = p->clipRegion(); - r.translate(native.dx(), native.dy()); - if (clip.isEmpty()) - clip = r; - else - clip &= r; - } - qt_mac_clip_cg(context, clip, 0); - - CGContextTranslateCTM(context, native.dx(), native.dy()); - } - } else { - CGContextRetain(context); - } -} - void qt_mac_cgimage_data_free(void *, const void *memoryToFree, size_t) { free(const_cast(memoryToFree)); @@ -453,7 +376,7 @@ static void qt_mac_draw_pattern(void *info, CGContextRef c) const QColor c0(0, 0, 0, 0), c1(255, 255, 255, 255); QPixmap pm(w*QMACPATTERN_MASK_MULTIPLIER, h*QMACPATTERN_MASK_MULTIPLIER); pm.fill(c0); - CGContextRef pm_ctx = qt_mac_cg_context(&pm); + QMacCGContext pm_ctx(&pm); CGContextSetFillColorWithColor(c, cgColorForQColor(c1, pat->pdev)); CGRect rect = CGRectMake(0, 0, w, h); for (int x = 0; x < QMACPATTERN_MASK_MULTIPLIER; ++x) { @@ -543,7 +466,8 @@ QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev) d->cosmeticPenSize = 1; d->current.clipEnabled = false; d->pixelSize = QPoint(1,1); - d->hd = qt_mac_cg_context(pdev); + QMacCGContext ctx(pdev); + d->hd = CGContextRetain(ctx); if (d->hd) { d->saveGraphicsState(); d->orig_xform = CGContextGetCTM(d->hd); diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h index e3cad3fd57e..ee98275b63d 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -149,6 +149,9 @@ public: PMPageFormat format() const { return static_cast([printInfo PMPageFormat]); } PMPrintSession session() const { return static_cast([printInfo PMPrintSession]); } PMPrintSettings settings() const { return static_cast([printInfo PMPrintSettings]); } + + QPaintEngine *aggregateEngine() Q_DECL_OVERRIDE { return paintEngine; } + Qt::HANDLE nativeHandle() Q_DECL_OVERRIDE { return q_func()->handle(); } }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h index 902cf5c6367..ce17919e8c1 100644 --- a/src/plugins/platforms/cocoa/qt_mac_p.h +++ b/src/plugins/platforms/cocoa/qt_mac_p.h @@ -90,44 +90,6 @@ public: } }; -class QMacCGContext -{ - CGContextRef context; -public: - QMacCGContext(QPainter *p); //qpaintengine_mac.mm - inline QMacCGContext() { context = 0; } - inline QMacCGContext(QPaintDevice *pdev) { - extern CGContextRef qt_mac_cg_context(QPaintDevice *); - context = qt_mac_cg_context(pdev); - } - inline QMacCGContext(CGContextRef cg, bool takeOwnership=false) { - context = cg; - if(!takeOwnership) - CGContextRetain(context); - } - inline QMacCGContext(const QMacCGContext ©) : context(0) { *this = copy; } - inline ~QMacCGContext() { - if(context) - CGContextRelease(context); - } - inline bool isNull() const { return context; } - inline operator CGContextRef() { return context; } - inline QMacCGContext &operator=(const QMacCGContext ©) { - if(context) - CGContextRelease(context); - context = copy.context; - CGContextRetain(context); - return *this; - } - inline QMacCGContext &operator=(CGContextRef cg) { - if(context) - CGContextRelease(context); - context = cg; - CGContextRetain(context); //we do not take ownership - return *this; - } -}; - class QMacInternalPasteboardMime; class QMimeData; diff --git a/src/plugins/platforms/haiku/qhaikuclipboard.cpp b/src/plugins/platforms/haiku/qhaikuclipboard.cpp index 0194a0415a5..774da4432af 100644 --- a/src/plugins/platforms/haiku/qhaikuclipboard.cpp +++ b/src/plugins/platforms/haiku/qhaikuclipboard.cpp @@ -91,7 +91,7 @@ QMimeData *QHaikuClipboard::mimeData(QClipboard::Mode mode) const status_t status = clipboard->FindData(name, B_MIME_TYPE, &data, &dataLen); if (dataLen && (status == B_OK)) { - const QString format = QString::fromLatin1(name); + const QLatin1String format(name); if (format == QLatin1String("text/plain")) { m_systemMimeData->setText(QString::fromLocal8Bit(reinterpret_cast(data), dataLen)); } else if (format == QLatin1String("text/html")) { diff --git a/src/plugins/platforms/ios/qiosbackingstore.mm b/src/plugins/platforms/ios/qiosbackingstore.mm index fb0c9805f9c..357a3db3c98 100644 --- a/src/plugins/platforms/ios/qiosbackingstore.mm +++ b/src/plugins/platforms/ios/qiosbackingstore.mm @@ -49,6 +49,8 @@ #include +QT_BEGIN_NAMESPACE + class QIOSPaintDevice : public QOpenGLPaintDevice { public: diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 50374dc951a..2d5286e9713 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -48,6 +48,8 @@ #import #import +QT_BEGIN_NAMESPACE + Q_LOGGING_CATEGORY(lcQpaGLContext, "qt.qpa.glcontext"); QIOSContext::QIOSContext(QOpenGLContext *context) @@ -314,3 +316,4 @@ bool QIOSContext::isSharing() const #include "moc_qioscontext.cpp" +QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosfiledialog.h b/src/plugins/platforms/ios/qiosfiledialog.h index 855bab04245..7fe24eaefee 100644 --- a/src/plugins/platforms/ios/qiosfiledialog.h +++ b/src/plugins/platforms/ios/qiosfiledialog.h @@ -43,10 +43,10 @@ #include #include -QT_BEGIN_NAMESPACE - Q_FORWARD_DECLARE_OBJC_CLASS(UIViewController); +QT_BEGIN_NAMESPACE + class QIOSFileDialog : public QPlatformFileDialogHelper { public: diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h index 50bedd7b28b..f74e3004cc5 100644 --- a/src/plugins/platforms/ios/qiosglobal.h +++ b/src/plugins/platforms/ios/qiosglobal.h @@ -74,6 +74,8 @@ QT_END_NAMESPACE + (id)currentFirstResponder; @end +QT_BEGIN_NAMESPACE + class FirstResponderCandidate : public QScopedValueRollback { public: @@ -84,4 +86,6 @@ private: static UIResponder *s_firstResponderCandidate; }; +QT_END_NAMESPACE + #endif // QIOSGLOBAL_H diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm index 7ca3c669716..1482ffc7af2 100644 --- a/src/plugins/platforms/ios/qiosglobal.mm +++ b/src/plugins/platforms/ios/qiosglobal.mm @@ -114,6 +114,8 @@ int infoPlistValue(NSString* key, int defaultValue) return value ? [value intValue] : defaultValue; } +QT_END_NAMESPACE + // ------------------------------------------------------------------------- @interface QtFirstResponderEvent : UIEvent @@ -164,6 +166,8 @@ int infoPlistValue(NSString* key, int defaultValue) } @end +QT_BEGIN_NAMESPACE + FirstResponderCandidate::FirstResponderCandidate(UIResponder *responder) : QScopedValueRollback(s_firstResponderCandidate, responder) { diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h index 2b0643f26e7..9fdf021d073 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.h +++ b/src/plugins/platforms/ios/qiosinputcontext.h @@ -51,13 +51,13 @@ const char kImePlatformDataInputView[] = "inputView"; const char kImePlatformDataInputAccessoryView[] = "inputAccessoryView"; const char kImePlatformDataReturnKeyType[] = "returnKeyType"; -QT_BEGIN_NAMESPACE - @class QIOSLocaleListener; @class QIOSKeyboardListener; @class QIOSTextInputResponder; @protocol KeyboardState; +QT_BEGIN_NAMESPACE + struct KeyboardState { KeyboardState() : diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index c6cbb9b1012..68088540c6c 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -97,14 +97,14 @@ static QUIView *focusView() @interface QIOSKeyboardListener : UIGestureRecognizer { @private - QIOSInputContext *m_context; + QT_PREPEND_NAMESPACE(QIOSInputContext) *m_context; } @property BOOL hasDeferredScrollToCursor; @end @implementation QIOSKeyboardListener -- (id)initWithQIOSInputContext:(QIOSInputContext *)context +- (id)initWithQIOSInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)context { if (self = [super initWithTarget:self action:@selector(gestureStateChanged:)]) { @@ -291,6 +291,8 @@ static QUIView *focusView() // ------------------------------------------------------------------------- +QT_BEGIN_NAMESPACE + Qt::InputMethodQueries ImeState::update(Qt::InputMethodQueries properties) { if (!properties) @@ -713,3 +715,5 @@ QLocale QIOSInputContext::locale() const { return QLocale(QString::fromNSString([[NSLocale currentLocale] objectForKey:NSLocaleIdentifier])); } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosmessagedialog.h b/src/plugins/platforms/ios/qiosmessagedialog.h index 971c8d8b4d7..e67e10a5e13 100644 --- a/src/plugins/platforms/ios/qiosmessagedialog.h +++ b/src/plugins/platforms/ios/qiosmessagedialog.h @@ -43,11 +43,11 @@ #include #include -QT_BEGIN_NAMESPACE - Q_FORWARD_DECLARE_OBJC_CLASS(UIAlertController); Q_FORWARD_DECLARE_OBJC_CLASS(UIAlertAction); +QT_BEGIN_NAMESPACE + class QIOSMessageDialog : public QPlatformMessageDialogHelper { public: diff --git a/src/plugins/platforms/ios/qiosplatformaccessibility.mm b/src/plugins/platforms/ios/qiosplatformaccessibility.mm index bc518507609..aef4216e03a 100644 --- a/src/plugins/platforms/ios/qiosplatformaccessibility.mm +++ b/src/plugins/platforms/ios/qiosplatformaccessibility.mm @@ -65,7 +65,7 @@ void invalidateCache(QAccessibleInterface *iface) // when items get added or removed from the screen foreach (QWindow *win, QGuiApplication::topLevelWindows()) { if (win && win->handle()) { - QIOSWindow *window = static_cast(win->handle()); + QT_PREPEND_NAMESPACE(QIOSWindow) *window = static_cast(win->handle()); window->clearAccessibleCache(); } } diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index cc83e7f3d29..9fcce428257 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -68,6 +68,8 @@ public: Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE; void setOrientationUpdateMask(Qt::ScreenOrientations mask) Q_DECL_OVERRIDE; + QPixmap grabWindow(WId window, int x, int y, int width, int height) const override; + UIScreen *uiScreen() const; UIWindow *uiWindow() const; diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 7dd2ce7f6e0..86bce0d70b6 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -48,6 +48,7 @@ #include #include +#include #include @@ -176,6 +177,8 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) // ------------------------------------------------------------------------- +QT_BEGIN_NAMESPACE + /*! Returns the model identifier of the device. @@ -458,6 +461,38 @@ void QIOSScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask) } } +QPixmap QIOSScreen::grabWindow(WId window, int x, int y, int width, int height) const +{ + if (window && ![reinterpret_cast(window) isKindOfClass:[UIView class]]) + return QPixmap(); + + UIView *view = window ? reinterpret_cast(window) : m_uiWindow; + + if (width < 0) + width = qMax(view.bounds.size.width - x, CGFloat(0)); + if (height < 0) + height = qMax(view.bounds.size.height - y, CGFloat(0)); + + CGRect captureRect = [m_uiWindow convertRect:CGRectMake(x, y, width, height) fromView:view]; + captureRect = CGRectIntersection(captureRect, m_uiWindow.bounds); + + UIGraphicsBeginImageContextWithOptions(captureRect.size, NO, 0.0); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextTranslateCTM(context, -captureRect.origin.x, -captureRect.origin.y); + + // Draws the complete view hierarchy of m_uiWindow into the given rect, which + // needs to be the same aspect ratio as the m_uiWindow's size. Since we've + // translated the graphics context, and are potentially drawing into a smaller + // context than the full window, the resulting image will be a subsection of the + // full screen. + [m_uiWindow drawViewHierarchyInRect:m_uiWindow.bounds afterScreenUpdates:NO]; + + UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return QPixmap::fromImage(qt_mac_toQImage(screenshot.CGImage)); +} + UIScreen *QIOSScreen::uiScreen() const { return m_uiScreen; diff --git a/src/plugins/platforms/ios/qiostextresponder.h b/src/plugins/platforms/ios/qiostextresponder.h index f7450df4c85..77be2cf2fe6 100644 --- a/src/plugins/platforms/ios/qiostextresponder.h +++ b/src/plugins/platforms/ios/qiostextresponder.h @@ -42,19 +42,23 @@ #include #include +QT_BEGIN_NAMESPACE + class QIOSInputContext; +QT_END_NAMESPACE + @interface QIOSTextInputResponder : UIResponder { @private - QIOSInputContext *m_inputContext; - QInputMethodQueryEvent *m_configuredImeState; + QT_PREPEND_NAMESPACE(QIOSInputContext) *m_inputContext; + QT_PREPEND_NAMESPACE(QInputMethodQueryEvent) *m_configuredImeState; QString m_markedText; BOOL m_inSendEventToFocusObject; BOOL m_inSelectionChange; } -- (id)initWithInputContext:(QIOSInputContext *)context; +- (id)initWithInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)context; - (BOOL)needsKeyboardReconfigure:(Qt::InputMethodQueries)updatedProperties; - (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties; diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index cd7945641ea..3c95083e45f 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -163,7 +163,7 @@ @implementation QIOSTextInputResponder -- (id)initWithInputContext:(QIOSInputContext *)inputContext +- (id)initWithInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)inputContext { if (!(self = [self init])) return self; diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h index 92c4e59d1af..f7b190ba222 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.h +++ b/src/plugins/platforms/ios/qiosviewcontroller.h @@ -38,12 +38,17 @@ ****************************************************************************/ #import +#include + +QT_BEGIN_NAMESPACE class QIOSScreen; +QT_END_NAMESPACE + @interface QIOSViewController : UIViewController -- (id)initWithQIOSScreen:(QIOSScreen *)screen; +- (id)initWithQIOSScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen; - (void)updateProperties; #ifndef Q_OS_TVOS diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index c8c07bd2985..72eb5e27a0b 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -58,7 +58,7 @@ @interface QIOSViewController () { @public - QPointer m_screen; + QPointer m_screen; BOOL m_updatingProperties; QMetaObject::Connection m_focusWindowChangeConnection; } @@ -126,7 +126,7 @@ { Q_UNUSED(subview); - QIOSScreen *screen = self.qtViewController->m_screen; + QT_PREPEND_NAMESPACE(QIOSScreen) *screen = self.qtViewController->m_screen; // The 'window' property of our view is not valid until the window // has been shown, so we have to access it through the QIOSScreen. @@ -229,7 +229,7 @@ @implementation QIOSViewController -- (id)initWithQIOSScreen:(QIOSScreen *)screen +- (id)initWithQIOSScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen { if (self = [self init]) { m_screen = screen; diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index afc2f0f89d8..81fad420f69 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -48,10 +48,10 @@ class QIOSContext; class QIOSWindow; -QT_BEGIN_NAMESPACE - @class QUIView; +QT_BEGIN_NAMESPACE + class QIOSWindow : public QObject, public QPlatformWindow { Q_OBJECT diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index cddfbe6b06b..ae14d87a30e 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -54,6 +54,8 @@ #include +QT_BEGIN_NAMESPACE + QIOSWindow::QIOSWindow(QWindow *window) : QPlatformWindow(window) , m_view([[QUIView alloc] initWithQIOSWindow:this]) diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm index 105d7cd65f5..a26ba61b3c2 100644 --- a/src/plugins/platforms/ios/quiaccessibilityelement.mm +++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm @@ -63,7 +63,7 @@ QAccessibleCache *cache = QAccessibleCache::instance(); - QMacAccessibilityElement *element = cache->elementForId(anId); + QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *element = cache->elementForId(anId); if (!element) { Q_ASSERT(QAccessible::accessibleInterface(anId)); element = [[self alloc] initWithId:anId withAccessibilityContainer: view]; diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h index fdaae943d82..1500f0b41c1 100644 --- a/src/plugins/platforms/ios/quiview.h +++ b/src/plugins/platforms/ios/quiview.h @@ -44,14 +44,18 @@ #include +QT_BEGIN_NAMESPACE + class QIOSWindow; +QT_END_NAMESPACE + @class QIOSViewController; @interface QUIView : UIView { @public - QIOSWindow *m_qioswindow; + QT_PREPEND_NAMESPACE(QIOSWindow) *m_qioswindow; @private QHash m_activeTouches; int m_nextTouchId; @@ -60,7 +64,7 @@ class QIOSWindow; NSMutableArray *m_accessibleElements; }; -- (id)initWithQIOSWindow:(QIOSWindow *)window; +- (id)initWithQIOSWindow:(QT_PREPEND_NAMESPACE(QIOSWindow) *)window; - (void)sendUpdatedExposeEvent; - (BOOL)isActiveWindow; @end diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 908c8b87f14..133269a0de8 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -60,7 +60,7 @@ return [CAEAGLLayer class]; } -- (id)initWithQIOSWindow:(QIOSWindow *)window +- (id)initWithQIOSWindow:(QT_PREPEND_NAMESPACE(QIOSWindow) *)window { if (self = [self initWithFrame:window->geometry().toCGRect()]) m_qioswindow = window; @@ -525,7 +525,7 @@ - (QWindow *)qwindow { if ([self isKindOfClass:[QUIView class]]) { - if (QIOSWindow *w = static_cast(self)->m_qioswindow) + if (QT_PREPEND_NAMESPACE(QIOSWindow) *w = static_cast(self)->m_qioswindow) return w->window(); } return nil; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index 39a4eb81ca9..ec73a4c0656 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -236,6 +237,82 @@ QWindowsFontEngineDirectWrite::~QWindowsFontEngineDirectWrite() m_directWriteBitmapRenderTarget->Release(); } +#ifndef Q_CC_MINGW +typedef IDWriteLocalFontFileLoader QIdWriteLocalFontFileLoader; + +static UUID uuidIdWriteLocalFontFileLoader() +{ + return __uuidof(IDWriteLocalFontFileLoader); +} +#else // !Q_CC_MINGW +DECLARE_INTERFACE_(QIdWriteLocalFontFileLoader, IDWriteFontFileLoader) +{ + STDMETHOD(GetFilePathLengthFromKey)(THIS_ void const *, UINT32, UINT32*) PURE; + STDMETHOD(GetFilePathFromKey)(THIS_ void const *, UINT32, WCHAR *, UINT32) PURE; + STDMETHOD(GetLastWriteTimeFromKey)(THIS_ void const *, UINT32, FILETIME *) PURE; +}; + +static UUID uuidIdWriteLocalFontFileLoader() +{ + static const UUID result = { 0xb2d9f3ec, 0xc9fe, 0x4a11, {0xa2, 0xec, 0xd8, 0x62, 0x8, 0xf7, 0xc0, 0xa2}}; + return result; +} +#endif // Q_CC_MINGW + +QString QWindowsFontEngineDirectWrite::filenameFromFontFile(IDWriteFontFile *fontFile) +{ + IDWriteFontFileLoader *loader = Q_NULLPTR; + + HRESULT hr = fontFile->GetLoader(&loader); + if (FAILED(hr)) { + qErrnoWarning("%s: GetLoader failed", __FUNCTION__); + return QString(); + } + + QIdWriteLocalFontFileLoader *localLoader = Q_NULLPTR; + hr = loader->QueryInterface(uuidIdWriteLocalFontFileLoader(), + reinterpret_cast(&localLoader)); + + const void *fontFileReferenceKey = Q_NULLPTR; + UINT32 fontFileReferenceKeySize = 0; + if (SUCCEEDED(hr)) { + hr = fontFile->GetReferenceKey(&fontFileReferenceKey, + &fontFileReferenceKeySize); + if (FAILED(hr)) + qErrnoWarning(hr, "%s: GetReferenceKey failed", __FUNCTION__); + } + + UINT32 filePathLength = 0; + if (SUCCEEDED(hr)) { + hr = localLoader->GetFilePathLengthFromKey(fontFileReferenceKey, + fontFileReferenceKeySize, + &filePathLength); + if (FAILED(hr)) + qErrnoWarning(hr, "GetFilePathLength failed", __FUNCTION__); + } + + QString ret; + if (SUCCEEDED(hr) && filePathLength > 0) { + QVarLengthArray filePath(filePathLength + 1); + + hr = localLoader->GetFilePathFromKey(fontFileReferenceKey, + fontFileReferenceKeySize, + filePath.data(), + filePathLength + 1); + if (FAILED(hr)) + qErrnoWarning(hr, "%s: GetFilePathFromKey failed", __FUNCTION__); + else + ret = QString::fromWCharArray(filePath.data()); + } + + if (localLoader != Q_NULLPTR) + localLoader->Release(); + + if (loader != Q_NULLPTR) + loader->Release(); + return ret; +} + void QWindowsFontEngineDirectWrite::collectMetrics() { DWRITE_FONT_METRICS metrics; @@ -250,6 +327,13 @@ void QWindowsFontEngineDirectWrite::collectMetrics() m_xHeight = DESIGN_TO_LOGICAL(metrics.xHeight); m_lineGap = DESIGN_TO_LOGICAL(metrics.lineGap); m_underlinePosition = DESIGN_TO_LOGICAL(metrics.underlinePosition); + + IDWriteFontFile *fontFile = Q_NULLPTR; + UINT32 numberOfFiles = 1; + if (SUCCEEDED(m_directWriteFontFace->GetFiles(&numberOfFiles, &fontFile))) { + m_faceId.filename = QFile::encodeName(filenameFromFontFile(fontFile)); + fontFile->Release(); + } } QFixed QWindowsFontEngineDirectWrite::underlinePosition() const @@ -351,6 +435,11 @@ bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGly return true; } +QFontEngine::FaceId QWindowsFontEngineDirectWrite::faceId() const +{ + return m_faceId; +} + void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const { QVarLengthArray glyphIndices(glyphs->numGlyphs); diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index fb2df00b7ef..1978304b134 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -49,6 +49,7 @@ struct IDWriteFont; struct IDWriteFontFace; +struct IDWriteFontFile; struct IDWriteFactory; struct IDWriteBitmapRenderTarget; struct IDWriteGdiInterop; @@ -92,6 +93,7 @@ public: QFixed leading() const Q_DECL_OVERRIDE; QFixed xHeight() const Q_DECL_OVERRIDE; qreal maxCharWidth() const Q_DECL_OVERRIDE; + FaceId faceId() const Q_DECL_OVERRIDE; bool supportsSubPixelPositions() const Q_DECL_OVERRIDE; @@ -113,6 +115,7 @@ private: QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform); void collectMetrics(); void renderGlyphRun(QImage *destination, float r, float g, float b, float a, IDWriteGlyphRunAnalysis *glyphAnalysis, const QRect &boundingRect); + static QString filenameFromFontFile(IDWriteFontFile *fontFile); const QSharedPointer m_fontEngineData; diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp index 968c47f2c20..63e5b0cf276 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp @@ -86,30 +86,31 @@ QWinRTInputContext::QWinRTInputContext(QWinRTScreen *screen) { qCDebug(lcQpaInputMethods) << __FUNCTION__ << screen; - ComPtr statics; - if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), - &statics))) { - qWarning("failed to retrieve input pane statics."); - return; - } + QEventDispatcherWinRT::runOnXamlThread([this]() { + ComPtr statics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(), + &statics))) { + qWarning("failed to retrieve input pane statics."); + return S_OK; + } - ComPtr inputPane; - statics->GetForCurrentView(&inputPane); - if (inputPane) { - QEventDispatcherWinRT::runOnXamlThread([this, inputPane]() { + ComPtr inputPane; + statics->GetForCurrentView(&inputPane); + if (inputPane) { EventRegistrationToken showToken, hideToken; inputPane->add_Showing(Callback( this, &QWinRTInputContext::onShowing).Get(), &showToken); inputPane->add_Hiding(Callback( this, &QWinRTInputContext::onHiding).Get(), &hideToken); - return S_OK; - }); - m_keyboardRect = getInputPaneRect(inputPane, m_screen->scaleFactor()); - m_isInputPanelVisible = !m_keyboardRect.isEmpty(); - } else { - qWarning("failed to retrieve InputPane."); - } + m_keyboardRect = getInputPaneRect(inputPane, m_screen->scaleFactor()); + m_isInputPanelVisible = !m_keyboardRect.isEmpty(); + } else { + qWarning("failed to retrieve InputPane."); + } + return S_OK; + }); + connect(QGuiApplication::inputMethod(), &QInputMethod::cursorRectangleChanged, this, &QWinRTInputContext::updateScreenCursorRect); } diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp index 749906d1e88..f71c5464d01 100644 --- a/src/plugins/platforms/xcb/qxcbmime.cpp +++ b/src/plugins/platforms/xcb/qxcbmime.cpp @@ -173,7 +173,7 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, // qDebug() << "mimeConvertDataToFormat" << format << atomName << data; if (!encoding.isEmpty() - && atomName == format + QLatin1String(";charset=") + QString::fromLatin1(encoding)) { + && atomName == format + QLatin1String(";charset=") + QLatin1String(encoding)) { #ifndef QT_NO_TEXTCODEC if (requestedType == QVariant::String) { diff --git a/src/plugins/sqldrivers/db2/qsql_db2.cpp b/src/plugins/sqldrivers/db2/qsql_db2.cpp index 4ccc3aca9ea..9408f464e04 100644 --- a/src/plugins/sqldrivers/db2/qsql_db2.cpp +++ b/src/plugins/sqldrivers/db2/qsql_db2.cpp @@ -1665,7 +1665,8 @@ QString QDB2Driver::formatValue(const QSqlField &field, bool trimStrings) const } case QVariant::ByteArray: { QByteArray ba = field.value().toByteArray(); - QString res = QString::fromLatin1("BLOB(X'"); + QString res; + res += QLatin1String("BLOB(X'"); static const char hexchars[] = "0123456789abcdef"; for (int i = 0; i < ba.size(); ++i) { uchar s = (uchar) ba[i]; diff --git a/src/printsupport/dialogs/qprintpreviewdialog.cpp b/src/printsupport/dialogs/qprintpreviewdialog.cpp index 435f8869c40..c996e0d5566 100644 --- a/src/printsupport/dialogs/qprintpreviewdialog.cpp +++ b/src/printsupport/dialogs/qprintpreviewdialog.cpp @@ -334,7 +334,7 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer) QString caption = QCoreApplication::translate("QPrintPreviewDialog", "Print Preview"); if (!printer->docName().isEmpty()) - caption += QString::fromLatin1(": ") + printer->docName(); + caption += QLatin1String(": ") + printer->docName(); q->setWindowTitle(caption); if (!printer->isValid() diff --git a/src/sql/models/qsqlrelationaltablemodel.h b/src/sql/models/qsqlrelationaltablemodel.h index 4da460389cc..f8b08b089f1 100644 --- a/src/sql/models/qsqlrelationaltablemodel.h +++ b/src/sql/models/qsqlrelationaltablemodel.h @@ -43,6 +43,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE @@ -53,17 +55,26 @@ public: QSqlRelation(const QString &aTableName, const QString &indexCol, const QString &displayCol) : tName(aTableName), iColumn(indexCol), dColumn(displayCol) {} + + void swap(QSqlRelation &other) Q_DECL_NOTHROW + { + qSwap(tName, other.tName); + qSwap(iColumn, other.iColumn); + qSwap(dColumn, other.dColumn); + } + inline QString tableName() const { return tName; } inline QString indexColumn() const { return iColumn; } inline QString displayColumn() const { return dColumn; } - inline bool isValid() const + bool isValid() const Q_DECL_NOTHROW { return !(tName.isEmpty() || iColumn.isEmpty() || dColumn.isEmpty()); } private: QString tName, iColumn, dColumn; }; +Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QSqlRelation) class QSqlRelationalTableModelPrivate; diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp index 5ce28d931b7..11bf8d79370 100644 --- a/src/tools/moc/preprocessor.cpp +++ b/src/tools/moc/preprocessor.cpp @@ -696,9 +696,9 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym next = arg.at(0); } - Symbol last = expansion.constLast(); - if (!expansion.isEmpty() && last.token == s.token && last.token != STRING_LITERAL) { - expansion.pop_back(); + if (!expansion.isEmpty() && expansion.constLast().token == s.token + && expansion.constLast().token != STRING_LITERAL) { + Symbol last = expansion.takeLast(); QByteArray lexem = last.lexem() + next.lexem(); expansion += Symbol(lineNum, last.token, lexem); diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp index 95888924fba..b8147621684 100644 --- a/src/widgets/accessible/qaccessiblewidgets.cpp +++ b/src/widgets/accessible/qaccessiblewidgets.cpp @@ -830,7 +830,7 @@ QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *end family = family.replace('=', QLatin1String("\\=")); family = family.replace(';', QLatin1String("\\;")); family = family.replace('\"', QLatin1String("\\\"")); - attrs["font-family"] = QString::fromLatin1("\"%1\"").arg(family); + attrs["font-family"] = QLatin1Char('"') + family + QLatin1Char('"'); } int fontSize = int(charFormatFont.pointSize()); diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp index 72aae647e0f..e0700d877e9 100644 --- a/src/widgets/kernel/qaction.cpp +++ b/src/widgets/kernel/qaction.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE */ static QString qt_strippedText(QString s) { - s.remove( QString::fromLatin1("...") ); + s.remove(QStringLiteral("...")); for (int i = 0; i < s.size(); ++i) { if (s.at(i) == QLatin1Char('&')) s.remove(i, 1); diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 1cdac672e2f..6fbc7c9eea0 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -97,6 +97,7 @@ #include #include #include +#include QT_USE_NAMESPACE @@ -521,47 +522,6 @@ static QString qt_mac_removeMnemonics(const QString &original) return returnText; } -static CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); - -namespace { -class QMacCGContext -{ - CGContextRef context; -public: - QMacCGContext(QPainter *p); - inline QMacCGContext() { context = 0; } - inline QMacCGContext(const QPaintDevice *pdev) { - context = qt_mac_cg_context(pdev); - } - inline QMacCGContext(CGContextRef cg, bool takeOwnership=false) { - context = cg; - if (!takeOwnership) - CGContextRetain(context); - } - inline QMacCGContext(const QMacCGContext ©) : context(0) { *this = copy; } - inline ~QMacCGContext() { - if (context) - CGContextRelease(context); - } - inline bool isNull() const { return context; } - inline operator CGContextRef() { return context; } - inline QMacCGContext &operator=(const QMacCGContext ©) { - if (context) - CGContextRelease(context); - context = copy.context; - CGContextRetain(context); - return *this; - } - inline QMacCGContext &operator=(CGContextRef cg) { - if (context) - CGContextRelease(context); - context = cg; - CGContextRetain(context); //we do not take ownership - return *this; - } -}; -} // anonymous namespace - OSStatus qt_mac_shape2QRegionHelper(int inMessage, HIShapeRef, const CGRect *inRect, void *inRefcon) { QRegion *region = static_cast(inRefcon); @@ -582,7 +542,6 @@ OSStatus qt_mac_shape2QRegionHelper(int inMessage, HIShapeRef, const CGRect *inR return noErr; } - /*! \internal Create's a mutable shape, it's the caller's responsibility to release. @@ -612,86 +571,6 @@ QRegion qt_mac_fromHIShapeRef(HIShapeRef shape) return returnRegion; } -CGColorSpaceRef m_genericColorSpace = 0; -static QHash m_displayColorSpaceHash; -bool m_postRoutineRegistered = false; - -static CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget); -static CGColorSpaceRef qt_mac_genericColorSpace() -{ -#if 0 - if (!m_genericColorSpace) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - } else - { - m_genericColorSpace = CGColorSpaceCreateDeviceRGB(); - } - if (!m_postRoutineRegistered) { - m_postRoutineRegistered = true; - qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); - } - } - return m_genericColorSpace; -#else - // Just return the main display colorspace for the moment. - return qt_mac_displayColorSpace(0); -#endif -} - -static void qt_mac_cleanUpMacColorSpaces() -{ - if (m_genericColorSpace) { - CFRelease(m_genericColorSpace); - m_genericColorSpace = 0; - } - QHash::const_iterator it = m_displayColorSpaceHash.constBegin(); - while (it != m_displayColorSpaceHash.constEnd()) { - if (it.value()) - CFRelease(it.value()); - ++it; - } - m_displayColorSpaceHash.clear(); -} - -/* - Ideally, we should pass the widget in here, and use CGGetDisplaysWithRect() etc. - to support multiple displays correctly. -*/ -static CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget) -{ - CGColorSpaceRef colorSpace; - - CGDirectDisplayID displayID; - if (widget == 0) { - displayID = CGMainDisplayID(); - } else { - displayID = CGMainDisplayID(); - /* - ### get correct display - const QRect &qrect = widget->window()->geometry(); - CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height()); - CGDisplayCount throwAway; - CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway); - if (dErr != kCGErrorSuccess) - return macDisplayColorSpace(0); // fall back on main display - */ - } - if ((colorSpace = m_displayColorSpaceHash.value(displayID))) - return colorSpace; - - colorSpace = CGDisplayCopyColorSpace(displayID); - if (colorSpace == 0) - colorSpace = CGColorSpaceCreateDeviceRGB(); - - m_displayColorSpaceHash.insert(displayID, colorSpace); - if (!m_postRoutineRegistered) { - m_postRoutineRegistered = true; - qAddPostRoutine(qt_mac_cleanUpMacColorSpaces); - } - return colorSpace; -} - bool qt_macWindowIsTextured(const QWidget *window) { if (QWindow *w = window->windowHandle()) @@ -2284,7 +2163,7 @@ void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush painter->setClipRegion(rgn); - QCFType cg = qt_mac_cg_context(target); + QMacCGContext cg(target); CGContextSaveGState(cg); HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationInverted); @@ -2358,7 +2237,7 @@ void QMacStyle::polish(QWidget* w) mtinfo.menuType = kThemeMenuTypePopUp; // HIRect rect = CGRectMake(0, 0, px.width(), px.height()); // ### - //HIThemeDrawMenuBackground(&rect, &mtinfo, QCFType(qt_mac_cg_context(&px)), + //HIThemeDrawMenuBackground(&rect, &mtinfo, QMacCGContext(&px)), // kHIThemeOrientationNormal); QPalette pal = w->palette(); QBrush background(px); @@ -7189,158 +7068,6 @@ int QMacStyle::layoutSpacing(QSizePolicy::ControlType control1, return_SIZE(10, 8, 6); // guess } -static void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform) -{ - CGAffineTransform old_xform = CGAffineTransformIdentity; - if (orig_xform) { //setup xforms - old_xform = CGContextGetCTM(hd); - CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform)); - CGContextConcatCTM(hd, *orig_xform); - } - - //do the clipping - CGContextBeginPath(hd); - if (rgn.isEmpty()) { - CGContextAddRect(hd, CGRectMake(0, 0, 0, 0)); - } else { - QCFType shape = qt_mac_toHIMutableShape(rgn); - Q_ASSERT(!HIShapeIsEmpty(shape)); - HIShapeReplacePathInCGContext(shape, hd); - } - CGContextClip(hd); - - if (orig_xform) {//reset xforms - CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); - CGContextConcatCTM(hd, old_xform); - } -} - -// move to QRegion? -void qt_mac_scale_region(QRegion *region, qreal scaleFactor) -{ - if (!region || !region->rectCount()) - return; - - QVector scaledRects; - scaledRects.reserve(region->rectCount()); - - for (const QRect &rect : *region) - scaledRects.append(QRect(rect.topLeft() * scaleFactor, rect.size() * scaleFactor)); - - region->setRects(&scaledRects[0], scaledRects.count()); -} - -static CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice); - -namespace { -QMacCGContext::QMacCGContext(QPainter *p) -{ - QPaintEngine *pe = p->paintEngine(); - pe->syncState(); - context = 0; - - int devType = p->device()->devType(); - if (pe->type() == QPaintEngine::Raster - && (devType == QInternal::Widget || - devType == QInternal::Pixmap || - devType == QInternal::Image)) { - - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pe->paintDevice()); - uint flags = kCGImageAlphaPremultipliedFirst; - flags |= kCGBitmapByteOrder32Host; - - const QImage *image = (const QImage *) pe->paintDevice(); - - context = CGBitmapContextCreate((void *) image->bits(), image->width(), image->height(), - 8, image->bytesPerLine(), colorspace, flags); - - // Invert y axis. - CGContextTranslateCTM(context, 0, image->height()); - CGContextScaleCTM(context, 1, -1); - - const qreal devicePixelRatio = image->devicePixelRatio(); - - if (devType == QInternal::Widget) { - // Set the clip rect which is an intersection of the system clip - // and the painter clip. To make matters more interesting these - // are in device pixels and device-independent pixels, respectively. - QRegion clip = p->paintEngine()->systemClip(); // get system clip in device pixels - QTransform native = p->deviceTransform(); // get device transform. dx/dy is in device pixels - - if (p->hasClipping()) { - QRegion r = p->clipRegion(); // get painter clip, which is in device-independent pixels - qt_mac_scale_region(&r, devicePixelRatio); // scale painter clip to device pixels - r.translate(native.dx(), native.dy()); - if (clip.isEmpty()) - clip = r; - else - clip &= r; - } - qt_mac_clip_cg(context, clip, 0); // clip in device pixels - - // Scale the context so that painting happens in device-independet pixels. - CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio); - CGContextTranslateCTM(context, native.dx() / devicePixelRatio, native.dy() / devicePixelRatio); - } else { - // Scale to paint in device-independent pixels. - CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio); - } - } else { - qDebug() << "QMacCGContext:: Unsupported painter devtype type" << devType; - } -} - -} // anonymous namespace - -static CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice) -{ - bool isWidget = (paintDevice->devType() == QInternal::Widget); - return qt_mac_displayColorSpace(isWidget ? static_cast(paintDevice) : 0); -} - -/*! \internal - - Returns the CoreGraphics CGContextRef of the paint device. 0 is - returned if it can't be obtained. It is the caller's responsibility to - CGContextRelease the context when finished using it. - - \warning This function is only available on \macos. - \warning This function is duplicated in the Cocoa platform plugin. -*/ - -CGContextRef qt_mac_cg_context(const QPaintDevice *pdev) -{ - if (pdev->devType() == QInternal::Pixmap) { - const QPixmap *pm = static_cast(pdev); - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); - uint flags = kCGImageAlphaPremultipliedFirst; - flags |= kCGBitmapByteOrder32Host; - CGContextRef ret = 0; - - QPlatformPixmap *data = const_cast(pm)->data_ptr().data(); - if (data->classId() == QPlatformPixmap::RasterClass) { - QImage *image = data->buffer(); - ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(), - 8, image->bytesPerLine(), colorspace, flags); - } else { - qDebug("qt_mac_cg_context: Unsupported pixmap class"); - } - - CGContextTranslateCTM(ret, 0, pm->height()); - qreal devicePixelRatio = pdev->devicePixelRatioF(); - CGContextScaleCTM(ret, devicePixelRatio, devicePixelRatio); - CGContextScaleCTM(ret, 1, -1); - return ret; - } else if (pdev->devType() == QInternal::Widget) { - //CGContextRef ret = static_cast(static_cast(pdev)->macCGHandle()); - ///CGContextRetain(ret); - //return ret; - qDebug("qt_mac_cg_context: not implemented: Widget class"); - return 0; - } - return 0; -} - /* FontHash::FontHash() { diff --git a/src/widgets/widgets/qlcdnumber.cpp b/src/widgets/widgets/qlcdnumber.cpp index 2703e5d8a32..aa052ef5cba 100644 --- a/src/widgets/widgets/qlcdnumber.cpp +++ b/src/widgets/widgets/qlcdnumber.cpp @@ -188,8 +188,8 @@ static QString int2string(int num, int base, int ndigits, bool *oflow) } while (n != 0); len = ndigits - len; if (len > 0) - s.fill(QLatin1Char(' '), len); - s += QString::fromLatin1(p); + s += QString(len, QLatin1Char(' ')); + s += QLatin1String(p); } break; } diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp index 5608a4aff9b..bf10b9fb75f 100644 --- a/src/widgets/widgets/qpushbutton.cpp +++ b/src/widgets/widgets/qpushbutton.cpp @@ -415,7 +415,7 @@ QSize QPushButton::sizeHint() const QString s(text()); bool empty = s.isEmpty(); if (empty) - s = QString::fromLatin1("XXXX"); + s = QStringLiteral("XXXX"); QFontMetrics fm = fontMetrics(); QSize sz = fm.size(Qt::TextShowMnemonic, s); if(!empty || !w) diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp index 9e369792f1a..2cf9ea4913b 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp @@ -41,7 +41,6 @@ #include #include #include -#include #include #include @@ -844,18 +843,18 @@ void tst_QMimeDatabase::findByFile() void tst_QMimeDatabase::fromThreads() { - QThreadPool::globalInstance()->setMaxThreadCount(20); + QThreadPool tp; + tp.setMaxThreadCount(20); // Note that data-based tests cannot be used here (QTest::fetchData asserts). - QFutureSynchronizer sync; - sync.addFuture(QtConcurrent::run(this, &tst_QMimeDatabase::mimeTypeForName)); - sync.addFuture(QtConcurrent::run(this, &tst_QMimeDatabase::aliases)); - sync.addFuture(QtConcurrent::run(this, &tst_QMimeDatabase::allMimeTypes)); - sync.addFuture(QtConcurrent::run(this, &tst_QMimeDatabase::icons)); - sync.addFuture(QtConcurrent::run(this, &tst_QMimeDatabase::inheritance)); - sync.addFuture(QtConcurrent::run(this, &tst_QMimeDatabase::knownSuffix)); - sync.addFuture(QtConcurrent::run(this, &tst_QMimeDatabase::mimeTypeForFileWithContent)); - sync.addFuture(QtConcurrent::run(this, &tst_QMimeDatabase::allMimeTypes)); // a second time - // sync dtor blocks waiting for finished + QtConcurrent::run(&tp, this, &tst_QMimeDatabase::mimeTypeForName); + QtConcurrent::run(&tp, this, &tst_QMimeDatabase::aliases); + QtConcurrent::run(&tp, this, &tst_QMimeDatabase::allMimeTypes); + QtConcurrent::run(&tp, this, &tst_QMimeDatabase::icons); + QtConcurrent::run(&tp, this, &tst_QMimeDatabase::inheritance); + QtConcurrent::run(&tp, this, &tst_QMimeDatabase::knownSuffix); + QtConcurrent::run(&tp, this, &tst_QMimeDatabase::mimeTypeForFileWithContent); + QtConcurrent::run(&tp, this, &tst_QMimeDatabase::allMimeTypes); // a second time + QVERIFY(tp.waitForDone(60000)); } #ifndef QT_NO_PROCESS diff --git a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp index 0fdafd9b012..2385aa992c3 100644 --- a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp +++ b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp @@ -341,6 +341,7 @@ void tst_QStringList::join() const QFETCH(QString, expectedResult); QCOMPARE(input.join(separator), expectedResult); + QCOMPARE(input.join(QLatin1String(separator.toLatin1())), expectedResult); } void tst_QStringList::join_data() const diff --git a/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp b/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp index 9d42ae5850b..43b2b796989 100644 --- a/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp +++ b/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp @@ -26,6 +26,7 @@ ** ****************************************************************************/ +#include #include #include @@ -38,6 +39,7 @@ public: public slots: void initTestCase(); + void cleanupTestCase(); private slots: void constructor(); @@ -54,6 +56,9 @@ private: bool appendFileContent(QFileOpenEvent& event, const QByteArray& writeContent); bool event(QEvent *); + + QTemporaryDir m_temporaryDir; + QString m_originalCurrent; }; tst_qfileopenevent::~tst_qfileopenevent() @@ -62,6 +67,13 @@ tst_qfileopenevent::~tst_qfileopenevent() void tst_qfileopenevent::initTestCase() { + m_originalCurrent = QDir::currentPath(); + QDir::setCurrent(m_temporaryDir.path()); +} + +void tst_qfileopenevent::cleanupTestCase() +{ + QDir::setCurrent(m_originalCurrent); } void tst_qfileopenevent::createFile(const QString &filename, const QByteArray &content) diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index 81ab693ee7f..19d9262bca9 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -14,3 +14,5 @@ ubuntu-14.04 ubuntu-16.04 [modalDialogClosingOneOfTwoModal] osx +[modalWindowModallity] +osx diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp old mode 100755 new mode 100644 diff --git a/tests/auto/network/access/http2/http2srv.h b/tests/auto/network/access/http2/http2srv.h old mode 100755 new mode 100644 diff --git a/tests/auto/tools/moc/parse-defines.h b/tests/auto/tools/moc/parse-defines.h index 9fb5da4b07f..6100bf67ad4 100644 --- a/tests/auto/tools/moc/parse-defines.h +++ b/tests/auto/tools/moc/parse-defines.h @@ -139,6 +139,9 @@ public slots: signals: DEFINE_CMDLINE_SIGNAL; +#define QTBUG55853(X) PD_DEFINE1(X, signalQTBUG55853) +#define PD_EMPTY /* empty */ + void QTBUG55853(PD_EMPTY)(); }; #undef QString diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index a3648c95b6d..601b1bb36b3 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -3397,6 +3397,9 @@ void tst_Moc::parseDefines() index = mo->indexOfSignal("cmdlineSignal(QMap)"); QVERIFY(index != -1); + + index = mo->indexOfSignal("signalQTBUG55853()"); + QVERIFY(index != -1); } void tst_Moc::preprocessorOnly()