Use ICU from Windows SDK for codec support (QStringConverter)

Windows has shipped a (limited) subset of ICU for quite a while:

  https://learn.microsoft.com/en-us/windows/win32/intl/international-components-for-unicode--icu-

The C API for this subset uses non-standard names for headers and lib
though, and is therefore not picked up by the ICU configure logic in
CMake.

This patch adds a separate configure test that enables the use of this
ICU API, specifically for text codec support in QStringConverter.
If a 'proper' ICU is enabled by the user, this still takes precedence.
Also, note that MinGW-w64 misses the respective Windows API, and will
therefore still use the old fallback.

[ChangeLog][QtCore][Text] Qt on Windows now uses the ICU API of the
Windows SDK for text codec support (if available and no 'full' ICU is
configured). This greatly enhances the list of supported text codecs
available.

Fixes: QTBUG-132056
Change-Id: Id02ae9f8cf56dee8c34795c0e60d2113f319bfd9
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Kai Köhne 2024-12-09 15:59:10 +01:00
parent 71246cbdc6
commit 92b5980a7e
5 changed files with 40 additions and 9 deletions

View File

@ -871,6 +871,11 @@ qt_internal_extend_target(Core CONDITION WIN32
text/qlocale_win.cpp text/qlocale_win.cpp
) )
qt_internal_extend_target(Core CONDITION QT_FEATURE_winsdkicu
LIBRARIES
icu
)
qt_internal_extend_target(Core CONDITION WASM qt_internal_extend_target(Core CONDITION WASM
SOURCES SOURCES
text/qlocale_wasm.cpp text/qlocale_wasm.cpp

View File

@ -515,6 +515,21 @@ renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_NOREPLACE | RENAME_WHITEO
} }
") ")
qt_config_compile_test(winsdkicu
LABEL "Windows SDK: ICU"
LIBRARIES icu
CODE
"#include <icu.h>
int main(void)
{
/* BEGIN TEST: */
/* END TEST: */
return 0;
}
"
)
# cpp_winrt # cpp_winrt
qt_config_compile_test(cpp_winrt qt_config_compile_test(cpp_winrt
LABEL "cpp/winrt" LABEL "cpp/winrt"
@ -666,6 +681,12 @@ qt_feature("icu" PRIVATE
AUTODETECT NOT WIN32 AUTODETECT NOT WIN32
CONDITION ICU_FOUND CONDITION ICU_FOUND
) )
qt_feature("winsdkicu" PRIVATE
LABEL "ICU (Windows SDK)"
AUTODETECT WIN32
CONDITION TEST_winsdkicu
DISABLE QT_FEATURE_icu
)
qt_feature("inotify" PUBLIC PRIVATE qt_feature("inotify" PUBLIC PRIVATE
LABEL "inotify" LABEL "inotify"
CONDITION TEST_inotify OR TEST_fsnotify CONDITION TEST_inotify OR TEST_fsnotify

View File

@ -94,5 +94,6 @@
#define QT_NO_TRANSLATION #define QT_NO_TRANSLATION
#define QT_FEATURE_translation -1 #define QT_FEATURE_translation -1
#define QT_NO_VARIANT -1 #define QT_NO_VARIANT -1
#define QT_FEATURE_winsdkicu -1
#endif // QT_BOOTSTRAPPED #endif // QT_BOOTSTRAPPED

View File

@ -19,7 +19,11 @@
#include <unicode/ucnv_cb.h> #include <unicode/ucnv_cb.h>
#include <unicode/ucnv_err.h> #include <unicode/ucnv_err.h>
#include <unicode/ustring.h> #include <unicode/ustring.h>
#endif #define QT_USE_ICU_CODECS
#elif QT_CONFIG(winsdkicu)
#include <icu.h>
#define QT_USE_ICU_CODECS
#endif // QT_CONFIG(icu) || QT_CONFIG(winsdkicu)
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <qt_windows.h> #include <qt_windows.h>
@ -1836,7 +1840,7 @@ void QStringConverter::State::clear() noexcept
void QStringConverter::State::reset() noexcept void QStringConverter::State::reset() noexcept
{ {
if (flags & Flag::UsesIcu) { if (flags & Flag::UsesIcu) {
#if QT_CONFIG(icu) #if defined(QT_USE_ICU_CODECS)
UConverter *converter = static_cast<UConverter *>(d[0]); UConverter *converter = static_cast<UConverter *>(d[0]);
if (converter) if (converter)
ucnv_reset(converter); ucnv_reset(converter);
@ -2152,7 +2156,7 @@ static bool nameMatch(const char *a, QAnyStringView b)
*/ */
#if QT_CONFIG(icu) #if defined(QT_USE_ICU_CODECS)
// only derives from QStringConverter to get access to protected types // only derives from QStringConverter to get access to protected types
struct QStringConverterICU : QStringConverter struct QStringConverterICU : QStringConverter
{ {
@ -2418,7 +2422,7 @@ QStringConverter::QStringConverter(QAnyStringView name, Flags f)
auto e = encodingForName(name); auto e = encodingForName(name);
if (e) if (e)
iface = encodingInterfaces + int(*e); iface = encodingInterfaces + int(*e);
#if QT_CONFIG(icu) #if defined(QT_USE_ICU_CODECS)
else else
iface = QStringConverterICU::make_icu_converter(&state, name); iface = QStringConverterICU::make_icu_converter(&state, name);
#endif #endif
@ -2430,7 +2434,7 @@ const char *QStringConverter::name() const noexcept
if (!iface) if (!iface)
return nullptr; return nullptr;
if (state.flags & QStringConverter::Flag::UsesIcu) { if (state.flags & QStringConverter::Flag::UsesIcu) {
#if QT_CONFIG(icu) #if defined(QT_USE_ICU_CODECS)
return static_cast<const char*>(state.d[1]); return static_cast<const char*>(state.d[1]);
#else #else
return nullptr; return nullptr;
@ -2610,7 +2614,7 @@ std::optional<QStringConverter::Encoding> QStringConverter::encodingForHtml(QByt
static qsizetype availableCodecCount() static qsizetype availableCodecCount()
{ {
#if !QT_CONFIG(icu) #if !defined(QT_USE_ICU_CODECS)
return QStringConverter::Encoding::LastEncoding; return QStringConverter::Encoding::LastEncoding;
#else #else
/* icu contains also the names of what Qt provides /* icu contains also the names of what Qt provides
@ -2637,7 +2641,7 @@ QStringList QStringConverter::availableCodecs()
{ {
auto availableCodec = [](qsizetype index) -> QString auto availableCodec = [](qsizetype index) -> QString
{ {
#if !QT_CONFIG(icu) #if !defined(QT_USE_ICU_CODECS)
return QString::fromLatin1(encodingInterfaces[index].name); return QString::fromLatin1(encodingInterfaces[index].name);
#else #else
if (index == 0) // "Locale", not provided by icu if (index == 0) // "Locale", not provided by icu

View File

@ -151,7 +151,7 @@ private slots:
void convertL1U16(); void convertL1U16();
#if QT_CONFIG(icu) #if QT_CONFIG(icu) || QT_CONFIG(winsdkicu)
void roundtripIcu_data(); void roundtripIcu_data();
void roundtripIcu(); void roundtripIcu();
void icuInvalidCharacter_data(); void icuInvalidCharacter_data();
@ -501,7 +501,7 @@ void tst_QStringConverter::convertL1U8()
} }
} }
#if QT_CONFIG(icu) #if QT_CONFIG(icu) || QT_CONFIG(winsdkicu)
void tst_QStringConverter::roundtripIcu_data() void tst_QStringConverter::roundtripIcu_data()
{ {