diff --git a/.cmake.conf b/.cmake.conf index 0ea15e5d..889ca7d8 100644 --- a/.cmake.conf +++ b/.cmake.conf @@ -8,7 +8,7 @@ if (NOT DEFINED QT_SUPERBUILD OR DEFINED QT_REPO_MODULE_VERSION) list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1") endif() -set(QT_REPO_MODULE_VERSION "6.5.1") +set(QT_REPO_MODULE_VERSION "6.5.3") set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1") set(QT_COPYRIGHT_YEAR "2023") diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dfe07704..00000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/.release-timestamp b/.release-timestamp index 476c7efc..e6b6e860 100644 --- a/.release-timestamp +++ b/.release-timestamp @@ -1 +1 @@ -QT_PACKAGEDATE_STR=2023-05-22 \ No newline at end of file +QT_PACKAGEDATE_STR=2023-09-25 \ No newline at end of file diff --git a/.tag b/.tag index e64403e9..dd5a7f29 100644 --- a/.tag +++ b/.tag @@ -1 +1 @@ -55aee8697512af105dfefabc1e2ec41d4df1e45e +372eaedc5b8c771c46acc4c96e91bbade4ca3624 diff --git a/CMakeLists.txt b/CMakeLists.txt index 15142a6f..fd370a54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,11 +40,26 @@ function(qt_internal_check_if_path_has_symlinks path) endwhile() endif() if(is_symlink) - message(FATAL_ERROR "The path \"${path}\" contains symlinks. \ - This is not supported. Possible solutions: - - map directories using a transparent mechanism such as mount --bind - - pass the real path of the build directory to CMake, e.g. using \ - cd $(realpath ) before invoking cmake .") + set(possible_solutions_for_resolving_symlink [[ + - Map directories using a transparent mechanism such as mount --bind + - Pass the real path of the build directory to CMake, e.g. using + cd $(realpath ) before invoking cmake . + ]]) + if(QT_ALLOW_SYMLINK_IN_PATHS) + # In some cases, e.g., Homebrew, it is beneficial to skip this check. + # Before this, Homebrew had to patch this out to be able to get their build. + message(WARNING + "The path \"${path}\" contains symlinks. " + "This is not recommended, and it may lead to unexpected issues. If you do " + "not have a good reason for enabling 'QT_ALLOW_SYMLINK_IN_PATHS', disable " + "it, and follow one of the following solutions: \n" + "${possible_solutions_for_resolving_symlink} ") + else() + message(FATAL_ERROR + "The path \"${path}\" contains symlinks. " + "This is not supported. Possible solutions: \n" + "${possible_solutions_for_resolving_symlink} ") + endif() endif() endfunction() qt_internal_check_if_path_has_symlinks("${CMAKE_BINARY_DIR}") diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake index 0733f1f7..9ac8e2fa 100644 --- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake +++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake @@ -128,7 +128,8 @@ check_cxx_source_compiles(" #include int main(int, char **) { - EGLint x = 0; EGLDisplay dpy = 0; EGLContext ctx = 0; + [[maybe_unused]] EGLint x = 0; + EGLDisplay dpy = 0; EGLContext ctx = 0; eglDestroyContext(dpy, ctx); }" HAVE_EGL) diff --git a/cmake/FindGSSAPI.cmake b/cmake/FindGSSAPI.cmake index cc89406a..44594941 100644 --- a/cmake/FindGSSAPI.cmake +++ b/cmake/FindGSSAPI.cmake @@ -12,12 +12,24 @@ find_path(GSSAPI_INCLUDE_DIRS HINTS ${PC_GSSAPI_INCLUDEDIR} ) +# On macOS, vcpkg opts for finding frameworks LAST. This is generally fine; +# however, in the case of GSSAPI, `usr/lib/libgssapi_krb5.tbd` which is a +# symlink to `Kerberos.framework` misses a few symols, e.g., +# `___gss_c_nt_hostbased_service_oid_desc`, and it causes build failure. +# So, we need to make sure that we find `GSS.framework`. +set(gssapi_library_names + GSS # framework + gss # solaris + gssapi # FreeBSD + gssapi_krb5 +) +if(APPLE) + list(REMOVE_ITEM gssapi_library_names "gssapi_krb5") +endif() + find_library(GSSAPI_LIBRARIES NAMES - GSS # framework - gss # solaris - gssapi # FreeBSD - gssapi_krb5 + ${gssapi_library_names} HINTS ${PC_GSSAPI_LIBDIR} ) @@ -44,4 +56,3 @@ mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES) include(FeatureSummary) set_package_properties(GSSAPI PROPERTIES DESCRIPTION "Generic Security Services Application Program Interface") - diff --git a/cmake/FindPPS.cmake b/cmake/FindPPS.cmake index 6556091c..09901924 100644 --- a/cmake/FindPPS.cmake +++ b/cmake/FindPPS.cmake @@ -18,9 +18,7 @@ find_package_handle_standard_args(PPS DEFAULT_MSG PPS_INCLUDE_DIR PPS_LIBRARY) mark_as_advanced(PPS_INCLUDE_DIR PPS_LIBRARY) if(PPS_FOUND) - add_library(__PPS INTERFACE IMPORTED) - target_link_libraries(__PPS INTERFACE "${PPS_LIBRARY}") - target_include_directories(__PPS INTERFACE "${PPS_INCLUDE_DIR}") - - add_library(PPS::PPS ALIAS __PPS) + add_library(PPS::PPS INTERFACE IMPORTED) + target_link_libraries(PPS::PPS INTERFACE "${PPS_LIBRARY}") + target_include_directories(PPS::PPS INTERFACE "${PPS_INCLUDE_DIR}") endif() diff --git a/cmake/FindWrapOpenGL.cmake b/cmake/FindWrapOpenGL.cmake index c4e0fe5d..48bc8fe2 100644 --- a/cmake/FindWrapOpenGL.cmake +++ b/cmake/FindWrapOpenGL.cmake @@ -17,14 +17,18 @@ if (OpenGL_FOUND) add_library(WrapOpenGL::WrapOpenGL INTERFACE IMPORTED) if(APPLE) + # CMake 3.27 and older: # On Darwin platforms FindOpenGL sets IMPORTED_LOCATION to the absolute path of the library # within the framework. This ends up as an absolute path link flag, which we don't want, # because that makes our .prl files un-relocatable. # Extract the framework path instead, and use that in INTERFACE_LINK_LIBRARIES, - # which CMake ends up transforming into a reloctable -framework flag. + # which CMake ends up transforming into a relocatable -framework flag. # See https://gitlab.kitware.com/cmake/cmake/-/issues/20871 for details. + # + # CMake 3.28 and above: + # IMPORTED_LOCATION is the absolute path the the OpenGL.framework folder. get_target_property(__opengl_fw_lib_path OpenGL::GL IMPORTED_LOCATION) - if(__opengl_fw_lib_path) + if(__opengl_fw_lib_path AND NOT __opengl_fw_lib_path MATCHES "/([^/]+)\\.framework$") get_filename_component(__opengl_fw_path "${__opengl_fw_lib_path}" DIRECTORY) endif() diff --git a/cmake/QtAppHelpers.cmake b/cmake/QtAppHelpers.cmake index 4be5c7d5..c0ad53ab 100644 --- a/cmake/QtAppHelpers.cmake +++ b/cmake/QtAppHelpers.cmake @@ -53,6 +53,7 @@ function(qt_internal_add_app target) ${arg_NO_UNITY_BUILD} ${forward_install_dir} SOURCES ${arg_SOURCES} + NO_PCH_SOURCES ${arg_NO_PCH_SOURCES} NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES} INCLUDE_DIRECTORIES ${arg_INCLUDE_DIRECTORIES} diff --git a/cmake/QtBaseConfigureTests.cmake b/cmake/QtBaseConfigureTests.cmake index b7929426..b62eec84 100644 --- a/cmake/QtBaseConfigureTests.cmake +++ b/cmake/QtBaseConfigureTests.cmake @@ -115,43 +115,38 @@ endfunction() function(qt_run_linker_version_script_support) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/version_flag.map" "VERS_1 { global: sym; }; -VERS_2 { global: sym; } -VERS_1; -") - if(DEFINED CMAKE_REQUIRED_FLAGS) - set(CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS}) - else() - set(CMAKE_REQUIRED_FLAGS "") - endif() - set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Wl,--version-script=\"${CMAKE_CURRENT_BINARY_DIR}/version_flag.map\"") - - # Pass the linker that the main project uses to the version script compile test. - qt_internal_get_active_linker_flags(linker_flags) - if(linker_flags) - set(CMAKE_REQUIRED_LINK_OPTIONS ${linker_flags}) - endif() - - check_cxx_source_compiles("int main(void){return 0;}" HAVE_LD_VERSION_SCRIPT) - if(DEFINED CMAKE_REQUIRED_FLAGS_SAVE) - set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE}) - endif() - file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map") - # For some reason the linker command line written by the XCode generator, which is # subsequently executed by xcodebuild, ignores the linker flag, and thus the test # seemingly succeeds. Explicitly disable the version script test on darwin platforms. - if(APPLE) - set(HAVE_LD_VERSION_SCRIPT OFF) - endif() # Also makes no sense with MSVC-style command-line - if(MSVC) + if(NOT APPLE AND NOT MSVC) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/version_flag.map" [=[ + VERS_1 { global: sym1; }; + VERS_2 { global: sym2; } VERS_1; + ]=]) + set(CMAKE_REQUIRED_LINK_OPTIONS "") + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS + "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/version_flag.map") + # Pass the linker that the main project uses to the version script compile test. + qt_internal_get_active_linker_flags(linker_flags) + if(linker_flags) + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${linker_flags}) + endif() + check_cxx_source_compiles([=[ + int sym1; + int sym2; + int main(void) { return 0; } + ]=] HAVE_LD_VERSION_SCRIPT) + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/version_flag.map") + else() set(HAVE_LD_VERSION_SCRIPT OFF) endif() - set(TEST_ld_version_script "${HAVE_LD_VERSION_SCRIPT}" CACHE INTERNAL "linker version script support") + set(TEST_ld_version_script "${HAVE_LD_VERSION_SCRIPT}" + CACHE INTERNAL "linker version script support") list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_ld_version_script) - set(QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT ${QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT} CACHE INTERNAL "Test variables that should be exported") + set(QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT ${QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT} + CACHE INTERNAL "Test variables that should be exported") endfunction() function(qt_internal_ensure_latest_win_nt_api) diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index e8d31006..cb5b6736 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -101,7 +101,8 @@ if(MACOS AND QT_IS_MACOS_UNIVERSAL QT_FEATURE_x86intrin) endif() -if(MACOS AND QT_IS_MACOS_UNIVERSAL AND __qt_osx_first_arch STREQUAL "x86_64") +if(MACOS AND QT_IS_MACOS_UNIVERSAL AND + (__qt_osx_first_arch STREQUAL "x86_64" OR __qt_osx_first_arch STREQUAL "x86_64h")) set(QT_FORCE_FEATURE_neon ON CACHE INTERNAL "Force enable neon due to platform requirements.") set(__QtFeature_custom_enabled_cache_variables TEST_subarch_neon @@ -373,6 +374,10 @@ qt_copy_or_install(DIRECTORY cmake/ FILES_MATCHING PATTERN "Find*.cmake" PATTERN "tests" EXCLUDE PATTERN "3rdparty" EXCLUDE + PATTERN "macos" EXCLUDE + PATTERN "ios" EXCLUDE + PATTERN "platforms" EXCLUDE + PATTERN "QtBuildInternals" EXCLUDE ) # In prefix builds we also need to copy the files into the build config directory, so that the @@ -383,6 +388,10 @@ if(QT_WILL_INSTALL) FILES_MATCHING PATTERN "Find*.cmake" PATTERN "tests" EXCLUDE PATTERN "3rdparty" EXCLUDE + PATTERN "macos" EXCLUDE + PATTERN "ios" EXCLUDE + PATTERN "platforms" EXCLUDE + PATTERN "QtBuildInternals" EXCLUDE ) endif() diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 1469abf1..97aa76fe 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -284,21 +284,21 @@ if(WIN32) if(CMAKE_SIZEOF_VOID_P EQUAL 8) list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS WIN64 _WIN64) endif() - if(MSVC) - if (CLANG) + + if(CLANG) + if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" OR MSVC) set(QT_DEFAULT_MKSPEC win32-clang-msvc) - elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + elseif(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU" OR MINGW) + set(QT_DEFAULT_MKSPEC win32-clang-g++) + endif() + elseif(MSVC) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") set(QT_DEFAULT_MKSPEC win32-arm64-msvc) else() set(QT_DEFAULT_MKSPEC win32-msvc) endif() - elseif(CLANG AND MINGW) - set(QT_DEFAULT_MKSPEC win32-clang-g++) elseif(MINGW) set(QT_DEFAULT_MKSPEC win32-g++) - endif() - - if (MINGW) list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS MINGW_HAS_SECURE_API=1) endif() elseif(LINUX) @@ -376,15 +376,23 @@ else() set(QT_QMAKE_HOST_MKSPEC "${QT_QMAKE_TARGET_MKSPEC}") endif() -if(NOT EXISTS "${QT_MKSPECS_DIR}/${QT_QMAKE_TARGET_MKSPEC}") +if(NOT QT_QMAKE_TARGET_MKSPEC OR NOT EXISTS "${QT_MKSPECS_DIR}/${QT_QMAKE_TARGET_MKSPEC}") + if(NOT QT_QMAKE_TARGET_MKSPEC) + set(reason "Platform is not detected. Please make sure your build environment is configured" + " properly or specify it manually using QT_QMAKE_TARGET_MKSPEC variable and one of the" + " known platforms.") + else() + set(reason "Unknown platform ${QT_QMAKE_TARGET_MKSPEC}") + endif() + file(GLOB known_platforms LIST_DIRECTORIES true RELATIVE "${QT_MKSPECS_DIR}" "${QT_MKSPECS_DIR}/*" ) list(JOIN known_platforms "\n " known_platforms) - message(FATAL_ERROR "Unknown platform ${QT_QMAKE_TARGET_MKSPEC}\n\ -Known platforms:\n ${known_platforms}") + message(FATAL_ERROR "${reason}\n" + "Known platforms:\n ${known_platforms}") endif() if(NOT DEFINED QT_DEFAULT_PLATFORM_DEFINITIONS) @@ -459,6 +467,7 @@ set(__default_private_args DISABLE_AUTOGEN_TOOLS ENABLE_AUTOGEN_TOOLS PLUGIN_TYPES + NO_PCH_SOURCES NO_UNITY_BUILD_SOURCES ) set(__default_public_args diff --git a/cmake/QtBuildInformation.cmake b/cmake/QtBuildInformation.cmake index 9d8a11cb..6929f913 100644 --- a/cmake/QtBuildInformation.cmake +++ b/cmake/QtBuildInformation.cmake @@ -109,7 +109,7 @@ from the build directory") set(QT_INTERNAL_BUILD_INSTRUCTIONS_SHOWN "TRUE" CACHE STRING "" FORCE) if(QT_SUPERBUILD) - qt_internal_save_previously_found_packages() + qt_internal_save_previously_visited_packages() endif() endfunction() diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake index 7a69a635..fe4cbe3e 100644 --- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake +++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake @@ -308,24 +308,19 @@ function(qt_build_internals_add_toplevel_targets) endfunction() macro(qt_enable_cmake_languages) - include(CheckLanguage) set(__qt_required_language_list C CXX) - set(__qt_optional_language_list ) + set(__qt_platform_required_language_list ) - # https://gitlab.kitware.com/cmake/cmake/-/issues/20545 if(APPLE) - list(APPEND __qt_optional_language_list OBJC OBJCXX) + list(APPEND __qt_platform_required_language_list OBJC OBJCXX) endif() foreach(__qt_lang ${__qt_required_language_list}) enable_language(${__qt_lang}) endforeach() - foreach(__qt_lang ${__qt_optional_language_list}) - check_language(${__qt_lang}) - if(CMAKE_${__qt_lang}_COMPILER) - enable_language(${__qt_lang}) - endif() + foreach(__qt_lang ${__qt_platform_required_language_list}) + enable_language(${__qt_lang}) endforeach() # The qtbase call is handled in qtbase/CMakeLists.txt. @@ -434,6 +429,12 @@ macro(qt_build_repo_begin) add_custom_target(sync_headers) endif() + # The special target that we use to sync 3rd-party headers before the gn run when building + # qtwebengine in top-level builds. + if(NOT TARGET thirdparty_sync_headers) + add_custom_target(thirdparty_sync_headers) + endif() + # Add global qt_plugins, qpa_plugins and qpa_default_plugins convenience custom targets. # Internal executables will add a dependency on the qpa_default_plugins target, # so that building and running a test ensures it won't fail at runtime due to a missing qpa @@ -562,7 +563,7 @@ macro(qt_build_repo_end) endif() if(NOT QT_SUPERBUILD) - qt_internal_save_previously_found_packages() + qt_internal_save_previously_visited_packages() endif() if(QT_INTERNAL_FRESH_REQUESTED) @@ -1415,3 +1416,13 @@ function(qt_internal_run_common_config_tests) qt_internal_check_cmp0099_available() qt_configure_end_summary_section() endfunction() + +# It is used in QtWebEngine to replace the REALPATH with ABSOLUTE path, which is +# useful for building Qt in Homebrew. +function(qt_internal_get_filename_path_mode out_var) + set(mode REALPATH) + if(APPLE AND QT_ALLOW_SYMLINK_IN_PATHS) + set(mode ABSOLUTE) + endif() + set(${out_var} ${mode} PARENT_SCOPE) +endfunction() diff --git a/cmake/QtCompilerOptimization.cmake b/cmake/QtCompilerOptimization.cmake index b5b49ab7..a093ed4d 100644 --- a/cmake/QtCompilerOptimization.cmake +++ b/cmake/QtCompilerOptimization.cmake @@ -124,5 +124,5 @@ endif() # Emscripten Clang if(WASM) set(QT_CFLAGS_OPTIMIZE_DEBUG "-O2 -g") # -Og is not supported - set(QT_CFLAGS_SSE2 -O2 -msimd128 -msse -msse2) + set(QT_CFLAGS_SSE2 "-O2 -msimd128 -msse -msse2") endif() diff --git a/cmake/QtExecutableHelpers.cmake b/cmake/QtExecutableHelpers.cmake index 8ebcadf3..c863d3f4 100644 --- a/cmake/QtExecutableHelpers.cmake +++ b/cmake/QtExecutableHelpers.cmake @@ -30,6 +30,7 @@ function(qt_internal_add_executable name) endif() _qt_internal_create_executable(${name}) + qt_internal_mark_as_internal_target(${name}) if(ANDROID) _qt_internal_android_executable_finalizer(${name}) endif() @@ -119,6 +120,7 @@ function(qt_internal_add_executable name) qt_internal_extend_target("${name}" ${arg_NO_UNITY_BUILD} SOURCES ${arg_SOURCES} + NO_PCH_SOURCES ${arg_NO_PCH_SOURCES} NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES} INCLUDE_DIRECTORIES ${private_includes} DEFINES ${arg_DEFINES} @@ -369,6 +371,7 @@ function(qt_internal_add_configure_time_executable target) set(target_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/configure_time_bins") if(arg_CONFIG) set(CMAKE_TRY_COMPILE_CONFIGURATION "${arg_CONFIG}") + string(TOUPPER "_${arg_CONFIG}" config_suffix) endif() get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG) @@ -462,6 +465,29 @@ function(qt_internal_add_configure_time_executable target) set(cmake_flags_arg CMAKE_FLAGS "${arg_CMAKE_FLAGS}") endif() configure_file("${template}" "${target_binary_dir}/CMakeLists.txt" @ONLY) + + qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages) + foreach(lang IN LISTS enabled_languages) + set(compiler_flags_var "CMAKE_${lang}_FLAGS") + list(APPEND cmake_flags_arg "-D${compiler_flags_var}:STRING=${${compiler_flags_var}}") + if(arg_CONFIG) + set(compiler_flags_var_config "${compiler_flags_var}${config_suffix}") + list(APPEND cmake_flags_arg + "-D${compiler_flags_var_config}:STRING=${${compiler_flags_var_config}}") + endif() + endforeach() + + qt_internal_get_target_link_types_for_flag_manipulation(target_link_types) + foreach(linker_type IN LISTS target_link_types) + set(linker_flags_var "CMAKE_${linker_type}_LINKER_FLAGS") + list(APPEND cmake_flags_arg "-D${linker_flags_var}:STRING=${${linker_flags_var}}") + if(arg_CONFIG) + set(linker_flags_var_config "${linker_flags_var}${config_suffix}") + list(APPEND cmake_flags_arg + "-D${linker_flags_var_config}:STRING=${${linker_flags_var_config}}") + endif() + endforeach() + try_compile(result "${target_binary_dir}" "${target_binary_dir}" diff --git a/cmake/QtFindPackageHelpers.cmake b/cmake/QtFindPackageHelpers.cmake index 407e41b8..15651b31 100644 --- a/cmake/QtFindPackageHelpers.cmake +++ b/cmake/QtFindPackageHelpers.cmake @@ -41,10 +41,13 @@ macro(qt_find_package) # Due to this behavior being different from what general CMake projects expect, it is only # done for -developer-builds. if(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES AND - NOT "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES) + NOT "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES + AND "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES) set(_qt_find_package_skip_find_package TRUE) endif() + set_property(GLOBAL APPEND PROPERTY _qt_previously_searched_packages "${ARGV0}") + if(QT_DEBUG_QT_FIND_PACKAGE AND ${ARGV0}_FOUND AND arg_PROVIDED_TARGETS) set(_qt_find_package_skip_find_package TRUE) foreach(qt_find_package_target_name ${arg_PROVIDED_TARGETS}) @@ -221,7 +224,7 @@ endmacro() # Only applies to -developer-builds by default. # Can also be opted in or opted out via QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES. # Opting out will need two reconfigurations to take effect. -function(qt_internal_save_previously_found_packages) +function(qt_internal_save_previously_visited_packages) if(DEFINED QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES) set(should_save "${QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES}") else() @@ -235,6 +238,7 @@ function(qt_internal_save_previously_found_packages) if(NOT should_save) # When the value is flipped to OFF, remove any previously saved packages. unset(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES CACHE) + unset(QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES CACHE) return() endif() @@ -244,6 +248,15 @@ function(qt_internal_save_previously_found_packages) set(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES "${_qt_previously_found_packages}" CACHE INTERNAL "List of CMake packages found during configuration using qt_find_package.") endif() + + get_property(_qt_previously_searched_packages GLOBAL PROPERTY _qt_previously_searched_packages) + if(_qt_previously_searched_packages) + list(REMOVE_DUPLICATES _qt_previously_searched_packages) + set(QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES + "${_qt_previously_searched_packages}" CACHE INTERNAL + "List of CMake packages searched during configuration using qt_find_package." + ) + endif() endfunction() # Return qmake library name for the given target, e.g. return "vulkan" for "Vulkan::Vulkan". diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake index d8597326..4ef1bd78 100644 --- a/cmake/QtFlagHandlingHelpers.cmake +++ b/cmake/QtFlagHandlingHelpers.cmake @@ -33,22 +33,15 @@ function(qt_internal_add_linker_version_script target) endif() string(APPEND contents "};\n") set(current "Qt_${PROJECT_VERSION_MAJOR}") - if (QT_NAMESPACE STREQUAL "") - set(tag_symbol "qt_version_tag") - else() - set(tag_symbol "qt_version_tag_${QT_NAMESPACE}") - endif() string(APPEND contents "${current} { *; };\n") - foreach(minor_version RANGE ${PROJECT_VERSION_MINOR}) - set(previous "${current}") - set(current "Qt_${PROJECT_VERSION_MAJOR}.${minor_version}") - if (minor_version EQUAL ${PROJECT_VERSION_MINOR}) - string(APPEND contents "${current} { ${tag_symbol}; } ${previous};\n") - else() - string(APPEND contents "${current} {} ${previous};\n") - endif() - endforeach() + get_target_property(type ${target} TYPE) + if(NOT target_type STREQUAL "INTERFACE_LIBRARY") + set(property_genex "$") + set(check_genex "$") + string(APPEND contents + "$<${check_genex}:${property_genex}>") + endif() set(infile "${CMAKE_CURRENT_BINARY_DIR}/${target}.version.in") set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${target}.version") @@ -87,6 +80,11 @@ function(qt_internal_add_link_flags_no_undefined target) if (NOT QT_BUILD_SHARED_LIBS OR WASM) return() endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + # ld64 defaults to -undefined,error, and in Xcode 15 + # passing this option is deprecated, causing a warning. + return() + endif() if ((GCC OR CLANG) AND NOT MSVC) if(CLANG AND QT_FEATURE_sanitizer) return() @@ -124,11 +122,20 @@ endfunction() function(qt_internal_apply_gc_binaries target visibility) set(possible_visibilities PRIVATE INTERFACE PUBLIC) - list(FIND possible_visibilities "${visibility}" known_visibility) - if (known_visibility EQUAL "-1") + if(NOT visibility IN_LIST possible_visibilities) message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.") endif() + string(JOIN "" clang_or_gcc_begin + "$<$," + "$," + "$," + "$" + ">:" + ) + set(clang_or_gcc_end ">") + if ((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC) if(APPLE) set(gc_sections_flag "-Wl,-dead_strip") @@ -137,16 +144,26 @@ function(qt_internal_apply_gc_binaries target visibility) elseif(LINUX OR BSD OR WIN32 OR ANDROID) set(gc_sections_flag "-Wl,--gc-sections") endif() + + # Save the flag value with and without genex wrapping, so we can remove the wrapping + # when generating .pc pkgconfig files. + set_property(GLOBAL PROPERTY _qt_internal_gc_sections_without_genex "${gc_sections_flag}") + + set(gc_sections_flag + "${clang_or_gcc_begin}${gc_sections_flag}${clang_or_gcc_end}") + + set_property(GLOBAL PROPERTY _qt_internal_gc_sections_with_genex "${gc_sections_flag}") endif() if(gc_sections_flag) target_link_options("${target}" ${visibility} "${gc_sections_flag}") endif() if((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC) - set(split_sections_flags "-ffunction-sections" "-fdata-sections") + set(split_sections_flags + "${clang_or_gcc_begin}-ffunction-sections;-fdata-sections${clang_or_gcc_end}") endif() if(split_sections_flags) - target_compile_options("${target}" ${visibility} ${split_sections_flags}) + target_compile_options("${target}" ${visibility} "${split_sections_flags}") endif() endfunction() @@ -156,13 +173,17 @@ function(qt_internal_apply_intel_cet target visibility) endif() set(possible_visibilities PRIVATE INTERFACE PUBLIC) - list(FIND possible_visibilities "${visibility}" known_visibility) - if (known_visibility EQUAL "-1") + if(NOT visibility IN_LIST possible_visibilities) message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.") endif() if(GCC) - set(flags "-mshstk") + string(JOIN "" flags + "$<$," + "$," + "$" + ">:-mshstk>") endif() if(flags) target_compile_options("${target}" ${visibility} "${flags}") @@ -287,14 +308,15 @@ function(qt_set_msvc_cplusplus_options target visibility) # Check qt_config_compile_test for more info. if(MSVC AND MSVC_VERSION GREATER_EQUAL 1913) set(flags "-Zc:__cplusplus" "-permissive-") - target_compile_options("${target}" ${visibility} "$<$:${flags}>") + target_compile_options("${target}" ${visibility} + "$<$,$>:${flags}>") endif() endfunction() function(qt_enable_utf8_sources target) set(utf8_flags "") if(MSVC) - list(APPEND utf8_flags "-utf-8") + list(APPEND utf8_flags "$<$:-utf-8>") endif() if(utf8_flags) @@ -557,12 +579,20 @@ endfunction() # Removes specified flags from CMAKE__FLAGS[_CONFIGS] variables # -# IN_CACHE enables flags removal from CACHE -# CONFIGS list of configurations that need to clear flags. Clears all configs by default if not -# specified. -# LANGUAGES list of LANGUAGES that need clear flags. Clears all languages by default if not -# specified. -# REGEX enables the flag processing as a regular expression. +# Option Arguments: +# IN_CACHE +# Enables flags removal from CACHE +# REGEX +# Enables the flag processing as a regular expression. +# +# Multi-value Arguments: +# CONFIGS +# List of configurations that need to clear flags. Clears all configs by default if not +# specified. +# +# LANGUAGES +# List of LANGUAGES that need clear flags. Clears all languages by default if not +# specified. function(qt_internal_remove_compiler_flags flags) cmake_parse_arguments(PARSE_ARGV 1 arg "IN_CACHE;REGEX" @@ -585,8 +615,7 @@ function(qt_internal_remove_compiler_flags flags) if(arg_CONFIGS) set(configs "${arg_CONFIGS}") else() - message(FATAL_ERROR - "You must specify at least one configuration for which to remove the flags.") + qt_internal_get_configs_for_flag_manipulation(configs) endif() if(arg_REGEX) @@ -992,14 +1021,42 @@ function(qt_internal_set_up_config_optimizations_like_in_qmake) IN_CACHE) endif() + # Legacy Android toolchain file adds the `-g` flag to CMAKE__FLAGS, as a + # result, our release build ends up containing debug symbols. To avoid that, we + # remove the flag from CMAKE__FLAGS and add + # it to CMAKE__FLAGS_DEBUG. + # + # Note: + # The new `android.toolchain.cmake` file does not have this problem, but + # it has other issues, eg., https://github.com/android/ndk/issues/1693, so we + # cannot force it. While we do load the new toolchain, it automatically falls + # back to the legacy toolchain, ie., `android-legacy.toolchain.cmake` which + # has the problem described above. + # + # Todo: + # When the new toolchain is fixed, and it doesn't fall back to the legacy + # anymore by default, then we should be able to remove this workaround. + if(ANDROID AND ANDROID_COMPILER_FLAGS MATCHES "(^| )-g") + qt_internal_remove_compiler_flags("-g") + qt_internal_add_compiler_flags(FLAGS "-g" CONFIGS DEBUG RELWITHDEBINFO) + endif() + # Update all relevant flags in the calling scope - foreach(config ${configs}) - foreach(lang ${enabled_languages}) + foreach(lang ${enabled_languages}) + set(flag_var_name "CMAKE_${lang}_FLAGS") + set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE) + + foreach(config ${configs}) set(flag_var_name "CMAKE_${lang}_FLAGS_${config}") set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE) endforeach() + endforeach() - foreach(t ${target_link_types}) + foreach(t ${target_link_types}) + set(flag_var_name "CMAKE_${t}_LINKER_FLAGS") + set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE) + + foreach(config ${configs}) set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}") set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE) endforeach() diff --git a/cmake/QtHeadersClean.cmake b/cmake/QtHeadersClean.cmake index 497c3f29..d04a80d9 100644 --- a/cmake/QtHeadersClean.cmake +++ b/cmake/QtHeadersClean.cmake @@ -185,6 +185,9 @@ function(qt_internal_add_headersclean_target module_target module_headers) # and violate the standards. set(hcleanFLAGS -std:c++latest -Zc:__cplusplus -WX -W3) + # Because we now add `-DNOMINMAX` to `PlatformCommonInternal`. + set(hcleanUDEFS -UNOMINMAX) + # cl.exe needs a source path get_filename_component(source_path "${QT_MKSPECS_DIR}/features/data/dummy.cpp" REALPATH) @@ -195,6 +198,7 @@ function(qt_internal_add_headersclean_target module_target module_headers) "${hcleanFLAGS}" "${target_includes_joined_genex}" "${hcleanDEFS}" + "${hcleanUDEFS}" ) string(JOIN " " compiler_command_line_variables "-FI" @@ -227,7 +231,7 @@ function(qt_internal_add_headersclean_target module_target module_headers) file(GENERATE OUTPUT "${headers_check_parameters}" CONTENT "${headers_check_parameters_content}") - set(sync_headers_dep "sync_headers") + set(sync_headers_dep "${module_target}_sync_headers") foreach(header ${hclean_headers}) # We need realpath here to make sure path starts with drive letter diff --git a/cmake/QtInternalTargets.cmake b/cmake/QtInternalTargets.cmake index ff906e94..b5831659 100644 --- a/cmake/QtInternalTargets.cmake +++ b/cmake/QtInternalTargets.cmake @@ -102,7 +102,7 @@ function(qt_internal_add_global_definition definition) set(optional_args) set(single_value_args VALUE) set(multi_value_args SCOPE) - cmake_parse_arguments(args + cmake_parse_arguments(arg "${optional_args}" "${single_value_args}" "${multi_value_args}" @@ -168,6 +168,8 @@ if(WIN32) # Needed for M_PI define. Same as mkspecs/features/qt_module.prf. # It's set for every module being built, but it's not propagated to user apps. target_compile_definitions(PlatformModuleInternal INTERFACE _USE_MATH_DEFINES) + # Not disabling min/max macros may result in unintended substitutions of std::min/max + target_compile_definitions(PlatformCommonInternal INTERFACE NOMINMAX) endif() if(FEATURE_largefile AND UNIX) target_compile_definitions(PlatformCommonInternal @@ -205,6 +207,14 @@ function(qt_internal_apply_bitcode_flags target) target_compile_options("${target}" INTERFACE ${bitcode_flags}) endfunction() +# Function guards linker options that are applicable for internal Qt targets only from propagating +# them to user projects. +function(qt_internal_platform_link_options target scope) + set(options ${ARGN}) + set(is_internal_target_genex "$>") + target_link_options(${target} ${scope} "$<${is_internal_target_genex}:${options}>") +endfunction() + # Apple deprecated the entire OpenGL API in favor of Metal, which # we are aware of, so silence the deprecation warnings in code. # This does not apply to user-code, which will need to silence @@ -283,7 +293,7 @@ if (MSVC) $<$>:-guard:cf -Gw> ) - target_link_options(PlatformCommonInternal INTERFACE + qt_internal_platform_link_options(PlatformCommonInternal INTERFACE -DYNAMICBASE -NXCOMPAT -LARGEADDRESSAWARE $<$>:-OPT:REF -OPT:ICF -GUARD:CF> ) @@ -299,7 +309,7 @@ endif() if(QT_FEATURE_intelcet) if(MSVC) - target_link_options(PlatformCommonInternal INTERFACE + qt_internal_platform_link_options(PlatformCommonInternal INTERFACE -CETCOMPAT ) else() @@ -328,30 +338,31 @@ endif() if(DEFINED QT_EXTRA_FRAMEWORKPATHS AND APPLE) list(TRANSFORM QT_EXTRA_FRAMEWORKPATHS PREPEND "-F" OUTPUT_VARIABLE __qt_fw_flags) target_compile_options(PlatformCommonInternal INTERFACE ${__qt_fw_flags}) - target_link_options(PlatformCommonInternal INTERFACE ${__qt_fw_flags}) + qt_internal_platform_link_options(PlatformCommonInternal INTERFACE ${__qt_fw_flags}) unset(__qt_fw_flags) endif() qt_internal_get_active_linker_flags(__qt_internal_active_linker_flags) if(__qt_internal_active_linker_flags) - target_link_options(PlatformCommonInternal INTERFACE "${__qt_internal_active_linker_flags}") + qt_internal_platform_link_options(PlatformCommonInternal INTERFACE + "${__qt_internal_active_linker_flags}") endif() unset(__qt_internal_active_linker_flags) if(QT_FEATURE_enable_gdb_index) - target_link_options(PlatformCommonInternal INTERFACE "-Wl,--gdb-index") + qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,--gdb-index") endif() if(QT_FEATURE_enable_new_dtags) - target_link_options(PlatformCommonInternal INTERFACE "-Wl,--enable-new-dtags") + qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,--enable-new-dtags") endif() function(qt_get_implicit_sse2_genex_condition out_var) set(is_shared_lib "$,SHARED_LIBRARY>") set(is_static_lib "$,STATIC_LIBRARY>") set(is_static_qt_build "$>") - set(is_staitc_lib_during_static_qt_build "$") - set(enable_sse2_condition "$") + set(is_static_lib_during_static_qt_build "$") + set(enable_sse2_condition "$") set(${out_var} "${enable_sse2_condition}" PARENT_SCOPE) endfunction() diff --git a/cmake/QtJavaHelpers.cmake b/cmake/QtJavaHelpers.cmake index edf4f54b..5aeffe1f 100644 --- a/cmake/QtJavaHelpers.cmake +++ b/cmake/QtJavaHelpers.cmake @@ -4,6 +4,10 @@ # This function can be used to compile java sources into a jar package. function(qt_internal_add_jar target) + set(options) + set(oneValueArgs OUTPUT_DIR) + set(multiValueArgs INCLUDE_JARS SOURCES) + cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) set(javac_target_version "${QT_ANDROID_JAVAC_TARGET}") if (NOT javac_target_version) @@ -18,4 +22,8 @@ function(qt_internal_add_jar target) set(CMAKE_JAVA_COMPILE_FLAGS -source "${javac_source_version}" -target "${javac_target_version}" -Xlint:unchecked -bootclasspath "${QT_ANDROID_JAR}") add_jar(${ARGV}) + foreach(f IN LISTS arg_SOURCES) + _qt_internal_expose_source_file_to_ide(${target} "${f}") + endforeach() + endfunction() diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index 41e0680e..0b42991e 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -37,7 +37,6 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi QMAKE_MODULE_CONFIG EXTRA_CMAKE_FILES EXTRA_CMAKE_INCLUDES - NO_PCH_SOURCES EXTERNAL_HEADERS POLICIES ${__default_private_args} @@ -447,6 +446,8 @@ function(qt_internal_add_module target) # If EXTERNAL_HEADERS_DIR is set we install the specified directory and keep the structure # without taking into the account the CMake source tree and syncqt outputs. if(arg_EXTERNAL_HEADERS_DIR) + set_property(TARGET ${target} + PROPERTY _qt_external_headers_dir "${arg_EXTERNAL_HEADERS_DIR}") qt_install(DIRECTORY "${arg_EXTERNAL_HEADERS_DIR}/" DESTINATION "${module_install_interface_include_dir}" ) @@ -1186,10 +1187,13 @@ function(qt_internal_collect_module_headers out_var target) get_target_property(target_type ${target} TYPE) if(target_type STREQUAL "INTERFACE_LIBRARY") set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}") + set(binary_dir "${CMAKE_CURRENT_BINARY_DIR}") else() get_target_property(source_dir ${target} SOURCE_DIR) + get_target_property(binary_dir ${target} BINARY_DIR) endif() get_filename_component(source_dir "${source_dir}" ABSOLUTE) + get_filename_component(binary_dir "${binary_dir}" ABSOLUTE) get_target_property(is_3rdparty_library ${target} _qt_module_is_3rdparty_header_library) @@ -1232,7 +1236,14 @@ function(qt_internal_collect_module_headers out_var target) "\nCondition:\n ${condition_string}") endif() - if(file_path MATCHES "3rdparty/.+" AND NOT is_3rdparty_library) + if(is_outside_module_source_dir) + set(base_dir "${binary_dir}") + else() + set(base_dir "${source_dir}") + endif() + + file(RELATIVE_PATH file_path_rel "${base_dir}" "${file_path}") + if(file_path_rel MATCHES "3rdparty/.+" AND NOT is_3rdparty_library) set(is_3rdparty_header TRUE) else() set(is_3rdparty_header FALSE) diff --git a/cmake/QtPkgConfigHelpers.cmake b/cmake/QtPkgConfigHelpers.cmake index 370ff607..dbe736c4 100644 --- a/cmake/QtPkgConfigHelpers.cmake +++ b/cmake/QtPkgConfigHelpers.cmake @@ -51,6 +51,17 @@ function(qt_internal_generate_pkg_config_file module) list(TRANSFORM loose_include_dirs REPLACE "${INSTALL_INCLUDEDIR}" "\${includedir}") list(TRANSFORM loose_include_dirs REPLACE "${INSTALL_MKSPECSDIR}" "\${mkspecsdir}") + # Remove genex wrapping around gc_sections flag because we can't evaluate genexes like + # $ in file(GENERATE). And given that .pc files don't support dynamic + # evaluation like the $ genex, distros will be expected to patch the .pc + # files according to which compiler they intend to be used with. + get_property(gc_sections_with_genex GLOBAL PROPERTY _qt_internal_gc_sections_with_genex) + get_property(gc_sections_without_genex GLOBAL PROPERTY _qt_internal_gc_sections_without_genex) + if(loose_link_options AND gc_sections_with_genex AND gc_sections_without_genex) + string(REPLACE "${gc_sections_with_genex}" "${gc_sections_without_genex}" + loose_link_options "${loose_link_options}") + endif() + qt_internal_set_pkg_config_cpp_flags(link_options "${loose_link_options}" "") qt_internal_set_pkg_config_cpp_flags(compile_defs "${loose_compile_defs}" -D) qt_internal_set_pkg_config_cpp_flags(include_dirs "${loose_include_dirs}" -I) diff --git a/cmake/QtPluginHelpers.cmake b/cmake/QtPluginHelpers.cmake index b4aaffb8..2db9d462 100644 --- a/cmake/QtPluginHelpers.cmake +++ b/cmake/QtPluginHelpers.cmake @@ -336,6 +336,8 @@ function(qt_internal_add_plugin target) qt_internal_extend_target("${target}" ${arg_NO_UNITY_BUILD} SOURCES ${arg_SOURCES} + NO_PCH_SOURCES + ${arg_NO_PCH_SOURCES} NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES} INCLUDE_DIRECTORIES diff --git a/cmake/QtPriHelpers.cmake b/cmake/QtPriHelpers.cmake index c619a50f..f1d45cdc 100644 --- a/cmake/QtPriHelpers.cmake +++ b/cmake/QtPriHelpers.cmake @@ -26,9 +26,14 @@ function(qt_generate_qmake_libraries_pri_content module_name output_root_dir out set(lib_incdir "") set(lib_libdir "") set(lib_libs "") + set(seen_targets "") while(lib_targets) list(POP_BACK lib_targets lib_target) if(TARGET ${lib_target}) + if(${lib_target} IN_LIST seen_targets) + continue() + endif() + list(APPEND seen_targets ${lib_target}) get_target_property(lib_target_type ${lib_target} TYPE) if(lib_target_type STREQUAL "INTERFACE_LIBRARY") get_target_property(iface_libs ${lib_target} INTERFACE_LINK_LIBRARIES) diff --git a/cmake/QtProcessConfigureArgs.cmake b/cmake/QtProcessConfigureArgs.cmake index 8fa4be2a..85f5b714 100644 --- a/cmake/QtProcessConfigureArgs.cmake +++ b/cmake/QtProcessConfigureArgs.cmake @@ -55,7 +55,10 @@ if("${MODULE_ROOT}" STREQUAL "") set(qtbase_or_top_level_build TRUE) else() # If MODULE_ROOT is passed without drive letter, we try to add it to the path. - get_filename_component(MODULE_ROOT "." REALPATH BASE_DIR "${MODULE_ROOT}") + # The check is necessary; otherwise, `get_filename_component` returns an empty string. + if(NOT MODULE_ROOT STREQUAL ".") + get_filename_component(MODULE_ROOT "." REALPATH BASE_DIR "${MODULE_ROOT}") + endif() set(qtbase_or_top_level_build FALSE) endif() set(configure_filename "configure.cmake") @@ -136,13 +139,6 @@ while(NOT "${configure_args}" STREQUAL "") list(POP_FRONT configure_args version) is_valid_qt_hex_version("${arg}" "${version}") push("-DQT_DISABLE_DEPRECATED_UP_TO=${version}") - elseif(arg STREQUAL "-unity-build") - push("-DQT_UNITY_BUILD=ON") - # QT_UNITY_BUILD_BATCH_SIZE will be set to 8, CMake's default. - elseif(arg STREQUAL "-unity-build-batch-size") - list(POP_FRONT configure_args unity_build_batch_size) - is_non_empty_valid_arg("${arg}" "${unity_build_batch_size}") - push("-DQT_UNITY_BUILD_BATCH_SIZE=${unity_build_batch_size}") elseif(arg STREQUAL "--") # Everything after this argument will be passed to CMake verbatim. list(APPEND cmake_args "${configure_args}") @@ -827,6 +823,8 @@ endfunction() drop_input(commercial) drop_input(confirm-license) translate_boolean_input(precompile_header BUILD_WITH_PCH) +translate_boolean_input(unity_build QT_UNITY_BUILD) +translate_string_input(unity_build_batch_size QT_UNITY_BUILD_BATCH_SIZE) translate_boolean_input(ccache QT_USE_CCACHE) translate_boolean_input(shared BUILD_SHARED_LIBS) translate_boolean_input(warnings_are_errors WARNINGS_ARE_ERRORS) diff --git a/cmake/QtPublicAppleHelpers.cmake b/cmake/QtPublicAppleHelpers.cmake index b60ef5e4..1d489f09 100644 --- a/cmake/QtPublicAppleHelpers.cmake +++ b/cmake/QtPublicAppleHelpers.cmake @@ -221,7 +221,7 @@ function(_qt_internal_find_ios_development_team_id out_var) endif() endfunction() -function(_qt_internal_get_ios_bundle_identifier_prefix out_var) +function(_qt_internal_get_apple_bundle_identifier_prefix out_var) get_property(prefix GLOBAL PROPERTY _qt_internal_ios_bundle_identifier_prefix) get_property(prefix_computed GLOBAL PROPERTY _qt_internal_ios_bundle_identifier_prefix_computed) @@ -269,8 +269,8 @@ function(_qt_internal_escape_rfc_1034_identifier value out_var) set("${out_var}" "${value}" PARENT_SCOPE) endfunction() -function(_qt_internal_get_default_ios_bundle_identifier out_var) - _qt_internal_get_ios_bundle_identifier_prefix(prefix) +function(_qt_internal_get_default_apple_bundle_identifier target out_var) + _qt_internal_get_apple_bundle_identifier_prefix(prefix) if(NOT prefix) set(prefix "com.yourcompany") @@ -281,14 +281,16 @@ function(_qt_internal_get_default_ios_bundle_identifier out_var) string(SHA1 hash "${team_id}") string(SUBSTRING "${hash}" 0 8 infix) string(APPEND prefix ".${infix}") - else() + endif() + + if(CMAKE_GENERATOR STREQUAL "Xcode") message(WARNING - "No organization bundle identifier prefix could be retrieved from Xcode " - "preferences. This can lead to code signing issues due to a non-unique bundle " - "identifier. Please set up an organization prefix by creating a new project within " - "Xcode, or consider providing a custom bundle identifier by specifying the " - "XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER property." - ) + "No organization bundle identifier prefix could be retrieved from Xcode preferences. \ + This can lead to code signing issues due to a non-unique bundle \ + identifier. Please set up an organization prefix by creating a new project within \ + Xcode, or consider providing a custom bundle identifier by specifying the \ + MACOSX_BUNDLE_GUI_IDENTIFIER or XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER property." + ) endif() endif() @@ -299,7 +301,12 @@ function(_qt_internal_get_default_ios_bundle_identifier out_var) # that the identifier is invalid. _qt_internal_escape_rfc_1034_identifier("${prefix}" prefix) - set(identifier "${prefix}.\${PRODUCT_NAME:rfc1034identifier}") + if(CMAKE_GENERATOR STREQUAL "Xcode") + set(identifier "${prefix}.$(PRODUCT_NAME:rfc1034identifier)") + else() + set(identifier "${prefix}.${target}") + endif() + set("${out_var}" "${identifier}" PARENT_SCOPE) endfunction() @@ -384,56 +391,72 @@ function(_qt_internal_set_xcode_development_team_id target) endif() endfunction() -function(_qt_internal_set_xcode_bundle_identifier target) +function(_qt_internal_set_apple_bundle_identifier target) # Skip all logic if requested. if(QT_NO_SET_XCODE_BUNDLE_IDENTIFIER) return() endif() - # There are two fields to consider: the CFBundleIdentifier key (CFBI) to be written to - # Info.plist - # and the PRODUCT_BUNDLE_IDENTIFIER (PBI) property to set in the Xcode project. - # The following logic enables the best out-of-the-box experience combined with maximum - # customization. - # 1) If values for both fields are not provided, assign ${PRODUCT_BUNDLE_IDENTIFIER} to CFBI - # (which is expanded by xcodebuild at build time and will use the value of PBI) and - # auto-compute a default PBI from Xcode's ${PRODUCT_NAME}. - # 2) If CFBI is set and PBI isn't, use given CFBI and keep PBI empty. - # 3) If PBI is set and CFBI isn't, assign ${PRODUCT_BUNDLE_IDENTIFIER} to CFBI and use - # the given PBI. - # 4) If both are set, use both given values. - # TLDR: - # cfbi pbi -> result_cfbi result_pbi - # unset unset computed computed - # set unset given_val unset - # unset set computed given_val - # set set given_val given_val + # There are two fields to consider: the CFBundleIdentifier key (ie., cmake_bundle_identifier) + # to be written to Info.plist and the PRODUCT_BUNDLE_IDENTIFIER (ie., xcode_bundle_identifier) + # property to set in the Xcode project. The `cmake_bundle_identifier` set by + # MACOSX_BUNDLE_GUI_IDENTIFIER applies to both Xcode, and other generators, while + # `xcode_bundle_identifier` set by XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER is + # Xcode specific. + # + # If Ninja is the generator, we set the value of `MACOSX_BUNDLE_GUI_IDENTIFIER` + # and don't touch the `XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER`. + # If Xcode is the generator, we set the value of `XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER`, + # and additionally, to silence a Xcode's warning, we set the `MACOSX_BUNDLE_GUI_IDENTIFIER` to + # `${PRODUCT_BUNDLE_IDENTIFIER}` so that Xcode could sort it out. - get_target_property(existing_cfbi "${target}" MACOSX_BUNDLE_GUI_IDENTIFIER) - if(NOT MACOSX_BUNDLE_GUI_IDENTIFIER AND NOT existing_cfbi) - set(is_cfbi_given FALSE) - else() - set(is_cfbi_given TRUE) + get_target_property(existing_cmake_bundle_identifier "${target}" + MACOSX_BUNDLE_GUI_IDENTIFIER) + get_target_property(existing_xcode_bundle_identifier "${target}" + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER) + + set(is_cmake_bundle_identifier_given FALSE) + if(existing_cmake_bundle_identifier) + set(is_cmake_bundle_identifier_given TRUE) + elseif(MACOSX_BUNDLE_GUI_IDENTIFIER) + set(is_cmake_bundle_identifier_given TRUE) + set(existing_cmake_bundle_identifier ${MACOSX_BUNDLE_GUI_IDENTIFIER}) endif() - if(NOT is_cfbi_given) + set(is_xcode_bundle_identifier_given FALSE) + if(existing_xcode_bundle_identifier) + set(is_xcode_bundle_identifier_given TRUE) + elseif(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER) + set(is_xcode_bundle_identifier_given TRUE) + set(existing_xcode_bundle_identifier ${CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER}) + endif() + + if(is_cmake_bundle_identifier_given + AND is_xcode_bundle_identifier_given + AND NOT existing_cmake_bundle_identifier STREQUAL existing_xcode_bundle_identifier) + message(WARNING + "MACOSX_BUNDLE_GUI_IDENTIFIER and XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER " + "are set to different values. You only need to set one of them. ") + endif() + + if(NOT is_xcode_bundle_identifier_given + AND NOT is_cmake_bundle_identifier_given) + _qt_internal_get_default_apple_bundle_identifier("${target}" bundle_id) + elseif(is_cmake_bundle_identifier_given) + set(bundle_id ${existing_cmake_bundle_identifier}) + elseif(is_xcode_bundle_identifier_given) + set(bundle_id ${existing_xcode_bundle_identifier}) + endif() + + if(CMAKE_GENERATOR STREQUAL "Xcode") set_target_properties("${target}" PROPERTIES - MACOSX_BUNDLE_GUI_IDENTIFIER "\${PRODUCT_BUNDLE_IDENTIFIER}") - endif() - - get_target_property(existing_pbi "${target}" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER) - if(NOT CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER AND NOT existing_pbi) - set(is_pbi_given FALSE) + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${bundle_id}" + MACOSX_BUNDLE_GUI_IDENTIFIER "$(PRODUCT_BUNDLE_IDENTIFIER)") else() - set(is_pbi_given TRUE) - endif() - - if(NOT is_pbi_given AND NOT is_cfbi_given) - _qt_internal_get_default_ios_bundle_identifier(bundle_id) set_target_properties("${target}" PROPERTIES - XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${bundle_id}") + MACOSX_BUNDLE_GUI_IDENTIFIER "${bundle_id}") endif() endfunction() @@ -503,7 +526,7 @@ function(_qt_internal_set_xcode_bundle_name target) if(CMAKE_GENERATOR STREQUAL Xcode) set_target_properties("${target}" PROPERTIES - MACOSX_BUNDLE_BUNDLE_NAME "\${PRODUCT_NAME}") + MACOSX_BUNDLE_BUNDLE_NAME "$(PRODUCT_NAME)") else() set_target_properties("${target}" PROPERTIES @@ -603,12 +626,13 @@ function(_qt_internal_finalize_apple_app target) # This affects things like the version number or application name as reported by Qt API. if(CMAKE_GENERATOR STREQUAL "Xcode") _qt_internal_set_xcode_development_team_id("${target}") - _qt_internal_set_xcode_bundle_identifier("${target}") _qt_internal_set_xcode_code_sign_style("${target}") _qt_internal_set_xcode_bundle_display_name("${target}") _qt_internal_set_xcode_install_path("${target}") endif() + _qt_internal_set_xcode_bundle_name("${target}") + _qt_internal_set_apple_bundle_identifier("${target}") _qt_internal_set_placeholder_apple_bundle_version("${target}") endfunction() diff --git a/cmake/QtPublicTargetHelpers.cmake b/cmake/QtPublicTargetHelpers.cmake index 6f0d3bb2..df9e87db 100644 --- a/cmake/QtPublicTargetHelpers.cmake +++ b/cmake/QtPublicTargetHelpers.cmake @@ -307,7 +307,17 @@ function(_qt_internal_set_up_static_runtime_library target) set_property(TARGET ${target} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") elseif(MINGW) - target_link_options(${target} INTERFACE "LINKER:-Bstatic") + get_target_property(target_type ${target} TYPE) + if(target_type STREQUAL "EXECUTABLE") + set(link_option PRIVATE) + else() + set(link_option INTERFACE) + endif() + if(CLANG) + target_link_options(${target} ${link_option} "LINKER:-Bstatic") + else() + target_link_options(${target} ${link_option} "-static") + endif() endif() endif() endfunction() diff --git a/cmake/QtRpathHelpers.cmake b/cmake/QtRpathHelpers.cmake index 2150b95e..7228ffbb 100644 --- a/cmake/QtRpathHelpers.cmake +++ b/cmake/QtRpathHelpers.cmake @@ -6,7 +6,7 @@ function(qt_internal_get_relative_rpath_base_token out_var) if(APPLE) set(rpath_rel_base "@loader_path") - elseif(LINUX OR SOLARIS OR FREEBSD OR HURD) + elseif(LINUX OR SOLARIS OR FREEBSD OR HURD OR OPENBSD) set(rpath_rel_base "$ORIGIN") else() set(rpath_rel_base "NO_KNOWN_RPATH_REL_BASE") diff --git a/cmake/QtSeparateDebugInfo.cmake b/cmake/QtSeparateDebugInfo.cmake index ff225ad5..5b263585 100644 --- a/cmake/QtSeparateDebugInfo.cmake +++ b/cmake/QtSeparateDebugInfo.cmake @@ -201,7 +201,11 @@ endfunction() # Enable separate debug information for the given target function(qt_enable_separate_debug_info target installDestination) set(flags QT_EXECUTABLE) - set(options) + if(APPLE) + set(options DSYM_OUTPUT_DIR) + else() + set(options) + endif() set(multiopts ADDITIONAL_INSTALL_ARGS) cmake_parse_arguments(arg "${flags}" "${options}" "${multiopts}" ${ARGN}) @@ -248,12 +252,20 @@ function(qt_enable_separate_debug_info target installDestination) get_target_property(is_framework ${target} FRAMEWORK) if(is_framework) qt_internal_get_framework_info(fw ${target}) - set(debug_info_bundle_dir "$.${debug_info_suffix}") set(BUNDLE_ID ${fw_name}) else() - set(debug_info_bundle_dir "$.${debug_info_suffix}") set(BUNDLE_ID ${target}) endif() + + if (NOT "x${arg_DSYM_OUTPUT_DIR}" STREQUAL "x") + set(debug_info_bundle_dir "${arg_DSYM_OUTPUT_DIR}/${target}") + elseif(is_framework) + set(debug_info_bundle_dir "$") + else() + set(debug_info_bundle_dir "$") + endif() + set(debug_info_bundle_dir "${debug_info_bundle_dir}.${debug_info_suffix}") + set(debug_info_contents_dir "${debug_info_bundle_dir}/Contents") set(debug_info_target_dir "${debug_info_contents_dir}/Resources/DWARF") configure_file( diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake index 90acbae5..c8209840 100644 --- a/cmake/QtSetup.cmake +++ b/cmake/QtSetup.cmake @@ -5,8 +5,8 @@ # Set the QT_IS_BUILDING_QT variable so we can verify whether we are building # Qt from source -set(QT_BUILDING_QT TRUE CACHE - TYPE STRING "When this is present and set to true, it signals that we are building Qt from source.") +set(QT_BUILDING_QT TRUE CACHE BOOL + "When this is present and set to true, it signals that we are building Qt from source.") # Pre-calculate the developer_build feature if it's set by the user via INPUT_developer_build if(NOT FEATURE_developer_build AND INPUT_developer_build @@ -352,6 +352,8 @@ if(QT_UNITY_BUILD) set(CMAKE_UNITY_BUILD_BATCH_SIZE "${QT_UNITY_BUILD_BATCH_SIZE}") endif() +option(QT_ALLOW_SYMLINK_IN_PATHS "Allows symlinks in paths." OFF) + # We need to clean up QT_FEATURE_*, but only once per configuration cycle get_property(qt_feature_clean GLOBAL PROPERTY _qt_feature_clean) if(NOT qt_feature_clean) diff --git a/cmake/QtSyncQtHelpers.cmake b/cmake/QtSyncQtHelpers.cmake index 2ee98722..f120a968 100644 --- a/cmake/QtSyncQtHelpers.cmake +++ b/cmake/QtSyncQtHelpers.cmake @@ -139,7 +139,6 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge set(syncqt_args "${common_syncqt_arguments}") list(APPEND syncqt_args - ${common_syncqt_arguments} -headers ${module_headers} -stagingDir "${syncqt_staging_dir}" -knownModules ${known_modules} @@ -150,6 +149,21 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge set(syncqt_args_rsp "${binary_dir_real}/${target}_syncqt_args") qt_configure_file(OUTPUT "${syncqt_args_rsp}" CONTENT "${syncqt_args_string}") + get_target_property(external_headers_dir ${target} _qt_external_headers_dir) + if(external_headers_dir) + if(NOT IS_ABSOLUTE "${external_headers_dir}") + get_filename_component(external_headers_dir "${external_headers_dir}" ABSOLUTE) + endif() + if(EXISTS "${external_headers_dir}") + set(external_headers_dir_copy_cmd + COMMAND + ${CMAKE_COMMAND} + -E copy_directory + "${external_headers_dir}" + "${module_build_interface_include_dir}" + ) + endif() + endif() add_custom_command( OUTPUT ${syncqt_outputs} @@ -157,6 +171,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge ${QT_CMAKE_EXPORT_NAMESPACE}::syncqt "@${syncqt_args_rsp}" ${build_time_syncqt_arguments} + ${external_headers_dir_copy_cmd} COMMAND ${CMAKE_COMMAND} -E touch "${syncqt_timestamp}" DEPENDS @@ -167,12 +182,22 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge "Running syncqt.cpp for module: ${module}" VERBATIM ) + + set(add_sync_headers_to_all "") + if(is_interface_lib) + set(add_sync_headers_to_all ALL) + endif() + add_custom_target(${target}_sync_headers + ${add_sync_headers_to_all} DEPENDS ${syncqt_outputs} ) add_dependencies(sync_headers ${target}_sync_headers) + if(is_3rd_party_library) + add_dependencies(thirdparty_sync_headers ${target}_sync_headers) + endif() # This target is required when building docs, to make all header files and their aliases # available for qdoc. # ${target}_sync_headers is added as dependency to make sure that @@ -185,6 +210,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::syncqt "@${syncqt_all_args_rsp}" + ${external_headers_dir_copy_cmd} DEPENDS ${module_headers} ${syncqt_all_args_rsp} diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake index 50d8691d..6e7ff453 100644 --- a/cmake/QtTargetHelpers.cmake +++ b/cmake/QtTargetHelpers.cmake @@ -14,6 +14,8 @@ # module, these files will raise a warning at configure time if the condition is not met. # COMPILE_FLAGS # Custom compilation flags. +# EXTRA_LINKER_SCRIPT_CONTENT +# Extra content that should be appended to a target linker script. Applicable for ld only. # NO_PCH_SOURCES # Skip the specified source files by PRECOMPILE_HEADERS feature. function(qt_internal_extend_target target) @@ -36,6 +38,7 @@ function(qt_internal_extend_target target) ) set(single_args PRECOMPILED_HEADER + EXTRA_LINKER_SCRIPT_CONTENT ) set(multi_args ${__default_public_args} @@ -44,7 +47,6 @@ function(qt_internal_extend_target target) CONDITION CONDITION_INDEPENDENT_SOURCES COMPILE_FLAGS - NO_PCH_SOURCES ) cmake_parse_arguments(PARSE_ARGV 1 arg @@ -237,6 +239,10 @@ function(qt_internal_extend_target target) ${sources_property} "${arg_CONDITION_INDEPENDENT_SOURCES}") endif() + if(arg_EXTRA_LINKER_SCRIPT_CONTENT) + set_target_properties(${target} PROPERTIES + _qt_extra_linker_script_content "${arg_EXTRA_LINKER_SCRIPT_CONTENT}") + endif() endfunction() function(qt_is_imported_target target out_var) @@ -1001,6 +1007,15 @@ endfunction() # Needed to allow selectively applying certain flags via PlatformXInternal targets. function(qt_internal_mark_as_internal_library target) set_target_properties(${target} PROPERTIES _qt_is_internal_library TRUE) + qt_internal_mark_as_internal_target(${target}) +endfunction() + +# Marks a target with a property that it was built using the internal Qt API (qt_internal_*) as +# opposed to it being a user project library or executable(qt_add_*, etc). +# +# Needed to allow selectively applying certain flags via PlatformXInternal targets. +function(qt_internal_mark_as_internal_target target) + set_target_properties(${target} PROPERTIES _qt_is_internal_target TRUE) endfunction() function(qt_internal_link_internal_platform_for_object_library target) diff --git a/cmake/QtTestHelpers.cmake b/cmake/QtTestHelpers.cmake index e6759c9e..4c6b7d56 100644 --- a/cmake/QtTestHelpers.cmake +++ b/cmake/QtTestHelpers.cmake @@ -214,6 +214,7 @@ function(qt_internal_get_test_arg_definitions optional_args single_value_args mu MANUAL NO_BATCH NO_INSTALL + BUNDLE_ANDROID_OPENSSL_LIBS PARENT_SCOPE ) set(${single_value_args} @@ -526,6 +527,21 @@ function(qt_internal_add_test name) endif() if (ANDROID) + if(arg_BUNDLE_ANDROID_OPENSSL_LIBS) + if(NOT OPENSSL_ROOT_DIR) + message(WARNING "The argument BUNDLE_ANDROID_OPENSSL_LIBS is set " + "but OPENSSL_ROOT_DIR parameter is not set.") + else() + if(EXISTS "${OPENSSL_ROOT_DIR}/${CMAKE_ANDROID_ARCH_ABI}/libcrypto_3.so") + set_property(TARGET ${name} APPEND PROPERTY QT_ANDROID_EXTRA_LIBS + "${OPENSSL_ROOT_DIR}/${CMAKE_ANDROID_ARCH_ABI}/libcrypto_3.so" + "${OPENSSL_ROOT_DIR}/${CMAKE_ANDROID_ARCH_ABI}/libssl_3.so") + else() + message(STATUS "Test should bundle OpenSSL libraries but they are not found." + " This is fine if OpenSSL was built statically.") + endif() + endif() + endif() qt_internal_android_test_arguments("${name}" test_executable extra_test_args) set(test_working_dir "${CMAKE_CURRENT_BINARY_DIR}") elseif(QNX) diff --git a/cmake/QtToolHelpers.cmake b/cmake/QtToolHelpers.cmake index 6902a1e2..db18a4db 100644 --- a/cmake/QtToolHelpers.cmake +++ b/cmake/QtToolHelpers.cmake @@ -15,6 +15,13 @@ # INSTALL_VERSIONED_LINK # Prefix build only. On installation, create a versioned hard-link of the installed file. # E.g. create a link of "bin/qmake6" to "bin/qmake". +# TRY_RUN +# On Windows, it creates a helper batch script that tests whether the tool can be executed +# successfully or not. If not, build halts and an error will be show, with tips on what +# might be cause, and how to fix it. TRY_RUN is disabled when cross-compiling. +# TRY_RUN_FLAGS +# Command line flags that are going to be passed to the tool for testing its correctness. +# If no flags were given, we default to `-v`. # # One-value Arguments: # EXTRA_CMAKE_FILES @@ -42,11 +49,13 @@ function(qt_internal_add_tool target_name) USER_FACING INSTALL_VERSIONED_LINK EXCEPTIONS - NO_UNITY_BUILD) + NO_UNITY_BUILD + TRY_RUN) set(one_value_keywords TOOLS_TARGET INSTALL_DIR CORE_LIBRARY + TRY_RUN_FLAGS ${__default_target_info_args}) set(multi_value_keywords EXTRA_CMAKE_FILES @@ -105,6 +114,7 @@ function(qt_internal_add_tool target_name) NO_INSTALL ${arg_NO_UNITY_BUILD} SOURCES ${arg_SOURCES} + NO_PCH_SOURCES ${arg_NO_PCH_SOURCES} NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES} INCLUDE_DIRECTORIES ${arg_INCLUDE_DIRECTORIES} @@ -224,10 +234,62 @@ function(qt_internal_add_tool target_name) qt_internal_apply_staging_prefix_build_rpath_workaround() endif() + if(arg_TRY_RUN AND WIN32 AND NOT CMAKE_CROSSCOMPILING) + if(NOT arg_TRY_RUN_FLAGS) + set(arg_TRY_RUN_FLAGS "-v") + endif() + _qt_internal_add_try_run_post_build("${target_name}" "${arg_TRY_RUN_FLAGS}") + endif() + qt_enable_separate_debug_info(${target_name} "${install_dir}" QT_EXECUTABLE) qt_internal_install_pdb_files(${target_name} "${install_dir}") endfunction() +function(_qt_internal_add_try_run_post_build target try_run_flags) + qt_internal_get_upper_case_main_cmake_configuration(main_cmake_configuration) + get_target_property(target_out_dir ${target} + RUNTIME_OUTPUT_DIRECTORY_${main_cmake_configuration}) + get_target_property(target_bin_dir ${target} + BINARY_DIR) + + set(try_run_scripts_path "${target_bin_dir}/${target}_try_run.bat") + # The only reason -h is passed is because some of the tools, e.g., moc + # wait for an input without any arguments. + + qt_configure_file(OUTPUT "${try_run_scripts_path}" + CONTENT "@echo off + +${target_out_dir}/${target}.exe ${try_run_flags} > nul 2>&1 + +if \"%errorlevel%\" == \"-1073741515\" ( +echo +echo '${target}' is built successfully, but some of the libraries +echo necessary for running it are missing. If you are building Qt with +echo 3rdparty libraries, make sure that you add their directory to the +echo PATH environment variable. +echo +exit /b %errorlevel% +) +echo. > ${target_bin_dir}/${target}_try_run_passed" + ) + + add_custom_command( + OUTPUT + ${target_bin_dir}/${target}_try_run_passed + DEPENDS + ${target} + COMMAND + ${CMAKE_COMMAND} -E env QT_COMMAND_LINE_PARSER_NO_GUI_MESSAGE_BOXES=1 + ${try_run_scripts_path} + COMMENT + "Testing ${target} by trying to run it." + VERBATIM + ) + + add_custom_target(${target}_try_run ALL + DEPENDS ${target_bin_dir}/${target}_try_run_passed) +endfunction() + function(qt_export_tools module_name) # Bail out when not building tools. if(NOT QT_WILL_BUILD_TOOLS) @@ -287,7 +349,7 @@ function(qt_export_tools module_name) string(REGEX REPLACE "_native$" "" tool_name ${tool_name}) endif() set(extra_cmake_statements "${extra_cmake_statements} -if (NOT QT_NO_CREATE_TARGETS) +if(NOT QT_NO_CREATE_TARGETS AND ${INSTALL_CMAKE_NAMESPACE}${target}_FOUND) __qt_internal_promote_target_to_global(${INSTALL_CMAKE_NAMESPACE}::${tool_name}) endif() ") diff --git a/cmake/QtToolchainHelpers.cmake b/cmake/QtToolchainHelpers.cmake index ae96c5e2..f6df13af 100644 --- a/cmake/QtToolchainHelpers.cmake +++ b/cmake/QtToolchainHelpers.cmake @@ -31,6 +31,14 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file} list(APPEND init_platform "set(CMAKE_SYSTEM_PROCESSOR arm64 CACHE STRING \"\")") endif() + if(QT_QMAKE_TARGET_MKSPEC) + list(APPEND init_platform + "if(NOT QT_QMAKE_TARGET_MKSPEC)" + " set(QT_QMAKE_TARGET_MKSPEC ${QT_QMAKE_TARGET_MKSPEC} CACHE STRING \"\")" + "endif()" + ) + endif() + if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "linux-g++-32" AND NOT QT_NO_AUTO_DETECT_LINUX_X86) set(__qt_toolchain_common_flags_init "-m32") @@ -121,14 +129,14 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file} endif() if(__qt_embed_toolchain_compilers) list(APPEND init_platform " - set(__qt_initial_c_compiler \"${CMAKE_C_COMPILER}\") - set(__qt_initial_cxx_compiler \"${CMAKE_CXX_COMPILER}\") - if(NOT DEFINED CMAKE_C_COMPILER AND EXISTS \"\${__qt_initial_c_compiler}\") - set(CMAKE_C_COMPILER \"\${__qt_initial_c_compiler}\" CACHE STRING \"\") - endif() - if(NOT DEFINED CMAKE_CXX_COMPILER AND EXISTS \"\${__qt_initial_cxx_compiler}\") - set(CMAKE_CXX_COMPILER \"\${__qt_initial_cxx_compiler}\" CACHE STRING \"\") - endif()") +set(__qt_initial_c_compiler \"${CMAKE_C_COMPILER}\") +set(__qt_initial_cxx_compiler \"${CMAKE_CXX_COMPILER}\") +if(NOT DEFINED CMAKE_C_COMPILER AND EXISTS \"\${__qt_initial_c_compiler}\") + set(CMAKE_C_COMPILER \"\${__qt_initial_c_compiler}\" CACHE STRING \"\") +endif() +if(NOT DEFINED CMAKE_CXX_COMPILER AND EXISTS \"\${__qt_initial_cxx_compiler}\") + set(CMAKE_CXX_COMPILER \"\${__qt_initial_cxx_compiler}\" CACHE STRING \"\") +endif()") endif() unset(init_additional_used_variables) diff --git a/cmake/QtWriteArgsFile.cmake b/cmake/QtWriteArgsFile.cmake index aeb83bc9..77a9eb24 100644 --- a/cmake/QtWriteArgsFile.cmake +++ b/cmake/QtWriteArgsFile.cmake @@ -6,17 +6,74 @@ # This is used for writing the config.opt file. # # This script takes the following arguments: -# IN_FILE: The input file. The whole command line as one string. +# IN_FILE: The input file. The whole command line as one string, or one argument per line. +# REDO_FILE: A file containing extra commands to be joined with IN_FILE. # OUT_FILE: The output file. One argument per line. # SKIP_ARGS: Number of arguments to skip from the front of the arguments list. # IGNORE_ARGS: List of arguments to be ignored, i.e. that are not written. +# +# If the REDO_FILE is given, its parameters will be merged with IN_FILE parameters +# and be written into the OUT_FILE. cmake_minimum_required(VERSION 3.16) # Read arguments from IN_FILE and separate them. file(READ "${IN_FILE}" raw_args) +# To catch cases where the path ends with an `\`, e.g., `-prefix "C:\Path\"` +string(REPLACE "\\\"" "\"" raw_args "${raw_args}") +string(REPLACE ";" "[[;]]" raw_args "${raw_args}") + separate_arguments(args NATIVE_COMMAND "${raw_args}") +string(REPLACE "\;" ";" args "${args}") +string(REPLACE "[[;]]" "\;" args "${args}") + +if(DEFINED REDO_FILE) + file(READ "${REDO_FILE}" raw_redo_args) + separate_arguments(redo_args NATIVE_COMMAND "${raw_redo_args}") + + if(args) + list(FIND args "--" args_ddash_loc) + list(FIND redo_args "--" redo_ddash_loc) + if("${redo_ddash_loc}" STREQUAL "-1") + if("${args_ddash_loc}" STREQUAL "-1") + list(LENGTH args args_ddash_loc) + endif() + # Avoid adding an empty line for an empty -redo + if(NOT "${redo_args}" STREQUAL "") + list(INSERT args ${args_ddash_loc} "${redo_args}") + endif() + else() + # Handling redo's configure options + list(SUBLIST redo_args 0 ${redo_ddash_loc} redo_config_args) + if(redo_config_args) + if("${args_ddash_loc}" STREQUAL "-1") + list(APPEND args "${redo_config_args}") + else() + list(INSERT args ${args_ddash_loc} "${redo_config_args}") + endif() + endif() + + # Handling redo's CMake options + list(LENGTH redo_args redo_args_len) + math(EXPR redo_ddash_loc "${redo_ddash_loc} + 1") + # Catch an unlikely case of -redo being called with an empty --, ie., `-redo --` + if(NOT ${redo_ddash_loc} STREQUAL ${redo_args_len}) + list(SUBLIST redo_args ${redo_ddash_loc} -1 redo_cmake_args) + endif() + + if(DEFINED redo_cmake_args) + if("${args_ddash_loc}" STREQUAL "-1") + list(APPEND args "--") + endif() + list(APPEND args "${redo_cmake_args}") + endif() + endif() + else() + list(APPEND args "${redo_args}") + endif() +endif() + # Skip arguments if requested if(DEFINED SKIP_ARGS) foreach(i RANGE 1 ${SKIP_ARGS}) diff --git a/cmake/modulecppexports.h.in b/cmake/modulecppexports.h.in index a7a34908..538c40e5 100644 --- a/cmake/modulecppexports.h.in +++ b/cmake/modulecppexports.h.in @@ -17,22 +17,22 @@ #endif #if !defined(QT_BUILD_@module_define_infix@_LIB) && !defined(QT_STATIC) -/* outside library → inline decl + defi */ +/* outside library -> inline decl + defi */ /* static builds treat everything as part of the library, so they never inline */ # define QT_@module_define_infix@_INLINE_SINCE(major, minor) inline # define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) 1 #elif defined(QT_@module_define_infix@_BUILD_REMOVED_API) /* inside library, inside removed_api.cpp: - * keep deprecated API → non-inline decl; - * remove deprecated API → inline decl; + * keep deprecated API -> non-inline decl; + * remove deprecated API -> inline decl; * definition is always available */ # define QT_@module_define_infix@_INLINE_SINCE(major, minor) \ QT_IF_DEPRECATED_SINCE(major, minor, inline, /* not inline */) # define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) 1 #else /* inside library, outside removed_api.cpp: - * keep deprecated API → non-inline decl, no defi; - * remove deprecated API → inline decl, defi */ + * keep deprecated API -> non-inline decl, no defi; + * remove deprecated API -> inline decl, defi */ # define QT_@module_define_infix@_INLINE_SINCE(major, minor) \ QT_IF_DEPRECATED_SINCE(major, minor, inline, /* not inline */) # define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) \ diff --git a/coin/instructions/cmake_build_and_upload_test_artifacts_host.yaml b/coin/instructions/cmake_build_and_upload_test_artifacts_host.yaml index 3592ac42..bc16368f 100644 --- a/coin/instructions/cmake_build_and_upload_test_artifacts_host.yaml +++ b/coin/instructions/cmake_build_and_upload_test_artifacts_host.yaml @@ -13,6 +13,11 @@ instructions: variableValue: "{{.Env.COMMON_TEST_CMAKE_ARGS}}" - !include "{{qt/qtbase}}/cmake_build_and_upload_test_artifacts.yaml" disable_if: - condition: property - property: features - contains_value: DisableTests + condition: or + conditions: + - condition: property + property: features + contains_value: DisableTests + - condition: property + property: features + contains_value: DoNotBuildTests diff --git a/coin/instructions/cmake_build_and_upload_test_artifacts_target.yaml b/coin/instructions/cmake_build_and_upload_test_artifacts_target.yaml index be4db4f6..afc20b98 100644 --- a/coin/instructions/cmake_build_and_upload_test_artifacts_target.yaml +++ b/coin/instructions/cmake_build_and_upload_test_artifacts_target.yaml @@ -34,6 +34,11 @@ instructions: variableValue: "{{.Env.COMMON_TARGET_TEST_CMAKE_ARGS}}" - !include "{{qt/qtbase}}/cmake_build_and_upload_test_artifacts.yaml" disable_if: - condition: property - property: features - contains_value: DisableTests + condition: or + conditions: + - condition: property + property: features + contains_value: DisableTests + - condition: property + property: features + contains_value: DoNotBuildTests diff --git a/coin/instructions/cmake_cross_compilation_module_build_instructions.yaml b/coin/instructions/cmake_cross_compilation_module_build_instructions.yaml index 45410882..4146b11a 100644 --- a/coin/instructions/cmake_cross_compilation_module_build_instructions.yaml +++ b/coin/instructions/cmake_cross_compilation_module_build_instructions.yaml @@ -61,9 +61,14 @@ instructions: - condition: property property: host.os equals_value: Windows - - condition: property - property: target.osVersion - not_in_values: [WebAssembly, Android_ANY] + - condition: and + conditions: + - condition: property + property: target.os + not_equals_value: QNX + - condition: property + property: target.osVersion + not_in_values: [WebAssembly, Android_ANY] - type: EnvironmentVariable variableName: COIN_CMAKE_INSTALL_LIBEXEC_DIR variableValue: "{{.InstallDir}}{{.Env.CI_PATH_SEP}}host{{.Env.CI_PATH_SEP}}bin" @@ -73,9 +78,14 @@ instructions: - condition: property property: host.os equals_value: Windows - - condition: property - property: target.osVersion - not_in_values: [WebAssembly, Android_ANY] + - condition: and + conditions: + - condition: property + property: target.os + not_equals_value: QNX + - condition: property + property: target.osVersion + not_in_values: [WebAssembly, Android_ANY] - !include "{{qt/qtbase}}/call_host_install.yaml" - type: EnvironmentVariable variableName: DESTDIR @@ -123,9 +133,14 @@ instructions: - condition: property property: host.os equals_value: Windows - - condition: property - property: target.osVersion - not_in_values: [WebAssembly, Android_ANY] + - condition: and + conditions: + - condition: property + property: target.os + not_equals_value: QNX + - condition: property + property: target.osVersion + not_in_values: [WebAssembly, Android_ANY] - type: EnvironmentVariable variableName: COIN_CMAKE_INSTALL_LIBEXEC_DIR variableValue: "{{.InstallDir}}{{.Env.CI_PATH_SEP}}target{{.Env.CI_PATH_SEP}}bin" @@ -135,9 +150,14 @@ instructions: - condition: property property: host.os equals_value: Windows - - condition: property - property: target.osVersion - not_in_values: [WebAssembly, Android_ANY] + - condition: and + conditions: + - condition: property + property: target.os + not_equals_value: QNX + - condition: property + property: target.osVersion + not_in_values: [WebAssembly, Android_ANY] - !include "{{qt/qtbase}}/call_target_install.yaml" - type: EnvironmentVariable variableName: DESTDIR diff --git a/coin/instructions/cmake_cross_compilation_qtbase_build_instructions.yaml b/coin/instructions/cmake_cross_compilation_qtbase_build_instructions.yaml index 4a1ed613..909b1504 100644 --- a/coin/instructions/cmake_cross_compilation_qtbase_build_instructions.yaml +++ b/coin/instructions/cmake_cross_compilation_qtbase_build_instructions.yaml @@ -47,9 +47,14 @@ instructions: - condition: property property: host.os equals_value: Windows - - condition: property - property: target.osVersion - not_in_values: [WebAssembly, Android_ANY] + - condition: and + conditions: + - condition: property + property: target.os + not_equals_value: QNX + - condition: property + property: target.osVersion + not_in_values: [WebAssembly, Android_ANY] - type: EnvironmentVariable variableName: COIN_CMAKE_BUILD_LIBEXEC_DIR variableValue: "{{.BuildDir}}{{.Env.CI_PATH_SEP}}bin" @@ -59,9 +64,14 @@ instructions: - condition: property property: host.os equals_value: Windows - - condition: property - property: target.osVersion - not_in_values: [WebAssembly, Android_ANY] + - condition: and + conditions: + - condition: property + property: target.os + not_equals_value: QNX + - condition: property + property: target.osVersion + not_in_values: [WebAssembly, Android_ANY] - !include "{{qt/qtbase}}/call_host_install.yaml" - type: EnvironmentVariable variableName: DESTDIR @@ -124,9 +134,14 @@ instructions: - condition: property property: host.os equals_value: Windows - - condition: property - property: target.osVersion - not_in_values: [WebAssembly, Android_ANY] + - condition: and + conditions: + - condition: property + property: target.os + not_equals_value: QNX + - condition: property + property: target.osVersion + not_in_values: [WebAssembly, Android_ANY] - type: EnvironmentVariable variableName: COIN_CMAKE_BUILD_LIBEXEC_DIR variableValue: "{{.Env.COIN_CMAKE_BUILD_DIR}}{{.Env.CI_PATH_SEP}}bin" @@ -136,9 +151,14 @@ instructions: - condition: property property: host.os equals_value: Windows - - condition: property - property: target.osVersion - not_in_values: [WebAssembly, Android_ANY] + - condition: and + conditions: + - condition: property + property: target.os + not_equals_value: QNX + - condition: property + property: target.osVersion + not_in_values: [WebAssembly, Android_ANY] - !include "{{qt/qtbase}}/call_target_install.yaml" - type: EnvironmentVariable variableName: DESTDIR diff --git a/coin/instructions/cmake_qtbase_build_instructions.yaml b/coin/instructions/cmake_qtbase_build_instructions.yaml index 31766865..399ae731 100644 --- a/coin/instructions/cmake_qtbase_build_instructions.yaml +++ b/coin/instructions/cmake_qtbase_build_instructions.yaml @@ -41,9 +41,14 @@ instructions: - condition: property property: host.os equals_value: Windows - - condition: property - property: target.osVersion - not_in_values: [WebAssembly, Android_ANY] + - condition: and + conditions: + - condition: property + property: target.os + not_equals_value: QNX + - condition: property + property: target.osVersion + not_in_values: [WebAssembly, Android_ANY] - type: EnvironmentVariable variableName: COIN_CMAKE_BUILD_LIBEXEC_DIR variableValue: "{{.Env.COIN_CMAKE_BUILD_DIR}}{{.Env.CI_PATH_SEP}}bin" @@ -53,9 +58,14 @@ instructions: - condition: property property: host.os equals_value: Windows - - condition: property - property: target.osVersion - not_in_values: [WebAssembly, Android_ANY] + - condition: and + conditions: + - condition: property + property: target.os + not_equals_value: QNX + - condition: property + property: target.osVersion + not_in_values: [WebAssembly, Android_ANY] - !include "{{qt/qtbase}}/call_host_install.yaml" - type: EnvironmentVariable variableName: DESTDIR diff --git a/coin/instructions/prepare_building_env.yaml b/coin/instructions/prepare_building_env.yaml index f816ef56..53fc2ae6 100644 --- a/coin/instructions/prepare_building_env.yaml +++ b/coin/instructions/prepare_building_env.yaml @@ -305,6 +305,14 @@ instructions: condition: property property: target.osVersion in_values: [QEMU] + # This fixes an issue where binfmts is sometimes disabled on the test VMs + - type: ExecuteCommand + command: sudo update-binfmts --enable + userMessageOnFailure: "Failed to enable binfmts" + enable_if: + condition: property + property: target.osVersion + equals_value: QEMU # Windows on Arm, cross-compilation with MSVC - type: Group diff --git a/conanfile.py b/conanfile.py deleted file mode 100644 index 3f05ceda..00000000 --- a/conanfile.py +++ /dev/null @@ -1,300 +0,0 @@ -# Copyright (C) 2021 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -from conans import ConanFile, tools -from conans.errors import ConanInvalidConfiguration -import os -import re -import shutil -from functools import lru_cache -from pathlib import Path -from typing import Dict, Union - - -class QtConanError(Exception): - pass - - -def add_cmake_prefix_path(conan_file: ConanFile, dep: str) -> None: - if dep not in conan_file.deps_cpp_info.deps: - raise QtConanError("Unable to find dependency: {0}".format(dep)) - dep_cpp_info = conan_file.deps_cpp_info[dep] - cmake_args_str = str(conan_file.options.get_safe("cmake_args_qtbase", default="")) - formatted_cmake_args_str = conan_file._shared.append_cmake_arg( - cmake_args_str, "CMAKE_PREFIX_PATH", dep_cpp_info.rootpath - ) - print("Adjusted cmake args for qtbase build: {0}".format(formatted_cmake_args_str)) - setattr(conan_file.options, "cmake_args_qtbase", formatted_cmake_args_str) - - -def _build_qtbase(conan_file: ConanFile): - # we call the Qt's configure(.bat) directly - script = Path("configure.bat") if tools.os_info.is_windows else Path("configure") - configure = Path(conan_file.build_folder).joinpath(script).resolve(strict=True) - - if conan_file.options.get_safe("icu", default=False): - # we need to tell Qt build system where to find the ICU - add_cmake_prefix_path(conan_file, dep="icu") - - # convert the Conan options to Qt configure(.bat) arguments - parser = conan_file._qt_option_parser - qt_configure_options = parser.convert_conan_options_to_qt_options(conan_file.options) - cmd = " ".join( - [str(configure), " ".join(qt_configure_options), "-prefix", conan_file.package_folder] - ) - cmake_args = parser.get_cmake_args_for_configure(conan_file.options) - if cmake_args: - cmd += " -- {0}".format(" ".join(cmake_args)) - conan_file.output.info("Calling: {0}".format(cmd)) - conan_file.run(cmd) - - cmd = " ".join(["cmake", "--build", ".", "--parallel"]) - conan_file.output.info("Calling: {0}".format(cmd)) - conan_file.run(cmd) - - -@lru_cache(maxsize=8) -def _parse_qt_version_by_key(key: str) -> str: - with open(Path(__file__).parent.resolve() / ".cmake.conf") as f: - m = re.search(fr'{key} .*"(.*)"', f.read()) - return m.group(1) if m else "" - - -def _get_qt_minor_version() -> str: - return ".".join(_parse_qt_version_by_key("QT_REPO_MODULE_VERSION").split(".")[:2]) - - -class QtBase(ConanFile): - name = "qtbase" - license = "LGPL-3.0, GPL-2.0+, Commercial Qt License Agreement" - author = "The Qt Company " - url = "https://code.qt.io/cgit/qt/qtbase.git" - description = "Qt6 core framework libraries and tools." - topics = ("qt", "qt6") - settings = "os", "compiler", "arch", "build_type" - _qt_option_parser = None - options = None - default_options = None - exports_sources = "*", "!conan*.*" - # use commit ID as the RREV (recipe revision) - revision_mode = "scm" - python_requires = "qt-conan-common/{0}@qt/everywhere".format(_get_qt_minor_version()) - short_paths = True - _shared = None - - def init(self): - self._shared = self.python_requires["qt-conan-common"].module - self._qt_option_parser = self._shared.QtOptionParser(Path(__file__).parent.resolve()) - self.options = self._qt_option_parser.get_qt_conan_options() - self.default_options = self._qt_option_parser.get_default_qt_conan_options() - - def set_version(self): - # Executed during "conan export" i.e. in source tree - _ver = _parse_qt_version_by_key("QT_REPO_MODULE_VERSION") - _prerelease = _parse_qt_version_by_key("QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT") - self.version = _ver + "-" + _prerelease if _prerelease else _ver - - def export(self): - self.copy("configure_options.json") - self.copy("configure_features.txt") - self.copy(".cmake.conf") - conf = self._shared.qt_sw_versions_config_folder() / self._shared.qt_sw_versions_config_name() - if not conf.exists(): - # If using "conan export" outside Qt CI provisioned machines - print("Warning: Couldn't find '{0}'. 3rd party dependencies skipped.".format(conf)) - else: - shutil.copy2(conf, self.export_folder) - - def requirements(self): - # list of tuples, (package_name, fallback version) - optional_requirements = [("icu", "56.1")] - for req_name, req_ver_fallback in optional_requirements: - if self.options.get_safe(req_name, default=False) == True: - # Note! If this conan package is being "conan export"ed outside Qt CI and the - # sw versions .ini file is not present then it will fall-back to default version - ver = self._shared.parse_qt_sw_pkg_dependency( - config_folder=Path(self.recipe_folder), - package_name=req_name, - target_os=str(self.settings.os), - ) - if not ver: - print( - "Warning: Using fallback version '{0}' for: {1}".format( - req_name, req_ver_fallback - ) - ) - ver = req_ver_fallback - requirement = "{0}/{1}@qt/everywhere".format(req_name, ver) - print("Setting 3rd party package requirement: {0}".format(requirement)) - self.requires(requirement) - - def _resolve_qt_host_path(self) -> Union[str, None]: - """ - Attempt to resolve QT_HOST_PATH. - - When cross-building the user needs to pass 'qt_host_path' which is transformed to - QT_HOST_PATH later on. Resolve the exact path if possible. - - Returns: - string: The resolved QT_HOST_PATH or None if unable to determine it. - """ - _host_p = self.options.get_safe("qt_host_path") - if _host_p: - return str(Path(os.path.expandvars(str(_host_p))).expanduser().resolve(strict=True)) - else: - print("Warning: 'qt_host_path' option was not given in cross-build context") - return None - - def configure(self): - if self.settings.compiler == "gcc" and tools.Version(self.settings.compiler.version) < "8": - raise ConanInvalidConfiguration("Qt6 does not support GCC before 8") - - def _set_default_if_not_set(option_name: str, option_value: bool) -> None: - # let it fail if option name does not exist, it means the recipe is not up to date - if self.options.get_safe(option_name) in [None, "None"]: - setattr(self.options, option_name, option_value) - - def _set_build_type(build_type: str) -> None: - if self.settings.build_type != build_type: - msg = ( - "The build_type '{0}' changed to '{1}'. Please check your Settings and " - "Options. The used Qt options enforce '{2}' as a build_type. ".format( - self.settings.build_type, build_type, build_type - ) - ) - raise QtConanError(msg) - self.settings.build_type = build_type - - def _check_mutually_exclusive_options(options: Dict[str, bool]) -> None: - if list(options.values()).count(True) > 1: - raise QtConanError( - "These Qt options are mutually exclusive: {0}" - ". Choose only one of them and try again.".format(list(options.keys())) - ) - - default_options = ["shared", "gui", "widgets", "accessibility", "system_proxies", "ico"] - - if self.settings.os == "Macos": - default_options.append("framework") - - for item in default_options: - _set_default_if_not_set(item, True) - - release = self.options.get_safe("release", default=False) - debug = self.options.get_safe("debug", default=False) - debug_and_release = self.options.get_safe("debug_and_release", default=False) - force_debug_info = self.options.get_safe("force_debug_info", default=False) - optimize_size = self.options.get_safe("optimize_size", default=False) - - # these options are mutually exclusive options so do a sanity check - _check_mutually_exclusive_options( - {"release": release, "debug": debug, "debug_and_release": debug_and_release} - ) - - # Prioritize Qt's configure options over Settings.build_type - if debug_and_release == True: - # Qt build system will build both debug and release binaries - if force_debug_info == True: - _set_build_type("RelWithDebInfo") - else: - _set_build_type("Release") - elif release == True: - _check_mutually_exclusive_options( - {"force_debug_info": force_debug_info, "optimize_size": optimize_size} - ) - if force_debug_info == True: - _set_build_type("RelWithDebInfo") - elif optimize_size == True: - _set_build_type("MinSizeRel") - else: - _set_build_type("Release") - elif debug == True: - _set_build_type("Debug") - else: - # As a fallback set the build type for Qt configure based on the 'build_type' - # defined in the conan build settings - build_type = self.settings.get_safe("build_type") - if build_type in [None, "None"]: - # set default that mirror the configure(.bat) default values - self.options.release = True - self.settings.build_type = "Release" - elif build_type == "Release": - self.options.release = True - elif build_type == "Debug": - self.options.debug = True - elif build_type == "RelWithDebInfo": - self.options.release = True - self.options.force_debug_info = True - elif build_type == "MinSizeRel": - self.options.release = True - self.options.optimize_size = True - else: - raise QtConanError("Unknown build_type: {0}".format(self.settings.build_type)) - - if self.settings.os == "Android": - if self.options.get_safe("android_sdk_version") == None: - cmake_args_qtbase = str(self.options.get_safe("cmake_args_qtbase")) - sdk_ver = self._shared.parse_android_sdk_version(cmake_args_qtbase) - if sdk_ver: - print("'android_sdk_version' not given. Deduced version: {0}".format(sdk_ver)) - self.options.android_sdk_version = sdk_ver - else: - # TODO, for now we have no clean means to query the Android SDK version from - # Qt build system so we just exclude the "android_sdk" from the package_id. - print("Can't deduce 'android_sdk_version'. Excluding it from 'package_id'") - delattr(self.info.options, "android_sdk_version") - if self.options.get_safe("android_ndk_version") == None: - ndk_ver = str(self.options.get_safe("android_ndk")) - ndk_ver = self._shared.parse_android_ndk_version(Path(ndk_ver, strict=True)) - print("'android_ndk_version' not given. Deduced version: {0}".format(ndk_ver)) - self.options.android_ndk_version = ndk_ver - - def build(self): - self._shared.build_env_wrap(self, _build_qtbase) - - def package(self): - self._shared.call_install(self) - - def package_info(self): - self._shared.package_info(self) - if tools.cross_building(conanfile=self): - qt_host_path = self._resolve_qt_host_path() - if qt_host_path: - self.env_info.QT_HOST_PATH.append(qt_host_path) - - def package_id(self): - # https://docs.conan.io/en/latest/creating_packages/define_abi_compatibility.html - - # The package_revision_mode() is too strict for Qt CI. This mode includes artifacts - # checksum in package_id which is problematic in Qt CI re-runs (re-run flaky - # build) which contain different build timestamps (cmake) which end up in library - # files -> different package_id. - self.info.requires.recipe_revision_mode() - - # Enable 'qt-conan-common' updates on client side with $conan install .. --update - self.info.python_requires.recipe_revision_mode() - - # Remove those configure(.bat) options which should not affect package_id. - # These point to local file system paths and in order to re-use pre-built - # binaries (by Qt CI) by others these should not affect the 'package_id' - # as those probably differ on each machine - rm_list = [ - "sdk", - "qpa", - "translationsdir", - "headersclean", - "qt_host_path", - "android_sdk", - "android_ndk", - ] - for item in rm_list: - if item in self.info.options: - delattr(self.info.options, item) - # filter also those cmake options that should not end up in the package_id - if hasattr(self.info.options, "cmake_args_qtbase"): - _filter = self._shared.filter_cmake_args_for_package_id - self.info.options.cmake_args_qtbase = _filter(self.info.options.cmake_args_qtbase) - - def deploy(self): - self.copy("*") # copy from current package - self.copy_deps("*") # copy from dependencies diff --git a/configure b/configure index a2b67a1d..e57707dc 100644 --- a/configure +++ b/configure @@ -8,14 +8,18 @@ #------------------------------------------------------------------------------- # the directory of this script is the "source tree" -relpath=`dirname $0` +relpath=`dirname "$0"` relpath=`(cd "$relpath"; /bin/pwd)` # the current directory is the "build tree" or "object tree" outpath=`/bin/pwd` +outpathPrefix=$outpath # do this early so we don't store it in config.status CFG_TOPLEVEL= -outpathPrefix= + +SAVED_IFS=$IFS +IFS=' +' checkTopLevelBuild() { @@ -23,7 +27,7 @@ checkTopLevelBuild() if [ x"$1" = x"-top-level" ]; then CFG_TOPLEVEL=yes relpathMangled=`dirname "$relpath"` - outpathPrefix=../ + outpathPrefix="$outpathPrefix/.." else if [ -f ../.qmake.super ]; then echo >&2 "ERROR: You cannot configure qtbase separately within a top-level build." @@ -35,41 +39,26 @@ checkTopLevelBuild() OPT_CMDLINE= # expanded version for the script determineOptFilePath() { +> "${outpathPrefix}/config.redo.in" set -f # suppress globbing in for loop -SAVED_IFS=$IFS -IFS=' -' for i in "$@"; do if [ x"$i" = x"-top-level" ]; then continue fi case $i in -redo|--redo) - optfile=${outpathPrefix}config.opt - if test -n "$CFG_TOPLEVEL" && ! test -f $optfile; then - optfile=config.opt - fi - if ! test -f $optfile; then + optfile=${outpathPrefix}/config.opt + if ! test -f "$optfile"; then echo >&2 "No config.opt present - cannot redo configuration." exit 1 fi - for a in `cat $optfile`; do - OPT_CMDLINE="$OPT_CMDLINE -$a" - done ;; *) - OPT_CMDLINE="$OPT_CMDLINE -$i" + # If redo-ing, write the rest of parameters into the config.redo.in file + echo \"$i\" >> "${outpathPrefix}/config.redo.in" ;; esac done -set -- -for i in $OPT_CMDLINE; do - set -- "$@" "$i" -done -set +f -IFS=$SAVED_IFS } #------------------------------------------------------------------------------- @@ -88,80 +77,10 @@ while [ "$#" -gt 0 ]; do CURRENT_OPT="$1" case "$1" in #Autoconf style options - --enable-*) - VAR=`echo $1 | sed 's,^--enable-\(.*\),\1,'` - VAL=yes - ;; - --disable-*) - VAR=`echo $1 | sed 's,^--disable-\(.*\),\1,'` - VAL=no - ;; - --*=*) - VAR=`echo $1 | sed 's,^--\(.*\)=.*,\1,'` - VAL=`echo $1 | sed 's,^--.*=\(.*\),\1,'` - ;; - --no-*) - VAR=`echo $1 | sed 's,^--no-\(.*\),\1,'` - VAL=no - ;; --*) VAR=`echo $1 | sed 's,^--\(.*\),\1,'` VAL=yes ;; - #Qt plugin options - -no-*-*|-plugin-*-*|-qt-*-*) - VAR=`echo $1 | sed 's,^-[^-]*-\(.*\),\1,'` - VAL=`echo $1 | sed 's,^-\([^-]*\).*,\1,'` - ;; - #Qt style no options - -no-*) - VAR=`echo $1 | sed 's,^-no-\(.*\),\1,'` - VAL=no - ;; - #Qt style options that pass an argument - -prefix| \ - -docdir| \ - -headerdir| \ - -plugindir| \ - -qmldir| \ - -archdatadir| \ - -datadir| \ - -libdir| \ - -bindir| \ - -libexecdir| \ - -translationdir| \ - -sysconfdir| \ - -examplesdir| \ - -testsdir| \ - -hostdatadir| \ - -extprefix| \ - -sysroot| \ - -make| \ - -nomake| \ - -skip| \ - -platform| \ - -xplatform| \ - -device| \ - -device-option| \ - -sdk| \ - -android-sdk| \ - -android-ndk| \ - -android-ndk-platform| \ - -android-arch) - VAR=`echo $1 | sed 's,^-\(.*\),\1,'` - shift - VAL="$1" - ;; - #Qt style complex options in one command - -enable-*|-disable-*) - VAR=`echo $1 | sed 's,^-\([^-]*\)-.*,\1,'` - VAL=`echo $1 | sed 's,^-[^-]*-\(.*\),\1,'` - ;; - #Qt Builtin/System style options - -no-*|-system-*|-qt-*) - VAR=`echo $1 | sed 's,^-[^-]*-\(.*\),\1,'` - VAL=`echo $1 | sed 's,^-\([^-]*\)-.*,\1,'` - ;; #General options, including Qt style yes options -*) VAR=`echo $1 | sed 's,^-\(.*\),\1,'` @@ -176,24 +95,16 @@ while [ "$#" -gt 0 ]; do shift - UNKNOWN_OPT=no case "$VAR" in h|help) if [ "$VAL" = "yes" ]; then OPT_HELP="$VAL" - else - UNKNOWN_OPT=yes fi ;; *) ;; esac - if [ "$UNKNOWN_OPT" = "yes" ]; then - echo "${CURRENT_OPT}: invalid command-line switch" - ERROR=yes - fi done -[ "x$ERROR" = "xyes" ] && exit 1 } #------------------------------------------------------------------------------- @@ -222,18 +133,27 @@ parseCommandline "$@" handleHelp determineOptFilePath "$@" +optfilepath=${outpathPrefix}/config.opt +opttmpfilepath=${outpathPrefix}/config.opt.in + +redofilepath=${outpathPrefix}/config.redo +redotmpfilepath=${outpathPrefix}/config.redo.in + fresh_requested_arg= -optfilename=config.opt if [ -z "$optfile" ]; then # only write optfile if not currently redoing - optfilepath=${outpathPrefix}${optfilename} - > "$optfilepath" - for arg in "$@"; do - if [ "$arg" = "-top-level" ]; then - continue - fi - echo $arg >> "$optfilepath" - done + > "$opttmpfilepath" + > "$redotmpfilepath" + + for arg in "$@"; do echo \"$arg\" >> "$opttmpfilepath"; done + + cmake -DIN_FILE="${opttmpfilepath}" -DOUT_FILE="${optfilepath}" -DIGNORE_ARGS=-top-level -P "${relpath}/cmake/QtWriteArgsFile.cmake" else + # Rewriting config.opt into config.opt.in anyway. Allows for direct manipulation of config.opt + > "$opttmpfilepath" + for arg in `cat $optfile`; do echo \"$arg\" >> "$opttmpfilepath"; done + + cmake -DIN_FILE="${opttmpfilepath}" -DREDO_FILE="${redotmpfilepath}" -DOUT_FILE="${redofilepath}" -DIGNORE_ARGS=-top-level -P "${relpath}/cmake/QtWriteArgsFile.cmake" + optfilepath=${redofilepath} fresh_requested_arg=-DFRESH_REQUESTED=TRUE fi @@ -243,4 +163,6 @@ if [ -n "$CFG_TOPLEVEL" ]; then cd .. fi -cmake "-DOPTFILE=$optfilename" $top_level_arg $fresh_requested_arg -P "$relpath/cmake/QtProcessConfigureArgs.cmake" +cmake "-DOPTFILE=${optfilepath}" ${top_level_arg} ${fresh_requested_arg} -P "${relpath}/cmake/QtProcessConfigureArgs.cmake" + +IFS=$SAVED_IFS diff --git a/configure.bat b/configure.bat index e93e0af3..1da3740a 100644 --- a/configure.bat +++ b/configure.bat @@ -65,9 +65,8 @@ goto doneargs :redo if not exist "%TOPQTDIR%\config.opt" goto redoerr - set rargs= - for /f "usebackq delims=" %%i in ("%TOPQTDIR%\config.opt") do set rargs=!rargs! "%%i" - call :doargs %rargs% + echo %ARGS% > %TOPQTDIR%\config.redo.in + set redoing="" goto nextarg :redoerr echo No config.opt present - cannot redo configuration. >&2 @@ -78,15 +77,26 @@ goto doneargs cd "%TOPQTDIR%" rem Write config.opt if we're not currently -redo'ing +set OPT_FILE_PATH=%TOPQTDIR%\config.opt +set OPT_TMP_FILE_PATH=%TOPQTDIR%\config.opt.in +set REDO_FILE_PATH=%TOPQTDIR%\config.redo +set REDO_TMP_FILE_PATH=%TOPQTDIR%\config.redo.in set FRESH_REQUESTED_ARG= -if "!rargs!" == "" ( - echo.%*>config.opt.in - cmake -DIN_FILE=config.opt.in -DOUT_FILE=config.opt -DIGNORE_ARGS=-top-level -P "%QTSRC%\cmake\QtWriteArgsFile.cmake" -) else if NOT "!rargs!" == "" ( +if not defined redoing ( + echo.%*>"%OPT_TMP_FILE_PATH%" + + cmake -DIN_FILE="%OPT_TMP_FILE_PATH%" -DOUT_FILE="%OPT_FILE_PATH%" -DIGNORE_ARGS=-top-level -P "%QTSRC%\cmake\QtWriteArgsFile.cmake" +) else ( + echo. 2> "%OPT_TMP_FILE_PATH%" + for /F "usebackq tokens=*" %%A in ("%OPT_FILE_PATH%") do echo "%%A" >> "%OPT_TMP_FILE_PATH%" + + cmake -DIN_FILE="%OPT_TMP_FILE_PATH%" -DREDO_FILE="%REDO_TMP_FILE_PATH%" -DOUT_FILE="%REDO_FILE_PATH%" -DIGNORE_ARGS="-top-level;-redo;--redo" -P "%QTSRC%\cmake\QtWriteArgsFile.cmake" + + set OPT_FILE_PATH=%REDO_FILE_PATH% set FRESH_REQUESTED_ARG=-DFRESH_REQUESTED=TRUE ) rem Launch CMake-based configure set TOP_LEVEL_ARG= if %TOPLEVEL% == true set TOP_LEVEL_ARG=-DTOP_LEVEL=TRUE -cmake -DOPTFILE=config.opt %TOP_LEVEL_ARG% %FRESH_REQUESTED_ARG% -P "%QTSRC%\cmake\QtProcessConfigureArgs.cmake" +cmake -DOPTFILE="%OPT_FILE_PATH%" %TOP_LEVEL_ARG% %FRESH_REQUESTED_ARG% -P "%QTSRC%\cmake\QtProcessConfigureArgs.cmake" diff --git a/configure.cmake b/configure.cmake index 450cadfe..be1a4f3b 100644 --- a/configure.cmake +++ b/configure.cmake @@ -22,6 +22,7 @@ qt_find_package(WrapOpenSSLHeaders PROVIDED_TARGETS WrapOpenSSLHeaders::WrapOpen # openssl_headers # OPENSSL_VERSION_MAJOR is not defined for OpenSSL 1.1.1 qt_config_compile_test(opensslv11_headers + LABEL "opensslv11_headers" LIBRARIES WrapOpenSSLHeaders::WrapOpenSSLHeaders CODE @@ -46,6 +47,7 @@ qt_find_package(WrapOpenSSL PROVIDED_TARGETS WrapOpenSSL::WrapOpenSSL MODULE_NAM # openssl # OPENSSL_VERSION_MAJOR is not defined for OpenSSL 1.1.1 qt_config_compile_test(opensslv11 + LABEL "opensslv11" LIBRARIES WrapOpenSSL::WrapOpenSSL CODE @@ -70,6 +72,7 @@ SSL_free(SSL_new(0)); # opensslv30 # openssl_headers qt_config_compile_test(opensslv30_headers + LABEL "opensslv30_headers" LIBRARIES WrapOpenSSLHeaders::WrapOpenSSLHeaders CODE @@ -87,6 +90,7 @@ int main(void) } ") qt_config_compile_test(opensslv30 + LABEL "opensslv30" LIBRARIES WrapOpenSSL::WrapOpenSSL CODE @@ -331,11 +335,13 @@ int main(void) "# FIXME: qmake: ['TEMPLATE = lib', 'CONFIG += dll bsymbolic_functions', 'isEmpty(QMAKE_LFLAGS_BSYMBOLIC_FUNC): error("Nope")'] ) +if(NOT MSVC AND NOT APPLE) + qt_config_compile_test("separate_debug_info" + LABEL "separate debug information support" + PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/config.tests/separate_debug_info" + ) +endif() -qt_config_compile_test("separate_debug_info" - LABEL "separate debug information support" - PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/config.tests/separate_debug_info" -) # signaling_nan qt_config_compile_test(signaling_nan LABEL "Signaling NaN for doubles" @@ -535,7 +541,7 @@ qt_feature("developer-build" PRIVATE LABEL "Developer build" AUTODETECT OFF ) -qt_feature("no-prefix" PRIVATE +qt_feature("no-prefix" LABEL "No prefix build" AUTODETECT NOT QT_WILL_INSTALL CONDITION NOT QT_WILL_INSTALL @@ -567,7 +573,7 @@ qt_feature_config("force_debug_info" QMAKE_PRIVATE_CONFIG) qt_feature("separate_debug_info" PUBLIC LABEL "Split off debug information" AUTODETECT OFF - CONDITION ( QT_FEATURE_shared ) AND ( QT_FEATURE_debug OR QT_FEATURE_debug_and_release OR QT_FEATURE_force_debug_info ) AND ( APPLE OR TEST_separate_debug_info ) + CONDITION ( QT_FEATURE_shared ) AND ( QT_FEATURE_debug OR QT_FEATURE_debug_and_release OR QT_FEATURE_force_debug_info ) AND ( MSVC OR APPLE OR TEST_separate_debug_info ) ) qt_feature_config("separate_debug_info" QMAKE_PUBLIC_QT_CONFIG) qt_feature("appstore-compliant" PUBLIC @@ -1157,6 +1163,18 @@ qt_configure_add_summary_entry( ARGS "ccache" CONDITION UNIX ) +qt_configure_add_summary_entry( + TYPE "message" ARGS "Unity Build" MESSAGE "yes" CONDITION QT_UNITY_BUILD +) +qt_configure_add_summary_entry( + TYPE "message" ARGS "Unity Build" MESSAGE "no" CONDITION NOT QT_UNITY_BUILD +) +qt_configure_add_summary_entry( + TYPE "message" + ARGS "Unity Build Batch Size" + MESSAGE "${QT_UNITY_BUILD_BATCH_SIZE}" + CONDITION QT_UNITY_BUILD +) qt_configure_add_summary_entry( TYPE "firstAvailableFeature" ARGS "use_bfd_linker use_gold_linker use_lld_linker use_mold_linker" @@ -1326,3 +1344,11 @@ qt_extra_definition("QT_VERSION_PATCH" ${PROJECT_VERSION_PATCH} PUBLIC) qt_extra_definition("QT_COPYRIGHT" \"${QT_COPYRIGHT}\" PRIVATE) qt_extra_definition("QT_COPYRIGHT_YEAR" \"${QT_COPYRIGHT_YEAR}\" PRIVATE) + +qt_configure_add_report_entry( + TYPE WARNING + MESSAGE "QT_ALLOW_SYMLINK_IN_PATHS is enabled. This is not recommended, and it may lead to unexpected issues. +E.g., When building QtWebEngine, enabling this option may result in build issues in certain platforms. +See https://bugreports.qt.io/browse/QTBUG-59769." + CONDITION QT_ALLOW_SYMLINK_IN_PATHS +) diff --git a/doc/config/exampleurl-qtpositioning.qdocconf b/doc/config/exampleurl-qtpositioning.qdocconf new file mode 100644 index 00000000..f8fd478e --- /dev/null +++ b/doc/config/exampleurl-qtpositioning.qdocconf @@ -0,0 +1 @@ +url.examples = "https://code.qt.io/cgit/qt/qtpositioning.git/tree/examples/\1?h=$QT_VER" diff --git a/doc/global/config.qdocconf b/doc/global/config.qdocconf index 59f95cf8..cd4f51fd 100644 --- a/doc/global/config.qdocconf +++ b/doc/global/config.qdocconf @@ -29,6 +29,5 @@ url = https://doc.qt.io/qt defines += qt6 -# Uncomment the following two lines to generate documentation marked as \internal -# alias.internal = disable -# macro.internal.HTML = "[internal]" +# Require Qt modules to define qhp.projects +qhp = true diff --git a/doc/global/html-header-offline.qdocconf b/doc/global/html-header-offline.qdocconf index 4b87e3c7..ffce22ee 100644 --- a/doc/global/html-header-offline.qdocconf +++ b/doc/global/html-header-offline.qdocconf @@ -2,11 +2,13 @@ #specify the CSS file used by this template HTML.stylesheets = template/style/offline.css \ - template/style/offline-dark.css + template/style/offline-dark.css \ + template/style/tech_preview.svg #for including files into the qch file qhp.extraFiles += style/offline.css \ - style/offline-dark.css + style/offline-dark.css \ + style/tech_preview.svg HTML.headerstyles = \ " \n" diff --git a/doc/global/html-header-online.qdocconf b/doc/global/html-header-online.qdocconf index d674e76b..8d258c2a 100644 --- a/doc/global/html-header-online.qdocconf +++ b/doc/global/html-header-online.qdocconf @@ -11,8 +11,10 @@ HTML.stylesheets = template/style/online.css \ template/style/icomoon.woff \ template/style/cookiebar-x.png \ template/style/doc_search.png \ + template/style/tech_preview.svg \ template/style/theqtcompany.png + #for including files into the qch file. Relative to the outputdir of a QDoc build. qhp.extraFiles += style/online.css \ style/cookie-confirm.css \ @@ -25,6 +27,7 @@ qhp.extraFiles += style/online.css \ style/icomoon.woff \ style/cookiebar-x.png \ style/doc_search.png \ + style/tech_preview.svg \ style/theqtcompany.png HTML.headerstyles = \ diff --git a/doc/global/macros.qdocconf b/doc/global/macros.qdocconf index 6c64abee..5a7b826f 100644 --- a/doc/global/macros.qdocconf +++ b/doc/global/macros.qdocconf @@ -56,6 +56,19 @@ macro.endqdoc.HTML = "*/" macro.borderedimage = "\\div {class=\"border\"} \\image \1\n\\enddiv" macro.examplecategory = "\\meta category {\1}\n\\ingroup category \1" +macro.QDS = "Qt Design Studio" +macro.QDV = "Qt Design Viewer" +macro.QB = "Qt Bridge" +macro.QBPS = "Qt Bridge for Adobe Photoshop" +macro.QBXD = "Qt Bridge for Adobe XD" +macro.QBSK = "Qt Bridge for Sketch" +macro.QBF = "Qt Bridge for Figma" +macro.QMCU = "Qt for MCUs" +macro.QUL = "Qt Quick Ultralite" +macro.QtAA = "Qt for Android Automotive" +macro.QOI = "Qt Online Installer" +macro.QMT = "Qt Maintenance Tool" + macro.beginfloatleft.HTML = "
" macro.beginfloatright.HTML = "
" macro.endfloat.HTML = "
" @@ -111,3 +124,8 @@ macro.cmakepropertywebassemblyonly = "\\note This property is used only if targe macro.cmakepropertyiosonly = "\\note This property is used only if targeting iOS." macro.cmakevariableiosonly = "\\note This variable is used only if targeting iOS." + +#Appends the tech preview link to the brief sentence and adds to tech_preview +#group. +#Must be placed directly under a \brief command +macro.techpreview = "(Technical preview)\n\n\\meta status {Technical preview}\n\\ingroup tech_preview\n" diff --git a/doc/global/manifest-meta.qdocconf b/doc/global/manifest-meta.qdocconf index bc8e66f5..6c7ffd86 100644 --- a/doc/global/manifest-meta.qdocconf +++ b/doc/global/manifest-meta.qdocconf @@ -94,7 +94,6 @@ manifestmeta.android.names = "Qt3D/Qt 3D: Basic Shapes C++ Example" \ "QtQuickControls/Qt Quick Controls - Flat Style" \ "QtQuickControls/Qt Quick Controls - Gallery" \ "QtQuickControls/Qt Quick Controls - Imagine Style Example: Automotive" \ - "QtQuickControls/Qt Quick Controls - Imagine Style Example: Music Player" \ "QtQuickControls/Qt Quick Controls - Side Panel" \ "QtQuickControls/Qt Quick Controls - Swipe to Remove" \ "QtQuickControls/Qt Quick Controls - Text Editor" \ @@ -166,7 +165,6 @@ manifestmeta.ios.names = "QtCore/Contiguous Cache Example" \ "QtWidgets/Easing Curves Example" \ "QtWidgets/Move Blocks Example" \ "QtWidgets/States Example" \ - "QtWidgets/Class Wizard Example" \ "QtWidgets/Find Files Example" \ "QtWidgets/License Wizard Example" \ "QtWidgets/Standard Dialogs Example" \ diff --git a/doc/global/template/style/offline.css b/doc/global/template/style/offline.css index 9f0cc8cd..d3846597 100644 --- a/doc/global/template/style/offline.css +++ b/doc/global/template/style/offline.css @@ -574,6 +574,20 @@ ol.I > li { padding: 3px 15px 3px 0 } +span.status.technical-preview { + display: inline-block; + position: relative; + background: center/contain no-repeat url(tech_preview.svg); + width: 26px; + height: 23px; +} + +td.memItemRight span.status { + margin-top: -10px; + right: -10px; + top: 6px; +} + .qml { display: block; margin: 10px; diff --git a/doc/global/template/style/online.css b/doc/global/template/style/online.css index 33487355..4f51864d 100644 --- a/doc/global/template/style/online.css +++ b/doc/global/template/style/online.css @@ -505,6 +505,18 @@ h1,h2,h3,h4,h5,h6 { font-size:150%; margin-bottom: 1em } +span.status.technical-preview { + display:inline-block; + position:relative; + background:center/contain no-repeat url(tech_preview.svg); + width:26px; + height:23px +} +td.memItemRight span.status { + margin-top:-10px; + right:-10px; + top:6px +} article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section { display:block } diff --git a/doc/global/template/style/tech_preview.svg b/doc/global/template/style/tech_preview.svg new file mode 100644 index 00000000..54ce08dd --- /dev/null +++ b/doc/global/template/style/tech_preview.svg @@ -0,0 +1 @@ + diff --git a/doc/src/images/application-menus.png b/doc/src/images/application-menus.png deleted file mode 100644 index 44ac9ca7..00000000 Binary files a/doc/src/images/application-menus.png and /dev/null differ diff --git a/doc/src/images/application.png b/doc/src/images/application.png deleted file mode 100644 index b5fd4597..00000000 Binary files a/doc/src/images/application.png and /dev/null differ diff --git a/doc/src/images/classwizard-flow.png b/doc/src/images/classwizard-flow.png deleted file mode 100644 index ad9446c4..00000000 Binary files a/doc/src/images/classwizard-flow.png and /dev/null differ diff --git a/doc/src/images/classwizard.png b/doc/src/images/classwizard.png deleted file mode 100644 index ea740bd2..00000000 Binary files a/doc/src/images/classwizard.png and /dev/null differ diff --git a/doc/src/images/extension-example.png b/doc/src/images/extension-example.png deleted file mode 100644 index 18fab528..00000000 Binary files a/doc/src/images/extension-example.png and /dev/null differ diff --git a/doc/src/images/extension_more.png b/doc/src/images/extension_more.png deleted file mode 100644 index 407af27c..00000000 Binary files a/doc/src/images/extension_more.png and /dev/null differ diff --git a/doc/src/images/screenshot-example.png b/doc/src/images/screenshot-example.png index 86894867..6bbad985 100644 Binary files a/doc/src/images/screenshot-example.png and b/doc/src/images/screenshot-example.png differ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 2bc1e4d3..0f6e6ba4 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,7 +5,6 @@ qt_examples_build_begin(EXTERNAL_BUILD) add_subdirectory(corelib) add_subdirectory(embedded) -add_subdirectory(qpa) if(TARGET Qt6::DBus) add_subdirectory(dbus) endif() diff --git a/examples/corelib/CMakeLists.txt b/examples/corelib/CMakeLists.txt index 638db2dd..7b0aad9d 100644 --- a/examples/corelib/CMakeLists.txt +++ b/examples/corelib/CMakeLists.txt @@ -6,9 +6,6 @@ add_subdirectory(mimetypes) add_subdirectory(serialization) add_subdirectory(tools) add_subdirectory(platform) -if(QT_FEATURE_permissions) - add_subdirectory(permissions) -endif() if(QT_FEATURE_thread) add_subdirectory(threads) endif() diff --git a/examples/corelib/bindableproperties/bindablesubscription/bindablesubscription.cpp b/examples/corelib/bindableproperties/bindablesubscription/bindablesubscription.cpp index a52b68f8..8b832185 100644 --- a/examples/corelib/bindableproperties/bindablesubscription/bindablesubscription.cpp +++ b/examples/corelib/bindableproperties/bindablesubscription/bindablesubscription.cpp @@ -38,8 +38,7 @@ double BindableSubscription::calculateDiscount() const case Yearly: return 0.6; } - Q_ASSERT(false); - return -1; + Q_UNREACHABLE_RETURN(-1); } int BindableSubscription::basePrice() const diff --git a/examples/corelib/bindableproperties/bindablesubscription/main.cpp b/examples/corelib/bindableproperties/bindablesubscription/main.cpp index 6cf73c13..dd4e26fb 100644 --- a/examples/corelib/bindableproperties/bindablesubscription/main.cpp +++ b/examples/corelib/bindableproperties/bindablesubscription/main.cpp @@ -11,6 +11,10 @@ #include #include #include +#include +#include +#include +#include int main(int argc, char *argv[]) { @@ -19,6 +23,8 @@ int main(int argc, char *argv[]) BindableSubscription subscription(&user); SubscriptionWindow w; + // clazy:excludeall=lambda-in-connect + // when subscription is out of scope so is window // Initialize subscription data QRadioButton *monthly = w.findChild("btnMonthly"); @@ -49,9 +55,8 @@ int main(int argc, char *argv[]) }); QSpinBox *ageSpinBox = w.findChild("ageSpinBox"); - QObject::connect(ageSpinBox, &QSpinBox::valueChanged, [&](int value) { - user.setAge(value); - }); + QBindable ageBindable(ageSpinBox, "value"); + user.bindableAge().setBinding([ageBindable](){ return ageBindable.value();}); QLabel *priceDisplay = w.findChild("priceDisplay"); diff --git a/examples/corelib/platform/androidnotifier/doc/src/androidnotifier-example.qdoc b/examples/corelib/platform/androidnotifier/doc/src/androidnotifier-example.qdoc index 8d2a9a47..37e81485 100644 --- a/examples/corelib/platform/androidnotifier/doc/src/androidnotifier-example.qdoc +++ b/examples/corelib/platform/androidnotifier/doc/src/androidnotifier-example.qdoc @@ -4,6 +4,7 @@ /*! \title Qt Android Notifier \example platform/androidnotifier + \examplecategory {Mobile} \brief Demonstrates calling Java code from Qt in an Android application. \image androidnotifier.png diff --git a/examples/corelib/serialization/CMakeLists.txt b/examples/corelib/serialization/CMakeLists.txt index 7dd5d476..8f6d57eb 100644 --- a/examples/corelib/serialization/CMakeLists.txt +++ b/examples/corelib/serialization/CMakeLists.txt @@ -1,11 +1,10 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -qt_internal_add_example(cbordump) -qt_internal_add_example(convert) -qt_internal_add_example(savegame) -if(TARGET Qt6::Network AND TARGET Qt6::Widgets) - qt_internal_add_example(rsslisting) +if(NOT ANDROID) + qt_internal_add_example(cbordump) + qt_internal_add_example(convert) + qt_internal_add_example(savegame) endif() if(TARGET Qt6::Widgets) qt_internal_add_example(streambookmarks) diff --git a/examples/corelib/serialization/cbordump/CMakeLists.txt b/examples/corelib/serialization/cbordump/CMakeLists.txt index 813b02b9..77e4a601 100644 --- a/examples/corelib/serialization/cbordump/CMakeLists.txt +++ b/examples/corelib/serialization/cbordump/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.16) project(cbordump LANGUAGES CXX) +if (ANDROID) + message(FATAL_ERROR "This project cannot be built on Android.") +endif() + if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif() diff --git a/examples/corelib/serialization/cbordump/doc/images/cbordump.png b/examples/corelib/serialization/cbordump/doc/images/cbordump.png index 72232c1a..d951ff9b 100644 Binary files a/examples/corelib/serialization/cbordump/doc/images/cbordump.png and b/examples/corelib/serialization/cbordump/doc/images/cbordump.png differ diff --git a/examples/corelib/serialization/cbordump/doc/src/cbordump.qdoc b/examples/corelib/serialization/cbordump/doc/src/cbordump.qdoc index f928b987..a4dc0111 100644 --- a/examples/corelib/serialization/cbordump/doc/src/cbordump.qdoc +++ b/examples/corelib/serialization/cbordump/doc/src/cbordump.qdoc @@ -3,7 +3,8 @@ /*! \example serialization/cbordump - \examplecategory {Input/Output} + \examplecategory {Data Processing & I/O} + \meta tag {network} \title Parsing and displaying CBOR data \brief A demonstration of how to parse files in CBOR format. diff --git a/examples/corelib/serialization/cbordump/main.cpp b/examples/corelib/serialization/cbordump/main.cpp index 106c408c..56d4070e 100644 --- a/examples/corelib/serialization/cbordump/main.cpp +++ b/examples/corelib/serialization/cbordump/main.cpp @@ -14,6 +14,8 @@ #include #include +using namespace Qt::StringLiterals; + /* * To regenerate: * curl -O https://www.iana.org/assignments/cbor-tags/cbor-tags.xml @@ -33,7 +35,7 @@ struct CborTagDescription { QCborTag tag; - const char *description; // with space and parentheses + const char *description; // with space and parentheses }; // CBOR Tags @@ -216,22 +218,18 @@ static const CborTagDescription tagDescriptions[] = { enum { // See RFC 7049 section 2. - SmallValueBitLength = 5, - SmallValueMask = (1 << SmallValueBitLength) - 1, /* 0x1f */ - Value8Bit = 24, - Value16Bit = 25, - Value32Bit = 26, - Value64Bit = 27 + SmallValueBitLength = 5, + SmallValueMask = (1 << SmallValueBitLength) - 1, /* 0x1f */ + Value8Bit = 24, + Value16Bit = 25, + Value32Bit = 26, + Value64Bit = 27 }; //! [0] struct CborDumper { - enum DumpOption { - ShowCompact = 0x01, - ShowWidthIndicators = 0x02, - ShowAnnotated = 0x04 - }; + enum DumpOption { ShowCompact = 0x01, ShowWidthIndicators = 0x02, ShowAnnotated = 0x04 }; Q_DECLARE_FLAGS(DumpOptions, DumpOption) CborDumper(QFile *f, DumpOptions opts_); @@ -268,8 +266,7 @@ static int cborNumberSize(quint64 value) return normalSize; } -CborDumper::CborDumper(QFile *f, DumpOptions opts_) - : opts(opts_) +CborDumper::CborDumper(QFile *f, DumpOptions opts_) : opts(opts_) { // try to mmap the file, this is faster char *ptr = reinterpret_cast(f->map(0, f->size(), QFile::MapPrivateOption)); @@ -316,7 +313,8 @@ QCborError CborDumper::dump() return err; } -template static inline bool canConvertTo(double v) +template +static inline bool canConvertTo(double v) { using TypeInfo = std::numeric_limits; // The [conv.fpint] (7.10 Floating-integral conversions) section of the @@ -337,31 +335,32 @@ template static inline bool canConvertTo(double v) return v == floor(v); } -static QString fpToString(double v, const char *suffix) +static QString fpToString(double v, QLatin1StringView suffix = ""_L1) { if (qIsInf(v)) - return v < 0 ? QStringLiteral("-inf") : QStringLiteral("inf"); + return v < 0 ? "-inf"_L1 : "inf"_L1; if (qIsNaN(v)) - return QStringLiteral("nan"); + return "nan"_L1; if (canConvertTo(v)) - return QString::number(qint64(v)) + ".0" + suffix; + return QString::number(qint64(v)) + ".0"_L1 + suffix; if (canConvertTo(v)) - return QString::number(quint64(v)) + ".0" + suffix; + return QString::number(quint64(v)) + ".0"_L1 + suffix; QString s = QString::number(v, 'g', QLocale::FloatingPointShortest); - if (!s.contains('.') && !s.contains('e')) - s += '.'; - s += suffix; + if (!s.contains(u'.') && !s.contains(u'e')) + s += u'.'; + if (suffix.size()) + s += suffix; return s; }; void CborDumper::dumpOne(int nestingLevel) { - QString indent(1, QLatin1Char(' ')); + QString indent(1, u' '); QString indented = indent; if (!opts.testFlag(ShowCompact)) { - indent = QLatin1Char('\n') + QString(4 * nestingLevel, QLatin1Char(' ')); - indented = QLatin1Char('\n') + QString(4 + 4 * nestingLevel, QLatin1Char(' ')); + indent = u'\n' + QString(4 * nestingLevel, u' '); + indented = u'\n' + QString(4 + 4 * nestingLevel, u' '); } switch (reader.type()) { @@ -401,7 +400,7 @@ void CborDumper::dumpOne(int nestingLevel) printStringWidthIndicator(r.data.size()); r = reader.readByteArray(); - comma = QLatin1Char(',') + indented; + comma = u',' + indented; } } else { auto r = reader.readString(); @@ -410,7 +409,7 @@ void CborDumper::dumpOne(int nestingLevel) printStringWidthIndicator(r.data.toUtf8().size()); r = reader.readString(); - comma = QLatin1Char(',') + indented; + comma = u',' + indented; } } @@ -466,7 +465,7 @@ void CborDumper::dumpOne(int nestingLevel) if (reader.next()) { printWidthIndicator(quint64(tag)); printf("("); - dumpOne(nestingLevel); // same level! + dumpOne(nestingLevel); // same level! printf(")"); } @@ -498,15 +497,15 @@ void CborDumper::dumpOne(int nestingLevel) break; case QCborStreamReader::Float16: - printf("%s", qPrintable(fpToString(reader.toFloat16(), "f16"))); + printf("%s", qPrintable(fpToString(reader.toFloat16(), "f16"_L1))); reader.next(); break; case QCborStreamReader::Float: - printf("%s", qPrintable(fpToString(reader.toFloat(), "f"))); + printf("%s", qPrintable(fpToString(reader.toFloat(), "f"_L1))); reader.next(); break; case QCborStreamReader::Double: - printf("%s", qPrintable(fpToString(reader.toDouble(), ""))); + printf("%s", qPrintable(fpToString(reader.toDouble()))); reader.next(); break; case QCborStreamReader::Invalid: @@ -559,7 +558,7 @@ void CborDumper::dumpOneDetailed(int nestingLevel) }; auto printFp = [=](const char *descr, double d) { - QString s = fpToString(d, ""); + QString s = fpToString(d); if (s.size() <= 6) return print(descr, "%s", qPrintable(s)); return print(descr, "%a", d); @@ -574,7 +573,7 @@ void CborDumper::dumpOneDetailed(int nestingLevel) qsizetype size = reader.currentStringChunkSize(); if (size < 0) - return; // error + return; // error if (size >= ChunkSizeLimit) { fprintf(stderr, "String length too big, %lli\n", qint64(size)); exit(EXIT_FAILURE); @@ -619,7 +618,7 @@ void CborDumper::dumpOneDetailed(int nestingLevel) printf(" %s%s", indent.constData(), section.toHex(' ').constData()); // print the decode - QByteArray spaces(width > 0 ? width - section.size() * 3 + 1: 0, ' '); + QByteArray spaces(width > 0 ? width - section.size() * 3 + 1 : 0, ' '); printf("%s # \"", spaces.constData()); auto ptr = reinterpret_cast(section.constData()); for (int j = 0; j < section.size(); ++j) @@ -631,7 +630,7 @@ void CborDumper::dumpOneDetailed(int nestingLevel) // get the next chunk size = reader.currentStringChunkSize(); if (size < 0) - return; // error + return; // error if (size >= ChunkSizeLimit) { fprintf(stderr, "String length too big, %lli\n", qint64(size)); exit(EXIT_FAILURE); @@ -770,7 +769,9 @@ void CborDumper::printByteArray(const QByteArray &ba) break; case quint8(QCborKnownTags::ExpectedBase64url): - printf("b64'%s'", ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals).constData()); + printf("b64'%s'", + ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals) + .constData()); break; } } @@ -811,23 +812,20 @@ int main(int argc, char *argv[]) setlocale(LC_ALL, "C"); QCommandLineParser parser; - parser.setApplicationDescription(QStringLiteral("CBOR Dumper tool")); + parser.setApplicationDescription("CBOR Dumper tool"_L1); parser.addHelpOption(); - QCommandLineOption compact({QStringLiteral("c"), QStringLiteral("compact")}, - QStringLiteral("Use compact form (no line breaks)")); + QCommandLineOption compact({"c"_L1, "compact"_L1}, "Use compact form (no line breaks)"_L1); parser.addOption(compact); - QCommandLineOption showIndicators({QStringLiteral("i"), QStringLiteral("indicators")}, - QStringLiteral("Show indicators for width of lengths and integrals")); + QCommandLineOption showIndicators({ "i"_L1, "indicators"_L1 }, + "Show indicators for width of lengths and integrals"_L1); parser.addOption(showIndicators); - QCommandLineOption verbose({QStringLiteral("a"), QStringLiteral("annotated")}, - QStringLiteral("Show bytes and annotated decoding")); + QCommandLineOption verbose({"a"_L1, "annotated"_L1}, "Show bytes and annotated decoding"_L1); parser.addOption(verbose); - parser.addPositionalArgument(QStringLiteral("[source]"), - QStringLiteral("CBOR file to read from")); + parser.addPositionalArgument("[source]"_L1, "CBOR file to read from"_L1); parser.process(app); diff --git a/examples/corelib/serialization/convert/CMakeLists.txt b/examples/corelib/serialization/convert/CMakeLists.txt index 5a10a78a..b5b960c0 100644 --- a/examples/corelib/serialization/convert/CMakeLists.txt +++ b/examples/corelib/serialization/convert/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.16) project(convert LANGUAGES CXX) +if (ANDROID) + message(FATAL_ERROR "This project cannot be built on Android.") +endif() + if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif() @@ -18,6 +22,7 @@ qt_add_executable(convert cborconverter.cpp cborconverter.h converter.h datastreamconverter.cpp datastreamconverter.h + debugtextdumper.cpp debugtextdumper.h jsonconverter.cpp jsonconverter.h main.cpp nullconverter.cpp nullconverter.h diff --git a/examples/corelib/serialization/convert/cborconverter.cpp b/examples/corelib/serialization/convert/cborconverter.cpp index 85ca8c12..f6a4ee35 100644 --- a/examples/corelib/serialization/convert/cborconverter.cpp +++ b/examples/corelib/serialization/convert/cborconverter.cpp @@ -3,19 +3,21 @@ #include "cborconverter.h" +#include +#include #include #include -#include -#include #include #include -#include #include +#include #include #include #include +using namespace Qt::StringLiterals; + static CborConverter cborConverter; static CborDiagnosticDumper cborDiagnosticDumper; @@ -118,33 +120,33 @@ static QCborValue convertFromVariant(const QVariant &v, TrimFloatingPoint fpTrim } //! [1] -QString CborDiagnosticDumper::name() +QString CborDiagnosticDumper::name() const { - return QStringLiteral("cbor-dump"); + return "cbor-dump"_L1; } -Converter::Direction CborDiagnosticDumper::directions() +Converter::Directions CborDiagnosticDumper::directions() const { - return Out; + return Direction::Out; } -Converter::Options CborDiagnosticDumper::outputOptions() +Converter::Options CborDiagnosticDumper::outputOptions() const { return SupportsArbitraryMapKeys; } -const char *CborDiagnosticDumper::optionsHelp() +const char *CborDiagnosticDumper::optionsHelp() const { return diagnosticHelp; } -bool CborDiagnosticDumper::probeFile(QIODevice *f) +bool CborDiagnosticDumper::probeFile(QIODevice *f) const { Q_UNUSED(f); return false; } -QVariant CborDiagnosticDumper::loadFile(QIODevice *f, Converter *&outputConverter) +QVariant CborDiagnosticDumper::loadFile(QIODevice *f, const Converter *&outputConverter) const { Q_UNREACHABLE(); Q_UNUSED(f); @@ -152,7 +154,8 @@ QVariant CborDiagnosticDumper::loadFile(QIODevice *f, Converter *&outputConverte return QVariant(); } -void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) +void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const { QCborValue::DiagnosticNotationOptions opts = QCborValue::LineWrapped; for (const QString &s : options) { @@ -181,8 +184,7 @@ void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, cons } QTextStream out(f); - out << convertFromVariant(contents, Double).toDiagnosticNotation(opts) - << Qt::endl; + out << convertFromVariant(contents, Double).toDiagnosticNotation(opts) << Qt::endl; } CborConverter::CborConverter() @@ -190,37 +192,37 @@ CborConverter::CborConverter() qRegisterMetaType(); } -QString CborConverter::name() +QString CborConverter::name() const { return "cbor"; } -Converter::Direction CborConverter::directions() +Converter::Directions CborConverter::directions() const { - return InOut; + return Direction::InOut; } -Converter::Options CborConverter::outputOptions() +Converter::Options CborConverter::outputOptions() const { return SupportsArbitraryMapKeys; } -const char *CborConverter::optionsHelp() +const char *CborConverter::optionsHelp() const { return cborOptionHelp; } -bool CborConverter::probeFile(QIODevice *f) +bool CborConverter::probeFile(QIODevice *f) const { if (QFile *file = qobject_cast(f)) { - if (file->fileName().endsWith(QLatin1String(".cbor"))) + if (file->fileName().endsWith(".cbor"_L1)) return true; } return f->isReadable() && f->peek(3) == QByteArray("\xd9\xd9\xf7", 3); } //! [2] -QVariant CborConverter::loadFile(QIODevice *f, Converter *&outputConverter) +QVariant CborConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const { const char *ptr = nullptr; if (auto file = qobject_cast(f)) @@ -256,7 +258,7 @@ QVariant CborConverter::loadFile(QIODevice *f, Converter *&outputConverter) } //! [2] //! [3] -void CborConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) +void CborConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) const { //! [3] bool useSignature = true; @@ -318,8 +320,9 @@ void CborConverter::saveFile(QIODevice *f, const QVariant &contents, const QStri exit(EXIT_FAILURE); } //! [4] - QCborValue v = convertFromVariant(contents, - useFloat16 == Always ? Float16 : useFloat == Always ? Float : Double); + QCborValue v = + convertFromVariant(contents, + useFloat16 == Always ? Float16 : useFloat == Always ? Float : Double); QCborStreamWriter writer(f); if (useSignature) writer.append(QCborKnownTags::Signature); diff --git a/examples/corelib/serialization/convert/cborconverter.h b/examples/corelib/serialization/convert/cborconverter.h index d19c9eb3..ff031856 100644 --- a/examples/corelib/serialization/convert/cborconverter.h +++ b/examples/corelib/serialization/convert/cborconverter.h @@ -10,13 +10,14 @@ class CborDiagnosticDumper : public Converter { // Converter interface public: - QString name() override; - Direction directions() override; - Options outputOptions() override; - const char *optionsHelp() override; - bool probeFile(QIODevice *f) override; - QVariant loadFile(QIODevice *f, Converter *&outputConverter) override; - void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override; + QString name() const override; + Directions directions() const override; + Options outputOptions() const override; + const char *optionsHelp() const override; + bool probeFile(QIODevice *f) const override; + QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override; + void saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const override; }; class CborConverter : public Converter @@ -26,13 +27,14 @@ public: // Converter interface public: - QString name() override; - Direction directions() override; - Options outputOptions() override; - const char *optionsHelp() override; - bool probeFile(QIODevice *f) override; - QVariant loadFile(QIODevice *f, Converter *&outputConverter) override; - void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override; + QString name() const override; + Directions directions() const override; + Options outputOptions() const override; + const char *optionsHelp() const override; + bool probeFile(QIODevice *f) const override; + QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override; + void saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const override; }; #endif // CBORCONVERTER_H diff --git a/examples/corelib/serialization/convert/convert.pro b/examples/corelib/serialization/convert/convert.pro index 4c6b0b55..5f4d8c20 100644 --- a/examples/corelib/serialization/convert/convert.pro +++ b/examples/corelib/serialization/convert/convert.pro @@ -12,17 +12,19 @@ INSTALLS += target SOURCES += main.cpp \ cborconverter.cpp \ - jsonconverter.cpp \ datastreamconverter.cpp \ + debugtextdumper.cpp \ + jsonconverter.cpp \ + nullconverter.cpp \ textconverter.cpp \ - xmlconverter.cpp \ - nullconverter.cpp + xmlconverter.cpp HEADERS += \ converter.h \ cborconverter.h \ - jsonconverter.h \ datastreamconverter.h \ + debugtextdumper.h \ + jsonconverter.h \ + nullconverter.h \ textconverter.h \ - xmlconverter.h \ - nullconverter.h + xmlconverter.h diff --git a/examples/corelib/serialization/convert/converter.h b/examples/corelib/serialization/convert/converter.h index 4da4d472..300f8379 100644 --- a/examples/corelib/serialization/convert/converter.h +++ b/examples/corelib/serialization/convert/converter.h @@ -5,10 +5,10 @@ #define CONVERTER_H #include +#include #include #include #include -#include class VariantOrderedMap : public QList> { @@ -32,26 +32,25 @@ protected: public: static Converter *null; - enum Direction { - In = 1, Out = 2, InOut = 3 - }; + enum class Direction { In = 1, Out = 2, InOut = In | Out }; + Q_DECLARE_FLAGS(Directions, Direction) - enum Option { - SupportsArbitraryMapKeys = 0x01 - }; + enum Option { SupportsArbitraryMapKeys = 0x01 }; Q_DECLARE_FLAGS(Options, Option) virtual ~Converter() = 0; - virtual QString name() = 0; - virtual Direction directions() = 0; - virtual Options outputOptions() = 0; - virtual const char *optionsHelp() = 0; - virtual bool probeFile(QIODevice *f) = 0; - virtual QVariant loadFile(QIODevice *f, Converter *&outputConverter) = 0; - virtual void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) = 0; + virtual QString name() const = 0; + virtual Directions directions() const = 0; + virtual Options outputOptions() const = 0; + virtual const char *optionsHelp() const = 0; + virtual bool probeFile(QIODevice *f) const = 0; + virtual QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const = 0; + virtual void saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const = 0; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(Converter::Directions) Q_DECLARE_OPERATORS_FOR_FLAGS(Converter::Options) #endif // CONVERTER_H diff --git a/examples/corelib/serialization/convert/datastreamconverter.cpp b/examples/corelib/serialization/convert/datastreamconverter.cpp index 451688e3..0cce9dd2 100644 --- a/examples/corelib/serialization/convert/datastreamconverter.cpp +++ b/examples/corelib/serialization/convert/datastreamconverter.cpp @@ -2,20 +2,21 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "datastreamconverter.h" +#include "debugtextdumper.h" #include -#include -#include + +using namespace Qt::StringLiterals; static const char dataStreamOptionHelp[] = "byteorder=host|big|little Byte order to use.\n" - "version= QDataStream version (default: Qt 5.0).\n" + "version= QDataStream version (default: Qt 6.0).\n" ; static const char signature[] = "qds"; -static DataStreamDumper dataStreamDumper; -static DataStreamConverter DataStreamConverter; +static DataStreamConverter dataStreamConverter; +static DebugTextDumper debugTextDumper; QDataStream &operator<<(QDataStream &ds, const VariantOrderedMap &map) { @@ -42,123 +43,43 @@ QDataStream &operator>>(QDataStream &ds, VariantOrderedMap &map) return ds; } - -static QString dumpVariant(const QVariant &v, const QString &indent = QLatin1String("\n")) -{ - QString result; - QString indented = indent + QLatin1String(" "); - - int type = v.userType(); - if (type == qMetaTypeId() || type == QMetaType::QVariantMap) { - const auto map = (type == QMetaType::QVariantMap) ? - VariantOrderedMap(v.toMap()) : qvariant_cast(v); - - result = QLatin1String("Map {"); - for (const auto &pair : map) { - result += indented + dumpVariant(pair.first, indented); - result.chop(1); // remove comma - result += QLatin1String(" => ") + dumpVariant(pair.second, indented); - - } - result.chop(1); // remove comma - result += indent + QLatin1String("},"); - } else if (type == QMetaType::QVariantList) { - const QVariantList list = v.toList(); - - result = QLatin1String("List ["); - for (const auto &item : list) - result += indented + dumpVariant(item, indented); - result.chop(1); // remove comma - result += indent + QLatin1String("],"); - } else { - QDebug debug(&result); - debug.nospace() << v << ','; - } - return result; -} - -QString DataStreamDumper::name() -{ - return QStringLiteral("datastream-dump"); -} - -Converter::Direction DataStreamDumper::directions() -{ - return Out; -} - -Converter::Options DataStreamDumper::outputOptions() -{ - return SupportsArbitraryMapKeys; -} - -const char *DataStreamDumper::optionsHelp() -{ - return nullptr; -} - -bool DataStreamDumper::probeFile(QIODevice *f) -{ - Q_UNUSED(f); - return false; -} - -QVariant DataStreamDumper::loadFile(QIODevice *f, Converter *&outputConverter) -{ - Q_UNREACHABLE(); - Q_UNUSED(f); - Q_UNUSED(outputConverter); - return QVariant(); -} - -void DataStreamDumper::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) -{ - Q_UNUSED(options); - QString s = dumpVariant(contents); - s[s.size() - 1] = QLatin1Char('\n'); // replace the comma with newline - - QTextStream out(f); - out << s; -} - DataStreamConverter::DataStreamConverter() { qRegisterMetaType(); } -QString DataStreamConverter::name() +QString DataStreamConverter::name() const { - return QStringLiteral("datastream"); + return "datastream"_L1; } -Converter::Direction DataStreamConverter::directions() +Converter::Directions DataStreamConverter::directions() const { - return InOut; + return Direction::InOut; } -Converter::Options DataStreamConverter::outputOptions() +Converter::Options DataStreamConverter::outputOptions() const { return SupportsArbitraryMapKeys; } -const char *DataStreamConverter::optionsHelp() +const char *DataStreamConverter::optionsHelp() const { return dataStreamOptionHelp; } -bool DataStreamConverter::probeFile(QIODevice *f) +bool DataStreamConverter::probeFile(QIODevice *f) const { return f->isReadable() && f->peek(sizeof(signature) - 1) == signature; } -QVariant DataStreamConverter::loadFile(QIODevice *f, Converter *&outputConverter) +QVariant DataStreamConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const { if (!outputConverter) - outputConverter = &dataStreamDumper; + outputConverter = &debugTextDumper; char c; - if (f->read(sizeof(signature) -1) != signature || - !f->getChar(&c) || (c != 'l' && c != 'B')) { + if (f->read(sizeof(signature) - 1) != signature || !f->getChar(&c) || (c != 'l' && c != 'B')) { fprintf(stderr, "Could not load QDataStream file: invalid signature.\n"); exit(EXIT_FAILURE); } @@ -175,9 +96,10 @@ QVariant DataStreamConverter::loadFile(QIODevice *f, Converter *&outputConverter return result; } -void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) +void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const { - QDataStream::Version version = QDataStream::Qt_5_0; + QDataStream::Version version = QDataStream::Qt_6_0; auto order = QDataStream::ByteOrder(QSysInfo::ByteOrder); for (const QString &option : options) { const QStringList pair = option.split('='); @@ -213,7 +135,7 @@ void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents, const exit(EXIT_FAILURE); } - char c = order == QDataStream::LittleEndian ? 'l' : 'B'; + char c = order == QDataStream::LittleEndian ? 'l' : 'B'; f->write(signature); f->write(&c, 1); diff --git a/examples/corelib/serialization/convert/datastreamconverter.h b/examples/corelib/serialization/convert/datastreamconverter.h index 95c8861e..201f3c47 100644 --- a/examples/corelib/serialization/convert/datastreamconverter.h +++ b/examples/corelib/serialization/convert/datastreamconverter.h @@ -6,19 +6,6 @@ #include "converter.h" -class DataStreamDumper : public Converter -{ - // Converter interface -public: - QString name() override; - Direction directions() override; - Options outputOptions() override; - const char *optionsHelp() override; - bool probeFile(QIODevice *f) override; - QVariant loadFile(QIODevice *f, Converter *&outputConverter) override; - void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override; -}; - class DataStreamConverter : public Converter { public: @@ -26,13 +13,14 @@ public: // Converter interface public: - QString name() override; - Direction directions() override; - Options outputOptions() override; - const char *optionsHelp() override; - bool probeFile(QIODevice *f) override; - QVariant loadFile(QIODevice *f, Converter *&outputConverter) override; - void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override; + QString name() const override; + Directions directions() const override; + Options outputOptions() const override; + const char *optionsHelp() const override; + bool probeFile(QIODevice *f) const override; + QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override; + void saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const override; }; #endif // DATASTREAMCONVERTER_H diff --git a/examples/corelib/serialization/convert/debugtextdumper.cpp b/examples/corelib/serialization/convert/debugtextdumper.cpp new file mode 100644 index 00000000..dfe3e562 --- /dev/null +++ b/examples/corelib/serialization/convert/debugtextdumper.cpp @@ -0,0 +1,89 @@ +// Copyright (C) 2018 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "debugtextdumper.h" + +#include +#include + +using namespace Qt::StringLiterals; + +// Static instance is declared in datastreamconverter.cpp, since it uses it. + +static QString dumpVariant(const QVariant &v, const QString &indent = "\n"_L1) +{ + QString result; + QString indented = indent + " "_L1; + + int type = v.userType(); + if (type == qMetaTypeId() || type == QMetaType::QVariantMap) { + const auto map = (type == QMetaType::QVariantMap) ? VariantOrderedMap(v.toMap()) + : qvariant_cast(v); + + result = "Map {"_L1; + for (const auto &pair : map) { + result += indented + dumpVariant(pair.first, indented); + result.chop(1); // remove comma + result += " => "_L1 + dumpVariant(pair.second, indented); + } + result.chop(1); // remove comma + result += indent + "},"_L1; + } else if (type == QMetaType::QVariantList) { + const QVariantList list = v.toList(); + + result = "List ["_L1; + for (const auto &item : list) + result += indented + dumpVariant(item, indented); + result.chop(1); // remove comma + result += indent + "],"_L1; + } else { + QDebug debug(&result); + debug.nospace() << v << ','; + } + return result; +} + +QString DebugTextDumper::name() const +{ + return "debugtext-dump"_L1; +} + +Converter::Directions DebugTextDumper::directions() const +{ + return Direction::Out; +} + +Converter::Options DebugTextDumper::outputOptions() const +{ + return SupportsArbitraryMapKeys; +} + +const char *DebugTextDumper::optionsHelp() const +{ + return nullptr; +} + +bool DebugTextDumper::probeFile(QIODevice *f) const +{ + Q_UNUSED(f); + return false; +} + +QVariant DebugTextDumper::loadFile(QIODevice *f, const Converter *&outputConverter) const +{ + Q_UNREACHABLE(); + Q_UNUSED(f); + Q_UNUSED(outputConverter); + return QVariant(); +} + +void DebugTextDumper::saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const +{ + Q_UNUSED(options); + QString s = dumpVariant(contents); + s[s.size() - 1] = u'\n'; // replace the comma with newline + + QTextStream out(f); + out << s; +} diff --git a/examples/corelib/serialization/convert/debugtextdumper.h b/examples/corelib/serialization/convert/debugtextdumper.h new file mode 100644 index 00000000..636e6ccb --- /dev/null +++ b/examples/corelib/serialization/convert/debugtextdumper.h @@ -0,0 +1,23 @@ +// Copyright (C) 2018 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DEBUGTEXTDUMPER_H +#define DEBUGTEXTDUMPER_H + +#include "converter.h" + +class DebugTextDumper : public Converter +{ + // Converter interface +public: + QString name() const override; + Directions directions() const override; + Options outputOptions() const override; + const char *optionsHelp() const override; + bool probeFile(QIODevice *f) const override; + QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override; + void saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const override; +}; + +#endif // DEBUGTEXTDUMPER_H diff --git a/examples/corelib/serialization/convert/doc/src/convert.qdoc b/examples/corelib/serialization/convert/doc/src/convert.qdoc index 156ee5ba..0557aa18 100644 --- a/examples/corelib/serialization/convert/doc/src/convert.qdoc +++ b/examples/corelib/serialization/convert/doc/src/convert.qdoc @@ -3,7 +3,8 @@ /*! \example serialization/convert - \examplecategory {Input/Output} + \examplecategory {Data Processing & I/O} + \meta tag {network} \title Convert Example \brief The Convert example demonstrates how to convert between different @@ -59,7 +60,7 @@ \section1 The DataStreamConverter Class The DataStreamConverter class is used to serialize to and from the - QDataStream format. There is also the DataStreamDumper class for outputting + QDataStream format. There is also the DebugTextDumper class for outputting the data lossless in a non-standardized human readable format. \section1 The JsonConverter Class diff --git a/examples/corelib/serialization/convert/jsonconverter.cpp b/examples/corelib/serialization/convert/jsonconverter.cpp index f52c9db5..b6a6a1dd 100644 --- a/examples/corelib/serialization/convert/jsonconverter.cpp +++ b/examples/corelib/serialization/convert/jsonconverter.cpp @@ -9,10 +9,11 @@ #include #include +using namespace Qt::StringLiterals; + static JsonConverter jsonConverter; -static const char jsonOptionHelp[] = - "compact=no|yes Use compact JSON form.\n"; +static const char jsonOptionHelp[] = "compact=no|yes Use compact JSON form.\n"; static QJsonDocument convertFromVariant(const QVariant &v) { @@ -24,34 +25,30 @@ static QJsonDocument convertFromVariant(const QVariant &v) return doc; } -JsonConverter::JsonConverter() +QString JsonConverter::name() const { + return "json"_L1; } -QString JsonConverter::name() +Converter::Directions JsonConverter::directions() const { - return "json"; + return Direction::InOut; } -Converter::Direction JsonConverter::directions() -{ - return InOut; -} - -Converter::Options JsonConverter::outputOptions() +Converter::Options JsonConverter::outputOptions() const { return {}; } -const char *JsonConverter::optionsHelp() +const char *JsonConverter::optionsHelp() const { return jsonOptionHelp; } -bool JsonConverter::probeFile(QIODevice *f) +bool JsonConverter::probeFile(QIODevice *f) const { if (QFile *file = qobject_cast(f)) { - if (file->fileName().endsWith(QLatin1String(".json"))) + if (file->fileName().endsWith(".json"_L1)) return true; } @@ -62,7 +59,7 @@ bool JsonConverter::probeFile(QIODevice *f) return false; } -QVariant JsonConverter::loadFile(QIODevice *f, Converter *&outputConverter) +QVariant JsonConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const { if (!outputConverter) outputConverter = this; @@ -87,13 +84,14 @@ QVariant JsonConverter::loadFile(QIODevice *f, Converter *&outputConverter) return doc.toVariant(); } -void JsonConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) +void JsonConverter::saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const { QJsonDocument::JsonFormat format = QJsonDocument::Indented; for (const QString &s : options) { - if (s == QLatin1String("compact=no")) { + if (s == "compact=no"_L1) { format = QJsonDocument::Indented; - } else if (s == QLatin1String("compact=yes")) { + } else if (s == "compact=yes"_L1) { format = QJsonDocument::Compact; } else { fprintf(stderr, "Unknown option '%s' to JSON output. Valid options are:\n%s", diff --git a/examples/corelib/serialization/convert/jsonconverter.h b/examples/corelib/serialization/convert/jsonconverter.h index 40430a6b..acff1433 100644 --- a/examples/corelib/serialization/convert/jsonconverter.h +++ b/examples/corelib/serialization/convert/jsonconverter.h @@ -8,18 +8,16 @@ class JsonConverter : public Converter { -public: - JsonConverter(); - // Converter interface public: - QString name() override; - Direction directions() override; - Options outputOptions() override; - const char *optionsHelp() override; - bool probeFile(QIODevice *f) override; - QVariant loadFile(QIODevice *f, Converter *&outputConverter) override; - void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override; + QString name() const override; + Directions directions() const override; + Options outputOptions() const override; + const char *optionsHelp() const override; + bool probeFile(QIODevice *f) const override; + QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override; + void saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const override; }; #endif // JSONCONVERTER_H diff --git a/examples/corelib/serialization/convert/main.cpp b/examples/corelib/serialization/convert/main.cpp index 00c626e1..9a272090 100644 --- a/examples/corelib/serialization/convert/main.cpp +++ b/examples/corelib/serialization/convert/main.cpp @@ -11,12 +11,14 @@ #include -static QList *availableConverters; +using namespace Qt::StringLiterals; + +static QList *availableConverters; Converter::Converter() { if (!availableConverters) - availableConverters = new QList; + availableConverters = new QList; availableConverters->append(this); } @@ -31,64 +33,68 @@ int main(int argc, char *argv[]) QStringList inputFormats; QStringList outputFormats; - for (Converter *conv : std::as_const(*availableConverters)) { + for (const Converter *conv : std::as_const(*availableConverters)) { auto direction = conv->directions(); QString name = conv->name(); - if (direction & Converter::In) + if (direction.testFlag(Converter::Direction::In)) inputFormats << name; - if (direction & Converter::Out) + if (direction.testFlag(Converter::Direction::Out)) outputFormats << name; } inputFormats.sort(); outputFormats.sort(); - inputFormats.prepend("auto"); - outputFormats.prepend("auto"); + inputFormats.prepend("auto"_L1); + outputFormats.prepend("auto"_L1); QCommandLineParser parser; - parser.setApplicationDescription(QStringLiteral("Qt file format conversion tool")); + parser.setApplicationDescription("Qt file format conversion tool"_L1); parser.addHelpOption(); - QCommandLineOption inputFormatOption(QStringList{"I", "input-format"}); - inputFormatOption.setDescription(QLatin1String("Select the input format for the input file. Available formats: ") + - inputFormats.join(", ")); - inputFormatOption.setValueName("format"); + QCommandLineOption inputFormatOption(QStringList{ "I"_L1, "input-format"_L1 }); + inputFormatOption.setDescription( + "Select the input format for the input file. Available formats: "_L1 + + inputFormats.join(", "_L1)); + inputFormatOption.setValueName("format"_L1); inputFormatOption.setDefaultValue(inputFormats.constFirst()); parser.addOption(inputFormatOption); - QCommandLineOption outputFormatOption(QStringList{"O", "output-format"}); - outputFormatOption.setDescription(QLatin1String("Select the output format for the output file. Available formats: ") + - outputFormats.join(", ")); - outputFormatOption.setValueName("format"); + QCommandLineOption outputFormatOption(QStringList{ "O"_L1, "output-format"_L1 }); + outputFormatOption.setDescription( + "Select the output format for the output file. Available formats: "_L1 + + outputFormats.join(", "_L1)); + outputFormatOption.setValueName("format"_L1); outputFormatOption.setDefaultValue(outputFormats.constFirst()); parser.addOption(outputFormatOption); - QCommandLineOption optionOption(QStringList{"o", "option"}); - optionOption.setDescription(QStringLiteral("Format-specific options. Use --format-options to find out what options are available.")); - optionOption.setValueName("options..."); + QCommandLineOption optionOption(QStringList{ "o"_L1, "option"_L1 }); + optionOption.setDescription( + "Format-specific options. Use --format-options to find out what options are available."_L1); + optionOption.setValueName("options..."_L1); optionOption.setDefaultValues({}); parser.addOption(optionOption); - QCommandLineOption formatOptionsOption("format-options"); - formatOptionsOption.setDescription(QStringLiteral("Prints the list of valid options for --option for the converter format .")); - formatOptionsOption.setValueName("format"); + QCommandLineOption formatOptionsOption("format-options"_L1); + formatOptionsOption.setDescription( + "Prints the list of valid options for --option for the converter format ."_L1); + formatOptionsOption.setValueName("format"_L1); parser.addOption(formatOptionsOption); - parser.addPositionalArgument(QStringLiteral("[source]"), - QStringLiteral("File to read from (stdin if none)")); - parser.addPositionalArgument(QStringLiteral("[destination]"), - QStringLiteral("File to write to (stdout if none)")); + parser.addPositionalArgument("[source]"_L1, "File to read from (stdin if none)"_L1); + parser.addPositionalArgument("[destination]"_L1, "File to write to (stdout if none)"_L1); parser.process(app); if (parser.isSet(formatOptionsOption)) { QString format = parser.value(formatOptionsOption); - for (Converter *conv : std::as_const(*availableConverters)) { + for (const Converter *conv : std::as_const(*availableConverters)) { if (conv->name() == format) { const char *help = conv->optionsHelp(); - if (help) - printf("The following options are available for format '%s':\n\n%s", qPrintable(format), help); - else + if (help) { + printf("The following options are available for format '%s':\n\n%s", + qPrintable(format), help); + } else { printf("Format '%s' supports no options.\n", qPrintable(format)); + } return EXIT_SUCCESS; } } @@ -97,10 +103,10 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - Converter *inconv = nullptr; + const Converter *inconv = nullptr; QString format = parser.value(inputFormatOption); - if (format != "auto") { - for (Converter *conv : std::as_const(*availableConverters)) { + if (format != "auto"_L1) { + for (const Converter *conv : std::as_const(*availableConverters)) { if (conv->name() == format) { inconv = conv; break; @@ -113,10 +119,10 @@ int main(int argc, char *argv[]) } } - Converter *outconv = nullptr; + const Converter *outconv = nullptr; format = parser.value(outputFormatOption); - if (format != "auto") { - for (Converter *conv : std::as_const(*availableConverters)) { + if (format != "auto"_L1) { + for (const Converter *conv : std::as_const(*availableConverters)) { if (conv->name() == format) { outconv = conv; break; @@ -155,8 +161,9 @@ int main(int argc, char *argv[]) if (!inconv) { // probe the input to find a file format - for (Converter *conv : std::as_const(*availableConverters)) { - if (conv->directions() & Converter::In && conv->probeFile(&input)) { + for (const Converter *conv : std::as_const(*availableConverters)) { + if (conv->directions().testFlag(Converter::Direction::In) + && conv->probeFile(&input)) { inconv = conv; break; } @@ -170,8 +177,9 @@ int main(int argc, char *argv[]) if (!outconv) { // probe the output to find a file format - for (Converter *conv : std::as_const(*availableConverters)) { - if (conv->directions() & Converter::Out && conv->probeFile(&output)) { + for (const Converter *conv : std::as_const(*availableConverters)) { + if (conv->directions().testFlag(Converter::Direction::Out) + && conv->probeFile(&output)) { outconv = conv; break; } diff --git a/examples/corelib/serialization/convert/nullconverter.cpp b/examples/corelib/serialization/convert/nullconverter.cpp index a3f0bcd9..aababe67 100644 --- a/examples/corelib/serialization/convert/nullconverter.cpp +++ b/examples/corelib/serialization/convert/nullconverter.cpp @@ -3,36 +3,38 @@ #include "nullconverter.h" +using namespace Qt::StringLiterals; + static NullConverter nullConverter; -Converter* Converter::null = &nullConverter; +Converter *Converter::null = &nullConverter; -QString NullConverter::name() +QString NullConverter::name() const { - return QLatin1String("null"); + return "null"_L1; } -Converter::Direction NullConverter::directions() +Converter::Directions NullConverter::directions() const { - return Out; + return Direction::Out; } -Converter::Options NullConverter::outputOptions() +Converter::Options NullConverter::outputOptions() const { return SupportsArbitraryMapKeys; } -const char *NullConverter::optionsHelp() +const char *NullConverter::optionsHelp() const { return nullptr; } -bool NullConverter::probeFile(QIODevice *f) +bool NullConverter::probeFile(QIODevice *f) const { Q_UNUSED(f); return false; } -QVariant NullConverter::loadFile(QIODevice *f, Converter *&outputConverter) +QVariant NullConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const { Q_UNUSED(f); Q_UNUSED(outputConverter); @@ -40,10 +42,12 @@ QVariant NullConverter::loadFile(QIODevice *f, Converter *&outputConverter) return QVariant(); } -void NullConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) +void NullConverter::saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const { if (!options.isEmpty()) { - fprintf(stderr, "Unknown option '%s' to null output. This format has no options.\n", qPrintable(options.first())); + fprintf(stderr, "Unknown option '%s' to null output. This format has no options.\n", + qPrintable(options.first())); exit(EXIT_FAILURE); } diff --git a/examples/corelib/serialization/convert/nullconverter.h b/examples/corelib/serialization/convert/nullconverter.h index b2c69593..fb215c31 100644 --- a/examples/corelib/serialization/convert/nullconverter.h +++ b/examples/corelib/serialization/convert/nullconverter.h @@ -10,13 +10,14 @@ class NullConverter : public Converter { // Converter interface public: - QString name() override; - Direction directions() override; - Options outputOptions() override; - const char *optionsHelp() override; - bool probeFile(QIODevice *f) override; - QVariant loadFile(QIODevice *f, Converter *&outputConverter) override; - void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override; + QString name() const override; + Directions directions() const override; + Options outputOptions() const override; + const char *optionsHelp() const override; + bool probeFile(QIODevice *f) const override; + QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override; + void saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const override; }; #endif // NULLCONVERTER_H diff --git a/examples/corelib/serialization/convert/textconverter.cpp b/examples/corelib/serialization/convert/textconverter.cpp index b02ce12f..2df2423b 100644 --- a/examples/corelib/serialization/convert/textconverter.cpp +++ b/examples/corelib/serialization/convert/textconverter.cpp @@ -6,6 +6,8 @@ #include #include +using namespace Qt::StringLiterals; + static void dumpVariant(QTextStream &out, const QVariant &v) { switch (v.userType()) { @@ -42,67 +44,62 @@ static void dumpVariant(QTextStream &out, const QVariant &v) } } -QString TextConverter::name() +QString TextConverter::name() const { - return QStringLiteral("text"); + return "text"_L1; } -Converter::Direction TextConverter::directions() +Converter::Directions TextConverter::directions() const { - return InOut; + return Direction::InOut; } -Converter::Options TextConverter::outputOptions() +Converter::Options TextConverter::outputOptions() const { return {}; } -const char *TextConverter::optionsHelp() +const char *TextConverter::optionsHelp() const { return nullptr; } -bool TextConverter::probeFile(QIODevice *f) +bool TextConverter::probeFile(QIODevice *f) const { if (QFile *file = qobject_cast(f)) - return file->fileName().endsWith(QLatin1String(".txt")); + return file->fileName().endsWith(".txt"_L1); return false; } -QVariant TextConverter::loadFile(QIODevice *f, Converter *&outputConverter) +QVariant TextConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const { if (!outputConverter) outputConverter = this; QVariantList list; QTextStream in(f); - QString line ; + QString line; while (!in.atEnd()) { in.readLineInto(&line); - bool ok; - qint64 v = line.toLongLong(&ok); - if (ok) { + + if (qint64 v = line.toLongLong(&ok); ok) list.append(v); - continue; - } - - double d = line.toDouble(&ok); - if (ok) { + else if (double d = line.toDouble(&ok); ok) list.append(d); - continue; - } - - list.append(line); + else + list.append(line); } return list; } -void TextConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) +void TextConverter::saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const { if (!options.isEmpty()) { - fprintf(stderr, "Unknown option '%s' to text output. This format has no options.\n", qPrintable(options.first())); + fprintf(stderr, "Unknown option '%s' to text output. This format has no options.\n", + qPrintable(options.first())); exit(EXIT_FAILURE); } diff --git a/examples/corelib/serialization/convert/textconverter.h b/examples/corelib/serialization/convert/textconverter.h index 6379ffc8..46e5500d 100644 --- a/examples/corelib/serialization/convert/textconverter.h +++ b/examples/corelib/serialization/convert/textconverter.h @@ -8,16 +8,16 @@ class TextConverter : public Converter { - // Converter interface public: - QString name() override; - Direction directions() override; - Options outputOptions() override; - const char *optionsHelp() override; - bool probeFile(QIODevice *f) override; - QVariant loadFile(QIODevice *f, Converter *&outputConverter) override; - void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override; + QString name() const override; + Directions directions() const override; + Options outputOptions() const override; + const char *optionsHelp() const override; + bool probeFile(QIODevice *f) const override; + QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override; + void saveFile(QIODevice *f, const QVariant &contents, + const QStringList &options) const override; }; #endif // TEXTCONVERTER_H diff --git a/examples/corelib/serialization/convert/xmlconverter.cpp b/examples/corelib/serialization/convert/xmlconverter.cpp index 080528f6..b625595f 100644 --- a/examples/corelib/serialization/convert/xmlconverter.cpp +++ b/examples/corelib/serialization/convert/xmlconverter.cpp @@ -13,8 +13,9 @@ #include #include -static const char xmlOptionHelp[] = - "compact=no|yes Use compact XML form.\n"; +using namespace Qt::StringLiterals; + +static const char xmlOptionHelp[] = "compact=no|yes Use compact XML form.\n"; static XmlConverter xmlConverter; @@ -23,7 +24,7 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options options) { QVariantList list; - while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("list"))) { + while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == "list"_L1)) { xml.readNext(); switch (xml.tokenType()) { case QXmlStreamReader::StartElement: @@ -47,8 +48,7 @@ static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options option break; } - fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", - xml.lineNumber(), xml.columnNumber(), + fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(), qPrintable(xml.tokenString()), qPrintable(xml.name().toString())); exit(EXIT_FAILURE); } @@ -57,10 +57,11 @@ static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options option return list; } -static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml, Converter::Options options) +static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml, + Converter::Options options) { QVariant key, value; - while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("entry"))) { + while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == "entry"_L1)) { xml.readNext(); switch (xml.tokenType()) { case QXmlStreamReader::StartElement: @@ -89,8 +90,7 @@ static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml, Conv break; } - fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", - xml.lineNumber(), xml.columnNumber(), + fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(), qPrintable(xml.tokenString()), qPrintable(xml.name().toString())); exit(EXIT_FAILURE); } @@ -103,11 +103,11 @@ static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options) QVariantMap map1; VariantOrderedMap map2; - while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("map"))) { + while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == "map"_L1)) { xml.readNext(); switch (xml.tokenType()) { case QXmlStreamReader::StartElement: - if (xml.name() == QLatin1String("entry")) { + if (xml.name() == "entry"_L1) { auto pair = mapEntryFromXml(xml, options); if (options & Converter::SupportsArbitraryMapKeys) map2.append(pair); @@ -134,8 +134,7 @@ static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options) break; } - fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", - xml.lineNumber(), xml.columnNumber(), + fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(), qPrintable(xml.tokenString()), qPrintable(xml.name().toString())); exit(EXIT_FAILURE); } @@ -149,18 +148,18 @@ static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options) static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options) { QStringView name = xml.name(); - if (name == QLatin1String("list")) + if (name == "list"_L1) return listFromXml(xml, options); - if (name == QLatin1String("map")) + if (name == "map"_L1) return mapFromXml(xml, options); - if (name != QLatin1String("value")) { + if (name != "value"_L1) { fprintf(stderr, "%lld:%lld: Invalid XML key '%s'.\n", xml.lineNumber(), xml.columnNumber(), qPrintable(name.toString())); exit(EXIT_FAILURE); } QXmlStreamAttributes attrs = xml.attributes(); - QStringView type = attrs.value(QLatin1String("type")); + QStringView type = attrs.value("type"_L1); forever { xml.readNext(); @@ -169,8 +168,7 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options if (xml.isCDATA() || xml.isCharacters() || xml.isEndElement()) break; - fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", - xml.lineNumber(), xml.columnNumber(), + fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(), qPrintable(xml.tokenString()), qPrintable(name.toString())); exit(EXIT_FAILURE); } @@ -180,45 +178,45 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options text = text.trimmed(); QVariant result; - bool ok; if (type.isEmpty()) { // ok - } else if (type == QLatin1String("number")) { + } else if (type == "number"_L1) { // try integer first + bool ok; qint64 v = text.toLongLong(&ok); if (ok) { result = v; } else { // let's see floating point double d = text.toDouble(&ok); - result = d; if (!ok) { fprintf(stderr, "%lld:%lld: Invalid XML: could not interpret '%s' as a number.\n", xml.lineNumber(), xml.columnNumber(), qPrintable(text.toString())); exit(EXIT_FAILURE); } + result = d; } - } else if (type == QLatin1String("bytes")) { + } else if (type == "bytes"_L1) { QByteArray data = text.toLatin1(); QStringView encoding = attrs.value("encoding"); - if (encoding == QLatin1String("base64url")) { + if (encoding == "base64url"_L1) { result = QByteArray::fromBase64(data, QByteArray::Base64UrlEncoding); - } else if (encoding == QLatin1String("hex")) { + } else if (encoding == "hex"_L1) { result = QByteArray::fromHex(data); - } else if (encoding.isEmpty() || encoding == QLatin1String("base64")) { + } else if (encoding.isEmpty() || encoding == "base64"_L1) { result = QByteArray::fromBase64(data); } else { fprintf(stderr, "%lld:%lld: Invalid XML: unknown encoding '%s' for bytes.\n", xml.lineNumber(), xml.columnNumber(), qPrintable(encoding.toString())); exit(EXIT_FAILURE); } - } else if (type == QLatin1String("string")) { + } else if (type == "string"_L1) { result = text.toString(); - } else if (type == QLatin1String("null")) { + } else if (type == "null"_L1) { result = QVariant::fromValue(nullptr); - } else if (type == QLatin1String("CBOR simple type")) { + } else if (type == "CBOR simple type"_L1) { result = QVariant::fromValue(QCborSimpleType(text.toShort())); - } else if (type == QLatin1String("bits")) { + } else if (type == "bits"_L1) { QBitArray ba; ba.resize(text.size()); qsizetype n = 0; @@ -238,13 +236,13 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options result = ba; } else { int id = QMetaType::UnknownType; - if (type == QLatin1String("datetime")) + if (type == "datetime"_L1) id = QMetaType::QDateTime; - else if (type == QLatin1String("url")) + else if (type == "url"_L1) id = QMetaType::QUrl; - else if (type == QLatin1String("uuid")) + else if (type == "uuid"_L1) id = QMetaType::QUuid; - else if (type == QLatin1String("regex")) + else if (type == "regex"_L1) id = QMetaType::QRegularExpression; else id = QMetaType::fromName(type.toLatin1()).id(); @@ -267,8 +265,7 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options } while (xml.isComment() || xml.isWhitespace()); if (!xml.isEndElement()) { - fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", - xml.lineNumber(), xml.columnNumber(), + fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(), qPrintable(xml.tokenString()), qPrintable(name.toString())); exit(EXIT_FAILURE); } @@ -287,9 +284,9 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v) variantToXml(xml, v); xml.writeEndElement(); } else if (type == QMetaType::QVariantMap || type == qMetaTypeId()) { - const VariantOrderedMap map = (type == QMetaType::QVariantMap) ? - VariantOrderedMap(v.toMap()) : - qvariant_cast(v); + const VariantOrderedMap map = (type == QMetaType::QVariantMap) + ? VariantOrderedMap(v.toMap()) + : qvariant_cast(v); xml.writeStartElement("map"); for (const auto &pair : map) { @@ -301,7 +298,7 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v) xml.writeEndElement(); } else { xml.writeStartElement("value"); - QString typeString = QStringLiteral("type"); + QString typeString = "type"_L1; switch (type) { case QMetaType::Short: case QMetaType::UShort: @@ -399,37 +396,37 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v) } } -QString XmlConverter::name() +QString XmlConverter::name() const { - return QStringLiteral("xml"); + return "xml"_L1; } -Converter::Direction XmlConverter::directions() +Converter::Directions XmlConverter::directions() const { - return InOut; + return Direction::InOut; } -Converter::Options XmlConverter::outputOptions() +Converter::Options XmlConverter::outputOptions() const { return SupportsArbitraryMapKeys; } -const char *XmlConverter::optionsHelp() +const char *XmlConverter::optionsHelp() const { return xmlOptionHelp; } -bool XmlConverter::probeFile(QIODevice *f) +bool XmlConverter::probeFile(QIODevice *f) const { if (QFile *file = qobject_cast(f)) { - if (file->fileName().endsWith(QLatin1String(".xml"))) + if (file->fileName().endsWith(".xml"_L1)) return true; } return f->isReadable() && f->peek(5) == " - -#include "rsslisting.h" - -/*! - Create an application and a main widget. Open the main widget for - user input, and exit with an appropriate return value when it is - closed. -*/ - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - RSSListing *rsslisting = new RSSListing; - rsslisting->show(); - return app.exec(); -} diff --git a/examples/corelib/serialization/rsslisting/rsslisting.cpp b/examples/corelib/serialization/rsslisting/rsslisting.cpp deleted file mode 100644 index 9269be40..00000000 --- a/examples/corelib/serialization/rsslisting/rsslisting.cpp +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -/* -rsslisting.cpp - -Provides a widget for displaying news items from RDF news sources. -RDF is an XML-based format for storing items of information (see -http://www.w3.org/RDF/ for details). - -The widget itself provides a simple user interface for specifying -the URL of a news source, and controlling the downloading of news. - -The widget downloads and parses the XML asynchronously, feeding the -data to an XML reader in pieces. This allows the user to interrupt -its operation, and also allows very large data sources to be read. -*/ - - -#include -#include -#include - -#include "rsslisting.h" - - -/* - Constructs an RSSListing widget with a simple user interface, and sets - up the XML reader to use a custom handler class. - - The user interface consists of a line edit, a push button, and a - list view widget. The line edit is used for entering the URLs of news - sources; the push button starts the process of reading the - news. -*/ - -RSSListing::RSSListing(QWidget *parent) - : QWidget(parent), currentReply(0) -{ - - lineEdit = new QLineEdit(this); - lineEdit->setText("http://blog.qt.io/feed/"); - - fetchButton = new QPushButton(tr("Fetch"), this); - - treeWidget = new QTreeWidget(this); - connect(treeWidget, &QTreeWidget::itemActivated, - this, &RSSListing::itemActivated); - QStringList headerLabels; - headerLabels << tr("Title") << tr("Link"); - treeWidget->setHeaderLabels(headerLabels); - treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents); - - connect(&manager, &QNetworkAccessManager::finished, - this, &RSSListing::finished); - - connect(lineEdit, &QLineEdit::returnPressed, this, &RSSListing::fetch); - connect(fetchButton, &QPushButton::clicked, this, &RSSListing::fetch); - - QVBoxLayout *layout = new QVBoxLayout(this); - - QHBoxLayout *hboxLayout = new QHBoxLayout; - - hboxLayout->addWidget(lineEdit); - hboxLayout->addWidget(fetchButton); - - layout->addLayout(hboxLayout); - layout->addWidget(treeWidget); - - setWindowTitle(tr("RSS listing example")); - resize(640,480); -} - -/* - Starts the network request and connects the needed signals -*/ -void RSSListing::get(const QUrl &url) -{ - QNetworkRequest request(url); - if (currentReply) { - currentReply->disconnect(this); - currentReply->deleteLater(); - } - currentReply = manager.get(request); - connect(currentReply, &QNetworkReply::readyRead, this, &RSSListing::readyRead); - connect(currentReply, &QNetworkReply::metaDataChanged, this, &RSSListing::metaDataChanged); - connect(currentReply, &QNetworkReply::errorOccurred, this, &RSSListing::error); -} - -/* - Starts fetching data from a news source specified in the line - edit widget. - - The line edit is made read only to prevent the user from modifying its - contents during the fetch; this is only for cosmetic purposes. - The fetch button is disabled, the list view is cleared, and we - define the last list view item to be 0, meaning that there are no - existing items in the list. - - A URL is created with the raw contents of the line edit and - a get is initiated. -*/ - -void RSSListing::fetch() -{ - lineEdit->setReadOnly(true); - fetchButton->setEnabled(false); - treeWidget->clear(); - - xml.clear(); - - QUrl url(lineEdit->text()); - get(url); -} - -void RSSListing::metaDataChanged() -{ - QUrl redirectionTarget = currentReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); - if (redirectionTarget.isValid()) { - get(redirectionTarget); - } -} - -/* - Reads data received from the RDF source. - - We read all the available data, and pass it to the XML - stream reader. Then we call the XML parsing function. -*/ - -void RSSListing::readyRead() -{ - int statusCode = currentReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if (statusCode >= 200 && statusCode < 300) { - QByteArray data = currentReply->readAll(); - xml.addData(data); - parseXml(); - } -} - -/* - Finishes processing an HTTP request. - - The default behavior is to keep the text edit read only. - - If an error has occurred, the user interface is made available - to the user for further input, allowing a new fetch to be - started. - - If the HTTP get request has finished, we make the - user interface available to the user for further input. -*/ - -void RSSListing::finished(QNetworkReply *reply) -{ - Q_UNUSED(reply); - lineEdit->setReadOnly(false); - fetchButton->setEnabled(true); -} - - -/* - Parses the XML data and creates treeWidget items accordingly. -*/ -void RSSListing::parseXml() -{ - while (!xml.atEnd()) { - xml.readNext(); - if (xml.isStartElement()) { - if (xml.name() == u"item") - linkString = xml.attributes().value("rss:about").toString(); - currentTag = xml.name().toString(); - } else if (xml.isEndElement()) { - if (xml.name() == u"item") { - - QTreeWidgetItem *item = new QTreeWidgetItem; - item->setText(0, titleString); - item->setText(1, linkString); - treeWidget->addTopLevelItem(item); - - titleString.clear(); - linkString.clear(); - } - - } else if (xml.isCharacters() && !xml.isWhitespace()) { - if (currentTag == "title") - titleString += xml.text(); - else if (currentTag == "link") - linkString += xml.text(); - } - } - if (xml.error() && xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) { - qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString(); - } -} - -/* - Open the link in the browser -*/ -void RSSListing::itemActivated(QTreeWidgetItem * item) -{ - QDesktopServices::openUrl(QUrl(item->text(1))); -} - -void RSSListing::error(QNetworkReply::NetworkError) -{ - qWarning("error retrieving RSS feed"); - currentReply->disconnect(this); - currentReply->deleteLater(); - currentReply = 0; -} diff --git a/examples/corelib/serialization/savegame/CMakeLists.txt b/examples/corelib/serialization/savegame/CMakeLists.txt index 8871a9d6..ab3d9a70 100644 --- a/examples/corelib/serialization/savegame/CMakeLists.txt +++ b/examples/corelib/serialization/savegame/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.16) project(savegame LANGUAGES CXX) +if (ANDROID) + message(FATAL_ERROR "This project cannot be built on Android.") +endif() + if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif() diff --git a/examples/corelib/serialization/savegame/character.cpp b/examples/corelib/serialization/savegame/character.cpp index 7be737f3..863fcb91 100644 --- a/examples/corelib/serialization/savegame/character.cpp +++ b/examples/corelib/serialization/savegame/character.cpp @@ -6,15 +6,10 @@ #include #include -Character::Character() - = default; +Character::Character() = default; -Character::Character(const QString &name, - int level, - Character::ClassType classType) : - mName(name), - mLevel(level), - mClassType(classType) +Character::Character(const QString &name, int level, Character::ClassType classType) + : mName(name), mLevel(level), mClassType(classType) { } @@ -48,35 +43,41 @@ void Character::setClassType(Character::ClassType classType) mClassType = classType; } -//! [0] -void Character::read(const QJsonObject &json) +//! [fromJson] +Character Character::fromJson(const QJsonObject &json) { - if (json.contains("name") && json["name"].isString()) - mName = json["name"].toString(); + Character result; - if (json.contains("level") && json["level"].isDouble()) - mLevel = json["level"].toInt(); + if (const QJsonValue v = json["name"]; v.isString()) + result.mName = v.toString(); - if (json.contains("classType") && json["classType"].isDouble()) - mClassType = ClassType(json["classType"].toInt()); + if (const QJsonValue v = json["level"]; v.isDouble()) + result.mLevel = v.toInt(); + + if (const QJsonValue v = json["classType"]; v.isDouble()) + result.mClassType = ClassType(v.toInt()); + + return result; } -//! [0] +//! [fromJson] -//! [1] -void Character::write(QJsonObject &json) const +//! [toJson] +QJsonObject Character::toJson() const { + QJsonObject json; json["name"] = mName; json["level"] = mLevel; json["classType"] = mClassType; + return json; } -//! [1] +//! [toJson] -void Character::print(int indentation) const +void Character::print(QTextStream &s, int indentation) const { const QString indent(indentation * 2, ' '); - QTextStream(stdout) << indent << "Name:\t" << mName << "\n"; - QTextStream(stdout) << indent << "Level:\t" << mLevel << "\n"; + const QString className = QMetaEnum::fromType().valueToKey(mClassType); - QString className = QMetaEnum::fromType().valueToKey(mClassType); - QTextStream(stdout) << indent << "Class:\t" << className << "\n"; + s << indent << "Name:\t" << mName << "\n" + << indent << "Level:\t" << mLevel << "\n" + << indent << "Class:\t" << className << "\n"; } diff --git a/examples/corelib/serialization/savegame/character.h b/examples/corelib/serialization/savegame/character.h index 4dc25139..05047503 100644 --- a/examples/corelib/serialization/savegame/character.h +++ b/examples/corelib/serialization/savegame/character.h @@ -8,15 +8,15 @@ #include #include +QT_FORWARD_DECLARE_CLASS(QTextStream) + //! [0] class Character { Q_GADGET public: - enum ClassType { - Warrior, Mage, Archer - }; + enum ClassType { Warrior, Mage, Archer }; Q_ENUM(ClassType) Character(); @@ -31,10 +31,11 @@ public: ClassType classType() const; void setClassType(ClassType classType); - void read(const QJsonObject &json); - void write(QJsonObject &json) const; + static Character fromJson(const QJsonObject &json); + QJsonObject toJson() const; + + void print(QTextStream &s, int indentation = 0) const; - void print(int indentation = 0) const; private: QString mName; int mLevel = 0; diff --git a/examples/corelib/serialization/savegame/doc/src/savegame.qdoc b/examples/corelib/serialization/savegame/doc/src/savegame.qdoc index 9b754577..36f02f98 100644 --- a/examples/corelib/serialization/savegame/doc/src/savegame.qdoc +++ b/examples/corelib/serialization/savegame/doc/src/savegame.qdoc @@ -3,7 +3,7 @@ /*! \example serialization/savegame - \examplecategory {Input/Output} + \examplecategory {Data Processing & I/O} \title JSON Save Game Example \brief The JSON Save Game example demonstrates how to save and load a @@ -11,11 +11,12 @@ Many games provide save functionality, so that the player's progress through the game can be saved and loaded at a later time. The process of saving a - game generally involves serializing each game object's member variables - to a file. Many formats can be used for this purpose, one of which is JSON. - With QJsonDocument, you also have the ability to serialize a document in a - \l {RFC 7049} {CBOR} format, which is great if you - don't want the save file to be readable, or if you need to keep the file size down. + game generally involves serializing each game object's member variables to a + file. Many formats can be used for this purpose, one of which is JSON. With + QJsonDocument, you also have the ability to serialize a document in a \l + {RFC 7049} {CBOR} format, which is great if you don't want the save file to + be easy to read (but see \l {Parsing and displaying CBOR data} for how it \e + can be read), or if you need to keep the file size down. In this example, we'll demonstrate how to save and load a simple game to and from JSON and binary formats. @@ -25,45 +26,83 @@ The Character class represents a non-player character (NPC) in our game, and stores the player's name, level, and class type. - It provides read() and write() functions to serialise its member variables. + It provides static fromJson() and non-static toJson() functions to + serialise itself. + + \note This pattern (fromJson()/toJson()) works because QJsonObjects can be + constructed independent of an owning QJsonDocument, and because the data + types being (de)serialized here are value types, so can be copied. When + serializing to another format — for example XML or QDataStream, which require passing + a document-like object — or when the object identity is important (QObject + subclasses, for example), other patterns may be more suitable. See the + \l{xml/dombookmarks} and \l{xml/streambookmarks} examples for XML, and the + implementation of \l QListWidgetItem::read() and \l QListWidgetItem::write() + for idiomatic QDataStream serialization. The \c{print()} functions in this example + are good examples of QTextStream serialization, even though they, of course, lack + the deserialization side. \snippet serialization/savegame/character.h 0 - Of particular interest to us are the read and write function + Of particular interest to us are the fromJson() and toJson() function implementations: - \snippet serialization/savegame/character.cpp 0 + \snippet serialization/savegame/character.cpp fromJson - In the read() function, we assign Character's members values from the - QJsonObject argument. You can use either \l QJsonObject::operator[]() or - QJsonObject::value() to access values within the JSON object; both are - const functions and return QJsonValue::Undefined if the key is invalid. We - check if the keys are valid before attempting to read them with - QJsonObject::contains(). + In the fromJson() function, we construct a local \c result Character object + and assign \c{result}'s members values from the QJsonObject argument. You + can use either \l QJsonObject::operator[]() or QJsonObject::value() to + access values within the JSON object; both are const functions and return + QJsonValue::Undefined if the key is invalid. In particular, the \c{is...} + functions (for example \l QJsonValue::isString(), \l + QJsonValue::isDouble()) return \c false for QJsonValue::Undefined, so we + can check for existence as well as the correct type in a single lookup. - \snippet serialization/savegame/character.cpp 1 + If a value does not exist in the JSON object, or has the wrong type, we + don't write to the corresponding \c result member, either, thereby + preserving any values the default constructor may have set. This means + default values are centrally defined in one location (the default + constructor) and need not be repeated in serialisation code + (\l{https://en.wikipedia.org/wiki/Don%27t_repeat_yourself}{DRY}). - In the write() function, we do the reverse of the read() function; assign - values from the Character object to the JSON object. As with accessing - values, there are two ways to set values on a QJsonObject: - \l QJsonObject::operator[]() and QJsonObject::insert(). Both will override - any existing value at the given key. + Observe the use of + \l{https://en.cppreference.com/w/cpp/language/if#If_statements_with_initializer} + {C++17 if-with-initializer} to separate scoping and checking of the variable \c v. + This means we can keep the variable name short, because its scope is limited. - Next up is the Level class: + Compare that to the naïve approach using \c QJsonObject::contains(): + + \badcode + if (json.contains("name") && json["name"].isString()) + result.mName = json["name"].toString(); + \endcode + + which, beside being less readable, requires a total of three lookups (no, + the compiler will \e not optimize these into one), so is three times + slower and repeats \c{"name"} three times (violating the DRY principle). + + \snippet serialization/savegame/character.cpp toJson + + In the toJson() function, we do the reverse of the fromJson() function; + assign values from the Character object to a new JSON object we then + return. As with accessing values, there are two ways to set values on a + QJsonObject: \l QJsonObject::operator[]() and \l QJsonObject::insert(). + Both will override any existing value at the given key. + + \section1 The Level Class \snippet serialization/savegame/level.h 0 - We want to have several levels in our game, each with several NPCs, so we - keep a QList of Character objects. We also provide the familiar read() and - write() functions. + We want the levels in our game to each each have several NPCs, so we keep a QList + of Character objects. We also provide the familiar fromJson() and toJson() + functions. - \snippet serialization/savegame/level.cpp 0 + \snippet serialization/savegame/level.cpp fromJson - Containers can be written and read to and from JSON using QJsonArray. In our + Containers can be written to and read from JSON using QJsonArray. In our case, we construct a QJsonArray from the value associated with the key \c "npcs". Then, for each QJsonValue element in the array, we call - toObject() to get the Character's JSON object. The Character object can then - read their JSON and be appended to our NPC array. + toObject() to get the Character's JSON object. Character::fromJson() can + then turn that QJSonObject into a Character object to append to our NPC array. \note \l{Container Classes}{Associate containers} can be written by storing the key in each value object (if it's not already). With this approach, the @@ -71,11 +110,13 @@ element is used as the key to construct the container when reading it back in. - \snippet serialization/savegame/level.cpp 1 + \snippet serialization/savegame/level.cpp toJson - Again, the write() function is similar to the read() function, except + Again, the toJson() function is similar to the fromJson() function, except reversed. + \section1 The Game Class + Having established the Character and Level classes, we can move on to the Game class: @@ -87,26 +128,43 @@ Next, we provide accessors for the player and levels. We then expose three functions: newGame(), saveGame() and loadGame(). - The read() and write() functions are used by saveGame() and loadGame(). + The read() and toJson() functions are used by saveGame() and loadGame(). - \snippet serialization/savegame/game.cpp 0 + \div{class="admonition note"}\b{Note:} + Despite \c Game being a value class, we assume that the author wants a game to have + identity, much like your main window would have. We therefore don't use a + static fromJson() function, which would create a new object, but a read() + function we can call on existing objects. There's a 1:1 correspondence + between read() and fromJson(), in that one can be implemented in terms of + the other: + + \code + void read(const QJsonObject &json) { *this = fromJson(json); } + static Game fromObject(const QJsonObject &json) { Game g; g.read(json); return g; } + \endcode + + We just use what's more convenient for callers of the functions. + \enddiv + + \snippet serialization/savegame/game.cpp newGame To setup a new game, we create the player and populate the levels and their NPCs. - \snippet serialization/savegame/game.cpp 1 + \snippet serialization/savegame/game.cpp read - The first thing we do in the read() function is tell the player to read - itself. We then clear the level array so that calling loadGame() on the - same Game object twice doesn't result in old levels hanging around. + The read() function starts by replacing the player with the + one read from JSON. We then clear() the level array so that calling + loadGame() on the same Game object twice doesn't result in old levels + hanging around. We then populate the level array by reading each Level from a QJsonArray. - \snippet serialization/savegame/game.cpp 2 + \snippet serialization/savegame/game.cpp toJson - We write the game to JSON similarly to how we write Level. + Writing the game to JSON is similar to writing a level. - \snippet serialization/savegame/game.cpp 3 + \snippet serialization/savegame/game.cpp loadGame When loading a saved game in loadGame(), the first thing we do is open the save file based on which format it was saved to; \c "save.json" for JSON, @@ -120,14 +178,16 @@ After constructing the QJsonDocument, we instruct the Game object to read itself and then return \c true to indicate success. - \snippet serialization/savegame/game.cpp 4 + \snippet serialization/savegame/game.cpp saveGame Not surprisingly, saveGame() looks very much like loadGame(). We determine the file extension based on the format, print a warning and return \c false if the opening of the file fails. We then write the Game object to a - QJsonDocument, and call either QJsonDocument::toJson() or to - QJsonDocument::toBinaryData() to save the game, depending on which format - was specified. + QJsonObject. To save the game in the format that was specified, we + convert the JSON object into either a QJsonDocument for a subsequent + QJsonDocument::toJson() call, or a QCborValue for QCborValue::toCbor(). + + \section1 Tying It All Together We are now ready to enter main(): diff --git a/examples/corelib/serialization/savegame/game.cpp b/examples/corelib/serialization/savegame/game.cpp index 21dedf94..f99ecb8b 100644 --- a/examples/corelib/serialization/savegame/game.cpp +++ b/examples/corelib/serialization/savegame/game.cpp @@ -11,6 +11,8 @@ #include #include +using namespace Qt::StringLiterals; + Character Game::player() const { return mPlayer; @@ -21,52 +23,45 @@ QList Game::levels() const return mLevels; } -//! [0] +//! [newGame] void Game::newGame() { mPlayer = Character(); - mPlayer.setName(QStringLiteral("Hero")); + mPlayer.setName("Hero"_L1); mPlayer.setClassType(Character::Archer); mPlayer.setLevel(QRandomGenerator::global()->bounded(15, 21)); mLevels.clear(); mLevels.reserve(2); - Level village(QStringLiteral("Village")); + Level village("Village"_L1); QList villageNpcs; villageNpcs.reserve(2); - villageNpcs.append(Character(QStringLiteral("Barry the Blacksmith"), - QRandomGenerator::global()->bounded(8, 11), - Character::Warrior)); - villageNpcs.append(Character(QStringLiteral("Terry the Trader"), - QRandomGenerator::global()->bounded(6, 8), - Character::Warrior)); + villageNpcs.append(Character("Barry the Blacksmith"_L1, + QRandomGenerator::global()->bounded(8, 11), Character::Warrior)); + villageNpcs.append(Character("Terry the Trader"_L1, + QRandomGenerator::global()->bounded(6, 8), Character::Warrior)); village.setNpcs(villageNpcs); mLevels.append(village); - Level dungeon(QStringLiteral("Dungeon")); + Level dungeon("Dungeon"_L1); QList dungeonNpcs; dungeonNpcs.reserve(3); - dungeonNpcs.append(Character(QStringLiteral("Eric the Evil"), - QRandomGenerator::global()->bounded(18, 26), - Character::Mage)); - dungeonNpcs.append(Character(QStringLiteral("Eric's Left Minion"), - QRandomGenerator::global()->bounded(5, 7), - Character::Warrior)); - dungeonNpcs.append(Character(QStringLiteral("Eric's Right Minion"), - QRandomGenerator::global()->bounded(4, 9), - Character::Warrior)); + dungeonNpcs.append(Character("Eric the Evil"_L1, + QRandomGenerator::global()->bounded(18, 26), Character::Mage)); + dungeonNpcs.append(Character("Eric's Left Minion"_L1, + QRandomGenerator::global()->bounded(5, 7), Character::Warrior)); + dungeonNpcs.append(Character("Eric's Right Minion"_L1, + QRandomGenerator::global()->bounded(4, 9), Character::Warrior)); dungeon.setNpcs(dungeonNpcs); mLevels.append(dungeon); } -//! [0] +//! [newGame] -//! [3] +//! [loadGame] bool Game::loadGame(Game::SaveFormat saveFormat) { - QFile loadFile(saveFormat == Json - ? QStringLiteral("save.json") - : QStringLiteral("save.dat")); + QFile loadFile(saveFormat == Json ? "save.json"_L1 : "save.dat"_L1); if (!loadFile.open(QIODevice::ReadOnly)) { qWarning("Couldn't open save file."); @@ -76,85 +71,72 @@ bool Game::loadGame(Game::SaveFormat saveFormat) QByteArray saveData = loadFile.readAll(); QJsonDocument loadDoc(saveFormat == Json - ? QJsonDocument::fromJson(saveData) - : QJsonDocument(QCborValue::fromCbor(saveData).toMap().toJsonObject())); + ? QJsonDocument::fromJson(saveData) + : QJsonDocument(QCborValue::fromCbor(saveData).toMap().toJsonObject())); read(loadDoc.object()); - QTextStream(stdout) << "Loaded save for " - << loadDoc["player"]["name"].toString() - << " using " - << (saveFormat != Json ? "CBOR" : "JSON") << "...\n"; + QTextStream(stdout) << "Loaded save for " << loadDoc["player"]["name"].toString() + << " using " << (saveFormat != Json ? "CBOR" : "JSON") << "...\n"; return true; } -//! [3] +//! [loadGame] -//! [4] +//! [saveGame] bool Game::saveGame(Game::SaveFormat saveFormat) const { - QFile saveFile(saveFormat == Json - ? QStringLiteral("save.json") - : QStringLiteral("save.dat")); + QFile saveFile(saveFormat == Json ? "save.json"_L1 : "save.dat"_L1); if (!saveFile.open(QIODevice::WriteOnly)) { qWarning("Couldn't open save file."); return false; } - QJsonObject gameObject; - write(gameObject); - saveFile.write(saveFormat == Json - ? QJsonDocument(gameObject).toJson() - : QCborValue::fromJsonValue(gameObject).toCbor()); + QJsonObject gameObject = toJson(); + saveFile.write(saveFormat == Json ? QJsonDocument(gameObject).toJson() + : QCborValue::fromJsonValue(gameObject).toCbor()); return true; } -//! [4] +//! [saveGame] -//! [1] +//! [read] void Game::read(const QJsonObject &json) { - if (json.contains("player") && json["player"].isObject()) - mPlayer.read(json["player"].toObject()); + if (const QJsonValue v = json["player"]; v.isObject()) + mPlayer = Character::fromJson(v.toObject()); - if (json.contains("levels") && json["levels"].isArray()) { - QJsonArray levelArray = json["levels"].toArray(); + if (const QJsonValue v = json["levels"]; v.isArray()) { + const QJsonArray levels = v.toArray(); mLevels.clear(); - mLevels.reserve(levelArray.size()); - for (const QJsonValue &v : levelArray) { - QJsonObject levelObject = v.toObject(); - Level level; - level.read(levelObject); - mLevels.append(level); - } + mLevels.reserve(levels.size()); + for (const QJsonValue &level : levels) + mLevels.append(Level::fromJson(level.toObject())); } } -//! [1] +//! [read] -//! [2] -void Game::write(QJsonObject &json) const +//! [toJson] +QJsonObject Game::toJson() const { - QJsonObject playerObject; - mPlayer.write(playerObject); - json["player"] = playerObject; + QJsonObject json; + json["player"] = mPlayer.toJson(); - QJsonArray levelArray; - for (const Level &level : mLevels) { - QJsonObject levelObject; - level.write(levelObject); - levelArray.append(levelObject); - } - json["levels"] = levelArray; + QJsonArray levels; + for (const Level &level : mLevels) + levels.append(level.toJson()); + json["levels"] = levels; + return json; } -//! [2] +//! [toJson] -void Game::print(int indentation) const +void Game::print(QTextStream &s, int indentation) const { const QString indent(indentation * 2, ' '); - QTextStream(stdout) << indent << "Player\n"; - mPlayer.print(indentation + 1); + s << indent << "Player\n"; + mPlayer.print(s, indentation + 1); - QTextStream(stdout) << indent << "Levels\n"; + s << indent << "Levels\n"; for (const Level &level : mLevels) - level.print(indentation + 1); + level.print(s, indentation + 1); } diff --git a/examples/corelib/serialization/savegame/game.h b/examples/corelib/serialization/savegame/game.h index 0e91343d..5ba59529 100644 --- a/examples/corelib/serialization/savegame/game.h +++ b/examples/corelib/serialization/savegame/game.h @@ -10,13 +10,13 @@ #include #include +QT_FORWARD_DECLARE_CLASS(QTextStream) + //! [0] class Game { public: - enum SaveFormat { - Json, Binary - }; + enum SaveFormat { Json, Binary }; Character player() const; QList levels() const; @@ -26,9 +26,10 @@ public: bool saveGame(SaveFormat saveFormat) const; void read(const QJsonObject &json); - void write(QJsonObject &json) const; + QJsonObject toJson() const; + + void print(QTextStream &s, int indentation = 0) const; - void print(int indentation = 0) const; private: Character mPlayer; QList mLevels; diff --git a/examples/corelib/serialization/savegame/level.cpp b/examples/corelib/serialization/savegame/level.cpp index c2f88c34..f30d35e5 100644 --- a/examples/corelib/serialization/savegame/level.cpp +++ b/examples/corelib/serialization/savegame/level.cpp @@ -6,9 +6,7 @@ #include #include -Level::Level(const QString &name) : mName(name) -{ -} +Level::Level(const QString &name) : mName(name) { } QString Level::name() const { @@ -25,46 +23,43 @@ void Level::setNpcs(const QList &npcs) mNpcs = npcs; } -//! [0] -void Level::read(const QJsonObject &json) +//! [fromJson] +Level Level::fromJson(const QJsonObject &json) { - if (json.contains("name") && json["name"].isString()) - mName = json["name"].toString(); + Level result; - if (json.contains("npcs") && json["npcs"].isArray()) { - QJsonArray npcArray = json["npcs"].toArray(); - mNpcs.clear(); - mNpcs.reserve(npcArray.size()); - for (const QJsonValue &v : npcArray) { - QJsonObject npcObject = v.toObject(); - Character npc; - npc.read(npcObject); - mNpcs.append(npc); - } + if (const QJsonValue v = json["name"]; v.isString()) + result.mName = v.toString(); + + if (const QJsonValue v = json["npcs"]; v.isArray()) { + const QJsonArray npcs = v.toArray(); + result.mNpcs.reserve(npcs.size()); + for (const QJsonValue &npc : npcs) + result.mNpcs.append(Character::fromJson(npc.toObject())); } -} -//! [0] -//! [1] -void Level::write(QJsonObject &json) const + return result; +} +//! [fromJson] + +//! [toJson] +QJsonObject Level::toJson() const { + QJsonObject json; json["name"] = mName; QJsonArray npcArray; - for (const Character &npc : mNpcs) { - QJsonObject npcObject; - npc.write(npcObject); - npcArray.append(npcObject); - } + for (const Character &npc : mNpcs) + npcArray.append(npc.toJson()); json["npcs"] = npcArray; + return json; } -//! [1] +//! [toJson] -void Level::print(int indentation) const +void Level::print(QTextStream &s, int indentation) const { const QString indent(indentation * 2, ' '); - QTextStream(stdout) << indent << "Name:\t" << mName << "\n"; - QTextStream(stdout) << indent << "NPCs:\n"; + s << indent << "Name:\t" << mName << "\n" << indent << "NPCs:\n"; for (const Character &character : mNpcs) - character.print(2); + character.print(s, indentation + 1); } diff --git a/examples/corelib/serialization/savegame/level.h b/examples/corelib/serialization/savegame/level.h index e09e2c9f..e487e55a 100644 --- a/examples/corelib/serialization/savegame/level.h +++ b/examples/corelib/serialization/savegame/level.h @@ -9,6 +9,8 @@ #include #include +QT_FORWARD_DECLARE_CLASS(QTextStream) + //! [0] class Level { @@ -21,10 +23,11 @@ public: QList npcs() const; void setNpcs(const QList &npcs); - void read(const QJsonObject &json); - void write(QJsonObject &json) const; + static Level fromJson(const QJsonObject &json); + QJsonObject toJson() const; + + void print(QTextStream &s, int indentation = 0) const; - void print(int indentation = 0) const; private: QString mName; QList mNpcs; diff --git a/examples/corelib/serialization/savegame/main.cpp b/examples/corelib/serialization/savegame/main.cpp index f97b0d59..3fc0f3af 100644 --- a/examples/corelib/serialization/savegame/main.cpp +++ b/examples/corelib/serialization/savegame/main.cpp @@ -17,9 +17,9 @@ int main(int argc, char *argv[]) const QStringList args = QCoreApplication::arguments(); const bool newGame - = args.size() <= 1 || QString::compare(args[1], "load"_L1, Qt::CaseInsensitive) == 0; + = args.size() <= 1 || QString::compare(args[1], "load"_L1, Qt::CaseInsensitive) != 0; const bool json - = args.size() <= 2 || QString::compare(args[2], "binary"_L1, Qt::CaseInsensitive) == 0; + = args.size() <= 2 || QString::compare(args[2], "binary"_L1, Qt::CaseInsensitive) != 0; Game game; if (newGame) @@ -29,8 +29,9 @@ int main(int argc, char *argv[]) // Game is played; changes are made... //! [0] //! [1] - QTextStream(stdout) << "Game ended in the following state:\n"; - game.print(); + QTextStream s(stdout); + s << "Game ended in the following state:\n"; + game.print(s); if (!game.saveGame(json ? Game::Json : Game::Binary)) return 1; diff --git a/examples/corelib/serialization/serialization.pro b/examples/corelib/serialization/serialization.pro index 9f0ced02..e20fcb57 100644 --- a/examples/corelib/serialization/serialization.pro +++ b/examples/corelib/serialization/serialization.pro @@ -6,6 +6,4 @@ SUBDIRS = \ qtHaveModule(widgets) { SUBDIRS += streambookmarks - qtHaveModule(network): SUBDIRS += \ - rsslisting } diff --git a/examples/corelib/serialization/streambookmarks/doc/images/filemenu.png b/examples/corelib/serialization/streambookmarks/doc/images/filemenu.png new file mode 100644 index 00000000..1a92895c Binary files /dev/null and b/examples/corelib/serialization/streambookmarks/doc/images/filemenu.png differ diff --git a/examples/corelib/serialization/streambookmarks/doc/images/helpmenu.png b/examples/corelib/serialization/streambookmarks/doc/images/helpmenu.png new file mode 100644 index 00000000..baa98bee Binary files /dev/null and b/examples/corelib/serialization/streambookmarks/doc/images/helpmenu.png differ diff --git a/examples/corelib/serialization/streambookmarks/doc/images/screenshot.png b/examples/corelib/serialization/streambookmarks/doc/images/screenshot.png new file mode 100644 index 00000000..422873b6 Binary files /dev/null and b/examples/corelib/serialization/streambookmarks/doc/images/screenshot.png differ diff --git a/examples/corelib/serialization/streambookmarks/doc/images/xmlstreamexample-filemenu.png b/examples/corelib/serialization/streambookmarks/doc/images/xmlstreamexample-filemenu.png deleted file mode 100644 index e074fb7c..00000000 Binary files a/examples/corelib/serialization/streambookmarks/doc/images/xmlstreamexample-filemenu.png and /dev/null differ diff --git a/examples/corelib/serialization/streambookmarks/doc/images/xmlstreamexample-helpmenu.png b/examples/corelib/serialization/streambookmarks/doc/images/xmlstreamexample-helpmenu.png deleted file mode 100644 index 0dc4392b..00000000 Binary files a/examples/corelib/serialization/streambookmarks/doc/images/xmlstreamexample-helpmenu.png and /dev/null differ diff --git a/examples/corelib/serialization/streambookmarks/doc/images/xmlstreamexample-screenshot.png b/examples/corelib/serialization/streambookmarks/doc/images/xmlstreamexample-screenshot.png deleted file mode 100644 index bbaa4230..00000000 Binary files a/examples/corelib/serialization/streambookmarks/doc/images/xmlstreamexample-screenshot.png and /dev/null differ diff --git a/examples/corelib/serialization/streambookmarks/doc/src/qxmlstreambookmarks.qdoc b/examples/corelib/serialization/streambookmarks/doc/src/qxmlstreambookmarks.qdoc index 108d7738..8e32dd8d 100644 --- a/examples/corelib/serialization/streambookmarks/doc/src/qxmlstreambookmarks.qdoc +++ b/examples/corelib/serialization/streambookmarks/doc/src/qxmlstreambookmarks.qdoc @@ -3,169 +3,221 @@ /*! \example serialization/streambookmarks + \examplecategory {Data Processing & I/O} + \meta tag {network} \title QXmlStream Bookmarks Example - \examplecategory {Input/Output} - \brief Demonstrates how to read and write to XBEL files. + \brief Demonstrates how to read and write XBEL files. \ingroup xml-examples - The QXmlStream Bookmarks example provides a reader for XML Bookmark - Exchange Language (XBEL) files using Qt's QXmlStreamReader class - for reading, and QXmlStreamWriter class for writing the files. + The QXmlStream Bookmarks example provides a viewer for XML Bookmark Exchange + Language (XBEL) files. It can read bookmarks using Qt's QXmlStreamReader and + write them back out again using QXmlStreamWriter. As this example aims to + show how to use these reader and writer types, it provides no means to open + a bookmark, add a new one, or merge two bookmark files, and only minimal + scope for editing bookmarks. None the less, it could surely be extended with + such features, if desired. - \image xmlstreamexample-screenshot.png + \image screenshot.png \section1 XbelWriter Class Definition - The \c XbelWriter class contains a private instance of QXmlStreamWriter, - which provides an XML writer with a streaming API. \c XbelWriter also - has a reference to the QTreeWidget instance where the bookmark hierarchy - is stored. + The \c XbelWriter class takes a \l{QTreeWidget}{tree widget} describing a + hierarchy of folders containing bookmarks. Its \c writeFile() provides the + means to write out this hierarchy, in XBEL format, to a given output device. + + Internally, it records the tree widget it was given and packages a private + instance of QXmlStreamWriter, which provides it with the means to stream + XML. It has an internal \c writeItem() to write each item in its tree. \snippet serialization/streambookmarks/xbelwriter.h 0 \section1 XbelWriter Class Implementation - The \c XbelWriter constructor accepts a \a treeWidget to initialize within - its definition. We enable \l{QXmlStreamWriter}'s auto-formatting property - to ensure line-breaks and indentations are added automatically to empty - sections between elements, increasing readability as the data is split into - several lines. + The \c XbelWriter constructor accepts the \a treeWidget it will describe. It + stores that and enables \l{QXmlStreamWriter}'s auto-formatting property. + This last splits the data into several lines, with indentation to indicate + the structure of the tree, which makes the XML output easier to read. \snippet serialization/streambookmarks/xbelwriter.cpp 0 - The \c writeFile() function accepts a QIODevice object and sets it using - \c setDevice(). This function then writes the document type - definition(DTD), the start element, the version, and \c{treeWidget}'s - top-level items. + The \c writeFile() function accepts a QIODevice object and directs its + QXmlStreamWriter member to write to this device, using \c setDevice(). This + function then writes the document type definition(DTD), the start element, + the version, and delegates writing of each of the \c{treeWidget}'s top-level + items to \c writeItem(). Finally, it closes the document and returns. \snippet serialization/streambookmarks/xbelwriter.cpp 1 - The \c writeItem() function accepts a QTreeWidgetItem object and writes it - to the stream, depending on its \c tagName, which can either be a "folder", - "bookmark", or "separator". + The \c writeItem() function accepts a QTreeWidgetItem object and writes to + its XML stream a representation of the object, which depends on its \c + UserRole, which can be one of a \c{"folder"}, \c{"bookmark"}, + or \c{"separator"}. Within each folder, it calls itself recursively on each + child item, to recursively include a representation of each child within the + folder's XML element. \snippet serialization/streambookmarks/xbelwriter.cpp 2 \section1 XbelReader Class Definition - The \c XbelReader contains a private instance of QXmlStreamReader, the - companion class to QXmlStreamWriter. \c XbelReader also contains a - reference to the QTreeWidget that is used to group the bookmarks according - to their hierarchy. + The \c XbelReader takes a \l{QTreeWidget}{tree widget} to populate with + items describing a bookmark hierarchy. It supports reading XBEL data from a + QIODevice as a source of these items. If parsing of the XBEL data fails, it + can report what went wrong. + + Internally, it records the QTreeWidget that it will populate and packages an + instance of QXmlStreamReader, the companion class to QXmlStreamWriter, which + it will use to read XBEL data. \snippet serialization/streambookmarks/xbelreader.h 0 \section1 XbelReader Class Implementation - The \c XbelReader constructor accepts a QTreeWidget to initialize the - \c treeWidget within its definition. A QStyle object is used to set - \c{treeWidget}'s style property. The \c folderIcon is set to QIcon::Normal - mode where the pixmap is only displayed when the user is not interacting - with the icon. The QStyle::SP_DirClosedIcon, QStyle::SP_DirOpenIcon, and - QStyle::SP_FileIcon correspond to standard pixmaps that follow the style - of your GUI. + Since the XBEL reader is only concerned with reading XML elements, it makes + extensive use of the \l{QXmlStreamReader::}{readNextStartElement()} + convenience function. + + The \c XbelReader constructor requires a QTreeWidget that it will populate. + It populates the tree widget's style with suitable icons: a folder icon that + changes form to indicate whether each folder as open or closed; and a + standard file icon for the individual bookmarks within those folders. \snippet serialization/streambookmarks/xbelreader.cpp 0 - The \c read() function accepts a QIODevice and sets it using - \l{QXmlStreamReader::}{setDevice()}. The actual process of reading only - takes place if the file is a valid XBEL 1.0 file. Note that the XML input - needs to be well-formed to be accepted by QXmlStreamReader. Otherwise, the - \l{QXmlStreamReader::}{raiseError()} function is used to display an error - message. Since the XBEL reader is only concerned with reading XML elements, - it makes extensive use of the \l{QXmlStreamReader::}{readNextStartElement()} - convenience function. + The \c read() function accepts a QIODevice. It directs its QXmlStreamReader + member to read content from that device. Note that the XML input must be + well-formed to be accepted by QXmlStreamReader. First it reads the outer + structure and verifies the content is an XBEL 1.0 file; if it is, \c read() + delegates the actual reading of content to the internal \c readXBEL(). + + Otherwise, the \l{QXmlStreamReader::}{raiseError()} function is used to + record an error message. The reader itself may also do the same if it + encounters errors in the input. When \c read() has finished, it returns + true if there were no errors. \snippet serialization/streambookmarks/xbelreader.cpp 1 - The \c errorString() function is used if an error occurred, in order to - obtain a description of the error complete with line and column number - information. + If \c read() returns false, its caller can obtain a description of the + error, complete with line and column number within the stream, by calling + the \c errorString() function. \snippet serialization/streambookmarks/xbelreader.cpp 2 - The \c readXBEL() function reads the name of a startElement and calls - the appropriate function to read it, depending on whether if its a - "folder", "bookmark" or "separator". Otherwise, it calls - \l{QXmlStreamReader::}{skipCurrentElement()}. The Q_ASSERT() macro is used - to provide a pre-condition for the function. + The \c readXBEL() function reads the name of a startElement and calls the + appropriate function to read it, depending on whether if its tag name + is \c{"folder"}, \c{"bookmark"} or \c{"separator"}. Any other elements + encountered are skipped. The function starts with a precondition, verifying + that the XML reader has just opened an \c{"xbel"} element. \snippet serialization/streambookmarks/xbelreader.cpp 3 - The \c readTitle() function reads the bookmark's title. - - \snippet serialization/streambookmarks/xbelreader.cpp 4 - - The \c readSeparator() function creates a separator and sets its flags. - The text is set to 30 "0xB7", the HEX equivalent for period. The element - is then skipped using \l{QXmlStreamReader::}{skipCurrentElement()}. + The \c readBookmark() function creates a new editable item representing a + single bookmark. It records the XML \c{"href"} attribute of the current + element as second column text of the item and provisionally sets its first + column text to \c{"Unknown title"} before scanning the rest of the element + for a title element to over-ride that, skipping any unrecognized child + elements. \snippet serialization/streambookmarks/xbelreader.cpp 5 + The \c readTitle() function reads a bookmark's title and records it as the + title (first column text) of the item for which it was called. + + \snippet serialization/streambookmarks/xbelreader.cpp 6 + + The \c readSeparator() function creates a separator and sets its flags. The + separator item's text is set to 30 centered dots. The rest of the element is + then skipped using \l{QXmlStreamReader::}{skipCurrentElement()}. + + \snippet serialization/streambookmarks/xbelreader.cpp 6 + + The \c readFolder() function creates an item and iterates the content of the + folder element, adding children to this item to represent the contents of + the folder element. The loop over folder content is similar in form to the + one in \c readXBEL(), save that it now accepts a title element to set the + title of the folder. + + \snippet serialization/streambookmarks/xbelreader.cpp 7 + + The \c createChildItem() helper function creates a new tree widget item + that's either a child of the given item or, if no parent item is given, a + direct child of the tree widget. It sets the new item's \c UserRole to the + tag name of the current XML element, matching how XbelWriter::writeFile() + uses that \c UserRole. + + \snippet serialization/streambookmarks/xbelreader.cpp 8 + \section1 MainWindow Class Definition - The \c MainWindow class is a subclass of QMainWindow, with a - \c File menu and a \c Help menu. + The \c MainWindow class is a subclass of QMainWindow, with a \c File menu + and a \c Help menu. \snippet serialization/streambookmarks/mainwindow.h 0 \section1 MainWindow Class Implementation - The \c MainWindow constructor instantiates the QTreeWidget object, \c - treeWidget and sets its header with a QStringList object, \c labels. - The constructor also invokes \c createActions() and \c createMenus() - to set up the menus and their corresponding actions. The \c statusBar() - is used to display the message "Ready" and the window's size is fixed - to 480x320 pixels. + The \c MainWindow constructor sets up its QTreeWidget object, \c treeWidget, + as its own central widget, with column headings for the title and location + of each book-mark. It configures a custom menu that enables the user to + perform actions on individual bookmarks within the tree widget. + + It invokes \c createMenus() to set up its own menus and their corresponding + actions. It sets its title, announces itself as ready and sets its size to a + reasonable proportion of the available screen space. \snippet serialization/streambookmarks/mainwindow.cpp 0 - The \c open() function enables the user to open an XBEL file using - QFileDialog::getOpenFileName(). A warning message is displayed along - with the \c fileName and \c errorString if the file cannot be read or - if there is a parse error. + A custom menu, triggered when the user right-clicks on a bookmark, provides + for copying the bookmark as a link or directing a desktop browser to open + the URL it references. This menu is implemented (when relevant features are + enabled) by \c onCustomContextMenuRequested(). \snippet serialization/streambookmarks/mainwindow.cpp 1 - The \c saveAs() function displays a QFileDialog, prompting the user for - a \c fileName using QFileDialog::getSaveFileName(). Similar to the - \c open() function, this function also displays a warning message if - the file cannot be written to. + The \c createMenus() function creates the \c fileMenu and \c helpMenu and + adds QAction objects to them, bound variously to the \c open(), \c saveAs() + and \c about() functions, along with QWidget::close() and + QApplication::aboutQt(). The connections are as shown below: \snippet serialization/streambookmarks/mainwindow.cpp 2 - The \c about() function displays a QMessageBox with a brief description - of the example. - - \snippet serialization/streambookmarks/mainwindow.cpp 3 - - In order to implement the \c open(), \c saveAs(), \c exit(), \c about() - and \c aboutQt() functions, we connect them to QAction objects and - add them to the \c fileMenu and \c helpMenu. The connections are as shown - below: - - \snippet serialization/streambookmarks/mainwindow.cpp 5 - - The \c createMenus() function creates the \c fileMenu and \c helpMenu - and adds the QAction objects to them in order to create the menu shown - in the screenshot below: + This creates the menu shown in the screenshots below: \table \row - \li \inlineimage xmlstreamexample-filemenu.png - \li \inlineimage xmlstreamexample-helpmenu.png + \li \inlineimage filemenu.png + \li \inlineimage helpmenu.png \endtable + The \c open() function, when triggered, offers the user a file dialog to use + to select a bookmarks file. If a file is selected, it is parsed using an \c + XBelReader to populate the \c treeWidget with bookmarks. If problems arise + with opening or parsing the file, a suitable warning message is displayed to + the user, including file name and error message. Otherwise, the bookmarks + read from the file are displayed and the window's status bar briefly reports + that the file has been loaded. + + \snippet serialization/streambookmarks/mainwindow.cpp 3 + + The \c saveAs() function displays a QFileDialog, prompting the user for a \c + fileName, to which to save a copy of the bookmarks data. Similar to the \c + open() function, this function also displays a warning message if the file + cannot be written to. + + \snippet serialization/streambookmarks/mainwindow.cpp 4 + + The \c about() function displays a QMessageBox with a brief description of + the example, or general information about Qt and the version of it in use. + \snippet serialization/streambookmarks/mainwindow.cpp 5 \section1 \c{main()} Function The \c main() function instantiates \c MainWindow and invokes the \c show() - function. + function to display it, then its \c open(), as this is most likely what the + user shall want to do first. \snippet serialization/streambookmarks/main.cpp 0 - See the \l{http://pyxml.sourceforge.net/topics/xbel/} - {XML Bookmark Exchange Language Resource Page} for more information - about XBEL files. + See the \l{https://pyxml.sourceforge.net/topics/xbel/} {XML Bookmark + Exchange Language Resource Page} for more information about XBEL files. */ diff --git a/examples/corelib/serialization/streambookmarks/jennifer.xbel b/examples/corelib/serialization/streambookmarks/jennifer.xbel index 2501c118..d5042368 100644 --- a/examples/corelib/serialization/streambookmarks/jennifer.xbel +++ b/examples/corelib/serialization/streambookmarks/jennifer.xbel @@ -3,66 +3,66 @@ Qt Resources - + Qt home page - + Qt Partners - - Training + + Professional Services - - Qt 5 documentation - - - Frequently Asked Questions + + Qt Documentation Community Resources - + + The Qt Project + + Qt Centre - - QtForum.org + + Forum.Qt.org - + The Independent Qt Tutorial - + German Qt Forum - + Korean Qt Community Site - + Russian Qt Forum Online Dictionaries - + Dictionary.com - + Merriam-Webster Online - + Cambridge Dictionaries Online - + OneLook Dictionary Search - - TU Chemnitz German-English Dictionary + + BEOLINGUS, a service of TU Chemnitz Trésor de la Langue Française informatisé - + Dictionnaire de l'Académie Française diff --git a/examples/corelib/serialization/streambookmarks/main.cpp b/examples/corelib/serialization/streambookmarks/main.cpp index 75b5d646..0fd317de 100644 --- a/examples/corelib/serialization/streambookmarks/main.cpp +++ b/examples/corelib/serialization/streambookmarks/main.cpp @@ -1,10 +1,10 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#include - #include "mainwindow.h" +#include + //! [0] int main(int argc, char *argv[]) { diff --git a/examples/corelib/serialization/streambookmarks/mainwindow.cpp b/examples/corelib/serialization/streambookmarks/mainwindow.cpp index 644681d7..a863f77a 100644 --- a/examples/corelib/serialization/streambookmarks/mainwindow.cpp +++ b/examples/corelib/serialization/streambookmarks/mainwindow.cpp @@ -1,22 +1,33 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#include - #include "mainwindow.h" #include "xbelreader.h" #include "xbelwriter.h" -//! [0] -MainWindow::MainWindow() -{ - QStringList labels; - labels << tr("Title") << tr("Location"); +#include +#include +#include +#include +#include +#include - treeWidget = new QTreeWidget; +#include +#if QT_CONFIG(clipboard) +# include +#endif +#include +#include +#include + +using namespace Qt::StringLiterals; + +//! [0] +MainWindow::MainWindow() : treeWidget(new QTreeWidget) +{ treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch); - treeWidget->setHeaderLabels(labels); -#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + treeWidget->setHeaderLabels(QStringList{tr("Title"), tr("Location")}); +#if QT_CONFIG(clipboard) && QT_CONFIG(contextmenu) treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); connect(treeWidget, &QWidget::customContextMenuRequested, this, &MainWindow::onCustomContextMenuRequested); @@ -33,7 +44,8 @@ MainWindow::MainWindow() } //! [0] -#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) +//! [1] +#if QT_CONFIG(clipboard) && QT_CONFIG(contextmenu) void MainWindow::onCustomContextMenuRequested(const QPoint &pos) { const QTreeWidgetItem *item = treeWidget->itemAt(pos); @@ -49,78 +61,10 @@ void MainWindow::onCustomContextMenuRequested(const QPoint &pos) else if (action == openAction) QDesktopServices::openUrl(QUrl(url)); } -#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD - -//! [1] -void MainWindow::open() -{ - QString fileName = - QFileDialog::getOpenFileName(this, tr("Open Bookmark File"), - QDir::currentPath(), - tr("XBEL Files (*.xbel *.xml)")); - if (fileName.isEmpty()) - return; - - treeWidget->clear(); - - - QFile file(fileName); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("QXmlStream Bookmarks"), - tr("Cannot read file %1:\n%2.") - .arg(QDir::toNativeSeparators(fileName), - file.errorString())); - return; - } - - XbelReader reader(treeWidget); - if (!reader.read(&file)) { - QMessageBox::warning(this, tr("QXmlStream Bookmarks"), - tr("Parse error in file %1:\n\n%2") - .arg(QDir::toNativeSeparators(fileName), - reader.errorString())); - } else { - statusBar()->showMessage(tr("File loaded"), 2000); - } - -} +#endif // QT_CONFIG(clipboard) && QT_CONFIG(contextmenu) //! [1] //! [2] -void MainWindow::saveAs() -{ - QString fileName = - QFileDialog::getSaveFileName(this, tr("Save Bookmark File"), - QDir::currentPath(), - tr("XBEL Files (*.xbel *.xml)")); - if (fileName.isEmpty()) - return; - - QFile file(fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("QXmlStream Bookmarks"), - tr("Cannot write file %1:\n%2.") - .arg(QDir::toNativeSeparators(fileName), - file.errorString())); - return; - } - - XbelWriter writer(treeWidget); - if (writer.writeFile(&file)) - statusBar()->showMessage(tr("File saved"), 2000); -} -//! [2] - -//! [3] -void MainWindow::about() -{ - QMessageBox::about(this, tr("About QXmlStream Bookmarks"), - tr("The QXmlStream Bookmarks example demonstrates how to use Qt's " - "QXmlStream classes to read and write XML documents.")); -} -//! [3] - -//! [5] void MainWindow::createMenus() { QMenu *fileMenu = menuBar()->addMenu(tr("&File")); @@ -137,6 +81,71 @@ void MainWindow::createMenus() QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addAction(tr("&About"), this, &MainWindow::about); - helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit); + helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); +} +//! [2] + +//! [3] +void MainWindow::open() +{ + QFileDialog fileDialog(this, tr("Open Bookmark File"), QDir::currentPath()); + fileDialog.setMimeTypeFilters({"application/x-xbel"_L1}); + if (fileDialog.exec() != QDialog::Accepted) + return; + + treeWidget->clear(); + + const QString fileName = fileDialog.selectedFiles().constFirst(); + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("QXmlStream Bookmarks"), + tr("Cannot read file %1:\n%2.") + .arg(QDir::toNativeSeparators(fileName), file.errorString())); + return; + } + + XbelReader reader(treeWidget); + if (!reader.read(&file)) { + QMessageBox::warning( + this, tr("QXmlStream Bookmarks"), + tr("Parse error in file %1:\n\n%2") + .arg(QDir::toNativeSeparators(fileName), reader.errorString())); + } else { + statusBar()->showMessage(tr("File loaded"), 2000); + } +} +//! [3] + +//! [4] +void MainWindow::saveAs() +{ + QFileDialog fileDialog(this, tr("Save Bookmark File"), QDir::currentPath()); + fileDialog.setAcceptMode(QFileDialog::AcceptSave); + fileDialog.setDefaultSuffix("xbel"_L1); + fileDialog.setMimeTypeFilters({"application/x-xbel"_L1}); + if (fileDialog.exec() != QDialog::Accepted) + return; + + const QString fileName = fileDialog.selectedFiles().constFirst(); + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("QXmlStream Bookmarks"), + tr("Cannot write file %1:\n%2.") + .arg(QDir::toNativeSeparators(fileName), file.errorString())); + return; + } + + XbelWriter writer(treeWidget); + if (writer.writeFile(&file)) + statusBar()->showMessage(tr("File saved"), 2000); +} +//! [4] + +//! [5] +void MainWindow::about() +{ + QMessageBox::about(this, tr("About QXmlStream Bookmarks"), + tr("The QXmlStream Bookmarks example demonstrates how to use Qt's " + "QXmlStream classes to read and write XML documents.")); } //! [5] diff --git a/examples/corelib/serialization/streambookmarks/mainwindow.h b/examples/corelib/serialization/streambookmarks/mainwindow.h index 7a4a922e..d9efe6b5 100644 --- a/examples/corelib/serialization/streambookmarks/mainwindow.h +++ b/examples/corelib/serialization/streambookmarks/mainwindow.h @@ -22,13 +22,13 @@ public slots: void open(); void saveAs(); void about(); -#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) +#if QT_CONFIG(clipboard) && QT_CONFIG(contextmenu) void onCustomContextMenuRequested(const QPoint &pos); #endif private: void createMenus(); - QTreeWidget *treeWidget; + QTreeWidget *const treeWidget; }; //! [0] diff --git a/examples/corelib/serialization/streambookmarks/streambookmarks.pro b/examples/corelib/serialization/streambookmarks/streambookmarks.pro index 9b067c7b..34d2caae 100644 --- a/examples/corelib/serialization/streambookmarks/streambookmarks.pro +++ b/examples/corelib/serialization/streambookmarks/streambookmarks.pro @@ -8,7 +8,7 @@ SOURCES = main.cpp \ QT += widgets requires(qtConfig(filedialog)) -EXAMPLE_FILES = frank.xbel jennifer.xbel +EXAMPLE_FILES = jennifer.xbel # install target.path = $$[QT_INSTALL_EXAMPLES]/corelib/serialization/streambookmarks diff --git a/examples/corelib/serialization/streambookmarks/xbelreader.cpp b/examples/corelib/serialization/streambookmarks/xbelreader.cpp index 74e25f12..c622cf66 100644 --- a/examples/corelib/serialization/streambookmarks/xbelreader.cpp +++ b/examples/corelib/serialization/streambookmarks/xbelreader.cpp @@ -1,20 +1,21 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#include - #include "xbelreader.h" +#include +#include + +using namespace Qt::StringLiterals; + //! [0] -XbelReader::XbelReader(QTreeWidget *treeWidget) - : treeWidget(treeWidget) +XbelReader::XbelReader(QTreeWidget *treeWidget) : treeWidget(treeWidget) { QStyle *style = treeWidget->style(); - folderIcon.addPixmap(style->standardPixmap(QStyle::SP_DirClosedIcon), - QIcon::Normal, QIcon::Off); - folderIcon.addPixmap(style->standardPixmap(QStyle::SP_DirOpenIcon), - QIcon::Normal, QIcon::On); + folderIcon.addPixmap(style->standardPixmap(QStyle::SP_DirClosedIcon), QIcon::Normal, + QIcon::Off); + folderIcon.addPixmap(style->standardPixmap(QStyle::SP_DirOpenIcon), QIcon::Normal, QIcon::On); bookmarkIcon.addPixmap(style->standardPixmap(QStyle::SP_FileIcon)); } //! [0] @@ -25,12 +26,10 @@ bool XbelReader::read(QIODevice *device) xml.setDevice(device); if (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("xbel") - && xml.attributes().value(versionAttribute()) == QLatin1String("1.0")) { + if (xml.name() == "xbel"_L1 && xml.attributes().value("version"_L1) == "1.0"_L1) readXBEL(); - } else { + else xml.raiseError(QObject::tr("The file is not an XBEL version 1.0 file.")); - } } return !xml.error(); @@ -50,15 +49,15 @@ QString XbelReader::errorString() const //! [3] void XbelReader::readXBEL() { - Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("xbel")); + Q_ASSERT(xml.isStartElement() && xml.name() == "xbel"_L1); while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("folder")) - readFolder(0); - else if (xml.name() == QLatin1String("bookmark")) - readBookmark(0); - else if (xml.name() == QLatin1String("separator")) - readSeparator(0); + if (xml.name() == "folder"_L1) + readFolder(nullptr); + else if (xml.name() == "bookmark"_L1) + readBookmark(nullptr); + else if (xml.name() == "separator"_L1) + readSeparator(nullptr); else xml.skipCurrentElement(); } @@ -66,75 +65,76 @@ void XbelReader::readXBEL() //! [3] //! [4] -void XbelReader::readTitle(QTreeWidgetItem *item) -{ - Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("title")); - - QString title = xml.readElementText(); - item->setText(0, title); -} -//! [4] - -//! [5] -void XbelReader::readSeparator(QTreeWidgetItem *item) -{ - Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("separator")); - - QTreeWidgetItem *separator = createChildItem(item); - separator->setFlags(item->flags() & ~Qt::ItemIsSelectable); - separator->setText(0, QString(30, u'\xB7')); - xml.skipCurrentElement(); -} -//! [5] - -void XbelReader::readFolder(QTreeWidgetItem *item) -{ - Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("folder")); - - QTreeWidgetItem *folder = createChildItem(item); - bool folded = (xml.attributes().value(foldedAttribute()) != QLatin1String("no")); - folder->setExpanded(!folded); - - while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("title")) - readTitle(folder); - else if (xml.name() == QLatin1String("folder")) - readFolder(folder); - else if (xml.name() == QLatin1String("bookmark")) - readBookmark(folder); - else if (xml.name() == QLatin1String("separator")) - readSeparator(folder); - else - xml.skipCurrentElement(); - } -} - void XbelReader::readBookmark(QTreeWidgetItem *item) { - Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("bookmark")); + Q_ASSERT(xml.isStartElement() && xml.name() == "bookmark"_L1); QTreeWidgetItem *bookmark = createChildItem(item); bookmark->setFlags(bookmark->flags() | Qt::ItemIsEditable); bookmark->setIcon(0, bookmarkIcon); bookmark->setText(0, QObject::tr("Unknown title")); - bookmark->setText(1, xml.attributes().value(hrefAttribute()).toString()); + bookmark->setText(1, xml.attributes().value("href"_L1).toString()); while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("title")) + if (xml.name() == "title"_L1) readTitle(bookmark); else xml.skipCurrentElement(); } } +//! [4] +//! [5] +void XbelReader::readTitle(QTreeWidgetItem *item) +{ + Q_ASSERT(xml.isStartElement() && xml.name() == "title"_L1); + item->setText(0, xml.readElementText()); +} +//! [5] + +//! [6] +void XbelReader::readSeparator(QTreeWidgetItem *item) +{ + Q_ASSERT(xml.isStartElement() && xml.name() == "separator"_L1); + constexpr char16_t midDot = u'\xB7'; + static const QString dots(30, midDot); + + QTreeWidgetItem *separator = createChildItem(item); + separator->setFlags(item ? item->flags() & ~Qt::ItemIsSelectable : Qt::ItemFlags{}); + separator->setText(0, dots); + xml.skipCurrentElement(); +} +//! [6] + +//! [7] +void XbelReader::readFolder(QTreeWidgetItem *item) +{ + Q_ASSERT(xml.isStartElement() && xml.name() == "folder"_L1); + + QTreeWidgetItem *folder = createChildItem(item); + bool folded = xml.attributes().value("folded"_L1) != "no"_L1; + folder->setExpanded(!folded); + + while (xml.readNextStartElement()) { + if (xml.name() == "title"_L1) + readTitle(folder); + else if (xml.name() == "folder"_L1) + readFolder(folder); + else if (xml.name() == "bookmark"_L1) + readBookmark(folder); + else if (xml.name() == "separator"_L1) + readSeparator(folder); + else + xml.skipCurrentElement(); + } +} +//! [7] + +//! [8] QTreeWidgetItem *XbelReader::createChildItem(QTreeWidgetItem *item) { - QTreeWidgetItem *childItem; - if (item) { - childItem = new QTreeWidgetItem(item); - } else { - childItem = new QTreeWidgetItem(treeWidget); - } + QTreeWidgetItem *childItem = item ? new QTreeWidgetItem(item) : new QTreeWidgetItem(treeWidget); childItem->setData(0, Qt::UserRole, xml.name().toString()); return childItem; } +//! [8] diff --git a/examples/corelib/serialization/streambookmarks/xbelreader.h b/examples/corelib/serialization/streambookmarks/xbelreader.h index 81a59b32..a3fa59d8 100644 --- a/examples/corelib/serialization/streambookmarks/xbelreader.h +++ b/examples/corelib/serialization/streambookmarks/xbelreader.h @@ -21,13 +21,8 @@ public: //! [1] bool read(QIODevice *device); - QString errorString() const; - static inline QString versionAttribute() { return QStringLiteral("version"); } - static inline QString hrefAttribute() { return QStringLiteral("href"); } - static inline QString foldedAttribute() { return QStringLiteral("folded"); } - private: //! [2] void readXBEL(); diff --git a/examples/corelib/serialization/streambookmarks/xbelwriter.cpp b/examples/corelib/serialization/streambookmarks/xbelwriter.cpp index 6cfcd2bc..596696c6 100644 --- a/examples/corelib/serialization/streambookmarks/xbelwriter.cpp +++ b/examples/corelib/serialization/streambookmarks/xbelwriter.cpp @@ -1,18 +1,15 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#include - #include "xbelwriter.h" #include "xbelreader.h" -static inline QString yesValue() { return QStringLiteral("yes"); } -static inline QString noValue() { return QStringLiteral("no"); } -static inline QString titleElement() { return QStringLiteral("title"); } +#include + +using namespace Qt::StringLiterals; //! [0] -XbelWriter::XbelWriter(const QTreeWidget *treeWidget) - : treeWidget(treeWidget) +XbelWriter::XbelWriter(const QTreeWidget *treeWidget) : treeWidget(treeWidget) { xml.setAutoFormatting(true); } @@ -24,9 +21,9 @@ bool XbelWriter::writeFile(QIODevice *device) xml.setDevice(device); xml.writeStartDocument(); - xml.writeDTD(QStringLiteral("")); - xml.writeStartElement(QStringLiteral("xbel")); - xml.writeAttribute(XbelReader::versionAttribute(), QStringLiteral("1.0")); + xml.writeDTD(""_L1); + xml.writeStartElement("xbel"_L1); + xml.writeAttribute("version"_L1, "1.0"_L1); for (int i = 0; i < treeWidget->topLevelItemCount(); ++i) writeItem(treeWidget->topLevelItem(i)); @@ -39,21 +36,21 @@ bool XbelWriter::writeFile(QIODevice *device) void XbelWriter::writeItem(const QTreeWidgetItem *item) { QString tagName = item->data(0, Qt::UserRole).toString(); - if (tagName == QLatin1String("folder")) { + if (tagName == "folder"_L1) { bool folded = !item->isExpanded(); xml.writeStartElement(tagName); - xml.writeAttribute(XbelReader::foldedAttribute(), folded ? yesValue() : noValue()); - xml.writeTextElement(titleElement(), item->text(0)); + xml.writeAttribute("folded"_L1, folded ? "yes"_L1 : "no"_L1); + xml.writeTextElement("title"_L1, item->text(0)); for (int i = 0; i < item->childCount(); ++i) writeItem(item->child(i)); xml.writeEndElement(); - } else if (tagName == QLatin1String("bookmark")) { + } else if (tagName == "bookmark"_L1) { xml.writeStartElement(tagName); if (!item->text(1).isEmpty()) - xml.writeAttribute(XbelReader::hrefAttribute(), item->text(1)); - xml.writeTextElement(titleElement(), item->text(0)); + xml.writeAttribute("href"_L1, item->text(1)); + xml.writeTextElement("title"_L1, item->text(0)); xml.writeEndElement(); - } else if (tagName == QLatin1String("separator")) { + } else if (tagName == "separator"_L1) { xml.writeEmptyElement(tagName); } } diff --git a/examples/corelib/threads/CMakeLists.txt b/examples/corelib/threads/CMakeLists.txt index 4ced9a50..3548be96 100644 --- a/examples/corelib/threads/CMakeLists.txt +++ b/examples/corelib/threads/CMakeLists.txt @@ -1,8 +1,10 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -qt_internal_add_example(semaphores) -qt_internal_add_example(waitconditions) +if(NOT ANDROID) + qt_internal_add_example(semaphores) + qt_internal_add_example(waitconditions) +endif() if(TARGET Qt6::Widgets) qt_internal_add_example(mandelbrot) qt_internal_add_example(queuedcustomtype) diff --git a/examples/corelib/threads/doc/src/mandelbrot.qdoc b/examples/corelib/threads/doc/src/mandelbrot.qdoc index fa9a7fc3..a42a8ee8 100644 --- a/examples/corelib/threads/doc/src/mandelbrot.qdoc +++ b/examples/corelib/threads/doc/src/mandelbrot.qdoc @@ -3,7 +3,7 @@ /*! \example threads/mandelbrot - \title Mandelbrot Example + \title Mandelbrot \ingroup qtconcurrent-mtexamples \brief The Mandelbrot example demonstrates multi-thread programming @@ -151,7 +151,7 @@ it needs to access \c{RenderThread}'s member variables (e.g., in \c render()). - The \c forever keyword is, like \c foreach, a Qt pseudo-keyword. + The \c forever keyword is a Qt pseudo-keyword. \snippet threads/mandelbrot/renderthread.cpp 4 \snippet threads/mandelbrot/renderthread.cpp 5 diff --git a/examples/corelib/threads/mandelbrot/main.cpp b/examples/corelib/threads/mandelbrot/main.cpp index d0d46809..8aafebf7 100644 --- a/examples/corelib/threads/mandelbrot/main.cpp +++ b/examples/corelib/threads/mandelbrot/main.cpp @@ -2,15 +2,14 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "mandelbrotwidget.h" +#include "renderthread.h" #include - -#include - #include #include #include -#include + +using namespace Qt::StringLiterals; //! [0] int main(int argc, char *argv[]) @@ -18,10 +17,10 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); QCommandLineParser parser; - parser.setApplicationDescription("Qt Mandelbrot Example"); + parser.setApplicationDescription(u"Qt Mandelbrot Example"_s); parser.addHelpOption(); parser.addVersionOption(); - QCommandLineOption passesOption("passes", "Number of passes (1-8)", "passes"); + QCommandLineOption passesOption(u"passes"_s, u"Number of passes (1-8)"_s, u"passes"_s); parser.addOption(passesOption); parser.process(app); diff --git a/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp b/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp index e0f33a2b..bbe69483 100644 --- a/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp +++ b/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp @@ -4,19 +4,20 @@ #include "mandelbrotwidget.h" #include +#include #include #include #include //! [0] -const double DefaultCenterX = -0.637011; -const double DefaultCenterY = -0.0395159; -const double DefaultScale = 0.00403897; +constexpr double DefaultCenterX = -0.637011; +constexpr double DefaultCenterY = -0.0395159; +constexpr double DefaultScale = 0.00403897; -const double ZoomInFactor = 0.8; -const double ZoomOutFactor = 1 / ZoomInFactor; -const int ScrollStep = 20; +constexpr double ZoomInFactor = 0.8; +constexpr double ZoomOutFactor = 1 / ZoomInFactor; +constexpr int ScrollStep = 20; //! [0] //! [1] @@ -46,7 +47,8 @@ void MandelbrotWidget::paintEvent(QPaintEvent * /* event */) if (pixmap.isNull()) { painter.setPen(Qt::white); - painter.drawText(rect(), Qt::AlignCenter|Qt::TextWordWrap, tr("Rendering initial image, please wait...")); + painter.drawText(rect(), Qt::AlignCenter|Qt::TextWordWrap, + tr("Rendering initial image, please wait...")); //! [2] //! [3] return; //! [3] //! [4] @@ -60,47 +62,47 @@ void MandelbrotWidget::paintEvent(QPaintEvent * /* event */) //! [6] //! [7] } else { //! [7] //! [8] - auto previewPixmap = qFuzzyCompare(pixmap.devicePixelRatio(), qreal(1)) + const auto previewPixmap = qFuzzyCompare(pixmap.devicePixelRatio(), qreal(1)) ? pixmap : pixmap.scaled(pixmap.deviceIndependentSize().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation); - double scaleFactor = pixmapScale / curScale; - int newWidth = int(previewPixmap.width() * scaleFactor); - int newHeight = int(previewPixmap.height() * scaleFactor); - int newX = pixmapOffset.x() + (previewPixmap.width() - newWidth) / 2; - int newY = pixmapOffset.y() + (previewPixmap.height() - newHeight) / 2; + const double scaleFactor = pixmapScale / curScale; + const int newWidth = int(previewPixmap.width() * scaleFactor); + const int newHeight = int(previewPixmap.height() * scaleFactor); + const int newX = pixmapOffset.x() + (previewPixmap.width() - newWidth) / 2; + const int newY = pixmapOffset.y() + (previewPixmap.height() - newHeight) / 2; painter.save(); painter.translate(newX, newY); painter.scale(scaleFactor, scaleFactor); - QRectF exposed = painter.transform().inverted().mapRect(rect()).adjusted(-1, -1, 1, 1); + const QRectF exposed = painter.transform().inverted().mapRect(rect()) + .adjusted(-1, -1, 1, 1); painter.drawPixmap(exposed, previewPixmap, exposed); painter.restore(); } //! [8] //! [9] - QFontMetrics metrics = painter.fontMetrics(); + const QFontMetrics metrics = painter.fontMetrics(); if (!info.isEmpty()){ - int infoWidth = metrics.horizontalAdvance(info); - int infoHeight = metrics.height(); + const int infoWidth = metrics.horizontalAdvance(info); + const int infoHeight = (infoWidth/width() + 1) * (metrics.height() + 5); painter.setPen(Qt::NoPen); painter.setBrush(QColor(0, 0, 0, 127)); - infoHeight = (infoWidth/width()+1) * (infoHeight + 5); painter.drawRect((width() - infoWidth) / 2 - 5, 0, infoWidth + 10, infoHeight); painter.setPen(Qt::white); painter.drawText(rect(), Qt::AlignHCenter|Qt::AlignTop|Qt::TextWordWrap, info); } - int helpWidth = metrics.horizontalAdvance(help); - int helpHeight = metrics.height(); + const int helpWidth = metrics.horizontalAdvance(help); + const int helpHeight = (helpWidth/width() + 1) * (metrics.height() + 5); painter.setPen(Qt::NoPen); painter.setBrush(QColor(0, 0, 0, 127)); - helpHeight = (helpWidth/width()+1) * (helpHeight + 5); - painter.drawRect((width() - helpWidth) / 2 - 5, height()-helpHeight, helpWidth + 10, helpHeight); + painter.drawRect((width() - helpWidth) / 2 - 5, height()-helpHeight, helpWidth + 10, + helpHeight); painter.setPen(Qt::white); painter.drawText(rect(), Qt::AlignHCenter|Qt::AlignBottom|Qt::TextWordWrap, help); @@ -184,8 +186,8 @@ void MandelbrotWidget::mouseReleaseEvent(QMouseEvent *event) lastDragPos = QPoint(); const auto pixmapSize = pixmap.deviceIndependentSize().toSize(); - int deltaX = (width() - pixmapSize.width()) / 2 - pixmapOffset.x(); - int deltaY = (height() - pixmapSize.height()) / 2 - pixmapOffset.y(); + const int deltaX = (width() - pixmapSize.width()) / 2 - pixmapOffset.x(); + const int deltaY = (height() - pixmapSize.height()) / 2 - pixmapOffset.y(); scroll(deltaX, deltaY); } } diff --git a/examples/corelib/threads/mandelbrot/mandelbrotwidget.h b/examples/corelib/threads/mandelbrot/mandelbrotwidget.h index 23c3a2bf..642feebd 100644 --- a/examples/corelib/threads/mandelbrot/mandelbrotwidget.h +++ b/examples/corelib/threads/mandelbrot/mandelbrotwidget.h @@ -4,11 +4,14 @@ #ifndef MANDELBROTWIDGET_H #define MANDELBROTWIDGET_H -#include -#include -#include #include "renderthread.h" +#include +#include + +QT_BEGIN_NAMESPACE +class QGestureEvent; +QT_END_NAMESPACE //! [0] class MandelbrotWidget : public QWidget diff --git a/examples/corelib/threads/mandelbrot/renderthread.cpp b/examples/corelib/threads/mandelbrot/renderthread.cpp index 9e6c884f..77a14a6a 100644 --- a/examples/corelib/threads/mandelbrot/renderthread.cpp +++ b/examples/corelib/threads/mandelbrot/renderthread.cpp @@ -4,7 +4,6 @@ #include "renderthread.h" #include - #include #include @@ -70,16 +69,16 @@ void RenderThread::run() //! [3] //! [4] - int halfWidth = resultSize.width() / 2; + const int halfWidth = resultSize.width() / 2; //! [4] //! [5] - int halfHeight = resultSize.height() / 2; + const int halfHeight = resultSize.height() / 2; QImage image(resultSize, QImage::Format_RGB32); image.setDevicePixelRatio(devicePixelRatio); int pass = 0; while (pass < numPasses) { const int MaxIterations = (1 << (2 * pass + 6)) + 32; - const int Limit = 4; + constexpr int Limit = 4; bool allBlack = true; timer.restart(); diff --git a/examples/corelib/threads/semaphores/CMakeLists.txt b/examples/corelib/threads/semaphores/CMakeLists.txt index bccf6e1e..fee3f7a5 100644 --- a/examples/corelib/threads/semaphores/CMakeLists.txt +++ b/examples/corelib/threads/semaphores/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.16) project(semaphores LANGUAGES CXX) +if (ANDROID) + message(FATAL_ERROR "This project cannot be built on Android.") +endif() + if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif() diff --git a/examples/corelib/threads/semaphores/semaphores.cpp b/examples/corelib/threads/semaphores/semaphores.cpp index 5a495551..103f331b 100644 --- a/examples/corelib/threads/semaphores/semaphores.cpp +++ b/examples/corelib/threads/semaphores/semaphores.cpp @@ -7,9 +7,9 @@ #include //! [0] -const int DataSize = 100000; +constexpr int DataSize = 100000; -const int BufferSize = 8192; +constexpr int BufferSize = 8192; char buffer[BufferSize]; QSemaphore freeBytes(BufferSize); diff --git a/examples/corelib/threads/waitconditions/CMakeLists.txt b/examples/corelib/threads/waitconditions/CMakeLists.txt index 45818e2b..a51cc5f8 100644 --- a/examples/corelib/threads/waitconditions/CMakeLists.txt +++ b/examples/corelib/threads/waitconditions/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.16) project(waitconditions LANGUAGES CXX) +if (ANDROID) + message(FATAL_ERROR "This project cannot be built on Android.") +endif() + if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif() diff --git a/examples/dbus/CMakeLists.txt b/examples/dbus/CMakeLists.txt index 738d1e47..b6276f56 100644 --- a/examples/dbus/CMakeLists.txt +++ b/examples/dbus/CMakeLists.txt @@ -4,9 +4,11 @@ if(NOT TARGET Qt6::DBus) return() endif() -qt_internal_add_example(pingpong) -if(QT_FEATURE_process) - qt_internal_add_example(complexpingpong) +if(NOT ANDROID) + qt_internal_add_example(pingpong) + if(QT_FEATURE_process) + qt_internal_add_example(complexpingpong) + endif() endif() if(TARGET Qt6::Widgets) qt_internal_add_example(chat) diff --git a/examples/dbus/complexpingpong/CMakeLists.txt b/examples/dbus/complexpingpong/CMakeLists.txt index 377b56b1..3d7f0089 100644 --- a/examples/dbus/complexpingpong/CMakeLists.txt +++ b/examples/dbus/complexpingpong/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.16) project(complexpingpong LANGUAGES CXX) +if (ANDROID) + message(FATAL_ERROR "This project cannot be built on Android.") +endif() + if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif() diff --git a/examples/dbus/doc/src/chat.qdoc b/examples/dbus/doc/src/chat.qdoc index 12bd498a..905c937e 100644 --- a/examples/dbus/doc/src/chat.qdoc +++ b/examples/dbus/doc/src/chat.qdoc @@ -4,6 +4,7 @@ /*! \example chat \title D-Bus Chat + \examplecategory {Connectivity} \ingroup examples-dbus \brief Demonstrates communication among instances of an application. diff --git a/examples/dbus/doc/src/complexpingpong.qdoc b/examples/dbus/doc/src/complexpingpong.qdoc index 0521eafb..84fccdf5 100644 --- a/examples/dbus/doc/src/complexpingpong.qdoc +++ b/examples/dbus/doc/src/complexpingpong.qdoc @@ -4,6 +4,7 @@ /*! \example complexpingpong \title D-Bus Complex Ping Pong + \examplecategory {Connectivity} \ingroup examples-dbus \brief Demonstrates usage of the Qt D-Bus typesystem. diff --git a/examples/dbus/doc/src/pingpong.qdoc b/examples/dbus/doc/src/pingpong.qdoc index 1e2b114a..1ab0ec62 100644 --- a/examples/dbus/doc/src/pingpong.qdoc +++ b/examples/dbus/doc/src/pingpong.qdoc @@ -4,6 +4,7 @@ /*! \example pingpong \title D-Bus Ping Pong + \examplecategory {Connectivity} \ingroup examples-dbus \brief Demonstrates a simple message system using D-Bus. diff --git a/examples/dbus/pingpong/CMakeLists.txt b/examples/dbus/pingpong/CMakeLists.txt index 5d598137..d9b28443 100644 --- a/examples/dbus/pingpong/CMakeLists.txt +++ b/examples/dbus/pingpong/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.16) project(pingpong LANGUAGES CXX) +if (ANDROID) + message(FATAL_ERROR "This project cannot be built on Android.") +endif() + if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif() diff --git a/examples/dbus/remotecontrolledcar/doc/src/dbus-remotecontrolledcar.qdoc b/examples/dbus/remotecontrolledcar/doc/src/dbus-remotecontrolledcar.qdoc index a9c04e82..94c914b6 100644 --- a/examples/dbus/remotecontrolledcar/doc/src/dbus-remotecontrolledcar.qdoc +++ b/examples/dbus/remotecontrolledcar/doc/src/dbus-remotecontrolledcar.qdoc @@ -4,6 +4,7 @@ /*! \example remotecontrolledcar \title D-Bus Remote Controlled Car + \examplecategory {Connectivity} \ingroup examples-dbus \brief Shows how to use Qt D-Bus to control a car from another application. diff --git a/examples/embedded/flightinfo/flightinfo.cpp b/examples/embedded/flightinfo/flightinfo.cpp index c4d81177..96a3e272 100644 --- a/examples/embedded/flightinfo/flightinfo.cpp +++ b/examples/embedded/flightinfo/flightinfo.cpp @@ -342,8 +342,6 @@ private: int main(int argc, char **argv) { - Q_INIT_RESOURCE(flightinfo); - QApplication app(argc, argv); FlightInfo w; diff --git a/examples/embedded/styleexample/main.cpp b/examples/embedded/styleexample/main.cpp index 2a7577e8..dba57e2d 100644 --- a/examples/embedded/styleexample/main.cpp +++ b/examples/embedded/styleexample/main.cpp @@ -7,7 +7,6 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); - Q_INIT_RESOURCE(styleexample); app.setApplicationName("style"); app.setOrganizationName("QtProject"); diff --git a/examples/examples.pro b/examples/examples.pro index fe6c6dc7..15e8167f 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -3,8 +3,7 @@ CONFIG += no_docs_target SUBDIRS = \ corelib \ - embedded \ - qpa + embedded !contains(TEMPLATE, "vc.*") { # QTBUG-91033 qtHaveModule(dbus): SUBDIRS += dbus diff --git a/examples/gui/doc/src/rasterwindow.qdoc b/examples/gui/doc/src/rasterwindow.qdoc index 4458f127..601b1d00 100644 --- a/examples/gui/doc/src/rasterwindow.qdoc +++ b/examples/gui/doc/src/rasterwindow.qdoc @@ -4,6 +4,7 @@ /*! \example rasterwindow \title Raster Window Example + \examplecategory {Graphics & Multimedia} \brief This example shows how to create a minimal QWindow based application using QPainter for rendering. diff --git a/examples/network/CMakeLists.txt b/examples/network/CMakeLists.txt index 4e19a2df..3aab043c 100644 --- a/examples/network/CMakeLists.txt +++ b/examples/network/CMakeLists.txt @@ -4,7 +4,7 @@ if(NOT TARGET Qt6::Network) return() endif() -if(NOT INTEGRITY) +if(NOT INTEGRITY AND NOT ANDROID) qt_internal_add_example(dnslookup) endif() if(TARGET Qt6::Widgets) @@ -18,6 +18,7 @@ if(TARGET Qt6::Widgets) qt_internal_add_example(multicastsender) qt_internal_add_example(fortuneclient) qt_internal_add_example(fortuneserver) + qt_internal_add_example(rsslisting) endif() if(QT_FEATURE_processenvironment AND TARGET Qt6::Widgets) qt_internal_add_example(network-chat) diff --git a/examples/network/dnslookup/CMakeLists.txt b/examples/network/dnslookup/CMakeLists.txt index e90cdaff..39f680f3 100644 --- a/examples/network/dnslookup/CMakeLists.txt +++ b/examples/network/dnslookup/CMakeLists.txt @@ -4,6 +4,10 @@ cmake_minimum_required(VERSION 3.16) project(dnslookup LANGUAGES CXX) +if (ANDROID) + message(FATAL_ERROR "This project cannot be built on Android.") +endif() + if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif() diff --git a/examples/network/dnslookup/dnslookup.cpp b/examples/network/dnslookup/dnslookup.cpp index 4af4567e..9ebdfb1f 100644 --- a/examples/network/dnslookup/dnslookup.cpp +++ b/examples/network/dnslookup/dnslookup.cpp @@ -79,7 +79,7 @@ CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *qu if (query->nameServer.isNull() || query->nameServer.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) { return { Status::Error, - u"Bad nameserver address: %1"_qs.arg(nameserver) }; + u"Bad nameserver address: %1"_s.arg(nameserver) }; } } @@ -88,14 +88,14 @@ CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *qu if (std::optional type = typeFromParameter(typeParameter)) query->type = *type; else - return { Status::Error, u"Bad record type: %1"_qs.arg(typeParameter) }; + return { Status::Error, u"Bad record type: %1"_s.arg(typeParameter) }; } const QStringList positionalArguments = parser.positionalArguments(); if (positionalArguments.isEmpty()) - return { Status::Error, u"Argument 'name' missing."_qs }; + return { Status::Error, u"Argument 'name' missing."_s }; if (positionalArguments.size() > 1) - return { Status::Error, u"Several 'name' arguments specified."_qs }; + return { Status::Error, u"Several 'name' arguments specified."_s }; query->name = positionalArguments.first(); return { Status::Ok }; @@ -202,7 +202,7 @@ int main(int argc, char *argv[]) case Status::Ok: break; case Status::Error: - std::fputs(qPrintable(parseResult.errorString.value_or(u"Unknown error occurred"_qs)), + std::fputs(qPrintable(parseResult.errorString.value_or(u"Unknown error occurred"_s)), stderr); std::fputs("\n\n", stderr); std::fputs(qPrintable(parser.helpText()), stderr); diff --git a/examples/network/doc/src/secureudpclient.qdoc b/examples/network/doc/src/secureudpclient.qdoc index 0f673b0a..b7a51c08 100644 --- a/examples/network/doc/src/secureudpclient.qdoc +++ b/examples/network/doc/src/secureudpclient.qdoc @@ -4,6 +4,7 @@ /*! \example secureudpclient \title DTLS client + \examplecategory {Networking} \ingroup examples-network \brief This example demonstrates how to implement client-side DTLS connections. diff --git a/examples/network/doc/src/secureudpserver.qdoc b/examples/network/doc/src/secureudpserver.qdoc index f98ee741..3d224d91 100644 --- a/examples/network/doc/src/secureudpserver.qdoc +++ b/examples/network/doc/src/secureudpserver.qdoc @@ -4,6 +4,7 @@ /*! \example secureudpserver \title DTLS server + \examplecategory {Networking} \ingroup examples-network \brief This examples demonstrates how to implement a simple DTLS server. diff --git a/examples/network/doc/src/torrent.qdoc b/examples/network/doc/src/torrent.qdoc index 301be186..124a6972 100644 --- a/examples/network/doc/src/torrent.qdoc +++ b/examples/network/doc/src/torrent.qdoc @@ -4,6 +4,7 @@ /*! \example torrent \title Torrent Example + \examplecategory {Networking} \ingroup examples-network \brief Demonstrates complex TCP/IP operations. diff --git a/examples/network/network.pro b/examples/network/network.pro index 79815609..a0fc95db 100644 --- a/examples/network/network.pro +++ b/examples/network/network.pro @@ -8,18 +8,16 @@ qtHaveModule(widgets) { blockingfortuneclient \ broadcastreceiver \ broadcastsender \ + fortuneclient \ + fortuneserver \ http \ - threadedfortuneserver \ - torrent \ multicastreceiver \ - multicastsender + multicastsender \ + rsslisting \ + threadedfortuneserver \ + torrent qtConfig(processenvironment): SUBDIRS += network-chat - - SUBDIRS += \ - fortuneclient \ - fortuneserver - qtConfig(ssl): SUBDIRS += securesocketclient qtConfig(dtls): SUBDIRS += secureudpserver secureudpclient qtConfig(sctp): SUBDIRS += multistreamserver multistreamclient diff --git a/examples/corelib/serialization/rsslisting/CMakeLists.txt b/examples/network/rsslisting/CMakeLists.txt similarity index 90% rename from examples/corelib/serialization/rsslisting/CMakeLists.txt rename to examples/network/rsslisting/CMakeLists.txt index 405a01ce..fc9d8d12 100644 --- a/examples/corelib/serialization/rsslisting/CMakeLists.txt +++ b/examples/network/rsslisting/CMakeLists.txt @@ -8,7 +8,7 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif() -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/corelib/serialization/rsslisting") +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/network/rsslisting") find_package(Qt6 REQUIRED COMPONENTS Core Gui Network Widgets) diff --git a/examples/network/rsslisting/doc/images/rsslisting.png b/examples/network/rsslisting/doc/images/rsslisting.png new file mode 100644 index 00000000..0b05375f Binary files /dev/null and b/examples/network/rsslisting/doc/images/rsslisting.png differ diff --git a/examples/network/rsslisting/doc/src/rsslisting.qdoc b/examples/network/rsslisting/doc/src/rsslisting.qdoc new file mode 100644 index 00000000..a1e91932 --- /dev/null +++ b/examples/network/rsslisting/doc/src/rsslisting.qdoc @@ -0,0 +1,129 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \example rsslisting + \examplecategory {Networking} + \meta tag {serialization} + \title A minimal RSS listing application + + \brief A demonstration of how to fetch and display a network resource. + + This example shows how to fetch a resource the user has requested and + display data contained in the response, illustrated by an RSS listing + application. (RDF Site Summary, or Really Simple Syndication, is a standard + format for communicating updates to web sites. See + https://www.rssboard.org/rss-specification for details.) The user inferface + in the illustration is simple, as the focus of this example is on how to use + networking, but naturally a more sophisticated interface would be wanted for + a serious RSS reader. + + The example also illustrates how to do asynchronous parsing of data as it is + received, preserving state in member variables so that an incremental parser + can consume chunks of data as they arrive over the network. Constituents of + the parsed content may start in one chunk of data but not be completed until + a later chunk, requiring the parser to retain state between calls. + + \image rsslisting.png + + The main program is fairly minimal. It simply instantiates a \l QApplication + and the \c RSSListing widget, shows the latter and hands over control to the + former. For the sake of illustration, it gives the widget the Qt blog's URL + as default value for the resource to check. + + \snippet rsslisting/main.cpp 0 + + \section1 The RSSListing class + + \snippet rsslisting/rsslisting.h 0 + + The widget itself provides a simple user interface for specifying the URL to + fetch and, once available updates are displayed, controlling the downloading + of updated items. A \l QLineEdit provides for input of the URL, and a + \l QTreeWidget for display of the results once fetched. + + The widget downloads and parses the RSS (a form of XML) asynchronously, + feeding the data to an XML reader as it arrives. This supports reading of + very large data sources. Because the data is streamed from the network + through the XML reader, there is no need to retain the full text of the XML + in memory. In other context, a similar approach can allow the user to + interrupt such incremental loading. + + \section2 Construction + + \snippet rsslisting/rsslisting.cpp setup + + The constructor sets up the assorted components of the widget and connects + their various signals to the slots it shall use to handle them. + + The user interface consists of a line edit, a push button, and a list view + widget. The line edit is used for entering the URL to fetch; the push button + starts the process of fetching updates. The line edit is empty by default, + but the constructor's caller can override that, as our \c main() has done. + In any case, the user can replace the default with the URL of another RSS + feed. + + The list view shows the updated items reported in the RSS feed. + Double-clicking on one of these sends its URL to the user's browser or other + user agent using \l QDesktopServices::openUrl(). + + \section2 The slots + + \snippet rsslisting/rsslisting.cpp slots + + All slots are kept simple by delegating any hard work to private methods. + + When the user completes input of a URL, either by clicking the "Fetch" + button or by pressing the return key in the line edit, the \c fetch() slot + disables the "Fetch" button and disables further editing of the line edit. + It clears the display of available updates and delegates to \c get() the + initiating of an HTTP GET request. + + When data is received, the network reply triggers its \l {QNetworkReply::} + {readyRead()} signal, which \c get() connects to the \c consumeData() + slot. This checks the response got a successful status code and, if it did, + calls \c parseXml() to consume the data. + + If the network reply gets an error, this is delivered to the \c error() + slot, which reports the error, clears the XML stream reader then disconnects + from the reply and deletes it. + + On completion (whether successful or otherwise) of a network reply, the \c + finished() slot restores the UI to be ready to accept a new URL to fetch by + re-enabling the line edit and "Fetch" button. + + \section2 The get() method + + \snippet rsslisting/rsslisting.cpp get + + The private \c get() method is used by the \c fetch() slot to initiate an + HTTP GET request. It first clears the XML stream reader and, if a reply is + currently active, disconnects and deletes it. If the URL it has been passed + is valid, it asks the network access manager to GET it. It connects its + relevant slots to signals of the resulting reply (if any) and sets up its + XML stream reader to read data from the reply - a network reply object is + also a \c QIODevice, from which data can be read. + + \section2 The parseXml() method + + \snippet rsslisting/rsslisting.cpp parse + + When data is received, and thus made available to the XML stream reader, \c + parseXml() reads from the XML stream, checking for \c item elements and, + within them, \c title and \c link elements. It will use the \c{rss:about} + attribute of an \c item as URL in the Link column of the tree-view, failing + that the content of its \c link element; and it uses the content of the \c + title element in the Title column of the tree-view. As each \c item element + closes, its details are turned into a new row in the tree widget, with the + extracted title and URL in the Title and Link columns. + + The variables that keep track of the parsing state - \c linkString, \c + titleString and \c currentTag - are member variables of the \c RSSListing + class, even though they are only accessed from this method, because this + method may be called repeatedly, as new data arrives, and one chunk of + received data may start an element that isn't completed until a later chunk + arrives. This enables the parser to operate asynchronously as the data + arrives, instead of having to wait until all the data has arrived. + + \sa QNetworkReply, QXmlStreamReader +*/ diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part1/main.cpp b/examples/network/rsslisting/main.cpp similarity index 50% rename from examples/widgets/tutorials/gettingStarted/gsQt/part1/main.cpp rename to examples/network/rsslisting/main.cpp index ef8c6ed1..7a64db8a 100644 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part1/main.cpp +++ b/examples/network/rsslisting/main.cpp @@ -1,15 +1,16 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#include "rsslisting.h" #include +using namespace Qt::StringLiterals; -int main(int argc, char *argv[]) +//! [0] +int main(int argc, char **argv) { QApplication app(argc, argv); - - QTextEdit textEdit; - textEdit.show(); - + RSSListing rsslisting(u"https://www.qt.io/blog/rss.xml"_s); + rsslisting.show(); return app.exec(); } - +//! [0] diff --git a/examples/network/rsslisting/rsslisting.cpp b/examples/network/rsslisting/rsslisting.cpp new file mode 100644 index 00000000..ed7c163c --- /dev/null +++ b/examples/network/rsslisting/rsslisting.cpp @@ -0,0 +1,126 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "rsslisting.h" + +#include +#include +#include + +//! [setup] +RSSListing::RSSListing(const QString &url, QWidget *parent) + : QWidget(parent), currentReply(0) +{ + connect(&manager, &QNetworkAccessManager::finished, this, &RSSListing::finished); + + lineEdit = new QLineEdit(this); + lineEdit->setText(url); + connect(lineEdit, &QLineEdit::returnPressed, this, &RSSListing::fetch); + + fetchButton = new QPushButton(tr("Fetch"), this); + connect(fetchButton, &QPushButton::clicked, this, &RSSListing::fetch); + + treeWidget = new QTreeWidget(this); + connect(treeWidget, &QTreeWidget::itemActivated, + // Open the link in the browser: + this, [](QTreeWidgetItem *item) { QDesktopServices::openUrl(QUrl(item->text(1))); }); + treeWidget->setHeaderLabels(QStringList { tr("Title"), tr("Link") }); + treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + + QHBoxLayout *hboxLayout = new QHBoxLayout; + hboxLayout->addWidget(lineEdit); + hboxLayout->addWidget(fetchButton); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addLayout(hboxLayout); + layout->addWidget(treeWidget); + + setWindowTitle(tr("RSS listing example")); + resize(640, 480); +} +//! [setup] + +//! [slots] +void RSSListing::fetch() +{ + lineEdit->setReadOnly(true); + fetchButton->setEnabled(false); + treeWidget->clear(); + + get(QUrl(lineEdit->text())); +} + +void RSSListing::consumeData() +{ + int statusCode = currentReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + if (statusCode >= 200 && statusCode < 300) + parseXml(); +} + +void RSSListing::error(QNetworkReply::NetworkError) +{ + qWarning("error retrieving RSS feed"); + xml.clear(); + currentReply->disconnect(this); + currentReply->deleteLater(); + currentReply = nullptr; +} + +void RSSListing::finished(QNetworkReply *reply) +{ + Q_UNUSED(reply); + lineEdit->setReadOnly(false); + fetchButton->setEnabled(true); +} +//! [slots] + +// Private methods + +//! [get] +void RSSListing::get(const QUrl &url) +{ + if (currentReply) { + currentReply->disconnect(this); + currentReply->deleteLater(); + } + currentReply = url.isValid() ? manager.get(QNetworkRequest(url)) : nullptr; + if (currentReply) { + connect(currentReply, &QNetworkReply::readyRead, this, &RSSListing::consumeData); + connect(currentReply, &QNetworkReply::errorOccurred, this, &RSSListing::error); + + } + xml.setDevice(currentReply); // Equivalent to clear() if currentReply is null. +} +//! [get] + +// TODO: this is a candidate for showing how to use coroutines, once available. +//! [parse] +void RSSListing::parseXml() +{ + while (!xml.atEnd()) { + xml.readNext(); + if (xml.isStartElement()) { + if (xml.name() == u"item") { + linkString = xml.attributes().value("rss:about").toString(); + titleString.clear(); + } + currentTag = xml.name().toString(); + } else if (xml.isEndElement()) { + if (xml.name() == u"item") { + + QTreeWidgetItem *item = new QTreeWidgetItem; + item->setText(0, titleString); + item->setText(1, linkString); + treeWidget->addTopLevelItem(item); + } + } else if (xml.isCharacters() && !xml.isWhitespace()) { + if (currentTag == "title") + titleString += xml.text(); + else if (currentTag == "link") + linkString += xml.text(); + } + } + if (xml.error() && xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) + qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString(); +} +//! [parse] diff --git a/examples/corelib/serialization/rsslisting/rsslisting.h b/examples/network/rsslisting/rsslisting.h similarity index 81% rename from examples/corelib/serialization/rsslisting/rsslisting.h rename to examples/network/rsslisting/rsslisting.h index 81c655f6..499bc5d1 100644 --- a/examples/corelib/serialization/rsslisting/rsslisting.h +++ b/examples/network/rsslisting/rsslisting.h @@ -7,49 +7,48 @@ #include #include #include -#include #include -#include - QT_BEGIN_NAMESPACE class QLineEdit; +class QPushButton; class QTreeWidget; class QTreeWidgetItem; -class QPushButton; +class QUrl; QT_END_NAMESPACE +//! [0] class RSSListing : public QWidget { Q_OBJECT public: - RSSListing(QWidget *widget = nullptr); + explicit RSSListing(const QString &url = QString(), QWidget *widget = nullptr); public slots: void fetch(); void finished(QNetworkReply *reply); - void readyRead(); - void metaDataChanged(); - void itemActivated(QTreeWidgetItem * item); + void consumeData(); void error(QNetworkReply::NetworkError); private: void parseXml(); void get(const QUrl &url); + // Parser state: QXmlStreamReader xml; QString currentTag; QString linkString; QString titleString; + // Network state: QNetworkAccessManager manager; QNetworkReply *currentReply; + // UI elements: QLineEdit *lineEdit; QTreeWidget *treeWidget; QPushButton *fetchButton; - }; +//! [0] #endif - diff --git a/examples/corelib/serialization/rsslisting/rsslisting.pro b/examples/network/rsslisting/rsslisting.pro similarity index 66% rename from examples/corelib/serialization/rsslisting/rsslisting.pro rename to examples/network/rsslisting/rsslisting.pro index 7619755b..aacbe312 100644 --- a/examples/corelib/serialization/rsslisting/rsslisting.pro +++ b/examples/network/rsslisting/rsslisting.pro @@ -4,5 +4,5 @@ QT += network widgets requires(qtConfig(treewidget)) # install -target.path = $$[QT_INSTALL_EXAMPLES]/corelib/serialization/rsslisting +target.path = $$[QT_INSTALL_EXAMPLES]/network/rsslisting INSTALLS += target diff --git a/examples/network/securesocketclient/main.cpp b/examples/network/securesocketclient/main.cpp index 5898bf08..7a59e6f7 100644 --- a/examples/network/securesocketclient/main.cpp +++ b/examples/network/securesocketclient/main.cpp @@ -11,8 +11,6 @@ QT_REQUIRE_CONFIG(ssl); int main(int argc, char **argv) { - Q_INIT_RESOURCE(securesocketclient); - QApplication app(argc, argv); if (!QSslSocket::supportsSsl()) { diff --git a/examples/network/torrent/main.cpp b/examples/network/torrent/main.cpp index a7a795fb..649f3343 100644 --- a/examples/network/torrent/main.cpp +++ b/examples/network/torrent/main.cpp @@ -9,8 +9,6 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); - Q_INIT_RESOURCE(icons); - MainWindow window; window.show(); diff --git a/examples/opengl/CMakeLists.txt b/examples/opengl/CMakeLists.txt index 2b075de2..eb7e2d27 100644 --- a/examples/opengl/CMakeLists.txt +++ b/examples/opengl/CMakeLists.txt @@ -7,7 +7,6 @@ if(TARGET Qt6::Widgets) qt_internal_add_example(contextinfo) qt_internal_add_example(2dpainting) qt_internal_add_example(hellogl2) - qt_internal_add_example(qopenglwidget) qt_internal_add_example(cube) qt_internal_add_example(textures) qt_internal_add_example(stereoqopenglwidget) diff --git a/examples/opengl/doc/src/2dpainting.qdoc b/examples/opengl/doc/src/2dpainting.qdoc index 934097f3..5fcb5ad3 100644 --- a/examples/opengl/doc/src/2dpainting.qdoc +++ b/examples/opengl/doc/src/2dpainting.qdoc @@ -5,6 +5,7 @@ \example 2dpainting \title 2D Painting Example \ingroup examples-widgets-opengl + \examplecategory {Graphics & Multimedia} \brief The 2D Painting example shows how QPainter and QOpenGLWidget can be used together to display accelerated 2D graphics on supported hardware. diff --git a/examples/opengl/doc/src/cube.qdoc b/examples/opengl/doc/src/cube.qdoc index e0a18706..cbcc460b 100644 --- a/examples/opengl/doc/src/cube.qdoc +++ b/examples/opengl/doc/src/cube.qdoc @@ -5,11 +5,14 @@ \example cube \ingroup examples-widgets-opengl \title Cube OpenGL ES 2.0 example + \examplecategory {Data Visualization & 3D} - \brief The Cube OpenGL ES 2.0 example shows how to write mouse rotatable - textured 3D cube using OpenGL ES 2.0 with Qt. It shows how to handle - polygon geometries efficiently and how to write simple vertex and - fragment shader for programmable graphics pipeline. In addition it + \brief Shows how to manually rotate a textured 3D cube with user input. + + The Cube OpenGL ES 2.0 example shows how to manually rotate a textured 3D + cube with user input, using OpenGL ES 2.0 with Qt. It shows how to + handle polygon geometries efficiently and how to write a simple vertex and + fragment shader for a programmable graphics pipeline. In addition it shows how to use quaternions for representing 3D object orientation. This example has been written for OpenGL ES 2.0 but it works also on diff --git a/examples/opengl/doc/src/hellogl2.qdoc b/examples/opengl/doc/src/hellogl2.qdoc index 3a81b0df..bb85e7ee 100644 --- a/examples/opengl/doc/src/hellogl2.qdoc +++ b/examples/opengl/doc/src/hellogl2.qdoc @@ -5,6 +5,7 @@ \example hellogl2 \title Hello GL2 Example \ingroup examples-widgets-opengl + \examplecategory {Data Visualization & 3D} \brief The Hello GL2 example demonstrates the basic use of the OpenGL-related classes provided with Qt. diff --git a/examples/opengl/doc/src/hellogles3.qdoc b/examples/opengl/doc/src/hellogles3.qdoc index e76536d9..bb699ec1 100644 --- a/examples/opengl/doc/src/hellogles3.qdoc +++ b/examples/opengl/doc/src/hellogles3.qdoc @@ -5,24 +5,144 @@ \example hellogles3 \title Hello GLES3 Example \ingroup examples-widgets-opengl + \examplecategory {Graphics & Multimedia} - \brief The Hello GLES3 example demonstrates easy, cross-platform usage of - OpenGL ES 3.0 functions via QOpenGLExtraFunctions in an application that + \brief Demonstrates OpenGL ES 3.0 functions via QOpenGLExtraFunctions. + + \image hellogles3-example.png + \section1 Overview + + This example demonstrates easy, cross-platform usage of OpenGL ES 3.0 + functions via QOpenGLExtraFunctions in an application that works identically on desktop platforms with OpenGL 3.3 and mobile/embedded devices with OpenGL ES 3.0. - The code is always the same, with the exception of two places: - \list - \li The OpenGL context creation has to have a sufficiently high version - number for the features that are in use. - \li The shader code's version directive is different. - \endlist - - This example has no QWidget dependencies. Instead, it uses QOpenGLWindow, a + This example has no QWidget dependencies, it uses QOpenGLWindow, a convenience subclass of QWindow that allows easy implementation of windows that contain OpenGL-rendered content. In this sense it complements the \l{OpenGL Window Example}, which shows the implementation of an OpenGL-based QWindow without using the convenience subclass. - \image hellogles3-example.png + The Qt logo shape implementation is included from the \l{Hello GL2 Example}. + + In other aspects pertaining to using OpenGL there are the following + differences. + + \list + \li The OpenGL context creation has to have a sufficiently high version + number for the features that are in use. + \li The shader's version directive is different. + \endlist + + \section1 Setting up in main.cpp + + Here we instantiate our QGuiApplication, QSurfaceformat and set its + \l{QSurfaceFormat::depthBufferSize()}{depth buffer size}: + + \quotefromfile hellogles3/main.cpp + \skipto int main(int argc, char *argv[]) + \printuntil fmt.setDepthBufferSize(24); + + We request an OpenGL 3.3 core or OpenGL ES 3.0 context, depending on + QOpenGLContext::openGLModuleType(): + + \skipto if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + \printuntil QSurfaceFormat::setDefaultFormat(fmt); + + We set the default surface format and instantiate our GLWindow \c glWindow. + + \section1 Implementing GLWindow + + This class delivers the features of the example application. + + To start, \c GLWindow is declared by implementing a subclass of + QOpenGLWindow: + + \quotefromfile hellogles3/glwindow.h + \skipto class GLWindow : public QOpenGLWindow + \printto { + + The following properties are declared using Q_PROPERTY: + + \printto public: + + The following public functions are declared: + + \printto private slots: + + The following private objects are declared: + + \printto }; + + On the implementation side, those functions that are not declared inline are + implemented (or re-implemented) in \c{glwindow.cpp}. The following selections + will cover implementation particulars pertaining to the use of OpenGL ES 3.0. + + \section2 Animations + + The following code pertains to the animations, and won't be explored here: + + \quotefromfile hellogles3/glwindow.cpp + \skipto GLWindow::GLWindow() + \printto static const char *vertexShaderSource = + + For more information see the documentation for \l QPropertyAnimation, + \l QSequentialAnimationGroup. + + \section2 Shaders + The shaders are defined like so: + + \printto QByteArray versionedShaderCode(const char *src) + + \note These are OpenGL version agnostic. We take this and append + the version like so: + + \printto void GLWindow::initializeGL() + + \section2 Initializing OpenGL + + Initializing the shader program in handled by \c initializeGL(): + + \printuntil m_program = new QOpenGLShaderProgram; + \skipto m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, versionedShaderCode(vertexShaderSource)); + + Now the OpenGL version is prepended and the various matrices and light + position is set: + + \printuntil m_lightPosLoc = m_program->uniformLocation("lightPos"); + + While not strictly required for ES 3, a vertex array object is created. + + \skipto delete m_vao; + \printuntil f->glEnable(GL_CULL_FACE); + + \section2 Resizing the window + + The perspective needs to be aligned with the new window size as so: + + \skipto void GLWindow::resizeGL(int w, int h) + \printto void GLWindow::paintGL() + + \section2 Painting + + We use QOpenGLExtraFunctions instead of QOpenGLFunctions as we want to + do more than what GL(ES) 2.0 offers: + + \printuntil QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions(); + + We clear the screen and buffers and bind our shader program and texture: + + \printuntil m_texture->bind(); + + Logic for handling an initial \c paintGL() call or a call after a + \c resizeGL() call is implemented like so: + + \printuntil } + + Last, we demonstrate a function introduced in OpenGL 3.1 or OpenGL ES 3.0: + + \skipto f->glDrawArraysInstanced(GL_TRIANGLES, 0, m_logo.vertexCount(), 32 * 36); + \printuntil } + + This works because we earlier requested 3.3 or 3.0 context. */ diff --git a/examples/opengl/doc/src/openglwindow.qdoc b/examples/opengl/doc/src/openglwindow.qdoc index 505ff20f..44ef047a 100644 --- a/examples/opengl/doc/src/openglwindow.qdoc +++ b/examples/opengl/doc/src/openglwindow.qdoc @@ -4,6 +4,8 @@ /*! \example openglwindow \title OpenGL Window Example + \ingroup examples-widgets-opengl + \examplecategory {Graphics & Multimedia} \brief This example shows how to create a minimal QWindow based application for the purpose of using OpenGL. diff --git a/examples/opengl/doc/src/stereoqopenglwidget.qdoc b/examples/opengl/doc/src/stereoqopenglwidget.qdoc index c4e51f9c..6037d370 100644 --- a/examples/opengl/doc/src/stereoqopenglwidget.qdoc +++ b/examples/opengl/doc/src/stereoqopenglwidget.qdoc @@ -4,7 +4,7 @@ /*! \example stereoqopenglwidget \title QOpenGLWidget Stereoscopic Rendering Example - + \examplecategory {Graphics & Multimedia} \brief This example shows how to create a minimal QOpenGLWidget based application with stereoscopic rendering support. diff --git a/examples/opengl/hellogl2/window.h b/examples/opengl/hellogl2/window.h index f9e06079..2099bc11 100644 --- a/examples/opengl/hellogl2/window.h +++ b/examples/opengl/hellogl2/window.h @@ -6,10 +6,8 @@ #include -QT_BEGIN_NAMESPACE -class QSlider; -class QPushButton; -QT_END_NAMESPACE +QT_FORWARD_DECLARE_CLASS(QSlider) +QT_FORWARD_DECLARE_CLASS(QPushButton) class GLWidget; class MainWindow; diff --git a/examples/opengl/hellogles3/glwindow.h b/examples/opengl/hellogles3/glwindow.h index fc2a0e48..54bc531a 100644 --- a/examples/opengl/hellogles3/glwindow.h +++ b/examples/opengl/hellogles3/glwindow.h @@ -9,14 +9,10 @@ #include #include "../hellogl2/logo.h" -QT_BEGIN_NAMESPACE - -class QOpenGLTexture; -class QOpenGLShaderProgram; -class QOpenGLBuffer; -class QOpenGLVertexArrayObject; - -QT_END_NAMESPACE +QT_FORWARD_DECLARE_CLASS(QOpenGLTexture) +QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram) +QT_FORWARD_DECLARE_CLASS(QOpenGLBuffer) +QT_FORWARD_DECLARE_CLASS(QOpenGLVertexArrayObject) class GLWindow : public QOpenGLWindow { diff --git a/examples/opengl/opengl.pro b/examples/opengl/opengl.pro index b0eac5ee..f33921a7 100644 --- a/examples/opengl/opengl.pro +++ b/examples/opengl/opengl.pro @@ -7,7 +7,6 @@ qtHaveModule(widgets) { SUBDIRS += contextinfo \ 2dpainting \ hellogl2 \ - qopenglwidget \ cube \ textures \ stereoqopenglwidget diff --git a/examples/opengl/openglwindow/openglwindow.h b/examples/opengl/openglwindow/openglwindow.h index 579f9eed..41bcbab9 100644 --- a/examples/opengl/openglwindow/openglwindow.h +++ b/examples/opengl/openglwindow/openglwindow.h @@ -7,11 +7,9 @@ #include #include -QT_BEGIN_NAMESPACE -class QPainter; -class QOpenGLContext; -class QOpenGLPaintDevice; -QT_END_NAMESPACE +QT_FORWARD_DECLARE_CLASS(QPainter) +QT_FORWARD_DECLARE_CLASS(QOpenGLContext) +QT_FORWARD_DECLARE_CLASS(QOpenGLPaintDevice) //! [1] class OpenGLWindow : public QWindow, protected QOpenGLFunctions diff --git a/examples/opengl/stereoqopenglwidget/CMakeLists.txt b/examples/opengl/stereoqopenglwidget/CMakeLists.txt index 69fd304b..214b359c 100644 --- a/examples/opengl/stereoqopenglwidget/CMakeLists.txt +++ b/examples/opengl/stereoqopenglwidget/CMakeLists.txt @@ -26,11 +26,11 @@ set_target_properties(stereoqopenglwidget PROPERTIES ) target_link_libraries(stereoqopenglwidget PUBLIC - Qt::Core - Qt::Gui - Qt::OpenGL - Qt::OpenGLWidgets - Qt::Widgets + Qt6::Core + Qt6::Gui + Qt6::OpenGL + Qt6::OpenGLWidgets + Qt6::Widgets ) diff --git a/examples/opengl/textures/main.cpp b/examples/opengl/textures/main.cpp index c1e91e62..7e5f0646 100644 --- a/examples/opengl/textures/main.cpp +++ b/examples/opengl/textures/main.cpp @@ -8,8 +8,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(textures); - QApplication app(argc, argv); QSurfaceFormat format; diff --git a/examples/qtconcurrent/imagescaling/doc/src/qtconcurrent-imagescaling.qdoc b/examples/qtconcurrent/imagescaling/doc/src/qtconcurrent-imagescaling.qdoc index 6e17d408..499cb165 100644 --- a/examples/qtconcurrent/imagescaling/doc/src/qtconcurrent-imagescaling.qdoc +++ b/examples/qtconcurrent/imagescaling/doc/src/qtconcurrent-imagescaling.qdoc @@ -6,6 +6,7 @@ \meta tags {widgets, threads, network} \title Image Scaling \ingroup qtconcurrentexamples + \examplecategory {Networking} \brief Demonstrates how to asynchronously download and scale images. This example shows how to use the QFuture, QPromise, and QFutureWatcher diff --git a/examples/qtconcurrent/primecounter/doc/src/qtconcurrent-primecounter.qdoc b/examples/qtconcurrent/primecounter/doc/src/qtconcurrent-primecounter.qdoc index 75877c5a..de6c94b0 100644 --- a/examples/qtconcurrent/primecounter/doc/src/qtconcurrent-primecounter.qdoc +++ b/examples/qtconcurrent/primecounter/doc/src/qtconcurrent-primecounter.qdoc @@ -6,6 +6,7 @@ \meta tags {widgets, threads} \title Prime Counter \ingroup qtconcurrentexamples + \examplecategory {Data Processing & I/O} \brief Demonstrates how to monitor the progress of concurrent operations. The following example demonstrates how to create an interactive and diff --git a/examples/qtconcurrent/wordcount/doc/src/qtconcurrent-wordcount.qdoc b/examples/qtconcurrent/wordcount/doc/src/qtconcurrent-wordcount.qdoc index 50b6fc29..adefdfdc 100644 --- a/examples/qtconcurrent/wordcount/doc/src/qtconcurrent-wordcount.qdoc +++ b/examples/qtconcurrent/wordcount/doc/src/qtconcurrent-wordcount.qdoc @@ -6,6 +6,7 @@ \meta tags {threads, console} \title Word Count \ingroup qtconcurrentexamples + \examplecategory {Data Processing & I/O} \brief Demonstrates how to use the map-reduce algorithm. The Qt Concurrent \e {Word Count} example demonstrates the use of the diff --git a/examples/sql/books/bookwindow.cpp b/examples/sql/books/bookwindow.cpp index 2ec5459e..b7baad48 100644 --- a/examples/sql/books/bookwindow.cpp +++ b/examples/sql/books/bookwindow.cpp @@ -89,6 +89,7 @@ BookWindow::BookWindow() ); ui.bookTable->setCurrentIndex(model->index(0, 0)); + ui.bookTable->selectRow(0); createMenuBar(); } diff --git a/examples/sql/books/bookwindow.h b/examples/sql/books/bookwindow.h index ba569292..8030516e 100644 --- a/examples/sql/books/bookwindow.h +++ b/examples/sql/books/bookwindow.h @@ -22,8 +22,8 @@ private slots: private: void showError(const QSqlError &err); Ui::BookWindow ui; - QSqlRelationalTableModel *model; - int authorIdx, genreIdx; + QSqlRelationalTableModel *model = nullptr; + int authorIdx = 0, genreIdx = 0; void createMenuBar(); }; diff --git a/examples/sql/books/bookwindow.ui b/examples/sql/books/bookwindow.ui index ce8f9f93..c93726c5 100644 --- a/examples/sql/books/bookwindow.ui +++ b/examples/sql/books/bookwindow.ui @@ -64,6 +64,9 @@ Details + + QFormLayout::ExpandingFieldsGrow + diff --git a/examples/sql/books/main.cpp b/examples/sql/books/main.cpp index d06568ed..e65ac936 100644 --- a/examples/sql/books/main.cpp +++ b/examples/sql/books/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char * argv[]) { - Q_INIT_RESOURCE(books); - QApplication app(argc, argv); BookWindow win; diff --git a/examples/sql/doc/src/books.qdoc b/examples/sql/doc/src/books.qdoc index c08d2f97..b4ca8bdd 100644 --- a/examples/sql/doc/src/books.qdoc +++ b/examples/sql/doc/src/books.qdoc @@ -5,6 +5,7 @@ \example books \title Books \ingroup sql_examples + \examplecategory {Data Processing & I/O} \brief Shows how to use Qt SQL classes with a model/view framework. The Books example shows how Qt's SQL classes can be used with the model/view diff --git a/examples/sql/doc/src/cachedtable.qdoc b/examples/sql/doc/src/cachedtable.qdoc index 35b8fdd4..ff60f7b1 100644 --- a/examples/sql/doc/src/cachedtable.qdoc +++ b/examples/sql/doc/src/cachedtable.qdoc @@ -3,8 +3,9 @@ /*! \example cachedtable - \title Cached Table Example + \title Cached SQL Table \ingroup sql_examples + \examplecategory {Data Processing & I/O} \brief The Cached Table example shows how a table view can be used to access a database, caching any changes to the data until the user explicitly submits them using a diff --git a/examples/sql/doc/src/drilldown.qdoc b/examples/sql/doc/src/drilldown.qdoc index 4e432b70..7d1c997a 100644 --- a/examples/sql/doc/src/drilldown.qdoc +++ b/examples/sql/doc/src/drilldown.qdoc @@ -5,6 +5,7 @@ \example drilldown \title Drill Down Example \ingroup sql_examples + \examplecategory {Data Processing & I/O} \brief The Drill Down example shows how to read data from a database as well as submit changes, using the QSqlRelationalTableModel and diff --git a/examples/sql/doc/src/masterdetail.qdoc b/examples/sql/doc/src/masterdetail.qdoc index 9fcf5087..fec579a6 100644 --- a/examples/sql/doc/src/masterdetail.qdoc +++ b/examples/sql/doc/src/masterdetail.qdoc @@ -5,6 +5,7 @@ \example masterdetail \title Master Detail Example \ingroup sql_examples + \examplecategory {Data Processing & I/O} \brief The Master Detail Example shows how to present data from different data sources in the same application. The album titles, and the diff --git a/examples/sql/doc/src/querymodel.qdoc b/examples/sql/doc/src/querymodel.qdoc index 38f7acab..c9fa4cec 100644 --- a/examples/sql/doc/src/querymodel.qdoc +++ b/examples/sql/doc/src/querymodel.qdoc @@ -5,6 +5,7 @@ \example querymodel \title Query Model Example \ingroup sql_examples + \examplecategory {Data Processing & I/O} \brief The Query Model example shows how to make customized versions of data obtained from a SQL query, using a model that encapsulates diff --git a/examples/sql/doc/src/relationaltablemodel.qdoc b/examples/sql/doc/src/relationaltablemodel.qdoc index cf95cb4a..371fef81 100644 --- a/examples/sql/doc/src/relationaltablemodel.qdoc +++ b/examples/sql/doc/src/relationaltablemodel.qdoc @@ -5,6 +5,7 @@ \example relationaltablemodel \title Relational Table Model Example \ingroup sql_examples + \examplecategory {Data Processing & I/O} \brief The Relational Table Model example shows how to use table views with a relational model to visualize the relations between items in a database. diff --git a/examples/sql/doc/src/sqlbrowser.qdoc b/examples/sql/doc/src/sqlbrowser.qdoc index 0cabea09..ad783f57 100644 --- a/examples/sql/doc/src/sqlbrowser.qdoc +++ b/examples/sql/doc/src/sqlbrowser.qdoc @@ -5,6 +5,7 @@ \example sqlbrowser \title SQL Browser \ingroup sql_examples + \examplecategory {Data Processing & I/O} \brief The SQL Browser example shows how a data browser can be used to visualize the results of SQL statements on a live database. diff --git a/examples/sql/doc/src/sqlwidgetmapper.qdoc b/examples/sql/doc/src/sqlwidgetmapper.qdoc index 2e921f47..7740e50b 100644 --- a/examples/sql/doc/src/sqlwidgetmapper.qdoc +++ b/examples/sql/doc/src/sqlwidgetmapper.qdoc @@ -5,6 +5,7 @@ \example sqlwidgetmapper \title SQL Widget Mapper Example \ingroup sql_examples + \examplecategory {Data Processing & I/O} \brief The SQL Widget Mapper example shows how to use a map information from a database to widgets on a form. @@ -101,8 +102,7 @@ As a result, the user is able to select an item from the combo box, and the associated value is written back to the model. - The rest of the constructor is very similar to that of the - \l{Simple Widget Mapper Example}: + The rest of the constructor sets up connections and layouts: \snippet sqlwidgetmapper/window.cpp Set up connections and layouts diff --git a/examples/sql/doc/src/tablemodel.qdoc b/examples/sql/doc/src/tablemodel.qdoc index 420c3cd9..1542d121 100644 --- a/examples/sql/doc/src/tablemodel.qdoc +++ b/examples/sql/doc/src/tablemodel.qdoc @@ -5,6 +5,7 @@ \example tablemodel \title Table Model Example \ingroup sql_examples + \examplecategory {Data Processing & I/O} \brief The Table Model example shows how to use a specialized SQL table model with table views to edit information in a database. diff --git a/examples/sql/drilldown/main.cpp b/examples/sql/drilldown/main.cpp index 5828a37a..77b87252 100644 --- a/examples/sql/drilldown/main.cpp +++ b/examples/sql/drilldown/main.cpp @@ -11,8 +11,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(drilldown); - QApplication app(argc, argv); if (!createConnection()) diff --git a/examples/sql/masterdetail/main.cpp b/examples/sql/masterdetail/main.cpp index 8b6ee618..e99d8e86 100644 --- a/examples/sql/masterdetail/main.cpp +++ b/examples/sql/masterdetail/main.cpp @@ -11,8 +11,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(masterdetail); - QApplication app(argc, argv); if (!createConnection()) diff --git a/examples/vulkan/doc/src/hellovulkancubes.qdoc b/examples/vulkan/doc/src/hellovulkancubes.qdoc index dc60b8bb..992a7643 100644 --- a/examples/vulkan/doc/src/hellovulkancubes.qdoc +++ b/examples/vulkan/doc/src/hellovulkancubes.qdoc @@ -7,6 +7,7 @@ \title Hello Vulkan Cubes Example \ingroup examples-vulkan \brief Shows the basics of using QVulkanWindow. + \examplecategory {Graphics & Multimedia} The \e{Hello Vulkan Cubes Example} shows more advanced usage of QVulkanWindow. diff --git a/examples/vulkan/doc/src/hellovulkantriangle.qdoc b/examples/vulkan/doc/src/hellovulkantriangle.qdoc index 75b08510..d716132c 100644 --- a/examples/vulkan/doc/src/hellovulkantriangle.qdoc +++ b/examples/vulkan/doc/src/hellovulkantriangle.qdoc @@ -7,6 +7,7 @@ \ingroup examples-vulkan \title Hello Vulkan Triangle Example \brief Shows the basics of rendering with QVulkanWindow and the Vulkan API. + \examplecategory {Graphics & Multimedia} The \e{Hello Vulkan Triangle Example} creates a full graphics pipeline, including a vertex and fragment shader, to render a triangle. diff --git a/examples/vulkan/doc/src/hellovulkanwidget.qdoc b/examples/vulkan/doc/src/hellovulkanwidget.qdoc index 0166a361..0f9ecf62 100644 --- a/examples/vulkan/doc/src/hellovulkanwidget.qdoc +++ b/examples/vulkan/doc/src/hellovulkanwidget.qdoc @@ -7,6 +7,7 @@ \ingroup examples-vulkan \title Hello Vulkan Widget Example \brief Shows the usage of QVulkanWindow in QWidget applications. + \examplecategory {Graphics & Multimedia} The \e{Hello Vulkan Widget Example} is a variant of \l hellovulkantriangle that embeds the QVulkanWindow into a QWidget-based user interface using diff --git a/examples/vulkan/hellovulkancubes/mainwindow.h b/examples/vulkan/hellovulkancubes/mainwindow.h index 2e931c1a..8ecb0002 100644 --- a/examples/vulkan/hellovulkancubes/mainwindow.h +++ b/examples/vulkan/hellovulkancubes/mainwindow.h @@ -6,12 +6,10 @@ #include -QT_BEGIN_NAMESPACE -class QLCDNumber; -class QLabel; -class QPushButton; -class QCheckBox; -QT_END_NAMESPACE +QT_FORWARD_DECLARE_CLASS(QLCDNumber) +QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QPushButton) +QT_FORWARD_DECLARE_CLASS(QCheckBox) class VulkanWindow; diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h index d545e681..cbebe17f 100644 --- a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h +++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h @@ -7,13 +7,11 @@ #include "../shared/trianglerenderer.h" #include -class VulkanWindow; +QT_FORWARD_DECLARE_CLASS(QTabWidget) +QT_FORWARD_DECLARE_CLASS(QPlainTextEdit) +QT_FORWARD_DECLARE_CLASS(QLCDNumber) -QT_BEGIN_NAMESPACE -class QTabWidget; -class QPlainTextEdit; -class QLCDNumber; -QT_END_NAMESPACE +class VulkanWindow; class MainWindow : public QWidget { diff --git a/examples/widgets/CMakeLists.txt b/examples/widgets/CMakeLists.txt index 315865b8..c5d3de8b 100644 --- a/examples/widgets/CMakeLists.txt +++ b/examples/widgets/CMakeLists.txt @@ -9,7 +9,6 @@ if(QT_FEATURE_animation) endif() add_subdirectory(desktop) add_subdirectory(dialogs) -add_subdirectory(effects) qt_internal_add_example(gallery) add_subdirectory(gestures) add_subdirectory(graphicsview) @@ -17,7 +16,6 @@ add_subdirectory(itemviews) add_subdirectory(layouts) add_subdirectory(painting) add_subdirectory(richtext) -add_subdirectory(scroller) add_subdirectory(tools) add_subdirectory(touch) add_subdirectory(tutorials) @@ -28,6 +26,3 @@ endif() if(QT_FEATURE_cursor) add_subdirectory(mainwindows) endif() -if(QT_FEATURE_opengl AND TARGET Qt6::Gui) - qt_internal_add_example(windowcontainer) -endif() diff --git a/examples/widgets/animation/easing/main.cpp b/examples/widgets/animation/easing/main.cpp index a1c01698..26009a6b 100644 --- a/examples/widgets/animation/easing/main.cpp +++ b/examples/widgets/animation/easing/main.cpp @@ -6,7 +6,6 @@ int main(int argc, char **argv) { - Q_INIT_RESOURCE(easing); QApplication app(argc, argv); Window w; diff --git a/examples/widgets/desktop/systray/doc/src/systray.qdoc b/examples/widgets/desktop/systray/doc/src/systray.qdoc index 5c435038..b0dff58e 100644 --- a/examples/widgets/desktop/systray/doc/src/systray.qdoc +++ b/examples/widgets/desktop/systray/doc/src/systray.qdoc @@ -4,6 +4,7 @@ /*! \example desktop/systray \title System Tray Icon Example + \examplecategory {Desktop} \ingroup examples-widgets \brief The System Tray Icon example shows how to add an icon with a menu and popup messages to a desktop environment's system tray. diff --git a/examples/widgets/desktop/systray/main.cpp b/examples/widgets/desktop/systray/main.cpp index d01f813d..d13bde11 100644 --- a/examples/widgets/desktop/systray/main.cpp +++ b/examples/widgets/desktop/systray/main.cpp @@ -10,8 +10,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(systray); - QApplication app(argc, argv); if (!QSystemTrayIcon::isSystemTrayAvailable()) { diff --git a/examples/widgets/dialogs/CMakeLists.txt b/examples/widgets/dialogs/CMakeLists.txt index a4031a68..b16cbc7f 100644 --- a/examples/widgets/dialogs/CMakeLists.txt +++ b/examples/widgets/dialogs/CMakeLists.txt @@ -2,12 +2,10 @@ # SPDX-License-Identifier: BSD-3-Clause if(QT_FEATURE_wizard) - qt_internal_add_example(classwizard) qt_internal_add_example(trivialwizard) + if(Qt6::PrintSupport) + qt_internal_add_example(licensewizard) + endif() endif() -qt_internal_add_example(extension) qt_internal_add_example(standarddialogs) qt_internal_add_example(tabdialog) -if(QT_FEATURE_wizard AND TARGET Qt6::PrintSupport) - qt_internal_add_example(licensewizard) -endif() diff --git a/examples/widgets/dialogs/dialogs.pro b/examples/widgets/dialogs/dialogs.pro index 1983c854..24936882 100644 --- a/examples/widgets/dialogs/dialogs.pro +++ b/examples/widgets/dialogs/dialogs.pro @@ -1,9 +1,7 @@ QT_FOR_CONFIG += widgets TEMPLATE = subdirs -SUBDIRS = classwizard \ - extension \ - licensewizard \ +SUBDIRS = licensewizard \ standarddialogs \ tabdialog \ trivialwizard diff --git a/examples/widgets/dialogs/licensewizard/licensewizard.cpp b/examples/widgets/dialogs/licensewizard/licensewizard.cpp index 05888ac6..67fa46bf 100644 --- a/examples/widgets/dialogs/licensewizard/licensewizard.cpp +++ b/examples/widgets/dialogs/licensewizard/licensewizard.cpp @@ -288,9 +288,12 @@ void ConclusionPage::initializePage() "You can use this software for 30 days and make one " "backup, but you are not allowed to distribute it."); } else if (wizard()->hasVisitedPage(LicenseWizard::Page_Details)) { +//! [accessField] + const QString emailAddress = field("details.email").toString(); licenseText = tr("First-Time License Agreement: " "You can use this software subject to the license " - "you will receive by email."); + "you will receive by email sent to %1.").arg(emailAddress); +//! [accessField] } else { licenseText = tr("Upgrade License Agreement: " "This software is licensed under the terms of your " diff --git a/examples/widgets/dialogs/licensewizard/main.cpp b/examples/widgets/dialogs/licensewizard/main.cpp index 13e13f0e..d16b5dc6 100644 --- a/examples/widgets/dialogs/licensewizard/main.cpp +++ b/examples/widgets/dialogs/licensewizard/main.cpp @@ -10,8 +10,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(licensewizard); - QApplication app(argc, argv); #ifndef QT_NO_TRANSLATION diff --git a/examples/widgets/dialogs/trivialwizard/trivialwizard.cpp b/examples/widgets/dialogs/trivialwizard/trivialwizard.cpp index 83de13f0..b9321338 100644 --- a/examples/widgets/dialogs/trivialwizard/trivialwizard.cpp +++ b/examples/widgets/dialogs/trivialwizard/trivialwizard.cpp @@ -86,10 +86,12 @@ int main(int argc, char *argv[]) app.installTranslator(translator); #endif +//! [linearAddPage] QWizard wizard; wizard.addPage(createIntroPage()); wizard.addPage(createRegistrationPage()); wizard.addPage(createConclusionPage()); +//! [linearAddPage] wizard.setWindowTitle("Trivial Wizard"); wizard.show(); diff --git a/examples/widgets/doc/dropsite.qdoc b/examples/widgets/doc/dropsite.qdoc index 5ebf0ff3..4c38ffc5 100644 --- a/examples/widgets/doc/dropsite.qdoc +++ b/examples/widgets/doc/dropsite.qdoc @@ -4,6 +4,7 @@ /*! \example draganddrop/dropsite \title Drop Site Example + \examplecategory {User Interface Components} \brief The example shows how to distinguish the various MIME formats available in a drag and drop operation. diff --git a/examples/widgets/doc/images/calendar-example.png b/examples/widgets/doc/images/calendar-example.png deleted file mode 100644 index 895ce76b..00000000 Binary files a/examples/widgets/doc/images/calendar-example.png and /dev/null differ diff --git a/examples/widgets/doc/images/draganddroppuzzle-example.png b/examples/widgets/doc/images/draganddroppuzzle-example.png deleted file mode 100644 index ca684458..00000000 Binary files a/examples/widgets/doc/images/draganddroppuzzle-example.png and /dev/null differ diff --git a/examples/widgets/doc/images/fademessageeffect-example-faded.png b/examples/widgets/doc/images/fademessageeffect-example-faded.png deleted file mode 100644 index ea66d2c7..00000000 Binary files a/examples/widgets/doc/images/fademessageeffect-example-faded.png and /dev/null differ diff --git a/examples/widgets/doc/images/fademessageeffect-example.png b/examples/widgets/doc/images/fademessageeffect-example.png deleted file mode 100644 index 823c8510..00000000 Binary files a/examples/widgets/doc/images/fademessageeffect-example.png and /dev/null differ diff --git a/examples/widgets/doc/images/fridgemagnets-example.png b/examples/widgets/doc/images/fridgemagnets-example.png deleted file mode 100644 index 2a890aad..00000000 Binary files a/examples/widgets/doc/images/fridgemagnets-example.png and /dev/null differ diff --git a/examples/widgets/doc/images/graphicsflowlayout-example.png b/examples/widgets/doc/images/graphicsflowlayout-example.png deleted file mode 100644 index 953d5408..00000000 Binary files a/examples/widgets/doc/images/graphicsflowlayout-example.png and /dev/null differ diff --git a/examples/widgets/doc/images/imageviewer-fit_to_window_1.png b/examples/widgets/doc/images/imageviewer-fit_to_window_1.png deleted file mode 100644 index 0fe1ba1c..00000000 Binary files a/examples/widgets/doc/images/imageviewer-fit_to_window_1.png and /dev/null differ diff --git a/examples/widgets/doc/images/imageviewer-fit_to_window_2.png b/examples/widgets/doc/images/imageviewer-fit_to_window_2.png deleted file mode 100644 index 29e3a93b..00000000 Binary files a/examples/widgets/doc/images/imageviewer-fit_to_window_2.png and /dev/null differ diff --git a/examples/widgets/doc/images/imageviewer-original_size.png b/examples/widgets/doc/images/imageviewer-original_size.png deleted file mode 100644 index c0443eba..00000000 Binary files a/examples/widgets/doc/images/imageviewer-original_size.png and /dev/null differ diff --git a/examples/widgets/doc/images/imageviewer-zoom_in_1.png b/examples/widgets/doc/images/imageviewer-zoom_in_1.png deleted file mode 100644 index 05b0fffe..00000000 Binary files a/examples/widgets/doc/images/imageviewer-zoom_in_1.png and /dev/null differ diff --git a/examples/widgets/doc/images/imageviewer-zoom_in_2.png b/examples/widgets/doc/images/imageviewer-zoom_in_2.png deleted file mode 100644 index 0c36111c..00000000 Binary files a/examples/widgets/doc/images/imageviewer-zoom_in_2.png and /dev/null differ diff --git a/examples/widgets/doc/images/itemviewspuzzle-example.png b/examples/widgets/doc/images/itemviewspuzzle-example.png deleted file mode 100644 index aae6a953..00000000 Binary files a/examples/widgets/doc/images/itemviewspuzzle-example.png and /dev/null differ diff --git a/examples/widgets/doc/images/mainwindow-demo.png b/examples/widgets/doc/images/mainwindow-demo.png deleted file mode 100644 index 0e146d15..00000000 Binary files a/examples/widgets/doc/images/mainwindow-demo.png and /dev/null differ diff --git a/examples/widgets/doc/images/plugandpaint-plugindialog.png b/examples/widgets/doc/images/plugandpaint-plugindialog.png deleted file mode 100644 index 4b601bd5..00000000 Binary files a/examples/widgets/doc/images/plugandpaint-plugindialog.png and /dev/null differ diff --git a/examples/widgets/doc/images/plugandpaint.png b/examples/widgets/doc/images/plugandpaint.png deleted file mode 100644 index bd5d001f..00000000 Binary files a/examples/widgets/doc/images/plugandpaint.png and /dev/null differ diff --git a/examples/widgets/doc/images/stylesheet-pagefold.png b/examples/widgets/doc/images/stylesheet-pagefold.png deleted file mode 100644 index d1358f32..00000000 Binary files a/examples/widgets/doc/images/stylesheet-pagefold.png and /dev/null differ diff --git a/examples/widgets/doc/images/textedit-demo.png b/examples/widgets/doc/images/textedit-demo.png deleted file mode 100644 index 3cf2883a..00000000 Binary files a/examples/widgets/doc/images/textedit-demo.png and /dev/null differ diff --git a/examples/widgets/doc/src/addressbook.qdoc b/examples/widgets/doc/src/addressbook.qdoc index 24bcee5a..8f251229 100644 --- a/examples/widgets/doc/src/addressbook.qdoc +++ b/examples/widgets/doc/src/addressbook.qdoc @@ -4,6 +4,7 @@ /*! \example itemviews/addressbook \title Address Book + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief The address book example shows how to use proxy models to display different views onto data from a single model. diff --git a/examples/widgets/doc/src/affine.qdoc b/examples/widgets/doc/src/affine.qdoc index accbf9ad..5aded0bd 100644 --- a/examples/widgets/doc/src/affine.qdoc +++ b/examples/widgets/doc/src/affine.qdoc @@ -4,8 +4,9 @@ /*! \example painting/affine \title Affine Transformations + \examplecategory {Graphics & Multimedia} \ingroup examples-painting - \brief Demonstrates how affine transformations in QPainter works. + \brief Demonstrates how affine transformations in QPainter work. \brief In this example we show Qt's ability to perform affine transformations on painting operations. diff --git a/examples/widgets/doc/src/analogclock.qdoc b/examples/widgets/doc/src/analogclock.qdoc index 27d14be8..4191b5e1 100644 --- a/examples/widgets/doc/src/analogclock.qdoc +++ b/examples/widgets/doc/src/analogclock.qdoc @@ -3,7 +3,7 @@ /*! \example widgets/analogclock - \examplecategory {Graphics} + \examplecategory {Graphics & Multimedia} \meta tags {widgets} \title Analog Clock diff --git a/examples/widgets/doc/src/application.qdoc b/examples/widgets/doc/src/application.qdoc deleted file mode 100644 index 43073a81..00000000 --- a/examples/widgets/doc/src/application.qdoc +++ /dev/null @@ -1,370 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example mainwindows/application - \title Qt Widgets - Application Example - \ingroup examples-mainwindow - - \brief The Application example shows how to implement a standard - widget application with menus, toolbars, and a status bar. The example - itself is a simple text editor program built around QPlainTextEdit. - - \image application.png Screenshot of the Application example - - Nearly all of the code for the Application example is in the \c - MainWindow class, which inherits QMainWindow. QMainWindow - provides the framework for windows that have menus, toolbars, - dock windows, and a status bar. The application provides - \uicontrol{File}, \uicontrol{Edit}, and \uicontrol{Help} entries in the menu - bar, with the following popup menus: - - \image application-menus.png The Application example's menu system - - The status bar at the bottom of the main window shows a - description of the menu item or toolbar button under the cursor. - - To keep the example simple, recently opened files aren't shown in - the \uicontrol{File} menu, even though this feature is desired in 90% - of applications. Furthermore, this example can only load one file at a - time. The \l{mainwindows/mdi}{MDI} example shows how to lift these - restrictions and how to implement recently opened files handling. - - \section1 MainWindow Class Definition - - Here's the class definition: - - \snippet mainwindows/application/mainwindow.h 0 - - The public API is restricted to the constructor. In the \c - protected section, we reimplement QWidget::closeEvent() to detect - when the user attempts to close the window, and warn the user - about unsaved changes. In the \c{private slots} section, we - declare slots that correspond to menu entries, as well as a - mysterious \c documentWasModified() slot. Finally, in the \c - private section of the class, we have various members that will - be explained in due time. - - \section1 MainWindow Class Implementation - - \snippet mainwindows/application/mainwindow.cpp 0 - - We start by including \c , a header file that contains the - definition of all classes in the Qt Core, Qt GUI and Qt Widgets - modules. This saves us from the trouble of having to include - every class individually. We also include \c mainwindow.h. - - You might wonder why we don't include \c in \c - mainwindow.h and be done with it. The reason is that including - such a large header from another header file can rapidly degrade - performances. Here, it wouldn't do any harm, but it's still - generally a good idea to include only the header files that are - strictly necessary from another header file. - - \snippet mainwindows/application/mainwindow.cpp 1 - \snippet mainwindows/application/mainwindow.cpp 2 - - In the constructor, we start by creating a QPlainTextEdit widget as a - child of the main window (the \c this object). Then we call - QMainWindow::setCentralWidget() to tell that this is going to be - the widget that occupies the central area of the main window, - between the toolbars and the status bar. - - Then we call \c createActions() and \c createStatusBar(), two private - functions that set up the user interface. After that, we call \c - readSettings() to restore the user's preferences. - - We establish a signal-slot connection between the QPlainTextEdit's - document object and our \c documentWasModified() slot. Whenever - the user modifies the text in the QPlainTextEdit, we want to update - the title bar to show that the file was modified. - - At the end, we set the window title using the private - \c setCurrentFile() function. We'll come back to this later. - - \target close event handler - \snippet mainwindows/application/mainwindow.cpp 3 - \snippet mainwindows/application/mainwindow.cpp 4 - - When the user attempts to close the window, we call the private - function \c maybeSave() to give the user the possibility to save - pending changes. The function returns true if the user wants the - application to close; otherwise, it returns false. In the first - case, we save the user's preferences to disk and accept the close - event; in the second case, we ignore the close event, meaning - that the application will stay up and running as if nothing - happened. - - \snippet mainwindows/application/mainwindow.cpp 5 - \snippet mainwindows/application/mainwindow.cpp 6 - - The \c newFile() slot is invoked when the user selects - \uicontrol{File|New} from the menu. We call \c maybeSave() to save any - pending changes and if the user accepts to go on, we clear the - QPlainTextEdit and call the private function \c setCurrentFile() to - update the window title and clear the - \l{QWidget::windowModified}{windowModified} flag. - - \snippet mainwindows/application/mainwindow.cpp 7 - \snippet mainwindows/application/mainwindow.cpp 8 - - The \c open() slot is invoked when the user clicks - \uicontrol{File|Open}. We pop up a QFileDialog asking the user to - choose a file. If the user chooses a file (i.e., \c fileName is - not an empty string), we call the private function \c loadFile() - to actually load the file. - - \snippet mainwindows/application/mainwindow.cpp 9 - \snippet mainwindows/application/mainwindow.cpp 10 - - The \c save() slot is invoked when the user clicks - \uicontrol{File|Save}. If the user hasn't provided a name for the file - yet, we call \c saveAs(); otherwise, we call the private function - \c saveFile() to actually save the file. - - \snippet mainwindows/application/mainwindow.cpp 11 - \snippet mainwindows/application/mainwindow.cpp 12 - - In \c saveAs(), we start by popping up a QFileDialog asking the - user to provide a name. If the user clicks \uicontrol{Cancel}, the - returned file name is empty, and we do nothing. - - \snippet mainwindows/application/mainwindow.cpp 13 - \snippet mainwindows/application/mainwindow.cpp 14 - - The application's About box is done using one statement, using - the QMessageBox::about() static function and relying on its - support for an HTML subset. - - The \l{QObject::tr()}{tr()} call around the literal string marks - the string for translation. It is a good habit to call - \l{QObject::tr()}{tr()} on all user-visible strings, in case you - later decide to translate your application to other languages. - The \l{Internationalization with Qt} overview covers - \l{QObject::tr()}{tr()} in more detail. - - \snippet mainwindows/application/mainwindow.cpp 15 - \snippet mainwindows/application/mainwindow.cpp 16 - - The \c documentWasModified() slot is invoked each time the text - in the QPlainTextEdit changes because of user edits. We call - QWidget::setWindowModified() to make the title bar show that the - file was modified. How this is done varies on each platform. - - \snippet mainwindows/application/mainwindow.cpp 17 - \snippet mainwindows/application/mainwindow.cpp 18 - \dots - \snippet mainwindows/application/mainwindow.cpp 22 - - The \c createActions() private function, which is called from the - \c MainWindow constructor, creates \l{QAction}s and populates - the menus and two toolbars. The code is very - repetitive, so we show only the actions corresponding to - \uicontrol{File|New}, \uicontrol{File|Open}, and \uicontrol{Help|About Qt}. - - A QAction is an object that represents one user action, such as - saving a file or invoking a dialog. An action can be put in a - QMenu or a QToolBar, or both, or in any other widget that - reimplements QWidget::actionEvent(). - - An action has a text that is shown in the menu, an icon, a - shortcut key, a tooltip, a status tip (shown in the status bar), - a "What's This?" text, and more. It emits a - \l{QAction::triggered()}{triggered()} signal whenever the user - invokes the action (e.g., by clicking the associated menu item or - toolbar button). - - Instances of QAction can be created by passing a parent QObject or - by using one of the convenience functions of QMenu, QMenuBar or QToolBar. - We create the actions that are in a menu as well as in a toolbar - parented on the window to prevent ownership issues. For actions - that are only in the menu, we use the convenience function - QMenu::addAction(), which allows us to pass text, icon and the - target object and its slot member function. - - Creating toolbars is very similar to creating menus. The same - actions that we put in the menus can be reused in the toolbars. - After creating the action, we add it to the toolbar using - QToolBar::addAction(). - - The code above contains one more idiom that must be explained. - For some of the actions, we specify an icon as a QIcon to the - QAction constructor. We use QIcon::fromTheme() to obtain - the correct standard icon from the underlying window system. - If that fails due to the platform not supporting it, we - pass a file name as fallback. Here, the file name starts - with \c{:}. Such file names aren't ordinary file names, but - rather path in the executable's stored resources. We'll come back - to this when we review the \c application.qrc file that's part of - the project. - - \snippet mainwindows/application/mainwindow.cpp 23 - \snippet mainwindows/application/mainwindow.cpp 24 - - The \uicontrol{Edit|Cut} and \uicontrol{Edit|Copy} actions must be available - only when the QPlainTextEdit contains selected text. We disable them - by default and connect the QPlainTextEdit::copyAvailable() signal to - the QAction::setEnabled() slot, ensuring that the actions are - disabled when the text editor has no selection. - - Just before we create the \uicontrol{Help} menu, we call - QMenuBar::addSeparator(). This has no effect for most widget - styles (e.g., Windows and \macos styles), but for some - styles this makes sure that \uicontrol{Help} is pushed to the right - side of the menu bar. - - \snippet mainwindows/application/mainwindow.cpp 32 - \snippet mainwindows/application/mainwindow.cpp 33 - - QMainWindow::statusBar() returns a pointer to the main window's - QStatusBar widget. Like with \l{QMainWindow::menuBar()}, the - widget is automatically created the first time the function is - called. - - \snippet mainwindows/application/mainwindow.cpp 34 - \snippet mainwindows/application/mainwindow.cpp 36 - - The \c readSettings() function is called from the constructor to - load the user's preferences and other application settings. The - QSettings class provides a high-level interface for storing - settings permanently on disk. On Windows, it uses the (in)famous - Windows registry; on \macos, it uses the native XML-based - CFPreferences API; on Unix/X11, it uses text files. - - The QSettings constructor takes arguments that identify your - company and the name of the product. This ensures that the - settings for different applications are kept separately. - - We use QSettings::value() to extract the value of the geometry setting. - The second argument to QSettings::value() is - optional and specifies a default value for the setting if there - exists none. This value is used the first time the application is - run. - - We use QWidget::saveGeometry() and Widget::restoreGeometry() to - save the position. They use an opaque QByteArray to store - screen number, geometry and window state. - - \snippet mainwindows/application/mainwindow.cpp 37 - \snippet mainwindows/application/mainwindow.cpp 39 - - The \c writeSettings() function is called from \c closeEvent(). - Writing settings is similar to reading them, except simpler. The - arguments to the QSettings constructor must be the same as in \c - readSettings(). - - \snippet mainwindows/application/mainwindow.cpp 40 - \snippet mainwindows/application/mainwindow.cpp 41 - - The \c maybeSave() function is called to save pending changes. If - there are pending changes, it pops up a QMessageBox giving the - user to save the document. The options are QMessageBox::Yes, - QMessageBox::No, and QMessageBox::Cancel. The \uicontrol{Yes} button is - made the default button (the button that is invoked when the user - presses \uicontrol{Return}) using the QMessageBox::Default flag; the - \uicontrol{Cancel} button is made the escape button (the button that is - invoked when the user presses \uicontrol{Esc}) using the - QMessageBox::Escape flag. - - The \c maybeSave() function returns \c true in all cases, except - when the user clicks \uicontrol{Cancel} or saving the file fails. - The caller must check the return value and stop whatever it was - doing if the return value is \c false. - - \snippet mainwindows/application/mainwindow.cpp 42 - \snippet mainwindows/application/mainwindow.cpp 43 - - In \c loadFile(), we use QFile and QTextStream to read in the - data. The QFile object provides access to the bytes stored in a - file. - - We start by opening the file in read-only mode. The QFile::Text - flag indicates that the file is a text file, not a binary file. - On Unix and \macos, this makes no difference, but on Windows, - it ensures that the "\\r\\n" end-of-line sequence is converted to - "\\n" when reading. - - If we successfully opened the file, we use a QTextStream object - to read in the data. QTextStream automatically converts the 8-bit - data into a Unicode QString and supports various encodings. If no - encoding is specified, QTextStream assumes the file is encoded in - UTF-8. - - Since the call to QTextStream::readAll() might take some time, we - set the cursor to be Qt::WaitCursor for the entire application - while it goes on. - - At the end, we call the private \c setCurrentFile() function, - which we'll cover in a moment, and we display the string "File - loaded" in the status bar for 2 seconds (2000 milliseconds). - - \snippet mainwindows/application/mainwindow.cpp 44 - \snippet mainwindows/application/mainwindow.cpp 45 - - Saving a file is similar to loading one. We use QSaveFile to ensure - all data are safely written and existing files are not damaged - should writing fail. - We use the QFile::Text flag to make sure that on Windows, "\\n" - is converted into "\\r\\n" to conform to the Windows convention. - - - \snippet mainwindows/application/mainwindow.cpp 46 - \snippet mainwindows/application/mainwindow.cpp 47 - - The \c setCurrentFile() function is called to reset the state of - a few variables when a file is loaded or saved, or when the user - starts editing a new file (in which case \c fileName is empty). - We update the \c curFile variable, clear the - QTextDocument::modified flag and the associated \c - QWidget:windowModified flag, and update the window title to - contain the new file name (or \c untitled.txt). - - The \c strippedName() function call around \c curFile in the - QWidget::setWindowTitle() call shortens the file name to exclude - the path. Here's the function: - - \snippet mainwindows/application/mainwindow.cpp 48 - \snippet mainwindows/application/mainwindow.cpp 49 - - \section1 The main() Function - - The \c main() function for this application is typical of - applications that contain one main window: - - \snippet mainwindows/application/main.cpp 0 - - The main function uses QCommandLineParser to check whether some file - argument was passed to the application and loads it via - MainWindow::loadFile(). - - \section1 The Resource File - - As you will probably recall, for some of the actions, we - specified icons with file names starting with \c{:} and mentioned - that such file names aren't ordinary file names, but path in the - executable's stored resources. These resources are compiled - - The resources associated with an application are specified in a - \c .qrc file, an XML-based file format that lists files on the - disk. Here's the \c application.qrc file that's used by the - Application example: - - \quotefile mainwindows/application/application.qrc - - The \c .png files listed in the \c application.qrc file are files - that are part of the Application example's source tree. Paths are - relative to the directory where the \c application.qrc file is - located (the \c mainwindows/application directory). - - The resource file must be mentioned in the \c application.pro - file so that \c qmake knows about it: - - \snippet mainwindows/application/application.pro 0 - - \c qmake will produce make rules to generate a file called \c - qrc_application.cpp that is linked into the application. This - file contains all the data for the images and other resources as - static C++ arrays of compressed binary data. See - \l{resources.html}{The Qt Resource System} for more information - about resources. -*/ diff --git a/examples/widgets/doc/src/basicdrawing.qdoc b/examples/widgets/doc/src/basicdrawing.qdoc index 7413dfc8..afba853f 100644 --- a/examples/widgets/doc/src/basicdrawing.qdoc +++ b/examples/widgets/doc/src/basicdrawing.qdoc @@ -4,6 +4,7 @@ /*! \example painting/basicdrawing \title Basic Drawing Example + \examplecategory {Graphics & Multimedia} \ingroup examples-painting \brief The Basic Drawing example shows how to display basic graphics primitives in a variety of styles using the QPainter diff --git a/examples/widgets/doc/src/basicgraphicslayouts.qdoc b/examples/widgets/doc/src/basicgraphicslayouts.qdoc index ce7176bf..07ead4e4 100644 --- a/examples/widgets/doc/src/basicgraphicslayouts.qdoc +++ b/examples/widgets/doc/src/basicgraphicslayouts.qdoc @@ -4,6 +4,7 @@ /*! \example graphicsview/basicgraphicslayouts \title Basic Graphics Layouts Example + \examplecategory {Graphics & Multimedia} \ingroup examples-graphicsview-layout \brief Demonstrates how to create basic graphics layout. diff --git a/examples/widgets/doc/src/basiclayouts.qdoc b/examples/widgets/doc/src/basiclayouts.qdoc index c5551468..e6f1cab4 100644 --- a/examples/widgets/doc/src/basiclayouts.qdoc +++ b/examples/widgets/doc/src/basiclayouts.qdoc @@ -4,6 +4,7 @@ /*! \example layouts/basiclayouts \title Basic Layouts Example + \examplecategory {User Interface Components} \brief Shows how to use the standard layout managers. \e{Basic Layouts} shows how to use the standard layout managers that are diff --git a/examples/widgets/doc/src/basicsortfiltermodel.qdoc b/examples/widgets/doc/src/basicsortfiltermodel.qdoc index 969ee0a9..c0b8a5f4 100644 --- a/examples/widgets/doc/src/basicsortfiltermodel.qdoc +++ b/examples/widgets/doc/src/basicsortfiltermodel.qdoc @@ -4,6 +4,7 @@ /*! \example itemviews/basicsortfiltermodel \title Basic Sort/Filter Model Example + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief The Basic Sort/Filter Model example illustrates how to use QSortFilterProxyModel to perform basic sorting and filtering. diff --git a/examples/widgets/doc/src/borderlayout.qdoc b/examples/widgets/doc/src/borderlayout.qdoc deleted file mode 100644 index 9ec5e96d..00000000 --- a/examples/widgets/doc/src/borderlayout.qdoc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example layouts/borderlayout - \title Border Layout Example - \ingroup examples-layout - \brief Shows how to arrange child widgets along a border. - - \e{Border Layout} implements a layout that arranges child widgets to - surround the main area. - - \image borderlayout-example.png - - The constructor of the Window class creates a QTextBrowser object, - to which a BorderLayout named \c layout is added. The declaration - of the BorderLayout class is quoted at the end of this document. - - \quotefromfile layouts/borderlayout/window.cpp - \skipto Window::Window() - \printuntil BorderLayout - - Several labeled widgets are added to \c layout with the orientation - \c {Center}, \c {North}, \c {West}, \c {East 1}, \c {East 2}, and - \c {South}. - - \skipto layout->addWidget - \printuntil setWindowTitle - - createLabel() in class \c Window sets the text of the labeled widgets - and the style. - - \skipto QLabel *Window::createLabel - \printuntil /^\}/ - - Class BorderLayout contains all the utilitarian functions for formatting - the widgets it contains. - - \quotefromfile layouts/borderlayout/borderlayout.h - \skipto class - \printuntil /^\}/ - - For more information, visit the \l{Layout Management} page. - - \include examples-run.qdocinc -*/ diff --git a/examples/widgets/doc/src/calculator.qdoc b/examples/widgets/doc/src/calculator.qdoc index cc015e46..c59d3cd1 100644 --- a/examples/widgets/doc/src/calculator.qdoc +++ b/examples/widgets/doc/src/calculator.qdoc @@ -4,6 +4,7 @@ /*! \example widgets/calculator \title Calculator Example + \examplecategory {User Interface Components} \ingroup examples-widgets \ingroup examples-layout \brief The example shows how to use signals and slots to implement the diff --git a/examples/widgets/doc/src/calendar.qdoc b/examples/widgets/doc/src/calendar.qdoc deleted file mode 100644 index 218ea5ea..00000000 --- a/examples/widgets/doc/src/calendar.qdoc +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example richtext/calendar - \title Calendar Example - \ingroup examples-richtext - \brief The Calendar example shows how to create rich text content - and display it using a rich text editor. - - \brief The Calendar example shows how to create rich text content and display it using - a rich text editor. - - \image calendar-example.png - - Specifically, the example demonstrates the following: - - \list - \li Use of a text editor with a text document - \li Insertion of tables and frames into a document - \li Navigation within a table - \li Insert text in different styles - \endlist - - The rich text editor used to display the document is used within a main window - application. - - \section1 MainWindow Class Definition - - The \c MainWindow class provides a text editor widget and some controls to - allow the user to change the month and year shown. The font size used for the - text can also be adjusted. - - \snippet richtext/calendar/mainwindow.h 0 - - The private \c insertCalendar() function performs most of the work, relying on - the \c fontSize and \c selectedDate variables to write useful information to - the \c editor. - - \section1 MainWindow Class Implementation - - The \c MainWindow constructor sets up the user interface and initializes - variables used to generate a calendar for each month. - - \snippet richtext/calendar/mainwindow.cpp 0 - - We begin by setting default values for the selected date that will be highlighted - in the calendar and the font size to be used. Since we are using a QMainWindow - for the user interface, we construct a widget for use as the central widget. - - The user interface will include a line of controls above the generated calendar; - we construct a label and a combobox to allow the month to be selected, and a - spin box for the year. These widgets are configured to provide a reasonable range - of values for the user to try: - - \snippet richtext/calendar/mainwindow.cpp 1 - - We use the \c selectedDate object to obtain the current month and year, and we - set these in the combobox and spin box: - - The font size is displayed in a spin box which we restrict to a sensible range - of values: - - \snippet richtext/calendar/mainwindow.cpp 2 - - We construct an editor and use the \c insertCalendar() function to create - a calendar for it. Each calendar is displayed in the same text editor; in - this example we use a QTextBrowser since we do not allow the calendar to be - edited. - - The controls used to set the month, year, and font size will not have any - effect on the appearance of the calendar unless we make some signal-slot - connections: - - \snippet richtext/calendar/mainwindow.cpp 3 - - The signals are connected to some simple slots in the \c MainWindow class - which we will describe later. - - We create layouts to manage the widgets we constructed: - - \snippet richtext/calendar/mainwindow.cpp 4 - - Finally, the central widget is set for the window. - - Each calendar is created for the editor by the \c insertCalendar() function - which uses the date and font size, defined by the private \a selectedDate - and \c fontSize variables, to produce a suitable plan for the specified - month and year. - - \snippet richtext/calendar/mainwindow.cpp 5 - - We begin by clearing the editor's rich text document, and obtain a text - cursor from the editor that we will use to add content. We also create a - QDate object based on the currently selected date. - - The calendar is made up of a table with a gray background color that contains - seven columns: one for each day of the week. It is placed in the center of the - page with equal space to the left and right of it. All of these properties are - set in a QTextTableFormat object: - - \snippet richtext/calendar/mainwindow.cpp 6 - - Each cell in the table will be padded and spaced to make the text easier to - read. - - We want the columns to have equal widths, so we provide a list containing - percentage widths for each of them and set the constraints in the - QTextTableFormat: - - \snippet richtext/calendar/mainwindow.cpp 7 - - The constraints used for the column widths are only useful if the table has - an appropriate number of columns. With the format for the table defined, we - construct a new table with one row and seven columns at the current cursor - position: - - \snippet richtext/calendar/mainwindow.cpp 8 - - We only need one row to start with; more can be added as we need them. Using - this approach means that we do not need to perform any date calculations - until we add cells to the table. - - When inserting objects into a document with the cursor's insertion functions, - the cursor is automatically moved inside the newly inserted object. This means - that we can immediately start modifying the table from within: - - \snippet richtext/calendar/mainwindow.cpp 9 - - Since the table has an outer frame, we obtain the frame and its format so that - we can customize it. After making the changes we want, we set the frame's format - using the modified format object. We have given the table an outer border one - pixel wide. - - \snippet richtext/calendar/mainwindow.cpp 10 - - In a similar way, we obtain the cursor's current character format and - create customized formats based on it. - - We do not set the format on the cursor because this would change the default - character format; instead, we use the customized formats explicitly when we - insert text. The following loop inserts the days of the week into the table - as bold text: - - \snippet richtext/calendar/mainwindow.cpp 11 - - For each day of the week, we obtain an existing table cell in the first row - (row 0) using the table's \l{QTextTable::cellAt()}{cellAt()} function. Since - we start counting the days of the week at day 1 (Monday), we subtract 1 from - \c weekDay to ensure that we obtain the cell for the correct column of the - table. - - Before text can be inserted into a cell, we must obtain a cursor with the - correct position in the document. The cell provides a function for this - purpose, and we use this cursor to insert text using the \c boldFormat - character format that we created earlier: - - \snippet richtext/calendar/mainwindow.cpp 12 - - Inserting text into document objects usually follows the same pattern. - Each object can provide a new cursor that corresponds to the first valid - position within itself, and this can be used to insert new content. We - continue to use this pattern as we insert the days of the month into the - table. - - Since every month has more than seven days, we insert a single row to begin - and add days until we reach the end of the month. If the current date is - encountered, it is inserted with a special format (created earlier) that - makes it stand out: - - \snippet richtext/calendar/mainwindow.cpp 13 - - We add a new row to the table at the end of each week only if the next week - falls within the currently selected month. - - For each calendar that we create, we change the window title to reflect the - currently selected month and year: - - \snippet richtext/calendar/mainwindow.cpp 14 - - The \c insertCalendar() function relies on up-to-date values for the month, - year, and font size. These are set in the following slots: - - \snippet richtext/calendar/mainwindow.cpp 15 - - The \c setFontSize() function simply changes the private \c fontSize variable - before updating the calendar. - - \snippet richtext/calendar/mainwindow.cpp 16 - - The \c setMonth slot is called when the QComboBox used to select the month is - updated. The value supplied is the currently selected row in the combobox. - We add 1 to this value to obtain a valid month number, and create a new QDate - based on the existing one. The calendar is then updated to use this new date. - - \snippet richtext/calendar/mainwindow.cpp 17 - - The \c setYear() slot is called when the QDateTimeEdit used to select the - year is updated. The value supplied is a QDate object; this makes - the construction of a new value for \c selectedDate simple. We update the - calendar afterwards to use this new date. -*/ diff --git a/examples/widgets/doc/src/calendarwidget.qdoc b/examples/widgets/doc/src/calendarwidget.qdoc index 6a91f5ef..898f4bbd 100644 --- a/examples/widgets/doc/src/calendarwidget.qdoc +++ b/examples/widgets/doc/src/calendarwidget.qdoc @@ -3,6 +3,7 @@ /*! \title Calendar Widget Example + \examplecategory {Graphics & Multimedia} \example widgets/calendarwidget \ingroup examples-widgets \ingroup examples-layout diff --git a/examples/widgets/doc/src/charactermap.qdoc b/examples/widgets/doc/src/charactermap.qdoc deleted file mode 100644 index ee616230..00000000 --- a/examples/widgets/doc/src/charactermap.qdoc +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! -\example widgets/charactermap -\title Character Map Example -\ingroup examples-widgets -\brief The Character Map example shows how to create a custom widget that can -both display its own content and respond to user input. - -The example displays an array of characters which the user can click on -to enter text in a line edit. The contents of the line edit can then be -copied into the clipboard, and pasted into other applications. The -purpose behind this sort of tool is to allow users to enter characters -that may be unavailable or difficult to locate on their keyboards. - -\borderedimage charactermap-example.png -\caption Screenshot of the Character Map example - -The example consists of the following classes: - -\list -\li \c CharacterWidget displays the available characters in the current - font and style. -\li \c MainWindow provides a standard main window that contains font and - style information, a view onto the characters, a line edit, and a push - button for submitting text to the clipboard. -\endlist - -\section1 CharacterWidget Class Definition - -The \c CharacterWidget class is used to display an array of characters in -a user-specified font and style. For flexibility, we subclass QWidget and -reimplement only the functions that we need to provide basic rendering -and interaction features. - -The class definition looks like this: - -\snippet widgets/charactermap/characterwidget.h 0 - -The widget does not contain any other widgets, so it must provide its own -size hint to allow its contents to be displayed correctly. -We reimplement \l{QWidget::paintEvent()} to draw custom content. We also -reimplement \l{QWidget::mousePressEvent()} to allow the user to interact -with the widget. - -The updateFont() and updateStyle() slots are used to update the font and -style of the characters in the widget whenever the user changes the -settings in the application. -The class defines the characterSelected() signal so that other parts -of the application are informed whenever the user selects a character in -the widget. -As a courtesy, the widget provides a tooltip that shows the current -character value. We reimplement the \l{QWidget::mouseMoveEvent()} event -handler and define showToolTip() to enable this feature. - -The \c columns, \c displayFont and \c currentKey private data members -are used to record the number of columns to be shown, the current font, -and the currently highlighted character in the widget. - -\section1 CharacterWidget Class Implementation - -Since the widget is to be used as a simple canvas, the constructor just -calls the base class constructor and defines some default values for -private data members. - -\snippet widgets/charactermap/characterwidget.cpp 0 - -We initialize \c currentKey with a value of -1 to indicate -that no character is initially selected. We enable mouse tracking to -allow us to follow the movement of the cursor across the widget. - -The class provides two functions to allow the font and style to be set up. -Each of these modify the widget's display font and call update(): - -\snippet widgets/charactermap/characterwidget.cpp 1 -\codeline -\snippet widgets/charactermap/characterwidget.cpp 2 - -We use a fixed size font for the display. Similarly, a fixed size hint is -provided by the sizeHint() function: - -\snippet widgets/charactermap/characterwidget.cpp 3 - -Three standard event functions are implemented so that the widget -can respond to clicks, provide tooltips, and render the available -characters. The paintEvent() shows how the contents of the widget are -arranged and displayed: - -\snippet widgets/charactermap/characterwidget.cpp 6 - -A QPainter is created for the widget and, in all cases, we ensure that the -widget's background is painted. The painter's font is set to the -user-specified display font. - -The area of the widget that needs to be redrawn is used to determine which -characters need to be displayed: - -\snippet widgets/charactermap/characterwidget.cpp 7 - -Using integer division, we obtain the row and column numbers of each -characters that should be displayed, and we draw a square on the widget -for each character displayed. - -\snippet widgets/charactermap/characterwidget.cpp 8 -\snippet widgets/charactermap/characterwidget.cpp 9 - -The symbols for each character in the array are drawn within each square, -with the symbol for the most recently selected character displayed in red: - -\snippet widgets/charactermap/characterwidget.cpp 10 - -We do not need to take into account the difference between the area -displayed in the viewport and the area we are drawing on because -everything outside the visible area will be clipped. - -The mousePressEvent() defines how the widget responds to mouse clicks. - -\snippet widgets/charactermap/characterwidget.cpp 5 - -We are only interested when the user clicks with the left mouse button -over the widget. When this happens, we calculate which character was -selected and emit the characterSelected() signal. -The character's number is found by dividing the x and y-coordinates of -the click by the size of each character's grid square. Since the number -of columns in the widget is defined by the \c columns variable, we -simply multiply the row index by that value and add the column number -to obtain the character number. - -If any other mouse button is pressed, the event is passed on to the -QWidget base class. This ensures that the event can be handled properly -by any other interested widgets. - -The mouseMoveEvent() maps the mouse cursor's position in global -coordinates to widget coordinates, and determines the character that -was clicked by performing the calculation - -\snippet widgets/charactermap/characterwidget.cpp 4 - -The tooltip is given a position defined in global coordinates. - -\section1 MainWindow Class Definition - -The \c MainWindow class provides a minimal user interface for the example, -with only a constructor, slots that respond to signals emitted by standard -widgets, and some convenience functions that are used to set up the user -interface. - -The class definition looks like this: - -\snippet widgets/charactermap/mainwindow.h 0 - -The main window contains various widgets that are used to control how -the characters will be displayed, and defines the findFonts() function -for clarity and convenience. The findStyles() slot is used by the widgets -to determine the styles that are available, insertCharacter() inserts -a user-selected character into the window's line edit, and -updateClipboard() synchronizes the clipboard with the contents of the -line edit. - -\section1 MainWindow Class Implementation - -In the constructor, we set up the window's central widget and fill it with -some standard widgets (two comboboxes, a line edit, and a push button). -We also construct a CharacterWidget custom widget, and add a QScrollArea -so that we can view its contents: - -\snippet widgets/charactermap/mainwindow.cpp 0 - -QScrollArea provides a viewport onto the \c CharacterWidget when we set -its widget and handles much of the work needed to provide a scrolling -viewport. - -The font combo box is automatically populated with a list of available -fonts. We list the available styles for the current font in the style -combobox using the following function: - -\snippet widgets/charactermap/mainwindow.cpp 1 - -The line edit and push button are used to supply text to the clipboard: - -\snippet widgets/charactermap/mainwindow.cpp 2 - -We also obtain a clipboard object so that we can send text entered by the -user to other applications. - -Most of the signals emitted in the example come from standard widgets. -We connect these signals to slots in this class, and to the slots provided -by other widgets. - -\snippet widgets/charactermap/mainwindow.cpp 4 - -The font combobox's -\l{QFontComboBox::currentFontChanged()}{currentFontChanged()} signal is -connected to the findStyles() function so that the list of available styles -can be shown for each font that is used. Since both the font and the style -can be changed by the user, the font combobox's currentFontChanged() signal -and the style combobox's -\l{QComboBox::currentIndexChanged()}{currentIndexChanged()} are connected -directly to the character widget. - -The final two connections allow characters to be selected in the character -widget, and text to be inserted into the clipboard: - -\snippet widgets/charactermap/mainwindow.cpp 5 - -The character widget emits the characterSelected() custom signal when -the user clicks on a character, and this is handled by the insertCharacter() -function in this class. The clipboard is changed when the push button emits -the clicked() signal, and we handle this with the updateClipboard() function. - -The remaining code in the constructor sets up the layout of the central widget, -and provides a window title: - -\snippet widgets/charactermap/mainwindow.cpp 6 - -The font combobox is automatically populated with a list of available font -families. The styles that can be used with each font are found by the -findStyles() function. This function is called whenever the user selects a -different font in the font combobox. - -\snippet widgets/charactermap/mainwindow.cpp 7 - -We begin by recording the currently selected style, and we clear the -style combobox so that we can insert the styles associated with the -current font family. - -\snippet widgets/charactermap/mainwindow.cpp 8 - -We use the font database to collect the styles that are available for the -current font, and insert them into the style combobox. The current item is -reset if the original style is not available for this font. - -The last two functions are slots that respond to signals from the character -widget and the main window's push button. The insertCharacter() function is -used to insert characters from the character widget when the user clicks a -character: - -\snippet widgets/charactermap/mainwindow.cpp 9 - -The character is inserted into the line edit at the current cursor position. - -The main window's "To clipboard" push button is connected to the -updateClipboard() function so that, when it is clicked, the clipboard is -updated to contain the contents of the line edit: - -\snippet widgets/charactermap/mainwindow.cpp 10 - -We copy all the text from the line edit to the clipboard, but we do not clear -the line edit. -*/ diff --git a/examples/widgets/doc/src/chart.qdoc b/examples/widgets/doc/src/chart.qdoc deleted file mode 100644 index abb1b3ab..00000000 --- a/examples/widgets/doc/src/chart.qdoc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example itemviews/chart - \title Chart Example - \ingroup examples-itemviews - \brief The Chart example shows how to create a custom view for the model/view framework. - - \image chart-example.png - - In this example, the items in a table model are represented as slices in a pie chart, - relying on the flexibility of the model/view architecture to handle custom editing - and selection features. - - \b{Note that you only need to create a new view class if your data requires a - specialized representation.} You should first consider using a standard QListView, - QTableView, or QTreeView with a custom QItemDelegate subclass if you need to - represent data in a special way. - - \omit - \section1 PieView Class Definition - - The \c PieView class is a subclass of QAbstractItemView. The base class provides - much of the functionality required by view classes, so we only need to provide - implementations for three public functions: visualRect(), scrollTo(), and - indexAt(). However, the view needs to maintain strict control over its look and - feel, so we also provide implementations for a number of other functions: - - \snippet itemviews/chart/pieview.h 0 - - - - \section1 PieView Class Implementation - - The paint event renders the data from the standard item model as a pie chart. - We interpret the data in the following way: - - \list - \li Column 0 contains data in two different roles: - The \l{Qt::ItemDataRole}{DisplayRole} contains a label, and the - \l{Qt::ItemDataRole}{DecorationRole} contains the color of the pie slice. - \li Column 1 contains a quantity which we will convert to the angular extent of - the slice. - \endlist - - The figure is always drawn with the chart on the left and the key on - the right. This means that we must try and obtain an area that is wider - than it is tall. We do this by imposing a particular aspect ratio on - the chart and applying it to the available vertical space. This ensures - that we always obtain the maximum horizontal space for the aspect ratio - used. - We also apply fixed size margin around the figure. - - We use logical coordinates to draw the chart and key, and position them - on the view using viewports. - \endomit -*/ diff --git a/examples/widgets/doc/src/chip.qdoc b/examples/widgets/doc/src/chip.qdoc index a76e1195..817fc7d6 100644 --- a/examples/widgets/doc/src/chip.qdoc +++ b/examples/widgets/doc/src/chip.qdoc @@ -4,6 +4,7 @@ /*! \example graphicsview/chip \title 40000 Chips + \examplecategory {Graphics & Multimedia} \ingroup examples-graphicsview \brief Visualizes a huge graphic view scene with 40000 chip items. diff --git a/examples/widgets/doc/src/classwizard.qdoc b/examples/widgets/doc/src/classwizard.qdoc deleted file mode 100644 index 8494a3c7..00000000 --- a/examples/widgets/doc/src/classwizard.qdoc +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example dialogs/classwizard - \title Class Wizard Example - \ingroup examples-dialogs - - \brief The Class Wizard example shows how to implement linear - wizards using QWizard. - - \image classwizard.png Screenshot of the Class Wizard example - - Most wizards have a linear structure, with page 1 followed by - page 2 and so on until the last page. Some wizards are more - complex in that they allow different traversal paths based on the - information provided by the user. The - \l{dialogs/licensewizard}{License Wizard} example shows how to - create such wizards. - - The Class Wizard example consists of the following classes: - - \list - \li \c ClassWizard inherits QWizard and provides a - three-step wizard that generates the skeleton of a C++ class - based on the user's input. - \li \c IntroPage, \c ClassInfoPage, \c CodeStylePage, \c - OutputFilesPage, and \c ConclusionPage are QWizardPage - subclasses that implement the wizard pages. - \endlist - - \section1 ClassWizard Class Definition - - \image classwizard-flow.png The Class Wizard pages - - We will see how to subclass QWizard to implement our own wizard. - The concrete wizard class is called \c ClassWizard and provides - five pages: - - \list - \li The first page is an introduction page, telling the user what - the wizard is going to do. - \li The second page asks for a class name and a base class, and - allows the user to specify whether the class should have a \c - Q_OBJECT macro and what constructors it should provide. - \li The third page allows the user to set some options related to the code - style, such as the macro used to protect the header file from - multiple inclusion (e.g., \c MYDIALOG_H). - \li The fourth page allows the user to specify the names of the - output files. - \li The fifth page is a conclusion page. - \endlist - - Although the program is just an example, if you press \uicontrol Finish - (\uicontrol Done on \macos), actual C++ source files will actually be - generated. - - \section1 The ClassWizard Class - - Here's the \c ClassWizard definition: - - \snippet dialogs/classwizard/classwizard.h 0 - - The class reimplements QDialog's \l{QDialog::}{accept()} slot. - This slot is called when the user clicks \uicontrol{Finish}. - - Here's the constructor: - - \snippet dialogs/classwizard/classwizard.cpp 1 - - We instantiate the five pages and insert them into the wizard - using QWizard::addPage(). The order in which they are inserted - is also the order in which they will be shown later on. - - We call QWizard::setPixmap() to set the banner and the - background pixmaps for all pages. The banner is used as a - background for the page header when the wizard's style is - \l{QWizard::}{ModernStyle}; the background is used as the - dialog's background in \l{QWizard::}{MacStyle}. (See \l{Elements - of a Wizard Page} for more information.) - - \snippet dialogs/classwizard/classwizard.cpp 3 - \snippet dialogs/classwizard/classwizard.cpp 4 - \dots - \snippet dialogs/classwizard/classwizard.cpp 5 - \snippet dialogs/classwizard/classwizard.cpp 6 - - If the user clicks \uicontrol Finish, we extract the information from - the various pages using QWizard::field() and generate the files. - The code is long and tedious (and has barely anything to do with - noble art of designing wizards), so most of it is skipped here. - See the actual example in the Qt distribution for the details if - you're curious. - - \section1 The IntroPage Class - - The pages are defined in \c classwizard.h and implemented in \c - classwizard.cpp, together with \c ClassWizard. We will start with - the easiest page: - - \snippet dialogs/classwizard/classwizard.h 1 - \codeline - \snippet dialogs/classwizard/classwizard.cpp 7 - - A page inherits from QWizardPage. We set a - \l{QWizardPage::}{title} and a - \l{QWizard::WatermarkPixmap}{watermark pixmap}. By not setting - any \l{QWizardPage::}{subTitle}, we ensure that no header is - displayed for this page. (On Windows, it is customary for wizards - to display a watermark pixmap on the first and last pages, and to - have a header on the other pages.) - - Then we create a QLabel and add it to a layout. - - \section1 The ClassInfoPage Class - - The second page is defined and implemented as follows: - - \snippet dialogs/classwizard/classwizard.h 2 - \codeline - \snippet dialogs/classwizard/classwizard.cpp 9 - \dots - \snippet dialogs/classwizard/classwizard.cpp 12 - \dots - \snippet dialogs/classwizard/classwizard.cpp 13 - - First, we set the page's \l{QWizardPage::}{title}, - \l{QWizardPage::}{subTitle}, and \l{QWizard::LogoPixmap}{logo - pixmap}. The logo pixmap is displayed in the page's header in - \l{QWizard::}{ClassicStyle} and \l{QWizard::}{ModernStyle}. - - Then we create the child widgets, create \l{Registering and Using - Fields}{wizard fields} associated with them, and put them into - layouts. The \c className field is created with an asterisk (\c - *) next to its name. This makes it a \l{mandatory fields}{mandatory field}, that - is, a field that must be filled before the user can press the - \uicontrol Next button (\uicontrol Continue on \macos). The fields' values - can be accessed from any other page using QWizardPage::field(), - or from the wizard code using QWizard::field(). - - \section1 The CodeStylePage Class - - The third page is defined and implemented as follows: - - \snippet dialogs/classwizard/classwizard.h 3 - \codeline - \snippet dialogs/classwizard/classwizard.cpp 14 - \dots - \snippet dialogs/classwizard/classwizard.cpp 15 - \codeline - \snippet dialogs/classwizard/classwizard.cpp 16 - - The code in the constructor is very similar to what we did for \c - ClassInfoPage, so we skipped most of it. - - The \c initializePage() function is what makes this class - interesting. It is reimplemented from QWizardPage and is used to - initialize some of the page's fields with values from the - previous page (namely, \c className and \c baseClass). For - example, if the class name on page 2 is \c SuperDuperWidget, the - default macro name on page 3 is \c SUPERDUPERWIDGET_H. - - The \c OutputFilesPage and \c ConclusionPage classes are very - similar to \c CodeStylePage, so we won't review them here. - - \sa QWizard, {License Wizard Example}, {Trivial Wizard Example} -*/ diff --git a/examples/widgets/doc/src/collidingmice-example.qdoc b/examples/widgets/doc/src/collidingmice-example.qdoc index 4f685940..54c893ee 100644 --- a/examples/widgets/doc/src/collidingmice-example.qdoc +++ b/examples/widgets/doc/src/collidingmice-example.qdoc @@ -4,6 +4,7 @@ /*! \example graphicsview/collidingmice \title Colliding Mice Example + \examplecategory {Graphics & Multimedia} \brief Demonstrates how to animate items on a graphics view. \ingroup examples-graphicsview diff --git a/examples/widgets/doc/src/coloreditorfactory.qdoc b/examples/widgets/doc/src/coloreditorfactory.qdoc index a7da4d68..bf4a13c9 100644 --- a/examples/widgets/doc/src/coloreditorfactory.qdoc +++ b/examples/widgets/doc/src/coloreditorfactory.qdoc @@ -4,6 +4,7 @@ /*! \example itemviews/coloreditorfactory \title Color Editor Factory Example + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief This example shows how to create an editor that can be used by a QItemDelegate. diff --git a/examples/widgets/doc/src/combowidgetmapper.qdoc b/examples/widgets/doc/src/combowidgetmapper.qdoc index 2f53bfd1..8a3e285d 100644 --- a/examples/widgets/doc/src/combowidgetmapper.qdoc +++ b/examples/widgets/doc/src/combowidgetmapper.qdoc @@ -4,20 +4,14 @@ /*! \example itemviews/combowidgetmapper \title Combo Widget Mapper Example + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief The Combo Widget Mapper example shows how to use a custom delegate to map information from a model to specific widgets on a form. \image combowidgetmapper-example.png - In the \l{Simple Widget Mapper Example}, we showed the basic use of a - widget mapper to relate data exposed by a model to simple input widgets - in a user interface. However, sometimes we want to use input widgets that - expose data as choices to the user, such as QComboBox, and we need a way - to relate their input to the values stored in the model. - - This example is very similar to the \l{Simple Widget Mapper Example}. - Again, we create a \c Window class with an almost identical user interface, + We create a \c Window class with an almost identical user interface, except that, instead of providing a spin box so that each person's age can be entered, we provide a combo box to allow their addresses to be classified as "Home", "Work" or "Other". @@ -65,8 +59,7 @@ interfering with the other input widgets. The implementation is shown later. \endomit - The rest of the constructor is very similar to that of the - \l{Simple Widget Mapper Example}: + The rest of the constructor sets up connections and layouts: \snippet itemviews/combowidgetmapper/window.cpp Set up connections and layouts diff --git a/examples/widgets/doc/src/completer.qdoc b/examples/widgets/doc/src/completer.qdoc index a64d7e1e..f3e4fe8f 100644 --- a/examples/widgets/doc/src/completer.qdoc +++ b/examples/widgets/doc/src/completer.qdoc @@ -4,6 +4,7 @@ /*! \example tools/completer \title Completer Example + \examplecategory {User Interface Components} \ingroup examples-widgets-tools \brief The Completer example shows how to provide string-completion facilities @@ -45,7 +46,7 @@ \snippet tools/completer/fsmodel.cpp 0 As mentioned earlier, the \c data() function is reimplemented in order to - get it to return the entire file parth for the display role. For example, + get it to return the entire file path for the display role. For example, with a QFileSystemModel, you will see "Program Files" in the view. However, with \c FileSystemModel, you will see "C:\\Program Files". @@ -201,7 +202,7 @@ \snippet tools/completer/mainwindow.cpp 14 - The \c changeMaxVisible() update the maximum number of visible items in + The \c changeMaxVisible() updates the maximum number of visible items in the completer. \snippet tools/completer/mainwindow.cpp 15 diff --git a/examples/widgets/doc/src/composition.qdoc b/examples/widgets/doc/src/composition.qdoc index 99fc0661..38cd34bc 100644 --- a/examples/widgets/doc/src/composition.qdoc +++ b/examples/widgets/doc/src/composition.qdoc @@ -4,6 +4,7 @@ /*! \example painting/composition \title Composition Modes + \examplecategory {Graphics & Multimedia} \ingroup examples-painting \brief Demonstrates how Composition Modes work in QPainter. @@ -18,5 +19,5 @@ drawn on top of the destination. In addition to these standard modes, Qt defines the complete set of composition modes - as defined by X. Porter and Y. Duff. See the QPainter documentation for details. + as defined by T. Porter and T. Duff. See the QPainter documentation for details. */ diff --git a/examples/widgets/doc/src/concentriccircles.qdoc b/examples/widgets/doc/src/concentriccircles.qdoc index ffdb0986..38842619 100644 --- a/examples/widgets/doc/src/concentriccircles.qdoc +++ b/examples/widgets/doc/src/concentriccircles.qdoc @@ -4,6 +4,7 @@ /*! \example painting/concentriccircles \title Concentric Circles Example + \examplecategory {Graphics & Multimedia} \ingroup examples-painting \brief Demonstrates the improved quality that antialiasing and floating point precision gives. @@ -13,7 +14,7 @@ how to do simple animations. The application's main window displays several widgets which are - drawn using the various combinations of precision and + drawn using various combinations of precision and anti-aliasing. \image concentriccircles-example.png diff --git a/examples/widgets/doc/src/customsortfiltermodel.qdoc b/examples/widgets/doc/src/customsortfiltermodel.qdoc index 5ee98362..b6ff8e7b 100644 --- a/examples/widgets/doc/src/customsortfiltermodel.qdoc +++ b/examples/widgets/doc/src/customsortfiltermodel.qdoc @@ -4,6 +4,7 @@ /*! \example itemviews/customsortfiltermodel \title Custom Sort/Filter Model Example + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief The Custom Sort/Filter Model example illustrates how to subclass QSortFilterProxyModel to perform advanced sorting and filtering. diff --git a/examples/widgets/doc/src/deform.qdoc b/examples/widgets/doc/src/deform.qdoc index 371f1a41..bda32f8c 100644 --- a/examples/widgets/doc/src/deform.qdoc +++ b/examples/widgets/doc/src/deform.qdoc @@ -4,6 +4,7 @@ /*! \example painting/deform \title Vector Deformation + \examplecategory {Graphics & Multimedia} \ingroup examples-painting \brief Demonstrates how to manipulate the elements of a QPainterPath. diff --git a/examples/widgets/doc/src/diagramscene.qdoc b/examples/widgets/doc/src/diagramscene.qdoc index 115f22ce..cd196136 100644 --- a/examples/widgets/doc/src/diagramscene.qdoc +++ b/examples/widgets/doc/src/diagramscene.qdoc @@ -4,6 +4,7 @@ /*! \example graphicsview/diagramscene \title Diagram Scene Example + \examplecategory {Graphics & Multimedia} \ingroup examples-graphicsview \brief Demonstrate how to use the Graphics View framework. @@ -12,7 +13,7 @@ The Diagram Scene example is an application in which you can create a flowchart diagram. It is possible to add flowchart shapes and text and connect the shapes by arrows as shown in the image - above. The shapes, arrows, and text can be given different + above. The shapes, arrows, and text can be given different colors, and it is possible to change the font, style, and underline of the text. @@ -121,9 +122,7 @@ We show an example of the creation of an action. The functionality the actions trigger is discussed in the slots we - connect the actions to. You can see the \l{Qt Widgets - Application - Example}{application example} if you need a high-level - introduction to actions. + connect the actions to. The is the \c createMenus() function: @@ -289,7 +288,7 @@ added to the scene. We set the mode of the scene back to the mode before the item was inserted, which is ItemMove or InsertText depending on which button is checked in the \c pointerTypeGroup. - We must also uncheck the button in the in the \c buttonGroup. + We must also uncheck the button in the \c buttonGroup. Here is the implementation of \c textInserted(): diff --git a/examples/widgets/doc/src/digitalclock.qdoc b/examples/widgets/doc/src/digitalclock.qdoc deleted file mode 100644 index d2427717..00000000 --- a/examples/widgets/doc/src/digitalclock.qdoc +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example widgets/digitalclock - \title Digital Clock Example - \ingroup examples-widgets - \brief The Digital Clock example shows how to use QLCDNumber to display a - number with LCD-like digits. - - \borderedimage digitalclock-example.png - \caption Screenshot of the Digital Clock example - - This example also demonstrates how QTimer can be used to update a widget - at regular intervals. - - \section1 DigitalClock Class Definition - - The \c DigitalClock class provides a clock widget showing the time with - hours and minutes separated by a blinking colon. We subclass QLCDNumber - and implement a private slot called \c showTime() to update the clock - display: - - \snippet widgets/digitalclock/digitalclock.h 0 - - \section1 DigitalClock Class Implementation - - \snippet widgets/digitalclock/digitalclock.cpp 0 - - In the constructor, we first change the look of the LCD numbers. The - QLCDNumber::Filled style produces raised segments filled with the - foreground color (typically black). We also set up a one-second timer - to keep track of the current time, and we connect - its \l{QTimer::timeout()}{timeout()} signal to the private \c showTime() slot - so that the display is updated every second. Then, we - call the \c showTime() slot; without this call, there would be a one-second - delay at startup before the time is shown. - - \snippet widgets/digitalclock/digitalclock.cpp 1 - \snippet widgets/digitalclock/digitalclock.cpp 2 - - The \c showTime() slot is called whenever the clock display needs - to be updated. - - The current time is converted into a string with the format "hh:mm". - When QTime::second() is a even number, the colon in the string is - replaced with a space. This makes the colon appear and vanish every - other second. - - Finally, we call QLCDNumber::display() to update the widget. -*/ diff --git a/examples/widgets/doc/src/dirview.qdoc b/examples/widgets/doc/src/dirview.qdoc deleted file mode 100644 index 5c63d99e..00000000 --- a/examples/widgets/doc/src/dirview.qdoc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example itemviews/dirview - \title Dir View Example - \ingroup examples-itemviews - \brief This example demonstrates the usage of a tree view, and smooth flicking on a touchscreen. - - The Dir View example shows a tree view of the local file - system. It uses the QFileSystemModel class to provide file - and directory information. - - \borderedimage dirview-example.png - - \quotefromfile itemviews/dirview/main.cpp - \skipto QCommandLineParser parser - \printuntil parser.positionalArguments - - The example supports a number of command line options. - These options include: - \list - \li Application description - \li -help option - \li -version option - \li if the optionc {-c} is specified, the application will not - use custom directory options - \endlist - - \skipto QFileSystemModel - \printuntil tree.setModel - - Declares \c model as data model for reading the local filesystem. - \c model.setRootPath("") sets the current folder as the folder from - which \c model will start reading. - QTreeView object \c tree visualizes the filesystem in a tree structure. - - \skipto tree.setAnimated(false) - \printuntil tree.setColumnWidth - - Sets layout options for animation, indentation, sorting, and sizing of the - filesystem tree. - - \skipto QScroller::grabGesture - \printuntil QScroller::grabGesture - - Creates a \l QScroller instance to recognize gestures on touchscreens, - so that you can flick the tree view with your finger. -*/ diff --git a/examples/widgets/doc/src/dockwidgets.qdoc b/examples/widgets/doc/src/dockwidgets.qdoc deleted file mode 100644 index 9907cea2..00000000 --- a/examples/widgets/doc/src/dockwidgets.qdoc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example mainwindows/dockwidgets - \title Dock Widgets Example - \ingroup examples-mainwindow - - \brief The Dock Widgets example shows how to add dock windows to an - application. It also shows how to use Qt's rich text engine. - - \image dockwidgets-example.png Screenshot of the Dock Widgets example - - The application presents a simple business letter template, and has - a list of customer names and addresses and a list of standard - phrases in two dock windows. The user can click a customer to have - their name and address inserted into the template, and click one or - more of the standard phrases. Errors can be corrected by clicking - the Undo button. Once the letter has been prepared it can be printed - or saved as HTML. - - \section1 MainWindow Class Definition - - Here's the class definition: - - \snippet mainwindows/dockwidgets/mainwindow.h 0 - - We will now review each function in turn. - - \section1 MainWindow Class Implementation - - \snippet mainwindows/dockwidgets/mainwindow.cpp 0 - - We start by including \c , a header file that contains the - definition of all classes in the Qt Core, Qt GUI and Qt Widgets - modules. This saves us from having to include - every class individually and is especially convenient if we add new - widgets. We also include \c mainwindow.h. - - \snippet mainwindows/dockwidgets/mainwindow.cpp 1 - - In the constructor, we start by creating a QTextEdit widget. Then we call - QMainWindow::setCentralWidget(). This function passes ownership of - the QTextEdit to the \c MainWindow and tells the \c MainWindow that - the QTextEdit will occupy the \c MainWindow's central area. - - Then we call \c createActions(), \c createMenus(), \c - createToolBars(), \c createStatusBar(), and \c createDockWindows() - to set up the user interface. Finally we call \c setWindowTitle() to - give the application a title, and \c newLetter() to create a new - letter template. - - We won't quote the \c createActions(), \c createMenus(), \c - createToolBars(), and \c createStatusBar() functions since they - follow the same pattern as all the other Qt examples. - - \snippet mainwindows/dockwidgets/mainwindow.cpp 9 - - We create the customers dock window first, and in addition to a - window title, we also pass it a \c this pointer so that it becomes a - child of \c MainWindow. Normally we don't have to pass a parent - because widgets are parented automatically when they are laid out: - but dock windows aren't laid out using layouts. - - We've chosen to restrict the customers dock window to the left and - right dock areas. (So the user cannot drag the dock window to the - top or bottom dock areas.) The user can drag the dock window out of - the dock areas entirely so that it becomes a free floating window. - We can change this (and whether the dock window is moveable or - closable) using QDockWidget::setFeatures(). - - Once we've created the dock window we create a list widget with the - dock window as parent, then we populate the list and make it the - dock window's widget. Finally we add the dock widget to the \c - MainWindow using \c addDockWidget(), choosing to put it in the right - dock area. - - We undertake a similar process for the paragraphs dock window, - except that we don't restrict which dock areas it can be dragged to. - - Finally we set up the signal-slot connections. If the user clicks a - customer or a paragraph their \c currentTextChanged() signal will be - emitted and we connect these to \c insertCustomer() and - addParagraph() passing the text that was clicked. - - We briefly discuss the rest of the implementation, but have now - covered everything relating to dock windows. - - \snippet mainwindows/dockwidgets/mainwindow.cpp 2 - - In this function we clear the QTextEdit so that it is empty. Next we - create a QTextCursor on the QTextEdit. We move the cursor to the - start of the document and create and format a frame. We then create - some character formats and a table format. We insert a table into - the document and insert the company's name and address into a table - using the table and character formats we created earlier. Then we - insert the skeleton of the letter including two markers \c NAME and - \c ADDRESS. We will also use the \c{Yours sincerely,} text as a marker. - - \snippet mainwindows/dockwidgets/mainwindow.cpp 6 - - If the user clicks a customer we split the customer details into - pieces. We then look for the \c NAME marker using the \c find() - function. This function selects the text it finds, so when we call - \c insertText() with the customer's name the name replaces the marker. - We then look for the \c ADDRESS marker and replace it with each line - of the customer's address. Notice that we wrapped all the insertions - between a \c beginEditBlock() and \c endEditBlock() pair. This means - that the entire name and address insertion is treated as a single - operation by the QTextEdit, so a single undo will revert all the - insertions. - - \snippet mainwindows/dockwidgets/mainwindow.cpp 7 - - This function works in a similar way to \c insertCustomer(). First - we look for the marker, in this case, \c {Yours sincerely,}, and then - replace it with the standard paragraph that the user clicked. Again - we use a \c beginEditBlock() ... \c endEditBlock() pair so that the - insertion can be undone as a single operation. - - \snippet mainwindows/dockwidgets/mainwindow.cpp 3 - - Qt's QTextDocument class makes printing documents easy. We simply - take the QTextEdit's QTextDocument, set up the printer and print the - document. - - \snippet mainwindows/dockwidgets/mainwindow.cpp 4 - - QTextEdit can output its contents in HTML format, so we prompt the - user for the name of an HTML file and if they provide one we simply - write the QTextEdit's contents in HTML format to the file. - - \snippet mainwindows/dockwidgets/mainwindow.cpp 5 - - If the focus is in the QTextEdit, pressing \uicontrol Ctrl+Z undoes as - expected. But for the user's convenience we provide an - application-wide undo function that simply calls the QTextEdit's - undo: this means that the user can undo regardless of where the - focus is in the application. -*/ diff --git a/examples/widgets/doc/src/draganddroppuzzle.qdoc b/examples/widgets/doc/src/draganddroppuzzle.qdoc deleted file mode 100644 index c2504b24..00000000 --- a/examples/widgets/doc/src/draganddroppuzzle.qdoc +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example draganddrop/puzzle - \title Drag and Drop Puzzle Example - - \brief The Drag and Drop Puzzle example demonstrates a way of using the drag and drop system with - item view widgets. - - \image draganddroppuzzle-example.png - - This example is an implementation of a simple jigsaw puzzle game using Qt's - drag and drop API. - The \l{Item Views Puzzle Example}{Item View Puzzle} example shows - many of the same features, but takes an alternative approach that uses Qt's - model/view framework to manage drag and drop operations. -*/ diff --git a/examples/widgets/doc/src/dragdroprobot.qdoc b/examples/widgets/doc/src/dragdroprobot.qdoc index ca62bf73..6b7f6952 100644 --- a/examples/widgets/doc/src/dragdroprobot.qdoc +++ b/examples/widgets/doc/src/dragdroprobot.qdoc @@ -4,6 +4,7 @@ /*! \example graphicsview/dragdroprobot \title Drag and Drop Robot Example + \examplecategory {Graphics & Multimedia} \ingroup examples-graphicsview \brief Demonstrates how to drag and drop items in a graphics view. diff --git a/examples/widgets/doc/src/draggableicons.qdoc b/examples/widgets/doc/src/draggableicons.qdoc index 9a0290c8..fd4f9e69 100644 --- a/examples/widgets/doc/src/draggableicons.qdoc +++ b/examples/widgets/doc/src/draggableicons.qdoc @@ -4,6 +4,7 @@ /*! \example draganddrop/draggableicons \title Draggable Icons Example + \examplecategory {User Interface Components} \brief The Draggable Icons example shows how to drag and drop image data between widgets in the same application, and between different applications. diff --git a/examples/widgets/doc/src/draggabletext.qdoc b/examples/widgets/doc/src/draggabletext.qdoc index 3cc3560b..6e15e7f9 100644 --- a/examples/widgets/doc/src/draggabletext.qdoc +++ b/examples/widgets/doc/src/draggabletext.qdoc @@ -4,6 +4,7 @@ /*! \example draganddrop/draggabletext \title Draggable Text Example + \examplecategory {User Interface Components} \brief Illustrates how to drag and drop text between widgets. \brief The Draggable Text example shows how to drag and drop textual data between widgets diff --git a/examples/widgets/doc/src/dynamiclayouts.qdoc b/examples/widgets/doc/src/dynamiclayouts.qdoc deleted file mode 100644 index 5dea8a7f..00000000 --- a/examples/widgets/doc/src/dynamiclayouts.qdoc +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example layouts/dynamiclayouts - \title Dynamic Layouts Example - \brief Shows how to re-orient widgets in running applications. - - \e{Dynamic Layouts} implements dynamically placed widgets within running - applications. The widget placement depends on whether \c Horizontal or \c - Vertical is chosen. - - \borderedimage dynamiclayouts-example.png - For more information, visit the \l{Layout Management} page. - - \section1 Dialog Constructor - - To begin with, the application creates the UI components by calling the - following methods: - - \list - \li createRotatableGroupBox() - \li createOptionsGroupBox() - \li createButtonBox() - \endlist - - It then adds the UI components to a GridLayout (\c mainLayout). - - Finally, \c Dialog::rotateWidgets() is called. - - \quotefromfile layouts/dynamiclayouts/dialog.cpp - \skipuntil createRotatableGroupBox - \printuntil setWindowTitle - - \section1 Creating the Main Widgets - - The \c createRotatableGroupBox() method creates a rotatable group box, - then adds a series of widgets: - - \list - \li QSpinBox - \li QSlider - \li QDial - \li QProgressBar - \endlist - - It goes on to add signals and slots to each widget, and assigns - a QGridLayout called \a rotatableLayout. - - \skipto Dialog::createRotatableGroupBox - \printuntil /^\}/ - - \section1 Adding Options - - \c createOptionsGroupBox() creates the following widgets: - \list - \li \c optionsGroupBox - \li \c buttonsOrientationLabel - \li \c buttonsOrientationComboBox. The orientation of the ComboBox is either - \c horizontal (default value) or \c vertical. These two values - are added during the startup of the application. It is not possible - to leave the option empty. - \endlist - - \skipto Dialog::createOptionsGroupBox() - \printuntil /^\}/ - - \section1 Adding Buttons - - createButtonBox() constructs a QDialogButtonBox called \c buttonBox - to which are added a \c closeButton, a \c helpButton and a - \c rotateWidgetsButton. - It then assigns a signal and a slot to each button in \c buttonBox. - - \skipto Dialog::createButtonBox() - \printuntil /^\}/ - - - \section1 Rotating the Widgets - - Removes the current widgets and activates the next widget. - - \quotefromfile layouts/dynamiclayouts/dialog.cpp - \skipto Dialog::rotateWidgets() - \printuntil rotatableLayout->addWidget(rotatableWidgets[i] - \printuntil } - \printuntil } - - \include examples-run.qdocinc -*/ - diff --git a/examples/widgets/doc/src/easing.qdoc b/examples/widgets/doc/src/easing.qdoc index c9f8752b..776d1613 100644 --- a/examples/widgets/doc/src/easing.qdoc +++ b/examples/widgets/doc/src/easing.qdoc @@ -4,6 +4,7 @@ /*! \example animation/easing \title Easing Curves Example + \examplecategory {Graphics & Multimedia} \brief The Easing Curves example shows how to use easing curves to control the speed of an animation. diff --git a/examples/widgets/doc/src/echoplugin.qdoc b/examples/widgets/doc/src/echoplugin.qdoc index 4cdd7005..1dfc19df 100644 --- a/examples/widgets/doc/src/echoplugin.qdoc +++ b/examples/widgets/doc/src/echoplugin.qdoc @@ -4,6 +4,7 @@ /*! \example tools/echoplugin \title Echo Plugin Example + \examplecategory {Data Processing & I/O} \ingroup examples-widgets-tools \ingroup examples-layout @@ -175,7 +176,5 @@ create plugins. We give an example of a plugin that extends Qt in the \l{Style - Plugin Example}{style plugin} example. The \l{Plug & Paint - Example}{plug and paint} example shows how to create static - plugins. + Plugin Example}{style plugin} example. */ diff --git a/examples/widgets/doc/src/editabletreemodel.qdoc b/examples/widgets/doc/src/editabletreemodel.qdoc index 96166107..efadfc68 100644 --- a/examples/widgets/doc/src/editabletreemodel.qdoc +++ b/examples/widgets/doc/src/editabletreemodel.qdoc @@ -4,9 +4,10 @@ /*! \example itemviews/editabletreemodel \title Editable Tree Model Example + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief This example shows how to implement a simple item-based tree model that can - be used with other classes the model/view framework. + be used with other classes in the model/view framework. \image itemviews-editabletreemodel.png diff --git a/examples/widgets/doc/src/elasticnodes.qdoc b/examples/widgets/doc/src/elasticnodes.qdoc index fbe50646..14ea63ef 100644 --- a/examples/widgets/doc/src/elasticnodes.qdoc +++ b/examples/widgets/doc/src/elasticnodes.qdoc @@ -4,6 +4,7 @@ /*! \example graphicsview/elasticnodes \title Elastic Nodes Example + \examplecategory {Graphics & Multimedia} \ingroup examples-graphicsview \brief Demonstrates how to interact with graphical items in a scene. diff --git a/examples/widgets/doc/src/embeddeddialogs.qdoc b/examples/widgets/doc/src/embeddeddialogs.qdoc deleted file mode 100644 index 09df334c..00000000 --- a/examples/widgets/doc/src/embeddeddialogs.qdoc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example graphicsview/embeddeddialogs - \title Embedded Dialogs - \ingroup examples-graphicsview-layout - \brief Demonstrates how to embed dialogs into a graphics view. - - This example shows how to embed standard dialogs into - Graphics View. It also shows how you can customize the - proxy class and add window shadows. - - \image embeddeddialogs-demo.png -*/ diff --git a/examples/widgets/doc/src/extension.qdoc b/examples/widgets/doc/src/extension.qdoc deleted file mode 100644 index 8f35e0e1..00000000 --- a/examples/widgets/doc/src/extension.qdoc +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example dialogs/extension - \title Extension Example - \ingroup examples-dialogs - - \brief The Extension example shows how to add an extension to a QDialog - using the QAbstractButton::toggled() signal and the - QWidget::setVisible() slot. - - \image extension-example.png Screenshot of the Extension example - - The Extension application lets the user add search parameters in - a dialog and launch a simple or advanced search. - - The simple search has two options: \uicontrol {Match case} and \uicontrol - {Search from start}. The advanced search offers search for \uicontrol {Whole words}, - \uicontrol {Search backward}, and \uicontrol {Search selection}. The - application starts with simple search as the default. Click the \uicontrol More button - to show the advanced search options: - - \image extension_more.png Screenshot of the Extension example - - \section1 FindDialog Class Definition - - The \c FindDialog class inherits QDialog. QDialog is the - base class for dialog windows. A dialog window is a top-level - window mostly used for short-term tasks and brief communications - with the user. - - \snippet dialogs/extension/finddialog.h 0 - - The \c FindDialog widget is the main application widget, and - displays the application's search options and controlling - buttons. - - In addition to the constructor, there are several child widgets: - - \list - \li A QLineEdit with an associated QLabel to let the - user type a word to search for. - \li Several \l {QCheckBox}{QCheckBox}es to facilitate the search options. - \li Three \l {QPushButton}{QPushButton}s: - \list - \li the \uicontrol Find button to start a search - \li the \uicontrol More button to enable an advanced search - \li a QWidget representing the application's extension part - \endlist - \endlist - - \section1 FindDialog Class Implementation - - Create the standard child widgets for the simple search in the constructor: - the QLineEdit with the associated QLabel, two {QCheckBox}es and all the - \l {QPushButton}{QPushButton}s. - - \snippet dialogs/extension/finddialog.cpp 0 - - This snippet illustrates how you can define a shortcut key - for a widget. A shortcut should be defined by putting the ampersand - character (\c &) in front of the letter that should - become the shortcut. - For example, for \uicontrol {Find what}, pressing \uicontrol Alt - and \uicontrol w transfers focus to the QLineEdit widget. - Shortcuts can also be used for checking on or off a checkmark. - For example, pressing \uicontrol Alt and \uicontrol c puts the check mark - on \uicontrol {Match Case} if it was unchecked and vice versa. - It is the QLabel::setBuddy() method that links a widget to the shortcut - character if it has been defined. - - Set the \uicontrol Find button's default property to true, using the - QPushButton::setDefault() function. Then the push button will be - pressed if the user presses the Enter (or Return) key. Note that a - QDialog can only have one default button. - - \snippet dialogs/extension/finddialog.cpp 2 - - Create the extension widget, and the \l {QCheckBox}{QCheckBox}es associated - with the advanced search options. - - \snippet dialogs/extension/finddialog.cpp 3 - - Now that the extension widget is created, connect the \uicontrol - More button's \l{QAbstractButton::toggled()}{toggled()} signal to - the extension widget's \l{QWidget::setVisible()}{setVisible()} slot. - - The QAbstractButton::toggled() signal is emitted whenever a - checkable button changes its state. The signal's argument is true - if the button is checked, or false if the button is unchecked. The - QWidget::setVisible() slot sets the widget's visible status. If - the status is true the widget is shown, otherwise the widget is - hidden. - - Since the \uicontrol More button is checkable, the connection makes - sure that the extension widget is shown depending on the state of - the \uicontrol More button. - - Create checkboxes associated with the advanced search options in - a layout installed on the extension widget. - - \snippet dialogs/extension/finddialog.cpp 4 - - Before creating the main layout, create several child layouts - for the widgets. First align the QLabel and its buddy, the - QLineEdit, using a QHBoxLayout. Then align the QLabel and the QLineEdit - vertically with the checkboxes associated with the simple search, - using a QVBoxLayout. Create also a QVBoxLayout for the buttons. - Finally, lay out the two latter layouts and the extension widget - using a QGridLayout. - - \snippet dialogs/extension/finddialog.cpp 5 - - Hide the extension widget using the QWidget::hide() - function, making the application only show the simple search - options when it starts. When the user wants to access the advanced - search options, the dialog only needs to change the visibility of - the extension widget. Qt's layout management takes care of the - dialog's appearance. -*/ diff --git a/examples/widgets/doc/src/fademessage.qdoc b/examples/widgets/doc/src/fademessage.qdoc deleted file mode 100644 index bd46593a..00000000 --- a/examples/widgets/doc/src/fademessage.qdoc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example effects/fademessage - \title Fade Message Effect Example - \ingroup examples-graphicsview-graphicseffects - \brief Demonstrates how to apply effects on items in the view. - - \div { style="text-align: left"} - \inlineimage fademessageeffect-example.png - \inlineimage fademessageeffect-example-faded.png - \enddiv - -*/ diff --git a/examples/widgets/doc/src/fetchmore.qdoc b/examples/widgets/doc/src/fetchmore.qdoc index 1e80e803..d8dae18f 100644 --- a/examples/widgets/doc/src/fetchmore.qdoc +++ b/examples/widgets/doc/src/fetchmore.qdoc @@ -4,6 +4,7 @@ /*! \example itemviews/fetchmore \title Fetch More Example + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief The Fetch More example shows how to add items to an item view model on demand. diff --git a/examples/widgets/doc/src/flowlayout.qdoc b/examples/widgets/doc/src/flowlayout.qdoc index 5a3316b6..03dfc164 100644 --- a/examples/widgets/doc/src/flowlayout.qdoc +++ b/examples/widgets/doc/src/flowlayout.qdoc @@ -4,6 +4,7 @@ /*! \example layouts/flowlayout \title Flow Layout Example + \examplecategory {User Interface Components} \ingroup examples-layout \brief Shows how to arrange widgets for different window sizes. diff --git a/examples/widgets/doc/src/fontsampler.qdoc b/examples/widgets/doc/src/fontsampler.qdoc deleted file mode 100644 index 3b014b57..00000000 --- a/examples/widgets/doc/src/fontsampler.qdoc +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example painting/fontsampler - \title Font Sampler Example - \ingroup examples-painting - \brief The Font Sampler example shows how to preview and print multi-page documents. - - The Font Sampler example shows how to preview and print multi-page documents. - - \image fontsampler-example.png -*/ diff --git a/examples/widgets/doc/src/fridgemagnets.qdoc b/examples/widgets/doc/src/fridgemagnets.qdoc deleted file mode 100644 index fccadd3b..00000000 --- a/examples/widgets/doc/src/fridgemagnets.qdoc +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example draganddrop/fridgemagnets - \title Fridge Magnets Example - \brief The Fridge Magnets example illustrates how to move around several types of - MIME-encoded data with drag and drop. - - The Fridge Magnets example shows how to supply more than one type - of MIME-encoded data with a drag and drop operation. - - \image fridgemagnets-example.png - - With this application the user can play around with a collection - of fridge magnets, using drag and drop to form new sentences from - the words on the magnets. The example consists of two classes: - - \list - \li \c DragLabel is a custom widget representing one - single fridge magnet. - \li \c DragWidget provides the main application window. - \endlist - - We will first take a look at the \c DragLabel class, then we will - examine the \c DragWidget class. - - \section1 DragLabel Class Definition - - Each fridge magnet is represented by an instance of the \c - DragLabel class: - - \snippet draganddrop/fridgemagnets/draglabel.h 0 - - Each instance of this QLabel subclass will be used to display an - pixmap generated from a text string. Since we cannot store both - text and a pixmap in a standard label, we declare a private variable - to hold the original text, and we define an additional member - function to allow it to be accessed. - - \section1 DragLabel Class Implementation - - In the \c DragLabel constructor, we first create a QImage object - on which we will draw the fridge magnet's text and frame: - - \snippet draganddrop/fridgemagnets/draglabel.cpp 0 - - Its size depends on the current font size, and its format is - QImage::Format_ARGB32_Premultiplied; i.e., the image is stored - using a premultiplied 32-bit ARGB format (0xAARRGGBB). - - We then construct a font object that uses the application's - default font, and set its style strategy. The style strategy tells - the font matching algorithm what type of fonts should be used to - find an appropriate default family. The QFont::ForceOutline forces - the use of outline fonts. - - To draw the text and frame onto the image, we use the QPainter - class. QPainter provides highly optimized methods to do most of - the drawing GUI programs require. It can draw everything from - simple lines to complex shapes like pies and chords. It can also - draw aligned text and pixmaps. - - \snippet draganddrop/fridgemagnets/draglabel.cpp 1 - - A painter can be activated by passing a paint device to the - constructor, or by using the \l{QPainter::}{begin()} method as we - do in this example. The \l{QPainter::}{end()} method deactivates - it. Note that the latter function is called automatically upon - destruction when the painter is activated by its constructor. The - QPainter::Antialiasing render hint ensures that the paint engine - will antialias the edges of primitives if possible. - - When the painting is done, we convert our image to a pixmap using - QPixmap's \l {QPixmap::}{fromImage()} method. This method also - takes an optional flags argument, and converts the given image to - a pixmap using the specified flags to control the conversion (the - flags argument is a bitwise-OR of the Qt::ImageConversionFlags; - passing 0 for flags sets all the default options). - - \snippet draganddrop/fridgemagnets/draglabel.cpp 2 - - Finally, we set the label's \l{QLabel::pixmap}{pixmap property} - and store the label's text for later use. - - \e{Note that setting the pixmap clears any previous content, including - any text previously set using QLabel::setText(), and disables - the label widget's buddy shortcut, if any.} - - \section1 DragWidget Class Definition - - The \c DragWidget class inherits QWidget, providing support for - drag and drop operations: - - \snippet draganddrop/fridgemagnets/dragwidget.h 0 - - To make the widget responsive to drag and drop operations, we simply - reimplement the \l{QWidget::}{dragEnterEvent()}, - \l{QWidget::}{dragMoveEvent()} and \l{QWidget::}{dropEvent()} event - handlers inherited from QWidget. - - We also reimplement \l{QWidget::}{mousePressEvent()} to make the - widget responsive to mouse clicks. This is where we will write code - to start drag and drop operations. - - \section1 DragWidget Class Implementation - - In the constructor, we first open the file containing the words on - our fridge magnets: - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 0 - - QFile is an I/O device for reading and writing text and binary - files and resources, and may be used by itself or in combination - with QTextStream or QDataStream. We have chosen to read the - contents of the file using the QTextStream class that provides a - convenient interface for reading and writing text. - - We then create the fridge magnets. As long as there is data (the - QTextStream::atEnd() method returns true if there is no more data - to be read from the stream), we read one line at a time using - QTextStream's \l {QTextStream::}{readLine()} method. - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 1 - - For each line, we create a \c DragLabel object using the read line - as text, we calculate its position and ensure that it is visible by - calling the QWidget::show() method. We set the Qt::WA_DeleteOnClose - attribute on each label to ensure that any unused labels will be - deleted; we will need to create new labels and delete old ones when - they are dragged around, and this ensures that the example does not - leak memory. - - We also set the \c FridgeMagnets widget's palette, minimum size - and window title. - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 2 - - Finally, to enable our user to move the fridge magnets around, we - must also set the \c FridgeMagnets widget's - \l{QWidget::acceptDrops}{acceptDrops} property. - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 3 - - Setting this property to true announces to the system that this - widget \e may be able to accept drop events (events that are sent - when drag and drop actions are completed). Later, we will - implement the functions that ensure that the widget accepts the - drop events it is interested in. - - \section2 Dragging - - Let's take a look at the \l{QWidget::}{mousePressEvent()} event - handler, where drag and drop operations begin: - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 13 - \snippet draganddrop/fridgemagnets/dragwidget.cpp 14 - - Mouse events occur when a mouse button is pressed or released - inside a widget, or when the mouse cursor is moved. By - reimplementing the \l{QWidget::}{mousePressEvent()} method we - ensure that we will receive mouse press events for the widget - containing the fridge magnets. - - Whenever we receive such an event, we first check to see if the - position of the click coincides with one of the labels. If not, - we simply return. - - If the user clicked a label, we determine the position of the - \e{hot spot} (the position of the click relative to the top-left - corner of the label). We create a byte array to store the label's - text and the hot spot, and we use a QDataStream object to stream - the data into the byte array. - - With all the information in place, we create a new QMimeData object. - As mentioned above, QMimeData objects associate the data that they - hold with the corresponding MIME types to ensure that information - can be safely transferred between applications. The - \l{QMimeData::}{setData()} method sets the data associated with a - given MIME type. In our case, we associate our item data with the - custom \c application/x-fridgemagnet type. - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 15 - - Note that we also associate the magnet's text with the - \c text/plain MIME type using QMimeData's \l{QMimeData::}{setText()} - method. Below, we will see how our widget detects both these MIME - types with its event handlers. - - Finally, we create a QDrag object. It is the QDrag class that - handles most of the details of a drag and drop operation, - providing support for MIME-based drag and drop data transfer. The - data to be transferred by the drag and drop operation is contained - in a QMimeData object. When we call QDrag's - \l{QDrag::}{setMimeData()} method the ownership of our item data is - transferred to the QDrag object. - - We call the \l{QDrag::}{setPixmap()} function to set the pixmap used - to represent the data during the drag and drop operation. - Typically, this pixmap shows an icon that represents the MIME type - of the data being transferred, but any pixmap can be used. In this - example, we simply use the pixmap used by the label itself to make - it look like the fridge magnet itself is being moved. - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 16 - - We also specify the cursor's hot spot, its position relative to the - top-level corner of the drag pixmap, to be the point we calculated - above. This makes the process of dragging the label feel more natural - because the cursor always points to the same place on the label - during the drag operation. - - We start the drag operation using QDrag's \l{QDrag::}{exec()} function, - requesting that the magnet is copied when the drag is completed. - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 17 - - The function returns the drop action actually performed by the user - (this can be either a copy or a move action in this case); if this - action is equal to Qt::MoveAction we will close the activated - fridge magnet widget because we will create a new one to replace it - (see the \l{drop}{dropEvent()} implementation). Otherwise, if - the drop is outside our main widget, we simply show the widget in - its original position. - - \section2 Dropping - - When a a drag and drop action enters our widget, we will receive a - drag enter \e event. QDragEnterEvent inherits most of its - functionality from QDragMoveEvent, which in turn inherits most of - its functionality from QDropEvent. Note that we must accept this - event in order to receive the drag move events that are sent while - the drag and drop action is in progress. The drag enter event is - always immediately followed by a drag move event. - - In our \c dragEnterEvent() implementation, we first determine - whether we support the event's MIME type or not: - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 4 - \snippet draganddrop/fridgemagnets/dragwidget.cpp 5 - \snippet draganddrop/fridgemagnets/dragwidget.cpp 6 - - If the type is \c application/x-fridgemagnet and the event - origins from any of this application's fridge magnet widgets, we - first set the event's drop action using the - QDropEvent::setDropAction() method. An event's drop action is the - action to be performed on the data by the target. Qt::MoveAction - indicates that the data is moved from the source to the target. - - Then we call the event's \l {QDragMoveEvent::}{accept()} method to - indicate that we have handled the event. In general, unaccepted - events might be propagated to the parent widget. If the event - origins from any other widget, we simply accept the proposed - action. - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 7 - - We also accept the proposed action if the event's MIME type is \c - text/plain, i.e., if QMimeData::hasText() returns true. If the - event has any other type, on the other hand, we call the event's - \l {QDragMoveEvent::}{ignore()} method allowing the event to be - propagated further. - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 8 - - Drag move events occur when the cursor enters a widget, when it - moves within the widget, and when a modifier key is pressed on the - keyboard while the widget has focus. Our widget will receive drag - move events repeatedly while a drag is within its boundaries. We - reimplement the \l {QWidget::}{dragMoveEvent()} method, and - examine the event in the exact same way as we did with drag enter - events. - - Note that the \l{QWidget::}{dropEvent()} event handler behaves - slightly differently: We first get hold of the event's MIME - data. - - \target drop - \snippet draganddrop/fridgemagnets/dragwidget.cpp 9 - - The QMimeData class provides a container for data that - records information about its MIME type. QMimeData objects - associate the data that they hold with the corresponding MIME - types to ensure that information can be safely transferred between - applications, and copied around within the same application. - - We retrieve the data associated with the \c application/x-fridgemagnet - MIME type using a data stream in order to create a new \c DragLabel - object. - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 10 - - The QDataStream class provides serialization of binary data to a - QIODevice (a data stream is a binary stream of encoded information - which is completely independent of the host computer's operating - system, CPU or byte order). - - Finally, we create a label and move it to the event's position: - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 11 - - If the source of the event is also the widget receiving the - drop event, we set the event's drop action to Qt::MoveAction and - call the event's \l{QDragMoveEvent::}{accept()} - method. Otherwise, we simply accept the proposed action. This - means that labels are moved rather than copied in the same - window. However, if we drag a label to a second instance of the - Fridge Magnets example, the default action is to copy it, leaving - the original in the first instance. - - If the event's MIME type is \c text/plain (i.e., if - QMimeData::hasText() returns true) we retrieve its text and split - it into words. For each word we create a new \c DragLabel action, - and show it at the event's position plus an offset depending on - the number of words in the text. In the end we accept the proposed - action. This lets the user drop selected text from a text editor or - Web browser onto the widget to add more fridge magnets. - - \snippet draganddrop/fridgemagnets/dragwidget.cpp 12 - - If the event has any other type, we call the event's - \l{QDragMoveEvent::}{ignore()} method allowing the event to be - propagated further. - - \section1 Summary - - We set our main widget's \l{QWidget::}{acceptDrops} property - and reimplemented QWidget's \l{QWidget::}{dragEnterEvent()}, - \l{QWidget::}{dragMoveEvent()} and \l{QWidget::}{dropEvent()} event - handlers to support content dropped on our widget. - - In addition, we reimplemented the \l{QWidget::}{mousePressEvent()} - function to let the user pick up fridge magnets in the first place. - - Because data is communicated using drag and drop operations and - encoded using MIME types, you can run more than one instance of this - example, and transfer magnets between them. -*/ diff --git a/examples/widgets/doc/src/frozencolumn.qdoc b/examples/widgets/doc/src/frozencolumn.qdoc index 54040bc9..c213ba17 100644 --- a/examples/widgets/doc/src/frozencolumn.qdoc +++ b/examples/widgets/doc/src/frozencolumn.qdoc @@ -4,6 +4,7 @@ /*! \example itemviews/frozencolumn \title Frozen Column Example + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief This example demonstrates how to freeze a column within a QTableView. diff --git a/examples/widgets/doc/src/gallery.qdoc b/examples/widgets/doc/src/gallery.qdoc index 5287fb5b..36b76d8f 100644 --- a/examples/widgets/doc/src/gallery.qdoc +++ b/examples/widgets/doc/src/gallery.qdoc @@ -5,6 +5,7 @@ \example gallery \meta {tag} {gallery} \title Widgets Gallery Example + \examplecategory {User Interface Components} \ingroup examples-widgets \brief The Widgets Gallery example shows widgets relevant for designing UIs. diff --git a/examples/widgets/doc/src/gradients.qdoc b/examples/widgets/doc/src/gradients.qdoc index 5a951ffb..5b84493c 100644 --- a/examples/widgets/doc/src/gradients.qdoc +++ b/examples/widgets/doc/src/gradients.qdoc @@ -4,6 +4,7 @@ /*! \example painting/gradients \title Gradients + \examplecategory {Graphics & Multimedia} \ingroup examples-painting \brief Shows how gradients can be used with QPainter. diff --git a/examples/widgets/doc/src/graphicsview-flowlayout.qdoc b/examples/widgets/doc/src/graphicsview-flowlayout.qdoc deleted file mode 100644 index 179f3501..00000000 --- a/examples/widgets/doc/src/graphicsview-flowlayout.qdoc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example graphicsview/flowlayout - \title Graphics View Flow Layout Example - \ingroup examples-graphicsview-layout - \brief Demonstrates flow layout on a graphics view scene. - - The Graphics View Flow Layout example shows the use of a flow layout - in a Graphics View widget. - - \image graphicsflowlayout-example.png - - This example uses a Graphics View to display the widget, which is a more - customizable approach than displaying the flow layout in the application - window (See \l {Flow Layout Example}). - - Graphics View Flow Layout snippet: - - \snippet graphicsview/flowlayout/main.cpp 1 - - Flow Layout Example snippet: - - \snippet layouts/flowlayout/main.cpp 1 - - -*/ diff --git a/examples/widgets/doc/src/graphicsview-simpleanchorlayout.qdoc b/examples/widgets/doc/src/graphicsview-simpleanchorlayout.qdoc index 49301013..a269aac5 100644 --- a/examples/widgets/doc/src/graphicsview-simpleanchorlayout.qdoc +++ b/examples/widgets/doc/src/graphicsview-simpleanchorlayout.qdoc @@ -4,6 +4,7 @@ /*! \example graphicsview/simpleanchorlayout \title Simple Anchor Layout Example + \examplecategory {Graphics & Multimedia} \ingroup examples-graphicsview-layout \brief Demonstrates anchor layout on a graphics view scene. diff --git a/examples/widgets/doc/src/groupbox.qdoc b/examples/widgets/doc/src/groupbox.qdoc index 5c565f1c..aa339098 100644 --- a/examples/widgets/doc/src/groupbox.qdoc +++ b/examples/widgets/doc/src/groupbox.qdoc @@ -4,6 +4,7 @@ /*! \example widgets/groupbox \title Group Box Example + \examplecategory {User Interface Components} \ingroup examples-widgets \brief The Group Box example shows how to use the different kinds of group boxes in Qt. diff --git a/examples/widgets/doc/src/icons.qdoc b/examples/widgets/doc/src/icons.qdoc deleted file mode 100644 index 8ec062ea..00000000 --- a/examples/widgets/doc/src/icons.qdoc +++ /dev/null @@ -1,805 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example widgets/icons - \title Icons Example - \ingroup examples-widgets - \brief The Icons example shows how QIcon can generate pixmaps reflecting - an icon's state, mode and size. - - These pixmaps are generated from the set of pixmaps made available to the - icon, and are used by Qt widgets to show an icon representing a particular - action. - - \image icons-example.png Screenshot of the Icons example - - Contents: - - \tableofcontents - - \section1 QIcon Overview - - The QIcon class provides scalable icons in different modes and - states. An icon's state and mode are depending on the intended use - of the icon. Qt currently defines four modes: - - \table - \header \li Mode \li Description - \row - \li QIcon::Normal - \li Display the pixmap when the user is not interacting with the - icon, but the functionality represented by the icon is - available. - \row - \li QIcon::Active - \li Display the pixmap when the functionality represented by the - icon is available and the user is interacting with the icon, - for example, moving the mouse over it or clicking it. - \row - \li QIcon::Disabled - \li Display the pixmap when the functionality represented by - the icon is not available. - \row - \li QIcon::Selected - \li Display the pixmap when the icon is selected. - \endtable - - QIcon's states are QIcon::On and QIcon::Off, which will display - the pixmap when the widget is in the respective state. The most - common usage of QIcon's states are when displaying checkable tool - buttons or menu entries (see QAbstractButton::setCheckable() and - QAction::setCheckable()). When a tool button or menu entry is - checked, the QIcon's state is \l{QIcon::}{On}, otherwise it's - \l{QIcon::}{Off}. You can, for example, use the QIcon's states to - display differing pixmaps depending on whether the tool button or - menu entry is checked or not. - - A QIcon can generate smaller, larger, active, disabled, and - selected pixmaps from the set of pixmaps it is given. Such - pixmaps are used by Qt widgets to show an icon representing a - particular action. - - \section1 Overview of the Icons Application - - With the Icons application you get a preview of an icon's - generated pixmaps reflecting its different states, modes and size. - - When an image is loaded into the application, it is converted into - a pixmap and becomes a part of the set of pixmaps available to the - icon. An image can be excluded from this set by checking off the - related checkbox. The application provides a sub directory - containing sets of images explicitly designed to illustrate how Qt - renders an icon in different modes and states. - - The application allows you to manipulate the icon size with some - predefined sizes and a spin box. The predefined sizes are style - dependent, but most of the styles have the same values. Only the - \macos style differs by using 32 pixels instead of 16 pixels - for toolbar buttons. You can navigate between the available styles - using the \uicontrol View menu. - - \image icons-view-menu.png Screenshot of the View menu - - The \uicontrol View menu also provide the option to make the application - guess the icon state and mode from an image's file name. The \uicontrol - File menu provide the options of adding an image and removing all - images. These last options are also available through a context - menu that appears if you press the right mouse button within the - table of image files. In addition, the \uicontrol File menu provide an - \uicontrol Exit option, and the \uicontrol Help menu provide information about - the example and about Qt. - - \image icons_find_normal.png Screenshot of the Find Files - - The screenshot above shows the application with one image file - loaded. The \uicontrol {Guess Image Mode/State} is enabled and the - style is Plastique. - - When QIcon is provided with only one available pixmap, that - pixmap is used for all the states and modes. In this case the - pixmap's icon mode is set to normal, and the generated pixmaps - for the normal and active modes will look the same. But in - disabled and selected mode, Qt will generate a slightly different - pixmap. - - The next screenshot shows the application with an additional file - loaded, providing QIcon with two available pixmaps. Note that the - new image file's mode is set to disabled. When rendering the \uicontrol - Disabled mode pixmaps, Qt will now use the new image. We can see - the difference: The generated disabled pixmap in the first - screenshot is slightly darker than the pixmap with the originally - set disabled mode in the second screenshot. - - \image icons_find_normal_disabled.png Screenshot of the Find Files - - When Qt renders the icon's pixmaps it searches through the set of - available pixmaps following a particular algorithm. The algorithm - is documented in QIcon, but we will describe some particular cases - below. - - \image icons_monkey_active.png Screenshot of the Find Files - - In the screenshot above, we have set \c monkey_on_32x32 to be an - Active/On pixmap and \c monkey_off_64x64 to be Normal/Off. To - render the other six mode/state combinations, QIcon uses the - search algorithm described in the table below: - - \table 100% - \header \li{2,1} Requested Pixmap \li {8,1} Preferred Alternatives (mode/state) - \header \li Mode \li State \li 1 \li 2 \li 3 \li 4 \li 5 \li 6 \li 7 \li 8 - \row \li{1,2} Normal \li Off \li \b N0 \li A0 \li N1 \li A1 \li D0 \li S0 \li D1 \li S1 - \row \li On \li N1 \li \b A1 \li N0 \li A0 \li D1 \li S1 \li D0 \li S0 - \row \li{1,2} Active \li Off \li A0 \li \b N0 \li A1 \li N1 \li D0 \li S0 \li D1 \li S1 - \row \li On \li \b A1 \li N1 \li A0 \li N0 \li D1 \li S1 \li D0 \li S0 - \row \li{1,2} Disabled \li Off \li D0 \li \b {N0'} \li A0' \li D1 \li N1' \li A1' \li S0' \li S1' - \row \li On \li D1 \li N1' \li \b {A1'} \li D0 \li N0' \li A0' \li S1' \li S0' - \row \li{1,2} Selected \li Off \li S0 \li \b {N0''} \li A0'' \li S1 \li N1'' \li A1'' \li D0'' \li D1'' - \row \li On \li S1 \li N1'' \li \b {A1''} \li S0 \li N0'' \li A0'' \li D1'' \li D0'' - \endtable - - In the table, "0" and "1" stand for "Off" and "On", respectively. - Single quotes indicates that QIcon generates a disabled ("grayed - out") version of the pixmap; similarly, double quuote indicate - that QIcon generates a selected ("blued out") version of the - pixmap. - - The alternatives used in the screenshot above are shown in bold. - For example, the Disabled/Off pixmap is derived by graying out - the Normal/Off pixmap (\c monkey_off_64x64). - - In the next screenshots, we loaded the whole set of monkey - images. By checking or unchecking file names from the image list, - we get different results: - - \table - \row - \li \inlineimage icons_monkey.png Screenshot of the Monkey Files - \li \inlineimage icons_monkey_mess.png Screenshot of the Monkey Files - \endtable - - For any given mode/state combination, it is possible to specify - several images at different resolutions. When rendering an - icon, QIcon will automatically pick the most suitable image - and scale it down if necessary. (QIcon never scales up images, - because this rarely looks good.) - - The screenshots below shows what happens when we provide QIcon - with three images (\c qt_extended_16x16.png, \c qt_extended_32x32.png, \c - qt_extended_48x48.png) and try to render the QIcon at various - resolutions: - - \table - \row - \li - \li \inlineimage icons_qt_extended_8x8.png Qt Extended icon at 8 x 8 - \li \inlineimage icons_qt_extended_16x16.png Qt Extended icon at 16 x 16 - \li \inlineimage icons_qt_extended_17x17.png Qt Extended icon at 17 x 17 - \row - \li - \li 8 x 8 - \li \b {16 x 16} - \li 17 x 17 - \row - \li \inlineimage icons_qt_extended_32x32.png Qt Extended icon at 32 x 32 - \li \inlineimage icons_qt_extended_33x33.png Qt Extended icon at 33 x 33 - \li \inlineimage icons_qt_extended_48x48.png Qt Extended icon at 48 x 48 - \li \inlineimage icons_qt_extended_64x64.png Qt Extended icon at 64 x 64 - \row - \li \b {32 x 32} - \li 33 x 33 - \li \b {48 x 48} - \li 64 x 64 - \endtable - - For sizes up to 16 x 16, QIcon uses \c qt_extended_16x16.png and - scales it down if necessary. For sizes between 17 x 17 and 32 x - 32, it uses \c qt_extended_32x32.png. For sizes above 32 x 32, it uses - \c qt_extended_48x48.png. - - \section1 Line-by-Line Walkthrough - - The Icons example consists of four classes: - - \list - \li \c MainWindow inherits QMainWindow and is the main application - window. - \li \c IconPreviewArea is a custom widget that displays all - combinations of states and modes for a given icon. - \li \c IconSizeSpinBox is a subclass of QSpinBox that lets the - user enter icon sizes (e.g., "48 x 48"). - \li \c ImageDelegate is a subclass of QStyledItemDelegate that - provides comboboxes for letting the user set the mode and state - associated with an image. - \endlist - - We will start by reviewing the \c IconPreviewArea class before we - take a look at the \c MainWindow class. Finally, we will review the - \c IconSizeSpinBox and \c ImageDelegate classes. - - \section2 IconPreviewArea Class Definition - - An \c IconPreviewArea widget consists of a group box containing a grid of - QLabel widgets displaying headers and pixmaps. - - \image icons_preview_area.png Screenshot of IconPreviewArea. - - \snippet widgets/icons/iconpreviewarea.h 0 - - The \c IconPreviewArea class inherits QWidget. It displays the - generated pixmaps corresponding to an icon's possible states and - modes at a given size. - - \snippet widgets/icons/iconpreviewarea.cpp 42 - - We would like the table columns to be in the order QIcon::Normal, - QIcon::Active, QIcon::Disabled, QIcon::Selected and the rows in the order - QIcon::Off, QIcon::On, which does not match the enumeration. The above code - provides arrays allowing to map from enumeration value to row/column - (by using QList::indexOf()) and back by using the array index and lists - of the matching strings. Qt's containers can be easily populated by - using C++ 11 initializer lists. - - We need two public functions to set the current icon and the - icon's size. In addition the class has three private functions: We - use the \c createHeaderLabel() and \c createPixmapLabel() - functions when constructing the preview area, and we need the \c - updatePixmapLabels() function to update the preview area when - the icon or the icon's size has changed. - - The \c NumModes and \c NumStates constants reflect \l{QIcon}'s - number of currently defined modes and states. - - \section2 IconPreviewArea Class Implementation - - \snippet widgets/icons/iconpreviewarea.cpp 0 - - In the constructor we create the labels displaying the headers and - the icon's generated pixmaps, and add them to a grid layout. - - When creating the header labels, we make sure the enums \c - NumModes and \c NumStates defined in the \c .h file, correspond - with the number of labels that we create. Then if the enums at - some point are changed, the \c Q_ASSERT() macro will alert that this - part of the \c .cpp file needs to be updated as well. - - If the application is built in debug mode, the \c Q_ASSERT() - macro will expand to - - \code - if (!condition) - qFatal("ASSERT: "condition" in file ..."); - \endcode - - In release mode, the macro simply disappear. The mode can be set - in the application's \c .pro file. One way to do so is to add an - option to \c qmake when building the application: - - \code - qmake "CONFIG += debug" icons.pro - \endcode - - or - - \code - qmake "CONFIG += release" icons.pro - \endcode - - Another approach is to add this line directly to the \c .pro - file. - - \snippet widgets/icons/iconpreviewarea.cpp 1 - \codeline - \snippet widgets/icons/iconpreviewarea.cpp 2 - - The public \c setIcon() and \c setSize() functions change the icon - or the icon size, and make sure that the generated pixmaps are - updated. - - \snippet widgets/icons/iconpreviewarea.cpp 3 - \codeline - \snippet widgets/icons/iconpreviewarea.cpp 4 - - We use the \c createHeaderLabel() and \c createPixmapLabel() - functions to create the preview area's labels displaying the - headers and the icon's generated pixmaps. Both functions return - the QLabel that is created. - - \snippet widgets/icons/iconpreviewarea.cpp 5 - - We use the private \c updatePixmapLabel() function to update the - generated pixmaps displayed in the preview area. - - For each mode, and for each state, we retrieve a pixmap using the - QIcon::pixmap() function, which generates a pixmap corresponding - to the given state, mode and size. We pass the QWindows instance - obtained by calling QWidget::windowHandle() on the top level - widget (QWidget::nativeParentWidget()) in order to retrieve - the pixmap that matches best. - We format a tooltip displaying size, actual size and device pixel - ratio. - - \section2 MainWindow Class Definition - - The \c MainWindow widget consists of three main elements: an - images group box, an icon size group box and a preview area. - - \image icons-example.png Screenshot of the Icons example - - \snippet widgets/icons/mainwindow.h 0 - - The MainWindow class inherits from QMainWindow. We reimplement the - constructor, and declare several private slots: - - \list - \li The \c about() slot simply provides information about the example. - \li The \c changeStyle() slot changes the application's GUI style and - adjust the style dependent size options. - \li The \c changeSize() slot changes the size of the preview area's icon. - \li The \c changeIcon() slot updates the set of pixmaps available to the - icon displayed in the preview area. - \li The \c addSampleImages() slot allows the user to load a new image - from the samples provided into the application. - \li The \c addOtherImages() slot allows the user to load a new image from - the directory obtained by calling - QStandardPaths::standardLocations(QStandardPaths::PicturesLocation). - \li The \c screenChanged() updates the display in the \uicontrol{High DPI} - group box to correctly display the parameters of the current screen - the window is located on. - \endlist - - In addition we declare several private functions to simplify the - constructor. - - \section2 MainWindow Class Implementation - - \snippet widgets/icons/mainwindow.cpp 0 - - In the constructor we first create the main window's central - widget and its child widgets, and put them in a grid layout. Then - we create the menus with their associated entries and actions. - - We set the window title and determine the current style for the - application. We also enable the icon size spin box by clicking the - associated radio button, making the current value of the spin box - the icon's initial size. - - \snippet widgets/icons/mainwindow.cpp 1 - - The \c about() slot displays a message box using the static - QMessageBox::about() function. In this example it displays a - simple box with information about the example. - - The \c about() function looks for a suitable icon in four - locations: It prefers its parent's icon if that exists. If it - doesn't, the function tries the top-level widget containing - parent, and if that fails, it tries the active window. As a last - resort it uses the QMessageBox's Information icon. - - \snippet widgets/icons/mainwindow.cpp 2 - - In the \c changeStyle() slot we first check the slot's - parameter. If it is false we immediately return, otherwise we find - out which style to change to, i.e. which action that triggered the - slot, using the QObject::sender() function. - - This function returns the sender as a QObject pointer. Since we - know that the sender is a QAction object, we can safely cast the - QObject. We could have used a C-style cast or a C++ \c - static_cast(), but as a defensive programming technique we use a - \l qobject_cast(). The advantage is that if the object has the - wrong type, a null pointer is returned. Crashes due to null - pointers are much easier to diagnose than crashes due to unsafe - casts. - - \snippet widgets/icons/mainwindow.cpp 3 - \snippet widgets/icons/mainwindow.cpp 4 - - Once we have the action, we extract the style name using - QAction::data(). Then we create a QStyle object using the static - QStyleFactory::create() function. - - Although we can assume that the style is supported by the - QStyleFactory: To be on the safe side, we use the \c Q_ASSERT() - macro to check if the created style is valid before we use the - QApplication::setStyle() function to set the application's GUI - style to the new style. QApplication will automatically delete - the style object when a new style is set or when the application - exits. - - The predefined icon size options provided in the application are - style dependent, so we need to update the labels in the icon size - group box and in the end call the \c changeSize() slot to update - the icon's size. - - \snippet widgets/icons/mainwindow.cpp 5 - - The \c changeSize() slot sets the size for the preview area's - icon. - - It is invoked by the QButtonGroup whose members are radio buttons for - controlling the icon size. In \c createIconSizeGroupBox(), each button is - assigned a QStyle::PixelMetric value as an id, which is passed as a - parameter to the slot. - - The special value \c OtherSize indicates that the spin box is - enabled. If it is, we extract the extent of the new size from the - box. If it's not, we query the style for the metric. Then we create - a QSize object based on the extent, and use that object to set the - size of the preview area's icon. - - \snippet widgets/icons/mainwindow.cpp 12 - - The function \c addImages() is called by the slot addSampleImages() - passing the samples directory, or by the slot addOtherImages() - passing the directory obtained by querying - QStandardPaths::standardLocations(). - - The first thing we do is to show a file dialog to the user. - We initialize it to show the filters returned by - QImageReader::supportedMimeTypes(). - - For each of the files the file dialog returns, we add a row to the - table widget. The table widget is listing the images the user has - loaded into the application. - - \snippet widgets/icons/mainwindow.cpp 13 - - We retrieve the image name using the QFileInfo::baseName() - function that returns the base name of the file without the path, - and create the first table widget item in the row. - We check if a high resolution version of the image exists (identified by - the suffix \c @2x on the base name) and display that along with the size - in the tooltip. - - We add the file's complete name to the item's data. Since an item can - hold several information pieces, we need to assign the file name a role - that will distinguish it from other data. This role can be Qt::UserRole - or any value above it. - - We also make sure that the item is not editable by removing the - Qt::ItemIsEditable flag. Table items are editable by default. - - \snippet widgets/icons/mainwindow.cpp 15 - - Then we create the second and third items in the row making the - default mode Normal and the default state Off. But if the \uicontrol - {Guess Image Mode/State} option is checked, and the file name - contains "_act", "_dis", or "_sel", the modes are changed to - Active, Disabled, or Selected. And if the file name contains - "_on", the state is changed to On. The sample files in the - example's \c images subdirectory respect this naming convention. - - \snippet widgets/icons/mainwindow.cpp 18 - - In the end we add the items to the associated row, and use the - QTableWidget::openPersistentEditor() function to create - comboboxes for the mode and state columns of the items. - - Due to the connection between the table widget's \l - {QTableWidget::itemChanged()}{itemChanged()} signal and the \c - changeIcon() slot, the new image is automatically converted into a - pixmap and made part of the set of pixmaps available to the icon - in the preview area. So, corresponding to this fact, we need to - make sure that the new image's check box is enabled. - - \snippet widgets/icons/mainwindow.cpp 6 - - The \c changeIcon() slot is called when the user alters the set - of images listed in the QTableWidget, to update the QIcon object - rendered by the \c IconPreviewArea. - - We first create a QIcon object, and then we run through the - QTableWidget, which lists the images the user has loaded into the - application. - - \snippet widgets/icons/mainwindow.cpp 8 - - We also extract the image file's name using the - QTableWidgetItem::data() function. This function takes a - Qt::DataItemRole as an argument to retrieve the right data - (remember that an item can hold several pieces of information) - and returns it as a QVariant. Then we use the - QVariant::toString() function to get the file name as a QString. - - To create a pixmap from the file, we need to first create an - image and then convert this image into a pixmap using - QPixmap::fromImage(). Once we have the final pixmap, we add it, - with its associated mode and state, to the QIcon's set of - available pixmaps. - - \snippet widgets/icons/mainwindow.cpp 11 - - After running through the entire list of images, we change the - icon of the preview area to the one we just created. - - \snippet widgets/icons/mainwindow.cpp 20 - - In the \c removeAllImages() slot, we simply set the table widget's - row count to zero, automatically removing all the images the user - has loaded into the application. Then we update the set of pixmaps - available to the preview area's icon using the \c changeIcon() - slot. - - \image icons_images_groupbox.png Screenshot of the images group box - - The \c createImagesGroupBox() function is implemented to simplify - the constructor. The main purpose of the function is to create a - QTableWidget that will keep track of the images the user has - loaded into the application. - - \snippet widgets/icons/mainwindow.cpp 21 - - First we create a group box that will contain the table widget. - Then we create a QTableWidget and customize it to suit our - purposes. - - We call QAbstractItemView::setSelectionMode() to prevent the user - from selecting items. - - The QAbstractItemView::setItemDelegate() call sets the item - delegate for the table widget. We create a \c ImageDelegate that - we make the item delegate for our view. - - The QStyledItemDelegate class can be used to provide an editor for an item view - class that is subclassed from QAbstractItemView. Using a delegate - for this purpose allows the editing mechanism to be customized and - developed independently from the model and view. - - In this example we derive \c ImageDelegate from QStyledItemDelegate. - QStyledItemDelegate usually provides line editors, while our subclass - \c ImageDelegate, provides comboboxes for the mode and state - fields. - - \snippet widgets/icons/mainwindow.cpp 22 - - Then we customize the QTableWidget's horizontal header, and hide - the vertical header. - - \snippet widgets/icons/mainwindow.cpp 24 - - At the end, we connect the QTableWidget::itemChanged() signal to - the \c changeIcon() slot to ensure that the preview area is in - sync with the image table. - - \image icons_size_groupbox.png Screenshot of the icon size group box - - The \c createIconSizeGroupBox() function is called from the - constructor. It creates the widgets controlling the size of the - preview area's icon. - - \snippet widgets/icons/mainwindow.cpp 26 - - First we create a group box that will contain all the widgets; - then we create the radio buttons and the spin box. We add the - radio buttons to an instance of QButtonGroup, using the value - of the QStyle::PixelMetric they represent as an integer id. - - \snippet widgets/icons/mainwindow.cpp 40 - - We introduce an enumeration constant \c OtherSize to represent - a custom size. - - The spin box is not a regular QSpinBox but an \c IconSizeSpinBox. - The \c IconSizeSpinBox class inherits QSpinBox and reimplements - two functions: QSpinBox::textFromValue() and - QSpinBox::valueFromText(). The \c IconSizeSpinBox is designed to - handle icon sizes, e.g., "32 x 32", instead of plain integer - values. - - \snippet widgets/icons/mainwindow.cpp 27 - - Then we connect all of the radio buttons - \l{QRadioButton::toggled()}{toggled()} signals and the spin box's - \l {QSpinBox::valueChanged()}{valueChanged()} signal to the \c - changeSize() slot to make sure that the size of the preview - area's icon is updated whenever the user changes the icon size. - In the end we put the widgets in a layout that we install on the - group box. - - \snippet widgets/icons/mainwindow.cpp 28 - - In the \c createActions() function we create and customize all the - actions needed to implement the functionality associated with the - menu entries in the application. - - In particular we create the \c styleActionGroup based on the - currently available GUI styles using - QStyleFactory. QStyleFactory::keys() returns a list of valid keys, - typically including "windows" and "fusion". Depending on the platform, - "windowsvista" and "macos" may be available. - - We create one action for each key, and adds the action to the - action group. Also, for each action, we call QAction::setData() - with the style name. We will retrieve it later using - QAction::data(). - - As we go along, we create the \uicontrol File, \uicontrol View and - \uicontrol Help menus and add the actions to them. - - The QMenu class provides a menu widget for use in menu bars, - context menus, and other popup menus. We put each menu in the - application's menu bar, which we retrieve using - QMainWindow::menuBar(). - - \snippet widgets/icons/mainwindow.cpp 30 - - QWidgets have a \l{QWidget::contextMenuPolicy}{contextMenuPolicy} - property that controls how the widget should behave when the user - requests a context menu (e.g., by right-clicking). We set the - QTableWidget's context menu policy to Qt::ActionsContextMenu, - meaning that the \l{QAction}s associated with the widget should - appear in its context menu. - - Then we add the \uicontrol{Add Image} and \uicontrol{Remove All Images} - actions to the table widget. They will then appear in the table - widget's context menu. - - \snippet widgets/icons/mainwindow.cpp 31 - - In the \c checkCurrentStyle() function we go through the group of - style actions, looking for the current GUI style. - - For each action, we first extract the style name using - QAction::data(). Since this is only a QStyleFactory key (e.g., - "macos"), we cannot compare it directly to the current - style's class name. We need to create a QStyle object using the - static QStyleFactory::create() function and compare the class - name of the created QStyle object with that of the current style. - As soon as we are done with a QStyle candidate, we delete it. - - For all QObject subclasses that use the \c Q_OBJECT macro, the - class name of an object is available through its - \l{QObject::metaObject()}{meta-object}. - - We can assume that the style is supported by - QStyleFactory, but to be on the safe side we use the \c - Q_ASSERT() macro to make sure that QStyleFactory::create() - returned a valid pointer. - - \snippet widgets/icons/mainwindow.cpp 44 - - We overload the show() function to set up the updating of the - current screen in \c screenChanged(). After calling QWidget::show(), - the QWindow associated with the QWidget is created and we can - connect to its QWindow::screenChanged() signal. - - \section2 IconSizeSpinBox Class Definition - - \snippet widgets/icons/iconsizespinbox.h 0 - - The \c IconSizeSpinBox class is a subclass of QSpinBox. A plain - QSpinBox can only handle integers. But since we want to display - the spin box's values in a more sophisticated way, we need to - subclass QSpinBox and reimplement the QSpinBox::textFromValue() - and QSpinBox::valueFromText() functions. - - \image icons_size_spinbox.png Screenshot of the icon size spinbox - - \section2 IconSizeSpinBox Class Implementation - - \snippet widgets/icons/iconsizespinbox.cpp 0 - - The constructor is trivial. - - \snippet widgets/icons/iconsizespinbox.cpp 2 - - QSpinBox::textFromValue() is used by the spin box whenever it - needs to display a value. The default implementation returns a - base 10 representation of the \c value parameter. - - Our reimplementation returns a QString of the form "32 x 32". - - \snippet widgets/icons/iconsizespinbox.cpp 1 - - The QSpinBox::valueFromText() function is used by the spin box - whenever it needs to interpret text typed in by the user. Since - we reimplement the \c textFromValue() function we also need to - reimplement the \c valueFromText() function to interpret the - parameter text and return the associated int value. - - We parse the text using a regular expression (a QRegularExpression). We - define an expression that matches one or several digits, - optionally followed by whitespace, an "x" or the times symbol, - whitespace and one or several digits again. - - The first digits of the regular expression are captured using - parentheses. This enables us to use the QRegularExpressionMatch::captured() - or QRegularExpressionMatch::capturedTexts() functions to extract the matched - characters. If the first and second numbers of the spin box value - differ (e.g., "16 x 24"), we use the first number. - - When the user presses \uicontrol Enter, QSpinBox first calls - QSpinBox::valueFromText() to interpret the text typed by the - user, then QSpinBox::textFromValue() to present it in a canonical - format (e.g., "16 x 16"). - - \section2 ImageDelegate Class Definition - - \snippet widgets/icons/imagedelegate.h 0 - - The \c ImageDelegate class is a subclass of QStyledItemDelegate. The - QStyledItemDelegate class provides display and editing facilities for - data items from a model. A single QStyledItemDelegate object is - responsible for all items displayed in a item view (in our case, - a QTableWidget). - - A QStyledItemDelegate can be used to provide an editor for an item view - class that is subclassed from QAbstractItemView. Using a delegate - for this purpose allows the editing mechanism to be customized and - developed independently from the model and view. - - \snippet widgets/icons/imagedelegate.h 1 - - The default implementation of QStyledItemDelegate creates a QLineEdit. - Since we want the editor to be a QComboBox, we need to subclass - QStyledItemDelegate and reimplement the QStyledItemDelegate::createEditor(), - QStyledItemDelegate::setEditorData() and QStyledItemDelegate::setModelData() - functions. - - \snippet widgets/icons/imagedelegate.h 2 - - The \c emitCommitData() slot is used to emit the - QImageDelegate::commitData() signal with the appropriate - argument. - - \section2 ImageDelegate Class Implementation - - \snippet widgets/icons/imagedelegate.cpp 0 - - The constructor is trivial. - - \snippet widgets/icons/imagedelegate.cpp 1 - - The default QStyledItemDelegate::createEditor() implementation returns - the widget used to edit the item specified by the model and item - index for editing. The parent widget and style option are used to - control the appearance of the editor widget. - - Our reimplementation creates and populates a combobox instead of - the default line edit. The contents of the combobox depends on - the column in the table for which the editor is requested. Column - 1 contains the QIcon modes, whereas column 2 contains the QIcon - states. - - In addition, we connect the combobox's \l - {QComboBox::activated()}{activated()} signal to the \c - emitCommitData() slot to emit the - QAbstractItemDelegate::commitData() signal whenever the user - chooses an item using the combobox. This ensures that the rest of - the application notices the change and updates itself. - - \snippet widgets/icons/imagedelegate.cpp 2 - - The QStyledItemDelegate::setEditorData() function is used by - QTableWidget to transfer data from a QTableWidgetItem to the - editor. The data is stored as a string; we use - QComboBox::findText() to locate it in the combobox. - - Delegates work in terms of models, not items. This makes it - possible to use them with any item view class (e.g., QListView, - QListWidget, QTreeView, etc.). The transition between model and - items is done implicitly by QTableWidget; we don't need to worry - about it. - - \snippet widgets/icons/imagedelegate.cpp 3 - - The QStyledItemDelegate::setEditorData() function is used by QTableWidget - to transfer data back from the editor to the \l{QTableWidgetItem}. - - \snippet widgets/icons/imagedelegate.cpp 4 - - The \c emitCommitData() slot simply emit the - QAbstractItemDelegate::commitData() signal for the editor that - triggered the slot. This signal must be emitted when the editor - widget has completed editing the data, and wants to write it back - into the model. - - \section2 The Implementation of the Function main() - - \snippet widgets/icons/main.cpp 45 - - We use QCommandLineParser to handle any command line options or parameters - passed to the application. Then, we resize the main window according - to the available screen geometry and show it. -*/ diff --git a/examples/widgets/doc/src/imagecomposition.qdoc b/examples/widgets/doc/src/imagecomposition.qdoc index 3b192f37..42ddab22 100644 --- a/examples/widgets/doc/src/imagecomposition.qdoc +++ b/examples/widgets/doc/src/imagecomposition.qdoc @@ -4,6 +4,7 @@ /*! \example painting/imagecomposition \title Image Composition Example + \examplecategory {Graphics & Multimedia} \ingroup examples-painting \ingroup examples-layout \brief Shows how composition modes work in QPainter. diff --git a/examples/widgets/doc/src/imageviewer.qdoc b/examples/widgets/doc/src/imageviewer.qdoc deleted file mode 100644 index aa6eec46..00000000 --- a/examples/widgets/doc/src/imageviewer.qdoc +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example widgets/imageviewer - \title Image Viewer Example - \ingroup examples-widgets - \brief The example shows how to combine QLabel and QScrollArea to - display an image. - - QLabel is typically used for displaying text, - but it can also display an image. QScrollArea provides a - scrolling view around another widget. If the child widget exceeds - the size of the frame, QScrollArea automatically provides scroll - bars. - - The example demonstrates how QLabel's ability to scale its - contents (QLabel::scaledContents), and QScrollArea's ability to - automatically resize its contents (QScrollArea::widgetResizable), - can be used to implement zooming and scaling features. In - addition the example shows how to use QPainter to print an image. - - \borderedimage imageviewer-example.png - \caption Screenshot of the Image Viewer example - - With the Image Viewer application, the users can view an image of - their choice. The \uicontrol File menu gives the user the possibility - to: - - \list - \li \uicontrol{Open...} - Open an image file - \li \uicontrol{Print...} - Print an image - \li \uicontrol{Exit} - Exit the application - \endlist - - Once an image is loaded, the \uicontrol View menu allows the users to: - - \list - \li \uicontrol{Zoom In} - Scale the image up by 25% - \li \uicontrol{Zoom Out} - Scale the image down by 25% - \li \uicontrol{Normal Size} - Show the image at its original size - \li \uicontrol{Fit to Window} - Stretch the image to occupy the entire window - \endlist - - In addition the \uicontrol Help menu provides the users with information - about the Image Viewer example in particular, and about Qt in - general. - - \section1 ImageViewer Class Definition - - \snippet widgets/imageviewer/imageviewer.h 0 - - The \c ImageViewer class inherits from QMainWindow. We reimplement - the constructor, and create several private slots to facilitate - the menu entries. In addition we create four private functions. - - We use \c createActions() and \c createMenus() when constructing - the \c ImageViewer widget. We use the \c updateActions() function - to update the menu entries when a new image is loaded, or when - the \uicontrol {Fit to Window} option is toggled. The zoom slots use \c - scaleImage() to perform the zooming. In turn, \c - scaleImage() uses \c adjustScrollBar() to preserve the focal point after - scaling an image. - - \section1 ImageViewer Class Implementation - - \snippet widgets/imageviewer/imageviewer.cpp 0 - - In the constructor we first create the label and the scroll area. - - We set \c {imageLabel}'s size policy to \l - {QSizePolicy::Ignored}{ignored}, making the users able to scale - the image to whatever size they want when the \uicontrol {Fit to Window} - option is turned on. Otherwise, the default size polizy (\l - {QSizePolicy::Preferred}{preferred}) will make scroll bars appear - when the scroll area becomes smaller than the label's minimum size - hint. - - We ensure that the label will scale its contents to fill all - available space, to enable the image to scale properly when - zooming. If we omitted to set the \c {imageLabel}'s \l - {QLabel::scaledContents}{scaledContents} property, zooming in - would enlarge the QLabel, but leave the pixmap at - its original size, exposing the QLabel's background. - - We make \c imageLabel the scroll area's child widget, and we make - \c scrollArea the central widget of the QMainWindow. At the end - we create the associated actions and menus, and customize the \c - {ImageViewer}'s appearance. - - \snippet widgets/imageviewer/imageviewer.cpp 1 - - In the \c open() slot, we show a file dialog to the user. We compile - a list of mime types for use as a filter by querying QImageReader - for the available mime type names. - - We show the file dialog until a valid file name is entered or - the user cancels. - - The function \c loadFile() is used to load the image. - - \snippet widgets/imageviewer/imageviewer.cpp 2 - - In the \c loadFile() function, we instantiate a QImageReader - and enable automatic transformations by calling - QImageReader::setAutoTransform(). For files in JPEG format, - this ensures that portrait mode images of digital cameras are shown - correctly by applying the appropriate orientation read from the - EXIF meta data stored in the image file. - - We then load the image using QImageReader::read(). If this returns - a null image, indicating that the file is not an image file, - we use a QMessageBox to alert the user. - - The QMessageBox class provides a modal dialog with a short - message, an icon, and some buttons. As with QFileDialog the - easiest way to create a QMessageBox is to use its static - convenience functions. QMessageBox provides a range of different - messages arranged along two axes: severity (question, - information, warning and critical) and complexity (the number of - necessary response buttons). In this particular example an - information message with an \uicontrol OK button (the default) is - sufficient, since the message is part of a normal operation. - - \snippet widgets/imageviewer/imageviewer.cpp 4 - - If the format is supported, we display the image in \c imageLabel - by setting the label's \l {QLabel::pixmap}{pixmap}. Then we enable - the \uicontrol Print and \uicontrol {Fit to Window} menu entries and update - the rest of the view menu entries. The \uicontrol Open and \uicontrol Exit - entries are enabled by default. - - If the \uicontrol {Fit to Window} option is turned off, the - QScrollArea::widgetResizable property is \c false and it is - our responsibility (not QScrollArea's) to give the QLabel a - reasonable size based on its contents. We call - \{QWidget::adjustSize()}{adjustSize()} to achieve this, which is - essentially the same as - - \code - imageLabel->resize(imageLabel->pixmap()->size()); - \endcode - - In the \c print() slot, we first make sure that an image has been - loaded into the application: - - \snippet widgets/imageviewer/imageviewer.cpp 5 - \snippet widgets/imageviewer/imageviewer.cpp 6 - - If the application is built in debug mode, the \c Q_ASSERT() macro - will expand to - - \code - if (imageLabel->pixmap().isNull()) - qFatal("ASSERT: "imageLabel->pixmap().isNull()" in file ..."); - \endcode - - In release mode, the macro simply disappear. The mode can be set - in the application's \c .pro file. One way to do so is to add an - option to \uicontrol qmake when building the application: - - \code - qmake "CONFIG += debug" foo.pro - \endcode - - or - - \code - qmake "CONFIG += release" foo.pro - \endcode - - Another approach is to add this line directly to the \c .pro - file. - - \snippet widgets/imageviewer/imageviewer.cpp 7 - \snippet widgets/imageviewer/imageviewer.cpp 8 - - Then we present a print dialog allowing the user to choose a - printer and to set a few options. We construct a painter with a - QPrinter as the paint device. We set the painter's window - and viewport in such a way that the image is as large as possible - on the paper, but without altering its - \l{Qt::KeepAspectRatio}{aspect ratio}. - - In the end we draw the pixmap at position (0, 0). - - \snippet widgets/imageviewer/imageviewer.cpp 9 - \snippet widgets/imageviewer/imageviewer.cpp 10 - - We implement the zooming slots using the private \c scaleImage() - function. We set the scaling factors to 1.25 and 0.8, - respectively. These factor values ensure that a \uicontrol {Zoom In} - action and a \uicontrol {Zoom Out} action will cancel each other (since - 1.25 * 0.8 == 1), and in that way the normal image size can be - restored using the zooming features. - - The screenshots below show an image in its normal size, and the - same image after zooming in: - - \table - \row - \li \inlineimage imageviewer-original_size.png - \li \inlineimage imageviewer-zoom_in_1.png - \li \inlineimage imageviewer-zoom_in_2.png - \endtable - - \snippet widgets/imageviewer/imageviewer.cpp 11 - \snippet widgets/imageviewer/imageviewer.cpp 12 - - When zooming, we use the QLabel's ability to scale its contents. - Such scaling doesn't change the actual size hint of the contents. - And since the \l {QLabel::adjustSize()}{adjustSize()} function - use those size hint, the only thing we need to do to restore the - normal size of the currently displayed image is to call \c - adjustSize() and reset the scale factor to 1.0. - - \snippet widgets/imageviewer/imageviewer.cpp 13 - \snippet widgets/imageviewer/imageviewer.cpp 14 - - The \c fitToWindow() slot is called each time the user toggled - the \uicontrol {Fit to Window} option. If the slot is called to turn on - the option, we tell the scroll area to resize its child widget - with the QScrollArea::setWidgetResizable() function. Then we - disable the \uicontrol {Zoom In}, \uicontrol {Zoom Out} and \uicontrol {Normal - Size} menu entries using the private \c updateActions() function. - - If the \l {QScrollArea::widgetResizable} property is set to \c - false (the default), the scroll area honors the size of its child - widget. If this property is set to \c true, the scroll area will - automatically resize the widget in order to avoid scroll bars - where they can be avoided, or to take advantage of extra space. - But the scroll area will honor the minimum size hint of its child - widget independent of the widget resizable property. So in this - example we set \c {imageLabel}'s size policy to \l - {QSizePolicy::Ignored}{ignored} in the constructor, to avoid that - scroll bars appear when the scroll area becomes smaller than the - label's minimum size hint. - - The screenshots below shows an image in its normal size, and the - same image with the \uicontrol {Fit to window} option turned on. - Enlarging the window will stretch the image further, as shown in - the third screenshot. - - \table - \row - \li \inlineimage imageviewer-original_size.png - \li \inlineimage imageviewer-fit_to_window_1.png - \li \inlineimage imageviewer-fit_to_window_2.png - \endtable - - If the slot is called to turn off the option, the - {QScrollArea::setWidgetResizable} property is set to \c false. We - also restore the image pixmap to its normal size by adjusting the - label's size to its content. And in the end we update the view - menu entries. - - \snippet widgets/imageviewer/imageviewer.cpp 15 - \snippet widgets/imageviewer/imageviewer.cpp 16 - - We implement the \c about() slot to create a message box - describing what the example is designed to show. - - \snippet widgets/imageviewer/imageviewer.cpp 17 - \snippet widgets/imageviewer/imageviewer.cpp 18 - - In the private \c createAction() function, we create the - actions providing the application features and populate - a menu with them. - - We assign a short-cut key to each action and connect them to the - appropriate slots. We only enable the \c openAct and \c exitAct at - the time of creation, the others are updated once an image has - been loaded into the application. In addition we make the \c - fitToWindowAct \l {QAction::checkable}{checkable}. - - The QMenu class provides a menu widget for use in menu bars, - context menus, and other popup menus. The QMenuBar class provides - a horizontal menu bar that consists of a list of pull-down menu - items. So we put the menus in the \c {ImageViewer}'s - menu bar which we retrieve with the QMainWindow::menuBar() - function. - - \snippet widgets/imageviewer/imageviewer.cpp 21 - \snippet widgets/imageviewer/imageviewer.cpp 22 - - The private \c updateActions() function enables or disables the - \uicontrol {Zoom In}, \uicontrol {Zoom Out} and \uicontrol {Normal Size} menu - entries depending on whether the \uicontrol {Fit to Window} option is - turned on or off. - - \snippet widgets/imageviewer/imageviewer.cpp 23 - \snippet widgets/imageviewer/imageviewer.cpp 24 - - In \c scaleImage(), we use the \c factor parameter to calculate - the new scaling factor for the displayed image, and resize \c - imageLabel. Since we set the - \l{QLabel::scaledContents}{scaledContents} property to \c true in - the constructor, the call to QWidget::resize() will scale the - image displayed in the label. We also adjust the scroll bars to - preserve the focal point of the image. - - At the end, if the scale factor is less than 33.3% or greater - than 300%, we disable the respective menu entry to prevent the - image pixmap from becoming too large, consuming too much - resources in the window system. - - \snippet widgets/imageviewer/imageviewer.cpp 25 - \snippet widgets/imageviewer/imageviewer.cpp 26 - - Whenever we zoom in or out, we need to adjust the scroll bars in - consequence. It would have been tempting to simply call - - \code - scrollBar->setValue(int(factor * scrollBar->value())); - \endcode - - but this would make the top-left corner the focal point, not the - center. Therefore we need to take into account the scroll bar - handle's size (the \l{QScrollBar::pageStep}{page step}). -*/ diff --git a/examples/widgets/doc/src/interview.qdoc b/examples/widgets/doc/src/interview.qdoc deleted file mode 100644 index 328e4fc9..00000000 --- a/examples/widgets/doc/src/interview.qdoc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example itemviews/interview - \title Interview - \ingroup examples-itemviews - \brief This example demonstrates the usage of the model/view framework. - - \brief The Interview example explores the flexibility and scalability of the - model/view framework by presenting an infinitely deep data structure using a model - and three different types of view. - - \image interview-demo.png -*/ diff --git a/examples/widgets/doc/src/itemviewspuzzle.qdoc b/examples/widgets/doc/src/itemviewspuzzle.qdoc deleted file mode 100644 index c1e0c361..00000000 --- a/examples/widgets/doc/src/itemviewspuzzle.qdoc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example itemviews/puzzle - \title Item Views Puzzle Example - \ingroup examples-itemviews - \brief The Puzzle example shows how to enable drag and drop with a custom model - to allow items to be transferred between a view and another widget. - - \image itemviewspuzzle-example.png - - This example is an implementation of a simple jigsaw puzzle game using the - built-in support for drag and drop provided by Qt's model/view framework. - The \l{Drag and Drop Puzzle Example}{Drag and Drop Puzzle} example shows - many of the same features, but takes an alternative approach that uses Qt's - drag and drop API at the application level to handle drag and drop - operations. -*/ diff --git a/examples/widgets/doc/src/licensewizard.qdoc b/examples/widgets/doc/src/licensewizard.qdoc index 2770a38a..66c822e4 100644 --- a/examples/widgets/doc/src/licensewizard.qdoc +++ b/examples/widgets/doc/src/licensewizard.qdoc @@ -4,6 +4,7 @@ /*! \example dialogs/licensewizard \title License Wizard Example + \examplecategory {User Interface Components} \ingroup examples-dialogs \brief The License Wizard example shows how to implement complex wizards in @@ -13,7 +14,7 @@ Most wizards have a linear structure, with page 1 followed by page 2 and so on until the last page. The - \l{dialogs/classwizard}{Class Wizard} example shows how to create + \l{dialogs/trivialwizard}{Trivial Wizard} example shows how to create such wizards. Some wizards are more complex in that they allow different @@ -191,5 +192,5 @@ option and disconnect the \c printButtonClicked() slot. \endlist - \sa QWizard, {Class Wizard Example}, {Trivial Wizard Example} + \sa QWizard, {Trivial Wizard Example} */ diff --git a/examples/widgets/doc/src/lineedits.qdoc b/examples/widgets/doc/src/lineedits.qdoc index c268f473..d11c080c 100644 --- a/examples/widgets/doc/src/lineedits.qdoc +++ b/examples/widgets/doc/src/lineedits.qdoc @@ -4,6 +4,7 @@ /*! \example widgets/lineedits \title Line Edits Example + \examplecateogry {User Interface Components} \ingroup examples-widgets \brief The Line Edits example demonstrates the many ways that QLineEdit can be used, and shows the effects of various properties and validators diff --git a/examples/widgets/doc/src/mainwindow.qdoc b/examples/widgets/doc/src/mainwindow.qdoc deleted file mode 100644 index ca284012..00000000 --- a/examples/widgets/doc/src/mainwindow.qdoc +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example mainwindows/mainwindow - \title Main Window - \ingroup examples-mainwindow - - \brief The Main Window example shows Qt's extensive support for tool bars, - dock windows, menus, and other standard application features. - - \image mainwindow-demo.png -*/ diff --git a/examples/widgets/doc/src/mdi.qdoc b/examples/widgets/doc/src/mdi.qdoc deleted file mode 100644 index 23daeeb9..00000000 --- a/examples/widgets/doc/src/mdi.qdoc +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example mainwindows/mdi - \title MDI Example - \ingroup examples-mainwindow - - \brief The MDI example shows how to implement a Multiple Document Interface using Qt's - QMdiArea class. - - \image mdi-example.png - -*/ diff --git a/examples/widgets/doc/src/menus.qdoc b/examples/widgets/doc/src/menus.qdoc index 2bffd17b..db03eeec 100644 --- a/examples/widgets/doc/src/menus.qdoc +++ b/examples/widgets/doc/src/menus.qdoc @@ -4,6 +4,7 @@ /*! \example mainwindows/menus \title Menus Example + \examplecategory {User Interface Components} \ingroup examples-mainwindow \ingroup examples-layout diff --git a/examples/widgets/doc/src/movie.qdoc b/examples/widgets/doc/src/movie.qdoc deleted file mode 100644 index d5aebc41..00000000 --- a/examples/widgets/doc/src/movie.qdoc +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example widgets/movie - \title Movie Example - \ingroup examples-widgets - \brief The Movie example demonstrates how to use QMovie and QLabel to - display animations. - - QMovie is mostly useful if one wants to play - a simple animation without the added complexity of a multimedia - framework to install and deploy. - - \borderedimage movie-example.png -*/ diff --git a/examples/widgets/doc/src/orderform.qdoc b/examples/widgets/doc/src/orderform.qdoc index 529ed6d2..7ae89dfd 100644 --- a/examples/widgets/doc/src/orderform.qdoc +++ b/examples/widgets/doc/src/orderform.qdoc @@ -4,6 +4,7 @@ /*! \example richtext/orderform \title Order Form Example + \examplecategory {User Interface Components} \ingroup examples-richtext \brief The Order Form example shows how to generate rich text documents by combining a simple template with data input by the diff --git a/examples/widgets/doc/src/painterpaths.qdoc b/examples/widgets/doc/src/painterpaths.qdoc index 55e78c84..05d21cc0 100644 --- a/examples/widgets/doc/src/painterpaths.qdoc +++ b/examples/widgets/doc/src/painterpaths.qdoc @@ -4,6 +4,7 @@ /*! \example painting/painterpaths \title Painter Paths Example + \examplecategory {Graphics & Multimedia} \ingroup examples-painting \brief The Painter Paths example shows how painter paths can be used to beuild complex shapes for rendering. diff --git a/examples/widgets/doc/src/pathstroke.qdoc b/examples/widgets/doc/src/pathstroke.qdoc index 01c3771d..cfb98bc3 100644 --- a/examples/widgets/doc/src/pathstroke.qdoc +++ b/examples/widgets/doc/src/pathstroke.qdoc @@ -4,6 +4,7 @@ /*! \example painting/pathstroke \title Path Stroking + \examplecategory {Graphics & Multimedia} \ingroup examples-painting \brief The Path Stroking example shows various types of pens that can be used with QPainter. diff --git a/examples/widgets/doc/src/pixelator.qdoc b/examples/widgets/doc/src/pixelator.qdoc deleted file mode 100644 index ab6f639d..00000000 --- a/examples/widgets/doc/src/pixelator.qdoc +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example itemviews/pixelator - \title Pixelator Example - \ingroup examples-itemviews - \brief The Pixelator example shows how delegates can be used to customize the way that - items are rendered in standard item views. - - \image pixelator-example.png - - By default, QTreeView, QTableView, and QListView use a standard item delegate - to display and edit a set of common data types that are sufficient for many - applications. However, an application may need to represent items of data in a - particular way, or provide support for rendering more specialized data types, - and this often requires the use of a custom delegate. - - In this example, we show how to use custom delegates to modify the appearance - of standard views. To do this, we implement the following components: - - \list - \li A model which represents each pixel in an image as an item of data, where each - item contains a value for the brightness of the corresponding pixel. - \li A custom delegate that uses the information supplied by the model to represent - each pixel as a black circle on a white background, where the radius of the - circle corresponds to the darkness of the pixel. - \endlist - - This example may be useful for developers who want to implement their own table - models or custom delegates. The process of creating custom delegates for editing - item data is covered in the \l{Spin Box Delegate Example}{Spin Box Delegate} - example. - - \section1 ImageModel Class Definition - - The \c ImageModel class is defined as follows: - - \snippet itemviews/pixelator/imagemodel.h 0 - - Since we only require a simple, read-only table model, we only need to implement - functions to indicate the dimensions of the image and supply data to other - components. - - \section1 ImageModel Class Implementation - - The constructor is trivial: - - \snippet itemviews/pixelator/imagemodel.cpp 0 - - The \c setImage() function sets the image that will be used by the model: - - \snippet itemviews/pixelator/imagemodel.cpp 1 - - The QAbstractItemModel::reset() call tells the view(s) that the model - has changed. - - The \c rowCount() and \c columnCount() functions return the height and width of - the image respectively: - - \snippet itemviews/pixelator/imagemodel.cpp 2 - \snippet itemviews/pixelator/imagemodel.cpp 3 - - Since the image is a simple two-dimensional structure, the \c parent arguments - to these functions are unused. They both simply return the relevant size from - the underlying image object. - - The \c data() function returns data for the item that corresponds to a given - model index in a format that is suitable for a particular role: - - \snippet itemviews/pixelator/imagemodel.cpp 4 - - In this implementation, we only check that the model index is valid, and that - the role requested is the \l{Qt::ItemDataRole}{DisplayRole}. If so, the function - returns the grayscale value of the relevant pixel in the image; otherwise, a null - model index is returned. - - This model can be used with QTableView to display the integer brightness values - for the pixels in the image. However, we will implement a custom delegate to - display this information in a more artistic way. - - The \c headerData() function is also reimplemented: - - \snippet itemviews/pixelator/imagemodel.cpp 5 - - We return (1, 1) as the size hint for a header item. If we - didn't, the headers would default to a larger size, preventing - us from displaying really small items (which can be specified - using the \uicontrol{Pixel size} combobox). - - \section1 PixelDelegate Class Definition - - The \c PixelDelegate class is defined as follows: - - \snippet itemviews/pixelator/pixeldelegate.h 0 - - This class provides only basic features for a delegate so, unlike the - \l{Spin Box Delegate Example}{Spin Box Delegate} example, we subclass - QAbstractItemDelegate instead of QItemDelegate. - - We only need to reimplement \l{QAbstractItemDelegate::paint()}{paint()} and - \l{QAbstractItemDelegate::sizeHint()}{sizeHint()} in this class. - However, we also provide a delegate-specific \c setPixelSize() function so - that we can change the delegate's behavior via the signals and slots mechanism. - - \section1 PixelDelegate Class Implementation - - The \c PixelDelegate constructor is used to set up a default value for - the size of each "pixel" that it renders. The base class constructor is - also called to ensure that the delegate is set up with a parent object, - if one is supplied: - - \snippet itemviews/pixelator/pixeldelegate.cpp 0 - - Each item is rendered by the delegate's - \l{QAbstractItemDelegate::paint()}{paint()} function. The view calls this - function with a ready-to-use QPainter object, style information that the - delegate should use to correctly draw the item, and an index to the item in - the model: - - \snippet itemviews/pixelator/pixeldelegate.cpp 1 - - The first task the delegate has to perform is to draw the item's background - correctly. Usually, selected items appear differently to non-selected items, - so we begin by testing the state passed in the style option and filling the - background if necessary. - - The radius of each circle is calculated in the following lines of code: - - \snippet itemviews/pixelator/pixeldelegate.cpp 3 - \snippet itemviews/pixelator/pixeldelegate.cpp 4 - - First, the largest possible radius of the circle is determined by taking the - smallest dimension of the style option's \c rect attribute. - Using the model index supplied, we obtain a value for the brightness of the - relevant pixel in the image. The radius of the circle is calculated by - scaling the brightness to fit within the item and subtracting it from the - largest possible radius. - - \snippet itemviews/pixelator/pixeldelegate.cpp 5 - \snippet itemviews/pixelator/pixeldelegate.cpp 6 - \snippet itemviews/pixelator/pixeldelegate.cpp 7 - - We save the painter's state, turn on antialiasing (to obtain smoother - curves), and turn off the pen. - - \snippet itemviews/pixelator/pixeldelegate.cpp 8 - \snippet itemviews/pixelator/pixeldelegate.cpp 9 - - The foreground of the item (the circle representing a pixel) must be - rendered using an appropriate brush. For unselected items, we will use a - solid black brush; selected items are drawn using a predefined brush from - the style option's palette. - - \snippet itemviews/pixelator/pixeldelegate.cpp 10 - - Finally, we paint the circle within the rectangle specified by the style - option and we call \l{QPainter::}{restore()} on the painter. - - The \c paint() function does not have to be particularly complicated; it is - only necessary to ensure that the state of the painter when the function - returns is the same as it was when it was called. This usually - means that any transformations applied to the painter must be preceded by - a call to QPainter::save() and followed by a call to QPainter::restore(). - - The delegate's \l{QAbstractItemDelegate::}{sizeHint()} function - returns a size for the item based on the predefined pixel size, initially set - up in the constructor: - - \snippet itemviews/pixelator/pixeldelegate.cpp 11 - - The delegate's size is updated whenever the pixel size is changed. - We provide a custom slot to do this: - - \snippet itemviews/pixelator/pixeldelegate.cpp 12 - - \section1 Using The Custom Delegate - - In this example, we use a main window to display a table of data, using the - custom delegate to render each cell in a particular way. Much of the - \c MainWindow class performs tasks that are not related to item views. Here, - we only quote the parts that are relevant. You can look at the rest of the - implementation by following the links to the code at the top of this - document. - - In the constructor, we set up a table view, turn off its grid, and hide its - headers: - - \snippet itemviews/pixelator/mainwindow.cpp 0 - \dots - \snippet itemviews/pixelator/mainwindow.cpp 1 - - This enables the items to be drawn without any gaps between them. Removing - the headers also prevents the user from adjusting the sizes of individual - rows and columns. - - We also set the minimum section size to 1 on the headers. If we - didn't, the headers would default to a larger size, preventing - us from displaying really small items (which can be specified - using the \uicontrol{Pixel size} combobox). - - The custom delegate is constructed with the main window as its parent, so - that it will be deleted correctly later, and we set it on the table view. - - \snippet itemviews/pixelator/mainwindow.cpp 2 - - Each item in the table view will be rendered by the \c PixelDelegate - instance. - - We construct a spin box to allow the user to change the size of each "pixel" - drawn by the delegate: - - \snippet itemviews/pixelator/mainwindow.cpp 3 - - This spin box is connected to the custom slot we implemented in the - \c PixelDelegate class. This ensures that the delegate always draws each - pixel at the currently specified size: - - \snippet itemviews/pixelator/mainwindow.cpp 4 - \dots - \snippet itemviews/pixelator/mainwindow.cpp 5 - - We also connect the spin box to a slot in the \c MainWindow class. This - forces the view to take into account the new size hints for each item; - these are provided by the delegate in its \c sizeHint() function. - - \snippet itemviews/pixelator/mainwindow.cpp 6 - - We explicitly resize the columns and rows to match the - \uicontrol{Pixel size} combobox. -*/ diff --git a/examples/widgets/doc/src/plugandpaint.qdoc b/examples/widgets/doc/src/plugandpaint.qdoc deleted file mode 100644 index 2ee08311..00000000 --- a/examples/widgets/doc/src/plugandpaint.qdoc +++ /dev/null @@ -1,527 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example tools/plugandpaint/app - \title Plug & Paint Example - \ingroup examples-widgets-tools - - \brief Demonstrates how to extend Qt applications using plugins. - - \image plugandpaint.png Screenshot of the Plug & Paint example - - A plugin is a dynamic library that can be loaded at run-time to - extend an application. Qt makes it possible to create custom - plugins and to load them using QPluginLoader. To ensure that - plugins don't get lost, it is also possible to link them - statically to the executable. The Plug & Paint example uses - plugins to support custom brushes, shapes, and image filters. A - single plugin can provide multiple brushes, shapes, and/or - filters. - - If you want to learn how to make your own application extensible - through plugins, we recommend that you start by reading this - overview, which explains how to make an application use plugins. - Afterwards, you can read the - \l{tools/plugandpaint/plugins/basictools}{Basic Tools} and - \l{tools/plugandpaint/plugins/extrafilters}{Extra Filters} - overviews, which show how to implement static and dynamic - plugins, respectively. - - Plug & Paint consists of the following classes: - - \list - \li \c MainWindow is a QMainWindow subclass that provides the menu - system and that contains a \c PaintArea as the central widget. - \li \c PaintArea is a QWidget that allows the user to draw using a - brush and to insert shapes. - \li \c PluginDialog is a dialog that shows information about the - plugins detected by the application. - \li \c BrushInterface, \c ShapeInterface, and \c FilterInterface are - abstract base classes that can be implemented by plugins to - provide custom brushes, shapes, and image filters. - \endlist - - \section1 The Plugin Interfaces - - We will start by reviewing the interfaces defined in \c - interfaces.h. These interfaces are used by the Plug & Paint - application to access extra functionality. They are implemented - in the plugins. - - - \snippet tools/plugandpaint/app/interfaces.h 0 - - The \c BrushInterface class declares four pure virtual functions. - The first pure virtual function, \c brushes(), returns a list of - strings that identify the brushes provided by the plugin. By - returning a QStringList instead of a QString, we make it possible - for a single plugin to provide multiple brushes. The other - functions have a \c brush parameter to identify which brush - (among those returned by \c brushes()) is used. - - \c mousePress(), \c mouseMove(), and \c mouseRelease() take a - QPainter and one or two \l{QPoint}s, and return a QRect - identifying which portion of the image was altered by the brush. - - The class also has a virtual destructor. Interface classes - usually don't need such a destructor (because it would make - little sense to \c delete the object that implements the - interface through a pointer to the interface), but some compilers - emit a warning for classes that declare virtual functions but no - virtual destructor. We provide the destructor to keep these - compilers happy. - - \snippet tools/plugandpaint/app/interfaces.h 1 - - The \c ShapeInterface class declares a \c shapes() function that - works the same as \c{BrushInterface}'s \c brushes() function, and - a \c generateShape() function that has a \c shape parameter. - Shapes are represented by a QPainterPath, a data type that can - represent arbitrary 2D shapes or combinations of shapes. The \c - parent parameter can be used by the plugin to pop up a dialog - asking the user to specify more information. - - \snippet tools/plugandpaint/app/interfaces.h 2 - - The \c FilterInterface class declares a \c filters() function - that returns a list of filter names, and a \c filterImage() - function that applies a filter to an image. - - \snippet tools/plugandpaint/app/interfaces.h 4 - - To make it possible to query at run-time whether a plugin - implements a given interface, we must use the \c - Q_DECLARE_INTERFACE() macro. The first argument is the name of - the interface. The second argument is a string identifying the - interface in a unique way. By convention, we use a "Java package - name" syntax to identify interfaces. If we later change the - interfaces, we must use a different string to identify the new - interface; otherwise, the application might crash. It is therefore - a good idea to include a version number in the string, as we did - above. - - The \l{tools/plugandpaint/plugins/basictools}{Basic Tools} plugin - and the \l{tools/plugandpaint/plugins/extrafilters}{Extra Filters} - plugin shows how to derive from \c BrushInterface, \c - ShapeInterface, and \c FilterInterface. - - A note on naming: It might have been tempting to give the \c - brushes(), \c shapes(), and \c filters() functions a more generic - name, such as \c keys() or \c features(). However, that would - have made multiple inheritance impractical. When creating - interfaces, we should always try to give unique names to the pure - virtual functions. - - \section1 The MainWindow Class - - The \c MainWindow class is a standard QMainWindow subclass, as - found in many of the other examples (e.g., - \l{mainwindows/application}{Application}). Here, we'll - concentrate on the parts of the code that are related to plugins. - - \snippet tools/plugandpaint/app/mainwindow.cpp 4 - - The \c loadPlugins() function is called from the \c MainWindow - constructor to detect plugins and update the \uicontrol{Brush}, - \uicontrol{Shapes}, and \uicontrol{Filters} menus. We start by handling static - plugins (available through QPluginLoader::staticInstances()) - - To the application that uses the plugin, a Qt plugin is simply a - QObject. That QObject implements plugin interfaces using multiple - inheritance. - - \snippet tools/plugandpaint/app/mainwindow.cpp 5 - - The next step is to load dynamic plugins. We initialize the \c - pluginsDir member variable to refer to the \c plugins - subdirectory of the Plug & Paint example. On Unix, this is just a - matter of initializing the QDir variable with - QApplication::applicationDirPath(), the path of the executable - file, and to do a \l{QDir::cd()}{cd()}. On Windows and \macos, - this file is usually located in a subdirectory, so we need to - take this into account. - - \snippet tools/plugandpaint/app/mainwindow.cpp 6 - \snippet tools/plugandpaint/app/mainwindow.cpp 7 - \snippet tools/plugandpaint/app/mainwindow.cpp 8 - - We use QDir::entryList() to get a list of all files in that - directory. Then we iterate over the result using a range-based for loop - and try to load the plugin using QPluginLoader. - - The QObject provided by the plugin is accessible through - QPluginLoader::instance(). If the dynamic library isn't a Qt - plugin, or if it was compiled against an incompatible version of - the Qt library, QPluginLoader::instance() returns a null pointer. - - If QPluginLoader::instance() is non-null, we add it to the menus. - - \snippet tools/plugandpaint/app/mainwindow.cpp 9 - - At the end, we enable or disable the \uicontrol{Brush}, \uicontrol{Shapes}, - and \uicontrol{Filters} menus based on whether they contain any items. - - \snippet tools/plugandpaint/app/mainwindow.cpp 10 - - For each plugin (static or dynamic), we check which interfaces it - implements using \l qobject_cast(). First, we try to cast the - plugin instance to a \c BrushInterface; if it works, we call the - private function \c addToMenu() with the list of brushes returned - by \c brushes(). Then we do the same with the \c ShapeInterface - and the \c FilterInterface. - - \snippet tools/plugandpaint/app/mainwindow.cpp 3 - - The \c aboutPlugins() slot is called on startup and can be - invoked at any time through the \uicontrol{About Plugins} action. It - pops up a \c PluginDialog, providing information about the loaded - plugins. - - \image plugandpaint-plugindialog.png Screenshot of the Plugin dialog - - - The \c addToMenu() function is called from \c loadPlugin() to - create \l{QAction}s for custom brushes, shapes, or filters and - add them to the relevant menu. The QAction is created with the - plugin from which it comes from as the parent; this makes it - convenient to get access to the plugin later. - - \snippet tools/plugandpaint/app/mainwindow.cpp 0 - - The \c changeBrush() slot is invoked when the user chooses one of - the brushes from the \uicontrol{Brush} menu. We start by finding out - which action invoked the slot using QObject::sender(). Then we - get the \c BrushInterface out of the plugin (which we - conveniently passed as the QAction's parent) and we call \c - PaintArea::setBrush() with the \c BrushInterface and the string - identifying the brush. Next time the user draws on the paint - area, \c PaintArea will use this brush. - - \snippet tools/plugandpaint/app/mainwindow.cpp 1 - - The \c insertShape() is invoked when the use chooses one of the - shapes from the \uicontrol{Shapes} menu. We retrieve the QAction that - invoked the slot, then the \c ShapeInterface associated with that - QAction, and finally we call \c ShapeInterface::generateShape() - to obtain a QPainterPath. - - \snippet tools/plugandpaint/app/mainwindow.cpp 2 - - The \c applyFilter() slot is similar: We retrieve the QAction - that invoked the slot, then the \c FilterInterface associated to - that QAction, and finally we call \c - FilterInterface::filterImage() to apply the filter onto the - current image. - - \section1 The PaintArea Class - - The \c PaintArea class contains some code that deals with \c - BrushInterface, so we'll review it briefly. - - \snippet tools/plugandpaint/app/paintarea.cpp 0 - - In \c setBrush(), we simply store the \c BrushInterface and the - brush that are given to us by \c MainWindow. - - \snippet tools/plugandpaint/app/paintarea.cpp 1 - - In the \l{QWidget::mouseMoveEvent()}{mouse move event handler}, - we call the \c BrushInterface::mouseMove() function on the - current \c BrushInterface, with the current brush. The mouse - press and mouse release handlers are very similar. - - \section1 The PluginDialog Class - - The \c PluginDialog class provides information about the loaded - plugins to the user. Its constructor takes a path to the plugins - and a list of plugin file names. It calls \c findPlugins() - to fill the QTreeWdiget with information about the plugins: - - \snippet tools/plugandpaint/app/plugindialog.cpp 0 - - The \c findPlugins() is very similar to \c - MainWindow::loadPlugins(). It uses QPluginLoader to access the - static and dynamic plugins. Its helper function \c - populateTreeWidget() uses \l qobject_cast() to find out which - interfaces are implemented by the plugins: - - \snippet tools/plugandpaint/app/plugindialog.cpp 1 - - \section1 Importing Static Plugins - - The \l{tools/plugandpaint/plugins/basictools}{Basic Tools} plugin - is built as a static plugin, to ensure that it is always - available to the application. This requires using the - Q_IMPORT_PLUGIN() macro somewhere in the application (in a \c - .cpp file) and specifying the plugin in the \c .pro file. - - For Plug & Paint, we have chosen to put Q_IMPORT_PLUGIN() in \c - main.cpp: - - \snippet tools/plugandpaint/app/main.cpp 0 - - The argument to Q_IMPORT_PLUGIN() is the plugin name, which corresponds - with the name of the class that declares metadata for the plugin with - Q_PLUGIN_METADATA(). - - In the \c .pro file, we need to specify the static library. - Here's the project file for building Plug & Paint: - - \snippet tools/plugandpaint/app/app.pro 0 - - The \c LIBS line variable specifies the library \c pnp_basictools - located in the \c ../plugandpaint/plugins/basictools directory. - (Although the \c LIBS syntax has a distinct Unix flavor, \c qmake - supports it on all platforms.) - - The \c CONFIG() code at the end is necessary for this example - because the example is part of the Qt distribution and Qt can be - configured to be built simultaneously in debug and in release - modes. You don't need to for your own plugin applications. - - This completes our review of the Plug & Paint application. At - this point, you might want to take a look at the - \l{tools/plugandpaint/plugins/basictools}{Basic Tools} example - plugin. -*/ - -/*! - \example tools/plugandpaint/plugins/basictools - \title Plug & Paint Basic Tools Example - \brief A plugin providing the basic tools for painting functionality. - - \image plugandpaint.png Screenshot of the Plug & Paint example - - The Basic Tools example is a static plugin for the - \l{tools/plugandpaint/app}{Plug & Paint} example. It provides a set - of basic brushes, shapes, and filters. Through the Basic Tools - example, we will review the four steps involved in writing a Qt - plugin: - - \list 1 - \li Declare a plugin class. - \li Implement the interfaces provided by the plugin. - \li Export the plugin using the Q_PLUGIN_METADATA() macro. - \li Build the plugin using an adequate \c .pro file. - \endlist - - \section1 Declaration of the Plugin Class - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.h 0 - - We start by including \c interfaces.h, which defines the plugin - interfaces for the \l{tools/plugandpaint/app}{Plug & Paint} - application. For the \c #include to work, we need to add an \c - INCLUDEPATH entry to the \c .pro file with the path to the - header file. - - The \c BasicToolsPlugin class is a QObject subclass that - implements the \c BrushInterface, the \c ShapeInterface, and the - \c FilterInterface. This is done through multiple inheritance. - The \c Q_INTERFACES() macro is necessary to tell \l{moc}, Qt's - meta-object compiler, that the base classes are plugin - interfaces. Without the \c Q_INTERFACES() macro, we couldn't use - \l qobject_cast() in the \l{tools/plugandpaint/app}{Plug & Paint} - application to detect interfaces. - For an explanation for the \c Q_PLUGIN_METADATA() macro see - \l {Exporting the Plugin}. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.h 2 - - In the \c public section of the class, we declare all the - functions from the three interfaces. - - \section1 Implementation of the Brush Interface - - Let's now review the implementation of the \c BasicToolsPlugin - member functions inherited from \c BrushInterface. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 0 - - The \c brushes() function returns a list of brushes provided by - this plugin. We provide three brushes: \uicontrol{Pencil}, \uicontrol{Air - Brush}, and \uicontrol{Random Letters}. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 1 - - On a mouse press event, we just call \c mouseMove() to draw the - spot where the event occurred. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 2 - - In \c mouseMove(), we start by saving the state of the QPainter - and we compute a few variables that we'll need later. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 3 - - Then comes the brush-dependent part of the code: - - \list - \li If the brush is \uicontrol{Pencil}, we just call - QPainter::drawLine() with the current QPen. - - \li If the brush is \uicontrol{Air Brush}, we start by setting the - painter's QBrush to Qt::Dense6Pattern to obtain a dotted - pattern. Then we draw a circle filled with that QBrush several - times, resulting in a thick line. - - \li If the brush is \uicontrol{Random Letters}, we draw a random letter - at the new cursor position. Most of the code is for setting - the font to be bold and larger than the default font and for - computing an appropriate bounding rect. - \endlist - - At the end, we restore the painter state to what it was upon - entering the function and we return the bounding rectangle. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 4 - - When the user releases the mouse, we do nothing and return an - empty QRect. - - \section1 Implementation of the Shape Interface - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 5 - - The plugin provides three shapes: \uicontrol{Circle}, \uicontrol{Star}, and - \uicontrol{Text...}. The three dots after \uicontrol{Text} are there because - the shape pops up a dialog asking for more information. We know - that the shape names will end up in a menu, so we include the - three dots in the shape name. - - A cleaner but more complicated design would have been to - distinguish between the internal shape name and the name used in - the user interface. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 6 - - The \c generateShape() creates a QPainterPath for the specified - shape. If the shape is \uicontrol{Text}, we pop up a QInputDialog to - let the user enter some text. - - \section1 Implementation of the Filter Interface - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 7 - - The plugin provides three filters: \uicontrol{Invert Pixels}, \uicontrol{Swap - RGB}, and \uicontrol{Grayscale}. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 8 - - The \c filterImage() function takes a filter name and a QImage as - parameters and returns an altered QImage. The first thing we do - is to convert the image to a 32-bit RGB format, to ensure that - the algorithms will work as expected. For example, - QImage::invertPixels(), which is used to implement the - \uicontrol{Invert Pixels} filter, gives counterintuitive results for - 8-bit images, because they invert the indices into the color - table instead of inverting the color table's entries. - - \section1 Exporting the Plugin - - To finally export your plugin you just have to add the - \c Q_PLUGIN_METADATA() macro right next to the \c Q_OBJECT() macro - into the header file of the plugin. - It must contain the plugins IID and optionally a filename pointing - to a json file containing the metadata for the plugin. - - \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.h 4 - - Within this example the json file does not need to export any metadata, - so it just contains an empty json object. - - \code - {} - \endcode - - \section1 The .pro File - - Here's the project file for building the Basic Tools plugin: - - \snippet tools/plugandpaint/plugins/basictools/basictools.pro 0 - - The \c .pro file differs from typical \c .pro files in many - respects. First, it starts with a \c TEMPLATE entry specifying \c - lib. (The default template is \c app.) It also adds \c plugin to - the \c CONFIG variable. This is necessary on some platforms to - avoid generating symbolic links with version numbers in the file - name, which is appropriate for most dynamic libraries but not for - plugins. - - To make the plugin a static plugin, all that is required is to - specify \c static in addition to \c plugin. The - \l{tools/plugandpaint/plugins/extrafilters}{Extra Filters} plugin, - which is compiled as a dynamic plugin, doesn't specify \c static - in its \c .pro file. - - The \c INCLUDEPATH variable sets the search paths for global - headers (i.e., header files included using \c{#include <...>}). - We add \c ../../app to the list, so that we can include - \c . - - The \c TARGET variable specifies which name we want to give the - target library. We use \c pnp_ as the prefix to show that the - plugin is designed to work with Plug & Paint. On Unix, \c lib is - also prepended to that name. On all platforms, a - platform-specific suffix is appended (e.g., \c .dll on Windows, - \c .a on Linux). - - The \c CONFIG() code at the end is necessary for this example - because the example is part of the Qt distribution and Qt can be - configured to be built simultaneously in debug and in release - modes. You don't need to for your own plugins. -*/ - -/*! - \example tools/plugandpaint/plugins/extrafilters - \title Plug & Paint Extra Filters Example - \brief A plugin providing the extra filters. - - \image plugandpaint.png Screenshot of the Plug & Paint example - - The Extra Filters example is a plugin for the - \l{tools/plugandpaint/app}{Plug & Paint} example. It provides a set - of filters in addition to those provided by the - \l{tools/plugandpaint/plugins/basictools}{Basic Tools} plugin. - - Since the approach is identical to - \l{tools/plugandpaint/plugins/basictools}{Basic Tools}, we won't - review the code here. The only part of interest is the - \c .pro file, since Extra Filters is a dynamic plugin - (\l{tools/plugandpaint/plugins/basictools}{Basic Tools} is - linked statically into the Plug & Paint executable). - - Here's the project file for building the Extra Filters plugin: - - \snippet tools/plugandpaint/plugins/extrafilters/extrafilters.pro 0 - - The \c .pro file differs from typical \c .pro files in many - respects. First, it starts with a \c TEMPLATE entry specifying \c - lib. (The default template is \c app.) It also adds \c plugin to - the \c CONFIG variable. This is necessary on some platforms to - avoid generating symbolic links with version numbers in the file - name, which is appropriate for most dynamic libraries but not for - plugins. - - The \c INCLUDEPATH variable sets the search paths for global - headers (i.e., header files included using \c{#include <...>}). - We add \c ../../app to the list, so that we can include - \c . - - The \c TARGET variable specifies which name we want to give the - target library. We use \c pnp_ as the prefix to show that the - plugin is designed to work with Plug & Paint. On Unix, \c lib is - also prepended to that name. On all platforms, a - platform-specific suffix is appended (e.g., \c .dll on Windows, - \c .so on Linux). - - The \c DESTDIR variable specifies where we want to install the - plugin. We put it in Plug & Paint's \c plugins subdirectory, - since that's where the application looks for dynamic plugins. - - The \c CONFIG() code at the end is necessary for this example - because the example is part of the Qt distribution and Qt can be - configured to be built simultaneously in debug and in release - modes. You don't need to for your own plugins. -*/ diff --git a/examples/widgets/doc/src/regularexpression.qdoc b/examples/widgets/doc/src/regularexpression.qdoc index 8d7aa616..f6f1e876 100644 --- a/examples/widgets/doc/src/regularexpression.qdoc +++ b/examples/widgets/doc/src/regularexpression.qdoc @@ -4,6 +4,7 @@ /*! \example tools/regularexpression \title QRegularExpression Example + \examplecategory {User Interface Components} \ingroup examples-widgets-tools \brief The QRegularExpression example shows how regular expressions in Qt are diff --git a/examples/widgets/doc/src/screenshot.qdoc b/examples/widgets/doc/src/screenshot.qdoc index 54826dc1..2e2b3123 100644 --- a/examples/widgets/doc/src/screenshot.qdoc +++ b/examples/widgets/doc/src/screenshot.qdoc @@ -3,7 +3,8 @@ /*! \example desktop/screenshot - \title Screenshot Example + \title Taking a Screenshot + \examplecategory {Desktop} \ingroup examples-desktop \brief The Screenshot example shows how to take a screenshot of the desktop. diff --git a/examples/widgets/doc/src/scribble.qdoc b/examples/widgets/doc/src/scribble.qdoc index 1a87576e..3cd72053 100644 --- a/examples/widgets/doc/src/scribble.qdoc +++ b/examples/widgets/doc/src/scribble.qdoc @@ -4,6 +4,7 @@ /*! \example widgets/scribble \title Scribble Example + \examplecategory {User Interface Components} \ingroup examples-widgets \brief The Scribble example shows how to reimplement some of QWidget's event handlers to receive the events generated for the diff --git a/examples/widgets/doc/src/settingseditor.qdoc b/examples/widgets/doc/src/settingseditor.qdoc index 55226a98..43c45008 100644 --- a/examples/widgets/doc/src/settingseditor.qdoc +++ b/examples/widgets/doc/src/settingseditor.qdoc @@ -4,6 +4,7 @@ /*! \example tools/settingseditor \title Settings Editor Example + \examplecategory {User Interface Components} \ingroup examples-widgets-tools \brief The Settings Editor example shows how Qt's standard settings support is used in an diff --git a/examples/widgets/doc/src/shapedclock.qdoc b/examples/widgets/doc/src/shapedclock.qdoc index 4ce34126..4bcd0468 100644 --- a/examples/widgets/doc/src/shapedclock.qdoc +++ b/examples/widgets/doc/src/shapedclock.qdoc @@ -3,17 +3,19 @@ /*! \example widgets/shapedclock - \title Shaped Clock Example + \title Translucent Background + \examplecategory {User Interface Components} \ingroup examples-widgets - \brief The Shaped Clock example shows how to apply a translucent background - and a widget mask to a top-level widget to produce a shaped window. + \brief The example shows how to make a round window with a translucent + background. \borderedimage shapedclock-example.png - Widget masks are used to customize the shapes of top-level widgets by - restricting the area available for painting and mouse input. Using a - translucent background facilitates partially transparent windows and smooth - edges. On most window systems, setting certain window flags will cause the + Widgets that set their background to be translucent will be transparent for all + unpainted pixels, and the background will shine through pixels painted with an + opacity of less than 100%. Pixels that are not painted at all will also not + receive any mouse input. This can be used to customize the shapes of top-level + widgets. On most window systems, setting certain window flags will cause the window decoration (title bar, window frame, buttons) to be disabled, allowing specially-shaped windows to be created. In this example, we use this feature to create a circular window containing an analog clock. @@ -30,12 +32,10 @@ \snippet widgets/shapedclock/shapedclock.h 0 - The \l{QWidget::paintEvent()}{paintEvent()} implementation is the same as - that found in the \c AnalogClock class, with one important exception: we - now must also draw background (the clock face) ourselves, since the widget - background is just transparent. We implement \l{QWidget::sizeHint()}{sizeHint()} - so that we don't have to resize the widget explicitly. We also provide an event - handler for resize events. This allows us to update the mask if the clock is resized. + The \l{QWidget::paintEvent()}{paintEvent()} implementation draws an analog clock + on a semi-transparent background (the clock face). In addition, we implement + \l{QWidget::sizeHint()}{sizeHint()} so that we don't have to resize the widget + explicitly. Since the window containing the clock widget will have no title bar, we provide implementations for \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()} and @@ -45,8 +45,9 @@ \section1 ShapedClock Class Implementation - The \c ShapedClock constructor performs many of the same tasks as the \c AnalogClock - constructor. We set up a timer and connect it to the widget's update() slot: + The \c ShapedClock constructor sets up a timer and connect it to the widget's + update() slot. In addition, we add an action to the widget, which will automatically + become available through a context menu when right-clicking on the widget. \snippet widgets/shapedclock/shapedclock.cpp 0 @@ -77,49 +78,14 @@ cursor position in global coordinates. If we drag the widget, we also accept the event. The \c paintEvent() function is mainly the same as described in the - \l{Analog Clock} example. The one addition is that we - use QPainter::drawEllipse() to draw a round clock face with the current - palette's default background color. We make the clock face a bit smaller - than the widget mask, so that the anti-aliased, semi-transparent pixels on - the edge are not clipped away by the widget mask. This gives the shaped - window smooth edges on the screen. + \l{Analog Clock} example. The one addition is that we use QPainter::drawEllipse() to + draw a round clock face. We reduce the painter's opacity to 90%, and use the palette's + default background color. \snippet widgets/shapedclock/shapedclock.cpp 3 - In the \c resizeEvent() handler, we re-use some of the code from the \c - paintEvent() to determine the region of the widget that is visible to the - user. This tells the system the area where mouse clicks should go to us, - and not to whatever window is behind us: - - \snippet widgets/shapedclock/shapedclock.cpp 4 - - Since the clock face is a circle drawn in the center of the widget, this is the region - we use as the mask. - - Although the lack of a window frame may make it difficult for the user to resize the - widget on some platforms, it will not necessarily be impossible. The \c resizeEvent() - function ensures that the widget mask will always be updated if the widget's dimensions - change, and additionally ensures that it will be set up correctly when the widget is - first displayed. - Finally, we implement the \c sizeHint() for the widget so that it is given a reasonable default size when it is first shown: - \snippet widgets/shapedclock/shapedclock.cpp 5 - - \section1 Notes on Widget Masks - - Widget masks are used to hint to the window system that the application - does not want mouse events for areas outside the mask. On most systems, - they also result in coarse visual clipping. To get smooth window edges, one - should use translucent background and anti-aliased painting, as shown in - this example. - - Since QRegion allows arbitrarily complex regions to be created, widget masks can be - made to suit the most unconventionally-shaped windows, and even allow widgets to be - displayed with holes in them. - - Widget masks can also be constructed by using the contents of pixmap to define the - opaque part of the widget. For a pixmap with an alpha channel, a suitable mask can be - obtained with QPixmap::mask(). + \snippet widgets/shapedclock/shapedclock.cpp 4 */ diff --git a/examples/widgets/doc/src/shortcuteditor.qdoc b/examples/widgets/doc/src/shortcuteditor.qdoc index 350609c9..9999a184 100644 --- a/examples/widgets/doc/src/shortcuteditor.qdoc +++ b/examples/widgets/doc/src/shortcuteditor.qdoc @@ -4,6 +4,7 @@ /*! \example widgets/shortcuteditor \title Shortcut Editor Example + \examplecategory {User Interface Components} \ingroup examples-widgets \brief The Shortcut Editor example shows how to create a basic, read-write hierarchical model to use with Qt's standard view and QKeySequenceEdit diff --git a/examples/widgets/doc/src/simpledommodel.qdoc b/examples/widgets/doc/src/simpledommodel.qdoc deleted file mode 100644 index 82bd5c5d..00000000 --- a/examples/widgets/doc/src/simpledommodel.qdoc +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example itemviews/simpledommodel - \title Simple DOM Model Example - \ingroup examples-itemviews - \brief The Simple DOM Model example shows how an existing class can be adapted for use with - the model/view framework. - - \image simpledommodel-example.png - - Qt provides two complementary sets of classes for reading XML files: The classes based - around QXmlReader provide a SAX-style API for incremental reading of large files, and - the classes based around QDomDocument enable developers to access the contents of XML - files using a Document Object Model (DOM) API. - - In this example, we create a model that uses the DOM API to expose the structure and - contents of XML documents to views via the standard QAbstractModel interface. - - \section1 Design and Concepts - - Reading an XML document with Qt's DOM classes is a straightforward process. Typically, - the contents of a file are supplied to QDomDocument, and nodes are accessed using the - functions provided by QDomNode and its subclasses. - - \omit - For example, the following code - snippet reads the contents of a file into a QDomDocument object and traverses the - document, reading all the plain text that can be found: - - \snippet doc/src/snippets/code/doc_src_examples_simpledommodel.cpp 0 - - In principle, the functions provided by QDomNode can be used to navigate from any - given starting point in a document to the piece of data requested by another component. - Since QDomDocument maintains information about the structure of a document, we can - use this to implement the required virtual functions in a QAbstractItemModel subclass. - \endomit - - The aim is to use the structure provided by QDomDocument by wrapping QDomNode objects - in item objects similar to the \c TreeItem objects used in the - \l{Simple Tree Model Example}{Simple Tree Model} example. - - \section1 DomModel Class Definition - - Let us begin by examining the \c DomModel class: - - \snippet itemviews/simpledommodel/dommodel.h 0 - - The class definition contains all the basic functions that are needed for a - read-only model. Only the constructor and \c document() function are specific to - this model. The private \c domDocument variable is used to hold the document - that is exposed by the model; the \c rootItem variable contains a pointer to - the root item in the model. - - \section1 DomItem Class Definition - - The \c DomItem class is used to hold information about a specific QDomNode in - the document: - - \snippet itemviews/simpledommodel/domitem.h 0 - - Each \c DomItem provides a wrapper for a QDomNode obtained from the underlying - document which contains a reference to the node, it's location in the parent node's - list of child nodes, and a pointer to a parent wrapper item. - - The \c parent(), \c child(), and \c row() functions are convenience functions for - the \c DomModel to use that provide basic information about the item to be discovered - quickly. The node() function provides access to the underlying QDomNode object. - - As well as the information supplied in the constructor, the class maintains a cache - of information about any child items. This is used to provide a collection of - persistent item objects that the model can identify consistently and improve the - performance of the model when accessing child items. - - \section1 DomItem Class Implementation - - Since the \c DomItem class is only a thin wrapper around QDomNode objects, with a - few additional features to help improve performance and memory usage, we can provide - a brief outline of the class before discussing the model itself. - - The constructor simply records details of the QDomNode that needs to be wrapped: - - \snippet itemviews/simpledommodel/domitem.cpp 0 - \snippet itemviews/simpledommodel/domitem.cpp 1 - - As a result, functions to provide the parent wrapper, the row number occupied by - the item in its parent's list of children, and the underlying QDomNode for each item - are straightforward to write: - - \snippet itemviews/simpledommodel/domitem.cpp 4 - \codeline - \snippet itemviews/simpledommodel/domitem.cpp 6 - \codeline - \snippet itemviews/simpledommodel/domitem.cpp 3 - - It is necessary to maintain a collection of items which can be consistently identified - by the model. For that reason, we maintain a hash of child wrapper items that, to - minimize memory usage, is initially empty. The model uses the item's \c child() - function to help create model indexes, and this constructs wrappers for the children - of the item's QDomNode, relating the row number of each child to the newly-constructed - wrapper: - - \snippet itemviews/simpledommodel/domitem.cpp 5 - - If a QDomNode was previously wrapped, the cached wrapper is returned; otherwise, a - new wrapper is constructed and stored for valid children, and zero is returned for - invalid ones. - - The class's destructor deletes all the child items of the wrapper: - - \snippet itemviews/simpledommodel/domitem.cpp 2 - - These, in turn, will delete their children and free any QDomNode objects in use. - - \section1 DomModel Class Implementation - - The structure provided by the \c DomItem class makes the implementation of \c DomModel - similar to the \c TreeModel shown in the - \l{Simple Tree Model Example}{Simple Tree Model} example. - - The constructor accepts an existing document and a parent object for the model: - - \snippet itemviews/simpledommodel/dommodel.cpp 0 - - A shallow copy of the document is stored for future reference, and a root item is - created to provide a wrapper around the document. We assign the root item a row - number of zero only to be consistent since the root item will have no siblings. - - Since the model only contains information about the root item, the destructor only - needs to delete this one item: - - \snippet itemviews/simpledommodel/dommodel.cpp 1 - - All of the child items in the tree will be deleted by the \c DomItem destructor as - their parent items are deleted. - - \section2 Basic Properties of The Model - - Some aspects of the model do not depend on the structure of the underlying document, - and these are simple to implement. - - The number of columns exposed by the model is returned by the \c columnCount() - function: - - \snippet itemviews/simpledommodel/dommodel.cpp 2 - - This value is fixed, and does not depend on the location or type of the underlying - node in the document. We will use these three columns to display different kinds of - data from the underlying document. - - Since we only implement a read-only model, the \c flags() function is straightforward - to write: - - \snippet itemviews/simpledommodel/dommodel.cpp 5 - - Since the model is intended for use in a tree view, the \c headerData() function only - provides a horizontal header: - - \snippet itemviews/simpledommodel/dommodel.cpp 6 - - The model presents the names of nodes in the first column, element attributes in the - second, and any node values in the third. - - \section2 Navigating The Document - - The index() function creates a model index for the item with the given row, column, - and parent in the model: - - \snippet itemviews/simpledommodel/dommodel.cpp 7 - - The function first has to relate the parent index to an item that contains a node - from the underlying document. If the parent index is invalid, it refers to the root - node in the document, so we retrieve the root item that wraps it; otherwise, we - obtain a pointer to the relevant item using the QModelIndex::internalPointer() - function. We are able to extract a pointer in this way because any valid model index - will have been created by this function, and we store pointers to item objects in - any new indexes that we create with QAbstractItemModel::createIndex(): - - \snippet itemviews/simpledommodel/dommodel.cpp 8 - - A child item for the given row is provided by the parent item's \c child() function. - If a suitable child item was found then we call - \l{QAbstractItemModel::createIndex()}{createIndex()} to produce a model index for the - requested row and column, passing a pointer to the child item for it to store - internally. If no suitable child item is found, an invalid model index is returned. - - Note that the items themselves maintain ownership of their child items. This means - that the model does not need to keep track of the child items that have been created, - and can let the items themselves tidy up when they are deleted. - - The number of rows beneath a given item in the model is returned by the \c rowCount() - function, and is the number of child nodes contained by the node that corresponds to - the specified model index: - - \snippet itemviews/simpledommodel/dommodel.cpp 10 - - To obtain the relevant node in the underlying document, we access the item via the - internal pointer stored in the model index. If an invalid index is supplied, the - root item is used instead. We use the item's \c node() function to access the node - itself, and simply count the number of child nodes it contains. - - Since the model is used to represent a hierarchical data structure, it needs to - provide an implementation for the \c parent() function. This returns a model index - that corresponds to the parent of a child model index supplied as its argument: - - \snippet itemviews/simpledommodel/dommodel.cpp 9 - - For valid indexes other than the index corresponding to the root item, we obtain - a pointer to the relevant item using the method described in the \c index() function, - and use the item's \c parent() function to obtain a pointer to the parent item. - - If no valid parent item exists, or if the parent item is the root item, we can simply - follow convention and return an invalid model index. For all other parent items, we - create a model index containing the appropriate row and column numbers, and a pointer - to the parent item we just obtained. - - Data is provided by the \c data() function. For simplicity, we only provide data for - the \l{Qt::DisplayRole}{display role}, returning an invalid variant for all other - requests: - - \snippet itemviews/simpledommodel/dommodel.cpp 3 - - As before, we obtain an item pointer for the index supplied, and use it to obtain - the underlying document node. Depending on the column specified, the data we return - is obtained in different ways: - - \snippet itemviews/simpledommodel/dommodel.cpp 4 - - For the first column, we return the node's name. For the second column, we read any - attributes that the node may have, and return a string that contains a space-separated - list of attribute-value assignments. For the third column, we return any value that - the node may have; this allows the contents of text nodes to be displayed in a view. - - If data from any other column is requested, an invalid variant is returned. - - \section1 Implementation Notes - - Ideally, we would rely on the structure provided by QDomDocument to help us write - the \l{QAbstractItemModel::parent()}{parent()} and - \l{QAbstractItemModel::index()}{index()} functions that are required when subclassing - QAbstractItemModel. However, since Qt's DOM classes use their own system for - dynamically allocating memory for DOM nodes, we cannot guarantee that the QDomNode - objects returned for a given piece of information will be the same for subsequent - accesses to the document. - - We use item wrappers for each QDomNode to provide consistent pointers that the model - can use to navigate the document structure. - \omit - Since these items contain value references to the QDomNode objects themselves, this - has the side effect that the DOM nodes themselves can be used to reliably navigate - the document [not sure about this - QDom* may return different QDomNode objects for - the same piece of information]. However, this advantage is redundant since we need to - use wrapper items to obtain it. [Possible use of QDomNode cache in the model itself.] - \endomit -*/ diff --git a/examples/widgets/doc/src/simpletreemodel.qdoc b/examples/widgets/doc/src/simpletreemodel.qdoc index 5892d052..9d8cc223 100644 --- a/examples/widgets/doc/src/simpletreemodel.qdoc +++ b/examples/widgets/doc/src/simpletreemodel.qdoc @@ -4,6 +4,7 @@ /*! \example itemviews/simpletreemodel \title Simple Tree Model Example + \examplecategory {User Interface Components} \ingroup examples-itemviews \ingroup examples-layout \brief The Simple Tree Model example shows how to use a hierarchical model diff --git a/examples/widgets/doc/src/simplewidgetmapper.qdoc b/examples/widgets/doc/src/simplewidgetmapper.qdoc deleted file mode 100644 index 508f9d20..00000000 --- a/examples/widgets/doc/src/simplewidgetmapper.qdoc +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example itemviews/simplewidgetmapper - \title Simple Widget Mapper Example - \ingroup examples-itemviews - \brief The Simple Widget Mapper example shows how to use a widget mapper to display - data from a model in a collection of widgets. - - \image simplewidgetmapper-example.png - - The QDataWidgetMapper class allows information obtained from a - \l{Model Classes}{model} to be viewed and edited in a collection of - widgets instead of in an \l{View Classes}{item view}. - Any model derived from QAbstractItemModel can be used as the source of - data and almost any input widget can be used to display it. - - The example itself is very simple: we create \c Window, a QWidget subclass - that we use to hold the widgets used to present the data, and show it. The - \c Window class will provide buttons that the user can click to show - different records from the model. - - \section1 Window Class Definition - - The class provides a constructor, a slot to keep the buttons up to date, - and a private function to set up the model: - - \snippet itemviews/simplewidgetmapper/window.h Window definition - - In addition to the QDataWidgetMapper object and the controls used to make - up the user interface, we use a QStandardItemModel to hold our data. - We could use a custom model, but this standard implementation is sufficient - for our purposes. - - \section1 Window Class Implementation - - The constructor of the \c Window class can be explained in three parts. - In the first part, we set up the widgets used for the user interface: - - \snippet itemviews/simplewidgetmapper/window.cpp Set up widgets - - We also set up the buddy relationships between various labels and the - corresponding input widgets. - - Next, we set up the widget mapper, relating each input widget to a column - in the model specified by the call to \l{QDataWidgetMapper::}{setModel()}: - - \snippet itemviews/simplewidgetmapper/window.cpp Set up the mapper - - We also connect the mapper to the \uicontrol{Next} and \uicontrol{Previous} buttons - via its \l{QDataWidgetMapper::}{toNext()} and - \l{QDataWidgetMapper::}{toPrevious()} slots. The mapper's - \l{QDataWidgetMapper::}{currentIndexChanged()} signal is connected to the - \c{updateButtons()} slot in the window which we'll show later. - - In the final part of the constructor, we set up the layout, placing each - of the widgets in a grid (we could also use a QFormLayout for this): - - \snippet itemviews/simplewidgetmapper/window.cpp Set up the layout - - Lastly, we set the window title and initialize the mapper by setting it to - refer to the first row in the model. - - The model is initialized in the window's \c{setupModel()} function. Here, - we create a standard model with 5 rows and 3 columns, and we insert some - sample names, addresses and ages into each row: - - \snippet itemviews/simplewidgetmapper/window.cpp Set up the model - - As a result, each row can be treated like a record in a database, and the - widget mapper will read the data from each row, using the column numbers - specified earlier to access the correct data for each widget. This is - shown in the following diagram: - - \image widgetmapper-simple-mapping.png - - Since the user can navigate using the buttons in the user interface, the - example is fully-functional at this point, but to make it a bit more - user-friendly, we implement the \c{updateButtons()} slot to show when the - user is viewing the first or last records: - - \snippet itemviews/simplewidgetmapper/window.cpp Slot for updating the buttons - - If the mapper is referring to the first row in the model, the \uicontrol{Previous} - button is disabled. Similarly, the \uicontrol{Next} button is disabled if the - mapper reaches the last row in the model. - - \section1 More Complex Mappings - - The QDataWidgetMapper class makes it easy to relate information from a - model to widgets in a user interface. However, it is sometimes necessary - to use input widgets which offer choices to the user, such as QComboBox, - in conjunction with a widget mapper. - - In these situations, although the mapping to input widgets remains simple, - more work needs to be done to expose additional data to the widget mapper. - This is covered by the \l{Combo Widget Mapper Example}{Combo Widget Mapper} - and \l{SQL Widget Mapper Example}{SQL Widget Mapper} - examples. -*/ diff --git a/examples/widgets/doc/src/sliders.qdoc b/examples/widgets/doc/src/sliders.qdoc index 26bfd441..871adf00 100644 --- a/examples/widgets/doc/src/sliders.qdoc +++ b/examples/widgets/doc/src/sliders.qdoc @@ -4,6 +4,7 @@ /*! \example widgets/sliders \title Sliders Example + \examplecategory {User Interface Components} \ingroup examples-widgets \brief The Sliders example shows how to use the different types of sliders available in Qt: QSlider, QScrollBar and QDial. diff --git a/examples/widgets/doc/src/spinboxdelegate.qdoc b/examples/widgets/doc/src/spinboxdelegate.qdoc index 025c5021..bd3b68aa 100644 --- a/examples/widgets/doc/src/spinboxdelegate.qdoc +++ b/examples/widgets/doc/src/spinboxdelegate.qdoc @@ -4,6 +4,7 @@ /*! \example itemviews/spinboxdelegate \title Spin Box Delegate Example + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief The Spin Box Delegate example shows how to create an editor for a custom delegate in the model/view framework by reusing a standard Qt editor widget. diff --git a/examples/widgets/doc/src/spinboxes.qdoc b/examples/widgets/doc/src/spinboxes.qdoc index 263fee91..eb42696c 100644 --- a/examples/widgets/doc/src/spinboxes.qdoc +++ b/examples/widgets/doc/src/spinboxes.qdoc @@ -4,6 +4,7 @@ /*! \example widgets/spinboxes \title Spin Boxes Example + \examplecategory {User Interface Components} \ingroup examples-widgets \brief The Spin Boxes example shows how to use the many different types of spin boxes available in Qt, from a simple QSpinBox widget to more complex diff --git a/examples/widgets/doc/src/spreadsheet.qdoc b/examples/widgets/doc/src/spreadsheet.qdoc index 9d7c89d6..02d5e0a9 100644 --- a/examples/widgets/doc/src/spreadsheet.qdoc +++ b/examples/widgets/doc/src/spreadsheet.qdoc @@ -4,6 +4,7 @@ /*! \example itemviews/spreadsheet \title Spreadsheet + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief The Spreadsheet example shows how to create a simple spreadsheet application. diff --git a/examples/widgets/doc/src/standarddialogs.qdoc b/examples/widgets/doc/src/standarddialogs.qdoc index 6770c918..396f1d10 100644 --- a/examples/widgets/doc/src/standarddialogs.qdoc +++ b/examples/widgets/doc/src/standarddialogs.qdoc @@ -4,6 +4,7 @@ /*! \example dialogs/standarddialogs \title Standard Dialogs Example + \examplecategory {User Interface Components} \ingroup examples-dialogs \brief The Standard Dialogs example shows the standard dialogs that are provided by Qt. diff --git a/examples/widgets/doc/src/stardelegate.qdoc b/examples/widgets/doc/src/stardelegate.qdoc index 5d45577c..44d75e64 100644 --- a/examples/widgets/doc/src/stardelegate.qdoc +++ b/examples/widgets/doc/src/stardelegate.qdoc @@ -4,6 +4,7 @@ /*! \example itemviews/stardelegate \title Star Delegate Example + \examplecategory {User Interface Components} \ingroup examples-itemviews \brief The Star Delegate example shows how to create a delegate that can paint itself and that supports editing. diff --git a/examples/widgets/doc/src/styleplugin.qdoc b/examples/widgets/doc/src/styleplugin.qdoc index d7a1faf2..a866d096 100644 --- a/examples/widgets/doc/src/styleplugin.qdoc +++ b/examples/widgets/doc/src/styleplugin.qdoc @@ -4,6 +4,7 @@ /*! \example tools/styleplugin \title Style Plugin Example + \examplecategory {User Interface Components} \ingroup examples-widgets-tools \brief This example shows how to create a plugin that extends Qt with a new @@ -133,7 +134,4 @@ In the \l{Echo Plugin Example}{echo plugin example} we show how to implement plugins that extends Qt applications rather than Qt itself, which is the case with the style plugin of this example. - The \l{Plug & Paint Example}{plug & paint} example shows how to - implement a static plugin as well as being a more involved example - on plugins that extend applications. */ diff --git a/examples/widgets/doc/src/styles.qdoc b/examples/widgets/doc/src/styles.qdoc deleted file mode 100644 index 53934c40..00000000 --- a/examples/widgets/doc/src/styles.qdoc +++ /dev/null @@ -1,448 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example widgets/styles - \title Styles Example - \ingroup examples-widgets - \brief The Styles example illustrates how to create custom widget - drawing styles using Qt, and demonstrates Qt's predefined styles. - - \borderedimage styles-enabledwood.png - \caption Screenshot of the Styles example - - A style in Qt is a subclass of QStyle or of one of its - subclasses. Styles perform drawing on behalf of widgets. Qt - provides a whole range of predefined styles, either built into - the Qt Widgets module or found in plugins. Styles are usually - customized by subclassing QProxyStyle and reimplementing a few - virtual functions. While QProxyStyle provides a transparent way - to customize either a specific style or the appropriate platform's - default style, Qt also provides QCommonStyle as a convenient base - for full custom style implementations. - - In this example, the custom style is called \c NorwegianWoodStyle - and derives from QProxyStyle. Its main features are the wooden - textures used for filling most of the widgets and its round - buttons and comboboxes. - - To implement the style, we use some advanced features provided by - QPainter, such as \l{QPainter::Antialiasing}{antialiasing} (to - obtain smoother button edges), \l{QColor::alpha()}{alpha blending} - (to make the buttons appeared raised or sunken), and - \l{QPainterPath}{painter paths} (to fill the buttons and draw the - outline). We also use many features of QBrush and QPalette. - - The example consists of the following classes: - - \list - \li \c NorwegianWoodStyle inherits from QProxyStyle and implements - the Norwegian Wood style. - \li \c WidgetGallery is a \c QDialog subclass that shows the most - common widgets and allows the user to switch style - dynamically. - \endlist - - \section1 NorwegianWoodStyle Class Definition - - Here's the definition of the \c NorwegianWoodStyle class: - - \snippet widgets/styles/norwegianwoodstyle.h 0 - - The public functions are all declared in QStyle (QProxyStyle's - grandparent class) and reimplemented here to override the Windows - look and feel. The private functions are helper functions. - - \section1 NorwegianWoodStyle Class Implementation - - We will now review the implementation of the \c - NorwegianWoodStyle class. - - \snippet widgets/styles/norwegianwoodstyle.cpp 0 - - The \c standardPalette() function is reimplemented from QStyle. - It returns a QPalette with the style's preferred colors and textures. - Most styles don't need to reimplement that function. The - Norwegian Wood style reimplements it to set a "wooden" palette. - - We start by defining a few \l{QColor}s that we'll need. Then we - load two PNG images. The \c : prefix in the file path indicates - that the PNG files are \l{The Qt Resource System}{embedded - resources}. - - \table - \row \li \inlineimage widgets/styles/images/woodbackground.png - - \li \b{woodbackground.png} - - This texture is used as the background of most widgets. - The wood pattern is horizontal. - - \row \li \inlineimage widgets/styles/images/woodbutton.png - - \li \b{woodbutton.png} - - This texture is used for filling push buttons and - comboboxes. The wood pattern is vertical and more reddish - than the texture used for the background. - \endtable - - The \c midImage variable is initialized to be the same as \c - buttonImage, but then we use a QPainter and fill it with a 25% - opaque black color (a black with an \l{QColor::alpha()}{alpha - channel} of 63). The result is a somewhat darker image than \c - buttonImage. This image will be used for filling buttons that the - user is holding down. - - \snippet widgets/styles/norwegianwoodstyle.cpp 1 - - We initialize the palette. Palettes have various - \l{QPalette::ColorRole}{color roles}, such as QPalette::Base - (used for filling text editors, item views, etc.), QPalette::Text - (used for foreground text), and QPalette::Window (used for - the background of most widgets). Each role has its own QBrush, - which usually is a plain color but can also be a brush pattern or - even a texture (a QPixmap). - - In addition to the roles, palettes have several - \l{QPalette::ColorGroup}{color groups}: active, disabled, and - inactive. The active color group is used for painting widgets in - the active window. The disabled group is used for disabled - widgets. The inactive group is used for all other widgets. Most - palettes have identical active and inactive groups, while the - disabled group uses darker shades. - - We initialize the QPalette object with a brown color. Qt - automatically derivates all color roles for all color groups from - that single color. We then override some of the default values. For - example, we use Qt::darkGreen instead of the default - (Qt::darkBlue) for the QPalette::Highlight role. The - QPalette::setBrush() overload that we use here sets the same - color or brush for all three color groups. - - The \c setTexture() function is a private function that sets the - texture for a certain color role, while preserving the existing - color in the QBrush. A QBrush can hold both a solid color and a - texture at the same time. The solid color is used for drawing - text and other graphical elements where textures don't look good. - - At the end, we set the brush for the disabled color group of the - palette. We use \c woodbackground.png as the texture for all - disabled widgets, including buttons, and use a darker color to - accompany the texture. - - \image styles-disabledwood.png The Norwegian Wood style with disabled widgets - - Let's move on to the other functions reimplemented from - QProxyStyle: - - \snippet widgets/styles/norwegianwoodstyle.cpp 3 - \snippet widgets/styles/norwegianwoodstyle.cpp 4 - - This QStyle::polish() overload is called once on every widget - drawn using the style. We reimplement it to set the Qt::WA_Hover - attribute on \l{QPushButton}s and \l{QComboBox}es. When this - attribute is set, Qt generates paint events when the mouse - pointer enters or leaves the widget. This makes it possible to - render push buttons and comboboxes differently when the mouse - pointer is over them. - - \snippet widgets/styles/norwegianwoodstyle.cpp 5 - \snippet widgets/styles/norwegianwoodstyle.cpp 6 - - This QStyle::unpolish() overload is called to undo any - modification done to the widget in \c polish(). For simplicity, - we assume that the flag wasn't set before \c polish() was called. - In an ideal world, we would remember the original state for each - widgets (e.g., using a QMap) and restore it in - \c unpolish(). - - \snippet widgets/styles/norwegianwoodstyle.cpp 7 - \snippet widgets/styles/norwegianwoodstyle.cpp 8 - - The \l{QStyle::pixelMetric()}{pixelMetric()} function returns the - size in pixels for a certain user interface element. By - reimplementing this function, we can affect the way certain - widgets are drawn and their size hint. Here, we return 8 as the - width around a shown in a QComboBox, ensuring that there is - enough place around the text and the arrow for the Norwegian Wood - round corners. The default value for this setting in the Windows - style is 2. - - We also change the extent of \l{QScrollBar}s, i.e., the height - for a horizontal scroll bar and the width for a vertical scroll - bar, to be 4 pixels more than in the Windows style. This makes the - style a bit more distinctive. - - For all other QStyle::PixelMetric elements, we use the Windows - settings. - - \snippet widgets/styles/norwegianwoodstyle.cpp 9 - \snippet widgets/styles/norwegianwoodstyle.cpp 10 - - The \l{QStyle::styleHint()}{styleHint()} function returns some - hints to widgets or to the base style (in our case QProxyStyle) - about how to draw the widgets. The Windows style returns \c true - for the QStyle::SH_DitherDisabledText hint, resulting in a most - unpleasing visual effect. We override this behavior and return \c - false instead. We also return \c true for the - QStyle::SH_EtchDisabledText hint, meaning that disabled text is - rendered with an embossed look. - - \snippet widgets/styles/norwegianwoodstyle.cpp 11 - \snippet widgets/styles/norwegianwoodstyle.cpp 12 - - The \l{QStyle::drawPrimitive()}{drawPrimitive()} function is - called by Qt widgets to draw various fundamental graphical - elements. Here we reimplement it to draw QPushButton and - QComboBox with round corners. The button part of these widgets is - drawn using the QStyle::PE_PanelButtonCommand primitive element. - - The \c option parameter, of type QStyleOption, contains - everything we need to know about the widget we want to draw on. - In particular, \c option->rect gives the rectangle within which - to draw the primitive element. The \c painter parameter is a - QPainter object that we can use to draw on the widget. - - The \c widget parameter is the widget itself. Normally, all the - information we need is available in \c option and \c painter, so - we don't need \c widget. We can use it to perform special - effects; for example, QMacStyle uses it to animate default - buttons. If you use it, be aware that the caller is allowed to - pass a null pointer. - - We start by defining three \l{QColor}s that we'll need later on. - We also put the x, y, width, and height components of the - widget's rectangle in local variables. The value used for the \c - semiTransparentWhite and for the \c semiTransparentBlack color's - alpha channel depends on whether the mouse cursor is over the - widget or not. Since we set the Qt::WA_Hover attribute on - \l{QPushButton}s and \l{QComboBox}es, we can rely on the - QStyle::State_MouseOver flag to be set when the mouse is over the - widget. - - \snippet widgets/styles/norwegianwoodstyle.cpp 13 - \snippet widgets/styles/norwegianwoodstyle.cpp 14 - - The \c roundRect variable is a QPainterPath. A QPainterPath is is - a vectorial specification of a shape. Any shape (rectangle, - ellipse, spline, etc.) or combination of shapes can be expressed - as a path. We will use \c roundRect both for filling the button - background with a wooden texture and for drawing the outline. The - \c roundRectPath() function is a private function; we will come - back to it later. - - \snippet widgets/styles/norwegianwoodstyle.cpp 15 - \snippet widgets/styles/norwegianwoodstyle.cpp 16 - \snippet widgets/styles/norwegianwoodstyle.cpp 17 - \snippet widgets/styles/norwegianwoodstyle.cpp 18 - - We define two variables, \c brush and \c darker, and initialize - them based on the state of the button: - - \list - \li If the button is a \l{QPushButton::flat}{flat button}, we use - the \l{QPalette::Window}{Window} brush. We set \c - darker to \c true if the button is - \l{QAbstractButton::down}{down} or - \l{QAbstractButton::checked}{checked}. - \li If the button is currently held down by the user or in the - \l{QAbstractButton::checked}{checked} state, we use the - \l{QPalette::Mid}{Mid} component of the palette. We set - \c darker to \c true if the button is - \l{QAbstractButton::checked}{checked}. - \li Otherwise, we use the \l{QPalette::Button}{Button} component - of the palette. - \endlist - - The screenshot below illustrates how \l{QPushButton}s are - rendered based on their state: - - \image styles-woodbuttons.png Norwegian Wood buttons in different states - - To discover whether the button is flat or not, we need to cast - the \c option parameter to QStyleOptionButton and check if the - \l{QStyleOptionButton::features}{features} member specifies the - QStyleOptionButton::Flat flag. The qstyleoption_cast() function - performs a dynamic cast; if \c option is not a - QStyleOptionButton, qstyleoption_cast() returns a null pointer. - - \snippet widgets/styles/norwegianwoodstyle.cpp 19 - \snippet widgets/styles/norwegianwoodstyle.cpp 20 - \snippet widgets/styles/norwegianwoodstyle.cpp 21 - \snippet widgets/styles/norwegianwoodstyle.cpp 22 - \snippet widgets/styles/norwegianwoodstyle.cpp 23 - - We turn on antialiasing on QPainter. Antialiasing is a technique - that reduces the visual distortion that occurs when the edges of - a shape are converted into pixels. For the Norwegian Wood style, - we use it to obtain smoother edges for the round buttons. - - \image styles-aliasing.png Norwegian wood buttons with and without antialiasing - - The first call to QPainter::fillPath() draws the background of - the button with a wooden texture. The second call to - \l{QPainter::fillPath()}{fillPath()} paints the same area with a - semi-transparent black color (a black color with an alpha channel - of 63) to make the area darker if \c darker is true. - - \snippet widgets/styles/norwegianwoodstyle.cpp 24 - \snippet widgets/styles/norwegianwoodstyle.cpp 25 - - Next, we draw the outline. The top-left half of the outline and - the bottom-right half of the outline are drawn using different - \l{QPen}s to produce a 3D effect. Normally, the top-left half of - the outline is drawn lighter whereas the bottom-right half is - drawn darker, but if the button is - \l{QAbstractButton::down}{down} or - \l{QAbstractButton::checked}{checked}, we invert the two - \l{QPen}s to give a sunken look to the button. - - \snippet widgets/styles/norwegianwoodstyle.cpp 26 - - We draw the top-left part of the outline by calling - QPainter::drawPath() with an appropriate - \l{QPainter::setClipRegion()}{clip region}. If the - \l{QStyleOption::direction}{layout direction} is right-to-left - instead of left-to-right, we swap the \c x1, \c x2, \c x3, and \c - x4 variables to obtain correct results. On right-to-left desktop, - the "light" comes from the top-right corner of the screen instead - of the top-left corner; raised and sunken widgets must be drawn - accordingly. - - The diagram below illustrates how 3D effects are drawn according - to the layout direction. The area in red on the diagram - corresponds to the \c topHalf polygon: - - \image styles-3d.png - - An easy way to test how a style looks in right-to-left mode is to - pass the \c -reverse command-line option to the application. This - option is recognized by the QApplication constructor. - - \snippet widgets/styles/norwegianwoodstyle.cpp 32 - \snippet widgets/styles/norwegianwoodstyle.cpp 33 - \snippet widgets/styles/norwegianwoodstyle.cpp 34 - - The bottom-right part of the outline is drawn in a similar - fashion. Then we draw a one-pixel wide outline around the entire - button, using the \l{QPalette::WindowText}{WindowText} component - of the QPalette. - - This completes the QStyle::PE_PanelButtonCommand case of the \c - switch statement. Other primitive elements are handled by the - base style. Let's now turn to the other \c NorwegianWoodStyle - member functions: - - \snippet widgets/styles/norwegianwoodstyle.cpp 35 - \snippet widgets/styles/norwegianwoodstyle.cpp 36 - - We reimplement QStyle::drawControl() to draw the text on a - QPushButton in a bright color when the button is - \l{QAbstractButton::down}{down} or - \l{QAbstractButton::checked}{checked}. - - If the \c option parameter points to a QStyleOptionButton object - (it normally should), we take a copy of the object and modify its - \l{QStyleOption::palette}{palette} member to make the - QPalette::ButtonText be the same as the QPalette::BrightText - component (unless the widget is disabled). - - \snippet widgets/styles/norwegianwoodstyle.cpp 37 - \snippet widgets/styles/norwegianwoodstyle.cpp 38 - - The \c setTexture() function is a private function that sets the - \l{QBrush::texture()}{texture} component of the \l{QBrush}es for - a certain \l{QPalette::ColorRole}{color role}, for all three - \l{QPalette::ColorGroup}{color groups} (active, disabled, - inactive). We used it to initialize the Norwegian Wood palette in - \c standardPalette. - - \snippet widgets/styles/norwegianwoodstyle.cpp 39 - \snippet widgets/styles/norwegianwoodstyle.cpp 40 - - The \c roundRectPath() function is a private function that - constructs a QPainterPath object for round buttons. The path - consists of eight segments: four arc segments for the corners and - four lines for the sides. - - With around 250 lines of code, we have a fully functional custom - style based on one of the predefined styles. Custom styles can be - used to provide a distinct look to an application or family of - applications. - - \section1 WidgetGallery Class - - For completeness, we will quickly review the \c WidgetGallery - class, which contains the most common Qt widgets and allows the - user to change style dynamically. Here's the class definition: - - \snippet widgets/styles/widgetgallery.h 0 - \dots - \snippet widgets/styles/widgetgallery.h 1 - - Here's the \c WidgetGallery constructor: - - \snippet widgets/styles/widgetgallery.cpp 0 - - We start by creating child widgets. The \uicontrol Style combobox is - initialized with all the styles known to QStyleFactory, in - addition to \c NorwegianWood. The \c create...() functions are - private functions that set up the various parts of the \c - WidgetGallery. - - \snippet widgets/styles/widgetgallery.cpp 1 - \snippet widgets/styles/widgetgallery.cpp 2 - - We connect the \uicontrol Style combobox to the \c changeStyle() - private slot, the \uicontrol{Use style's standard palette} check box to - the \c changePalette() slot, and the \uicontrol{Disable widgets} check - box to the child widgets' - \l{QWidget::setDisabled()}{setDisabled()} slot. - - \snippet widgets/styles/widgetgallery.cpp 3 - \snippet widgets/styles/widgetgallery.cpp 4 - - Finally, we put the child widgets in layouts. - - \snippet widgets/styles/widgetgallery.cpp 5 - \snippet widgets/styles/widgetgallery.cpp 6 - - When the user changes the style in the combobox, we call - QApplication::setStyle() to dynamically change the style of the - application. - - \snippet widgets/styles/widgetgallery.cpp 7 - \snippet widgets/styles/widgetgallery.cpp 8 - - If the user turns the \uicontrol{Use style's standard palette} on, the - current style's \l{QStyle::standardPalette()}{standard palette} - is used; otherwise, the system's default palette is honored. - - \snippet widgets/styles/widgetgallery.cpp 9 - \snippet widgets/styles/widgetgallery.cpp 10 - - The \c advanceProgressBar() slot is called at regular intervals - to advance the progress bar. Since we don't know how long the - user will keep the Styles application running, we use a - logarithmic formula: The closer the progress bar gets to 100%, - the slower it advances. - - We will review \c createProgressBar() in a moment. - - \snippet widgets/styles/widgetgallery.cpp 11 - \snippet widgets/styles/widgetgallery.cpp 12 - - The \c createTopLeftGroupBox() function creates the QGroupBox - that occupies the top-left corner of the \c WidgetGallery. We - skip the \c createTopRightGroupBox(), \c - createBottomLeftTabWidget(), and \c createBottomRightGroupBox() - functions, which are very similar. - - \snippet widgets/styles/widgetgallery.cpp 13 - - In \c createProgressBar(), we create a QProgressBar at the bottom - of the \c WidgetGallery and connect its - \l{QTimer::timeout()}{timeout()} signal to the \c - advanceProgressBar() slot. -*/ diff --git a/examples/widgets/doc/src/stylesheet.qdoc b/examples/widgets/doc/src/stylesheet.qdoc deleted file mode 100644 index b85ccdb0..00000000 --- a/examples/widgets/doc/src/stylesheet.qdoc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example widgets/stylesheet - \title Style Sheet Example - \ingroup examples-widgets - \brief The Style Sheet Example shows how to use style sheets. - - \borderedimage stylesheet-pagefold.png - \caption Screen Shot of the Pagefold style sheet - - The Style Sheet example shows how widgets can be styled using Qt Style Sheets. - You can open the style editor by selecting \uicontrol File > \uicontrol Edit Style Sheet, - to select an existing style sheet or design your own style and load it. - - The Style Sheet example consists of 2 classes: - \list - \li \c MainWindow - \li \c StyleSheetEditor - \endlist - - - \section1 MainWindow Class - - \c MainWindow inherits QWidget, and is the application's main window defined in - \c mainwindow.ui. The style of \c MainWindow can be modified with \c StyleSheetEditor. - - - \section1 StyleSheetEditor Class - - \c StyleSheetEditor enables you to open an editor where you can load an existing style sheet. - It is also possible to define a new stylesheet and load it. Its layout is defined in - \c stylesheeteditor.ui. - - \quotefromfile widgets/stylesheet/stylesheeteditor.cpp - \skipto setStyleName - \printline setStyleName - - Sets the specified \a styleName and grays the \c applyButton. - - \skipto setStyleSheetName - \printline setStyleSheetName - - Loads the stylesheet from \c styleSheetName. - - \skipto setModified() - \printline setModified() - - Enables the \c applyButton when the text in the buffer has changed. - - \skipto apply() - \printline apply() - - Sets the stylesheet properties in \l qApp and disables the \c applyButton. - - \skipto loadStyleSheet(const QString &sheetName) - \printline loadStyleSheet(const QString &sheetName) - - Loads the specified \a sheetName, and sets its properties in - \l qApp. - -*/ - diff --git a/examples/widgets/doc/src/syntaxhighlighter.qdoc b/examples/widgets/doc/src/syntaxhighlighter.qdoc index bdd13abd..17bcc1fa 100644 --- a/examples/widgets/doc/src/syntaxhighlighter.qdoc +++ b/examples/widgets/doc/src/syntaxhighlighter.qdoc @@ -4,6 +4,7 @@ /*! \example richtext/syntaxhighlighter \title Syntax Highlighter Example + \examplecategory {User Interface Components} \ingroup examples-richtext \brief The Syntax Highlighter example shows how to perform simple syntax highlighting. diff --git a/examples/widgets/doc/src/tabdialog.qdoc b/examples/widgets/doc/src/tabdialog.qdoc index f3887c94..fb45bbae 100644 --- a/examples/widgets/doc/src/tabdialog.qdoc +++ b/examples/widgets/doc/src/tabdialog.qdoc @@ -4,6 +4,7 @@ /*! \example dialogs/tabdialog \title Tab Dialog Example + \examplecategory {User Interface Components} \ingroup examples-dialogs \brief The Tab Dialog example shows how to construct a tab dialog using the diff --git a/examples/widgets/doc/src/tablet.qdoc b/examples/widgets/doc/src/tablet.qdoc index efbb769e..9d49d8de 100644 --- a/examples/widgets/doc/src/tablet.qdoc +++ b/examples/widgets/doc/src/tablet.qdoc @@ -4,6 +4,7 @@ /*! \example widgets/tablet \title Tablet Example + \examplecategory {User Interface Components} \ingroup examples-widgets \brief This example shows how to use a Wacom tablet in Qt applications. @@ -13,7 +14,7 @@ generated. You need to reimplement the \l{QWidget::}{tabletEvent()} event handler if you want to handle tablet events. Events are generated when the tool (stylus) used for drawing enters and leaves the proximity of the - tablet (i.e., when it is close but not pressed down on it), when the tool + tablet (i.e., when it is closed but not pressed down on it), when the tool is pressed down and released from it, when the tool is moved across the tablet, and when one of the buttons on the tool is pressed or released. @@ -31,7 +32,7 @@ draw on the tablet as you use a pencil on paper. When you draw with the airbrush you get a spray of virtual paint; the finger wheel is used to change the density of the spray. When you draw with the art pen, you get a - a line whose width and endpoint angle depend on the rotation of the pen. + line whose width and endpoint angle depend on the rotation of the pen. The pressure and tilt can also be assigned to change the alpha and saturation values of the color and the width of the stroke. @@ -88,8 +89,6 @@ in a submenu of the \b Tablet menu, for selecting which property of each QTabletEvent will be used to vary the translucency (alpha channel) of the line being drawn or color being airbrushed. - (See the \l{Qt Widgets - Application Example}{application example} if you want - a high-level introduction to QActions.) \snippet widgets/tablet/mainwindow.cpp 9 diff --git a/examples/widgets/doc/src/tetrix.qdoc b/examples/widgets/doc/src/tetrix.qdoc deleted file mode 100644 index 1f6ed760..00000000 --- a/examples/widgets/doc/src/tetrix.qdoc +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example widgets/tetrix - \title Tetrix Example - \ingroup examples-widgets - \brief The Tetrix example is a Qt version of the classic Tetrix game. - - \borderedimage tetrix-example.png - - The object of the game is to stack pieces dropped from the top of the - playing area so that they fill entire rows at the bottom of the playing area. - - When a row is filled, all the blocks on that row are removed, the player earns - a number of points, and the pieces above are moved down to occupy that row. - If more than one row is filled, the blocks on each row are removed, and the - player earns extra points. - - The \uicontrol{Left} cursor key moves the current piece one space to the left, the - \uicontrol{Right} cursor key moves it one space to the right, the \uicontrol{Up} cursor - key rotates the piece counter-clockwise by 90 degrees, and the \uicontrol{Down} - cursor key rotates the piece clockwise by 90 degrees. - - To avoid waiting for a piece to fall to the bottom of the board, press \uicontrol{D} - to immediately move the piece down by one row, or press the \uicontrol{Space} key to - drop it as close to the bottom of the board as possible. - - This example shows how a simple game can be created using only three classes: - - \list - \li The \c TetrixWindow class is used to display the player's score, number of - lives, and information about the next piece to appear. - \li The \c TetrixBoard class contains the game logic, handles keyboard input, and - displays the pieces on the playing area. - \li The \c TetrixPiece class contains information about each piece. - \endlist - - In this approach, the \c TetrixBoard class is the most complex class, since it - handles the game logic and rendering. One benefit of this is that the - \c TetrixWindow and \c TetrixPiece classes are very simple and contain only a - minimum of code. - - \section1 TetrixWindow Class Definition - - The \c TetrixWindow class is used to display the game information and contains - the playing area: - - \snippet widgets/tetrix/tetrixwindow.h 0 - - We use private member variables for the board, various display widgets, and - buttons to allow the user to start a new game, pause the current game, and quit. - - Although the window inherits QWidget, the constructor does not provide an - argument to allow a parent widget to be specified. This is because the window - will always be used as a top-level widget. - - \section1 TetrixWindow Class Implementation - - The constructor sets up the user interface elements for the game: - - \snippet widgets/tetrix/tetrixwindow.cpp 0 - - We begin by constructing a \c TetrixBoard instance for the playing area and a - label that shows the next piece to be dropped into the playing area; the label - is initially empty. - - Three QLCDNumber objects are used to display the score, number of lives, and - lines removed. These initially show default values, and will be filled in - when a game begins: - - \snippet widgets/tetrix/tetrixwindow.cpp 1 - - Three buttons with shortcuts are constructed so that the user can start a - new game, pause the current game, and quit the application: - - \snippet widgets/tetrix/tetrixwindow.cpp 2 - \snippet widgets/tetrix/tetrixwindow.cpp 3 - - These buttons are configured so that they never receive the keyboard focus; - we want the keyboard focus to remain with the \c TetrixBoard instance so that - it receives all the keyboard events. Nonetheless, the buttons will still respond - to \uicontrol{Alt} key shortcuts. - - We connect \l{QAbstractButton::}{clicked()} signals from the \uicontrol{Start} - and \uicontrol{Pause} buttons to the board, and from the \uicontrol{Quit} button to the - application's \l{QCoreApplication::quit()} slot. - - \snippet widgets/tetrix/tetrixwindow.cpp 4 - \snippet widgets/tetrix/tetrixwindow.cpp 5 - - Signals from the board are also connected to the LCD widgets for the purpose of - updating the score, number of lives, and lines removed from the playing area. - - We place the label, LCD widgets, and the board into a QGridLayout - along with some labels that we create with the \c createLabel() convenience - function: - - \snippet widgets/tetrix/tetrixwindow.cpp 6 - - Finally, we set the grid layout on the widget, give the window a title, and - resize it to an appropriate size. - - The \c createLabel() convenience function simply creates a new label on the - heap, gives it an appropriate alignment, and returns it to the caller: - - \snippet widgets/tetrix/tetrixwindow.cpp 7 - - Since each label will be used in the widget's layout, it will become a child - of the \c TetrixWindow widget and, as a result, it will be deleted when the - window is deleted. - - \section1 TetrixPiece Class Definition - - The \c TetrixPiece class holds information about a piece in the game's - playing area, including its shape, position, and the range of positions it can - occupy on the board: - - \snippet widgets/tetrix/tetrixpiece.h 0 - - Each shape contains four blocks, and these are defined by the \c coords private - member variable. Additionally, each piece has a high-level description that is - stored internally in the \c pieceShape variable. - - The constructor is written inline in the definition, and simply ensures that - each piece is initially created with no shape. The \c shape() function simply - returns the contents of the \c pieceShape variable, and the \c x() and \c y() - functions return the x and y-coordinates of any given block in the shape. - - \section1 TetrixPiece Class Implementation - - The \c setRandomShape() function is used to select a random shape for a piece: - - \snippet widgets/tetrix/tetrixpiece.cpp 0 - - For convenience, it simply chooses a random shape from the \c TetrixShape enum - and calls the \c setShape() function to perform the task of positioning the - blocks. - - The \c setShape() function uses a look-up table of pieces to associate each - shape with an array of block positions: - - \snippet widgets/tetrix/tetrixpiece.cpp 1 - \snippet widgets/tetrix/tetrixpiece.cpp 2 - - These positions are read from the table into the piece's own array of positions, - and the piece's internal shape information is updated to use the new shape. - - The \c x() and \c y() functions are implemented inline in the class definition, - returning positions defined on a grid that extends horizontally and vertically - with coordinates from -2 to 2. Although the predefined coordinates for each - piece only vary horizontally from -1 to 1 and vertically from -1 to 2, each - piece can be rotated by 90, 180, and 270 degrees. - - The \c minX() and \c maxX() functions return the minimum and maximum horizontal - coordinates occupied by the blocks that make up the piece: - - \snippet widgets/tetrix/tetrixpiece.cpp 3 - \snippet widgets/tetrix/tetrixpiece.cpp 4 - - Similarly, the \c minY() and \c maxY() functions return the minimum and maximum - vertical coordinates occupied by the blocks: - - \snippet widgets/tetrix/tetrixpiece.cpp 5 - \snippet widgets/tetrix/tetrixpiece.cpp 6 - - The \c rotatedLeft() function returns a new piece with the same shape as an - existing piece, but rotated counter-clockwise by 90 degrees: - - \snippet widgets/tetrix/tetrixpiece.cpp 7 - - Similarly, the \c rotatedRight() function returns a new piece with the same - shape as an existing piece, but rotated clockwise by 90 degrees: - - \snippet widgets/tetrix/tetrixpiece.cpp 9 - - These last two functions enable each piece to create rotated copies of itself. - - \section1 TetrixBoard Class Definition - - The \c TetrixBoard class inherits from QFrame and contains the game logic and display features: - - \snippet widgets/tetrix/tetrixboard.h 0 - - Apart from the \c setNextPieceLabel() function and the \c start() and \c pause() - public slots, we only provide public functions to reimplement QWidget::sizeHint() - and QWidget::minimumSizeHint(). The signals are used to communicate changes to - the player's information to the \c TetrixWindow instance. - - The rest of the functionality is provided by reimplementations of protected event - handlers and private functions: - - \snippet widgets/tetrix/tetrixboard.h 1 - - The board is composed of a fixed-size array whose elements correspond to - spaces for individual blocks. Each element in the array contains a \c TetrixShape - value corresponding to the type of shape that occupies that element. - - Each shape on the board will occupy four elements in the array, and these will - all contain the enum value that corresponds to the type of the shape. - - We use a QBasicTimer to control the rate at which pieces fall toward the bottom - of the playing area. This allows us to provide an implementation of - \l{QObject::}{timerEvent()} that we can use to update the widget. - - \section1 TetrixBoard Class Implementation - - In the constructor, we customize the frame style of the widget, ensure that - keyboard input will be received by the widget by using Qt::StrongFocus for the - focus policy, and initialize the game state: - - \snippet widgets/tetrix/tetrixboard.cpp 0 - - The first (next) piece is also set up with a random shape. - - The \c setNextPieceLabel() function is used to pass in an externally-constructed - label to the board, so that it can be shown alongside the playing area: - - \snippet widgets/tetrix/tetrixboard.cpp 1 - - We provide a reasonable size hint and minimum size hint for the board, based on - the size of the space for each block in the playing area: - - \snippet widgets/tetrix/tetrixboard.cpp 2 - \snippet widgets/tetrix/tetrixboard.cpp 3 - - By using a minimum size hint, we indicate to the layout in the parent widget - that the board should not shrink below a minimum size. - - A new game is started when the \c start() slot is called. This resets the - game's state, the player's score and level, and the contents of the board: - - \snippet widgets/tetrix/tetrixboard.cpp 4 - - We also emit signals to inform other components of these changes before creating - a new piece that is ready to be dropped into the playing area. We start the - timer that determines how often the piece drops down one row on the board. - - The \c pause() slot is used to temporarily stop the current game by stopping the - internal timer: - - \snippet widgets/tetrix/tetrixboard.cpp 5 - \snippet widgets/tetrix/tetrixboard.cpp 6 - - We perform checks to ensure that the game can only be paused if it is already - running and not already paused. - - The \c paintEvent() function is straightforward to implement. We begin by - calling the base class's implementation of \l{QWidget::}{paintEvent()} before - constructing a QPainter for use on the board: - - \snippet widgets/tetrix/tetrixboard.cpp 7 - - Since the board is a subclass of QFrame, we obtain a QRect that covers the area - \e inside the frame decoration before drawing our own content. - - If the game is paused, we want to hide the existing state of the board and - show some text. We achieve this by painting text onto the widget and returning - early from the function. The rest of the painting is performed after this point. - - The position of the top of the board is found by subtracting the total height - of each space on the board from the bottom of the frame's internal rectangle. - For each space on the board that is occupied by a piece, we call the - \c drawSquare() function to draw a block at that position. - - \snippet widgets/tetrix/tetrixboard.cpp 8 - \snippet widgets/tetrix/tetrixboard.cpp 9 - - Spaces that are not occupied by blocks are left blank. - - Unlike the existing pieces on the board, the current piece is drawn - block-by-block at its current position: - - \snippet widgets/tetrix/tetrixboard.cpp 10 - \snippet widgets/tetrix/tetrixboard.cpp 11 - \snippet widgets/tetrix/tetrixboard.cpp 12 - - The \c keyPressEvent() handler is called whenever the player presses a key while - the \c TetrixBoard widget has the keyboard focus. - - \snippet widgets/tetrix/tetrixboard.cpp 13 - - If there is no current game, the game is running but paused, or if there is no - current shape to control, we simply pass on the event to the base class. - - We check whether the event is about any of the keys that the player uses to - control the current piece and, if so, we call the relevant function to handle - the input: - - \snippet widgets/tetrix/tetrixboard.cpp 14 - - In the case where the player presses a key that we are not interested in, we - again pass on the event to the base class's implementation of - \l{QWidget::}{keyPressEvent()}. - - The \c timerEvent() handler is called every time the class's QBasicTimer - instance times out. We need to check that the event we receive corresponds to - our timer. If it does, we can update the board: - - \snippet widgets/tetrix/tetrixboard.cpp 15 - \snippet widgets/tetrix/tetrixboard.cpp 16 - \snippet widgets/tetrix/tetrixboard.cpp 17 - - If a row (or line) has just been filled, we create a new piece and reset the - timer; otherwise we move the current piece down by one row. We let the base - class handle other timer events that we receive. - - The \c clearBoard() function simply fills the board with the - \c TetrixShape::NoShape value: - - \snippet widgets/tetrix/tetrixboard.cpp 18 - - The \c dropDown() function moves the current piece down as far as possible on - the board, either until it is touching the bottom of the playing area or it is - stacked on top of another piece: - - \snippet widgets/tetrix/tetrixboard.cpp 19 - \snippet widgets/tetrix/tetrixboard.cpp 20 - - The number of rows the piece has dropped is recorded and passed to the - \c pieceDropped() function so that the player's score can be updated. - - The \c oneLineDown() function is used to move the current piece down by one row - (line), either when the user presses the \uicontrol{D} key or when the piece is - scheduled to move: - - \snippet widgets/tetrix/tetrixboard.cpp 21 - - If the piece cannot drop down by one line, we call the \c pieceDropped() function - with zero as the argument to indicate that it cannot fall any further, and that - the player should receive no extra points for the fall. - - The \c pieceDropped() function itself is responsible for awarding points to the - player for positioning the current piece, checking for full rows on the board - and, if no lines have been removed, creating a new piece to replace the current - one: - - \snippet widgets/tetrix/tetrixboard.cpp 22 - \snippet widgets/tetrix/tetrixboard.cpp 23 - - We call \c removeFullLines() each time a piece has been dropped. This scans - the board from bottom to top, looking for blank spaces on each row. - - \snippet widgets/tetrix/tetrixboard.cpp 24 - \snippet widgets/tetrix/tetrixboard.cpp 25 - \snippet widgets/tetrix/tetrixboard.cpp 26 - \snippet widgets/tetrix/tetrixboard.cpp 27 - - If a row contains no blank spaces, the rows above it are copied down by one row - to compress the stack of pieces, the top row on the board is cleared, and the - number of full lines found is incremented. - - \snippet widgets/tetrix/tetrixboard.cpp 28 - \snippet widgets/tetrix/tetrixboard.cpp 29 - - If some lines have been removed, the player's score and the total number of lines - removed are updated. The \c linesRemoved() and \c scoreChanged() signals are - emitted to send these new values to other widgets in the window. - - Additionally, we set the timer to elapse after half a second, set the - \c isWaitingAfterLine flag to indicate that lines have been removed, unset - the piece's shape to ensure that it is not drawn, and update the widget. - The next time that the \c timerEvent() handler is called, a new piece will be - created and the game will continue. - - The \c newPiece() function places the next available piece at the top of the - board, and creates a new piece with a random shape: - - \snippet widgets/tetrix/tetrixboard.cpp 30 - \snippet widgets/tetrix/tetrixboard.cpp 31 - - We place a new piece in the middle of the board at the top. The game is over if - the piece can't move, so we unset its shape to prevent it from being drawn, stop - the timer, and unset the \c isStarted flag. - - The \c showNextPiece() function updates the label that shows the next piece to - be dropped: - - \snippet widgets/tetrix/tetrixboard.cpp 32 - \snippet widgets/tetrix/tetrixboard.cpp 33 - - We draw the piece's component blocks onto a pixmap that is then set on the label. - - The \c tryMove() function is used to determine whether a piece can be positioned - at the specified coordinates: - - \snippet widgets/tetrix/tetrixboard.cpp 34 - - We examine the spaces on the board that the piece needs to occupy and, if they - are already occupied by other pieces, we return \c false to indicate that the - move has failed. - - \snippet widgets/tetrix/tetrixboard.cpp 35 - - If the piece could be placed on the board at the desired location, we update the - current piece and its position, update the widget, and return \c true to indicate - success. - - The \c drawSquare() function draws the blocks (normally squares) that make up - each piece using different colors for pieces with different shapes: - - \snippet widgets/tetrix/tetrixboard.cpp 36 - - We obtain the color to use from a look-up table that relates each shape to an - RGB value, and use the painter provided to draw the block at the specified - coordinates. -*/ diff --git a/examples/widgets/doc/src/textedit.qdoc b/examples/widgets/doc/src/textedit.qdoc deleted file mode 100644 index f41a58fe..00000000 --- a/examples/widgets/doc/src/textedit.qdoc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example richtext/textedit - \title Text Edit - \ingroup examples-richtext - \brief The Text Edit example shows Qt's rich text editing facilities - in action. - - \brief The Text Edit example shows Qt's rich text editing facilities in action, - providing an example document for you to experiment with. - - \image textedit-demo.png -*/ diff --git a/examples/widgets/doc/src/tooltips.qdoc b/examples/widgets/doc/src/tooltips.qdoc index 3af3768f..6dc0d2fb 100644 --- a/examples/widgets/doc/src/tooltips.qdoc +++ b/examples/widgets/doc/src/tooltips.qdoc @@ -4,6 +4,7 @@ /*! \example widgets/tooltips \title Tool Tips Example + \examplecategory {User Interface Components} \ingroup examples-widgets \brief The Tool Tips example shows how to provide static and dynamic tool tips for an application's widgets. diff --git a/examples/widgets/doc/src/transformations.qdoc b/examples/widgets/doc/src/transformations.qdoc index aabb672b..ab54bbcb 100644 --- a/examples/widgets/doc/src/transformations.qdoc +++ b/examples/widgets/doc/src/transformations.qdoc @@ -4,6 +4,7 @@ /*! \example painting/transformations \title Transformations Example + \examplecategory {Graphics & Multimedia} \ingroup examples-painting \brief The Transformations example shows how transformations influence the way that QPainter renders graphics primitives. diff --git a/examples/widgets/doc/src/treemodelcompleter.qdoc b/examples/widgets/doc/src/treemodelcompleter.qdoc index 9734c3bc..ae7c18f4 100644 --- a/examples/widgets/doc/src/treemodelcompleter.qdoc +++ b/examples/widgets/doc/src/treemodelcompleter.qdoc @@ -4,6 +4,7 @@ /*! \example tools/treemodelcompleter \title Tree Model Completer Example + \examplecategory {User Interface Components} \ingroup examples-widgets-tools \brief The Tree Model Completer example shows how to provide completion diff --git a/examples/widgets/doc/src/trivialwizard.qdoc b/examples/widgets/doc/src/trivialwizard.qdoc index f62e9174..75d007f3 100644 --- a/examples/widgets/doc/src/trivialwizard.qdoc +++ b/examples/widgets/doc/src/trivialwizard.qdoc @@ -4,6 +4,7 @@ /*! \example dialogs/trivialwizard \title Trivial Wizard Example + \examplecategory {User Interface Components} \ingroup examples-dialogs \brief The Trivial Wizard example illustrates how to create a linear three-page @@ -55,5 +56,5 @@ \snippet dialogs/trivialwizard/trivialwizard.cpp 10 - \sa QWizard, {Class Wizard Example}, {License Wizard Example} + \sa QWizard, {License Wizard Example} */ diff --git a/examples/widgets/doc/src/undoframework.qdoc b/examples/widgets/doc/src/undoframework.qdoc index 6ca2b4b1..e8d895b7 100644 --- a/examples/widgets/doc/src/undoframework.qdoc +++ b/examples/widgets/doc/src/undoframework.qdoc @@ -4,6 +4,7 @@ /*! \example tools/undoframework \title Undo Framework Example + \examplecategory {Data Processing & I/O} \ingroup examples-widgets-tools \brief This example shows how to implement undo/redo functionality diff --git a/examples/widgets/doc/src/validators.qdoc b/examples/widgets/doc/src/validators.qdoc deleted file mode 100644 index a0b88617..00000000 --- a/examples/widgets/doc/src/validators.qdoc +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \example widgets/validators - \title Validators Example - \brief The Validators example shows the signal emission behavior of input - validators. - - \borderedimage validators.png -*/ diff --git a/examples/widgets/doc/src/windowflags.qdoc b/examples/widgets/doc/src/windowflags.qdoc index d521894a..10b04967 100644 --- a/examples/widgets/doc/src/windowflags.qdoc +++ b/examples/widgets/doc/src/windowflags.qdoc @@ -4,6 +4,7 @@ /*! \example widgets/windowflags \title Window Flags Example + \examplecategory {User Interface Components} \ingroup examples-widgets \brief The Window Flags example shows how to use the window flags available in Qt. diff --git a/examples/widgets/draganddrop/CMakeLists.txt b/examples/widgets/draganddrop/CMakeLists.txt index c75600f6..ccd0ef54 100644 --- a/examples/widgets/draganddrop/CMakeLists.txt +++ b/examples/widgets/draganddrop/CMakeLists.txt @@ -4,5 +4,3 @@ qt_internal_add_example(draggableicons) qt_internal_add_example(draggabletext) qt_internal_add_example(dropsite) -qt_internal_add_example(fridgemagnets) -qt_internal_add_example(puzzle) diff --git a/examples/widgets/draganddrop/draganddrop.pro b/examples/widgets/draganddrop/draganddrop.pro index 1ecafd33..ad56f3f6 100644 --- a/examples/widgets/draganddrop/draganddrop.pro +++ b/examples/widgets/draganddrop/draganddrop.pro @@ -1,6 +1,4 @@ TEMPLATE = subdirs SUBDIRS = draggableicons \ draggabletext \ - dropsite \ - fridgemagnets \ - puzzle + dropsite diff --git a/examples/widgets/draganddrop/draggableicons/main.cpp b/examples/widgets/draganddrop/draggableicons/main.cpp index cd22e4e3..fe927085 100644 --- a/examples/widgets/draganddrop/draggableicons/main.cpp +++ b/examples/widgets/draganddrop/draggableicons/main.cpp @@ -8,8 +8,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(draggableicons); - QApplication app(argc, argv); QWidget mainWidget; diff --git a/examples/widgets/draganddrop/draggabletext/main.cpp b/examples/widgets/draganddrop/draggabletext/main.cpp index f6ab39ae..ebfd481e 100644 --- a/examples/widgets/draganddrop/draggabletext/main.cpp +++ b/examples/widgets/draganddrop/draggabletext/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(draggabletext); - QApplication app(argc, argv); DragWidget window; window.show(); diff --git a/examples/widgets/effects/CMakeLists.txt b/examples/widgets/effects/CMakeLists.txt deleted file mode 100644 index 8b1471d1..00000000 --- a/examples/widgets/effects/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -qt_internal_add_example(blurpicker) -qt_internal_add_example(fademessage) diff --git a/examples/widgets/effects/effects.pro b/examples/widgets/effects/effects.pro deleted file mode 100644 index 05911979..00000000 --- a/examples/widgets/effects/effects.pro +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE = \ - subdirs -SUBDIRS = \ - blurpicker \ - fademessage diff --git a/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc b/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc index 7722da68..878da3f8 100644 --- a/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc +++ b/examples/widgets/gestures/imagegestures/doc/src/imagegestures.qdoc @@ -4,6 +4,7 @@ /*! \example gestures/imagegestures \title Image Gestures Example + \examplecategory {User Interface Components} \brief Demonstrates the use of simple gestures in a widget. This example shows how to enable gestures for a widget and use gesture input diff --git a/examples/widgets/gestures/imagegestures/imagewidget.cpp b/examples/widgets/gestures/imagegestures/imagewidget.cpp index e17bf3c0..3ee72392 100644 --- a/examples/widgets/gestures/imagegestures/imagewidget.cpp +++ b/examples/widgets/gestures/imagegestures/imagewidget.cpp @@ -149,15 +149,23 @@ void ImageWidget::openDirectory(const QString &path) this->path = path; QDir dir(path); const QStringList nameFilters{"*.jpg", "*.png"}; - files = dir.entryList(nameFilters, QDir::Files|QDir::Readable, QDir::Name); + files = dir.entryInfoList(nameFilters, QDir::Files|QDir::Readable, QDir::Name); position = 0; goToImage(0); update(); } -QImage ImageWidget::loadImage(const QString &fileName) const +/* + With Android's content scheme paths, it might not be possible to simply + append a file name to the chosen directory path to be able to open the image, + because usually paths are returned by an Android file provider and handling those + paths manually is not guaranteed to work. For that reason, it's better to keep + around QFileInfo objects and use absoluteFilePath(). +*/ +QImage ImageWidget::loadImage(const QFileInfo &fileInfo) const { + const QString fileName = fileInfo.absoluteFilePath(); QImageReader reader(fileName); reader.setAutoTransform(true); qCDebug(lcExample) << "loading" << QDir::toNativeSeparators(fileName) << position << '/' << files.size(); @@ -187,7 +195,7 @@ void ImageWidget::goNextImage() prevImage = currentImage; currentImage = nextImage; if (position+1 < files.size()) - nextImage = loadImage(path + QLatin1Char('/') + files.at(position+1)); + nextImage = loadImage(files.at(position + 1)); else nextImage = QImage(); } @@ -204,7 +212,7 @@ void ImageWidget::goPrevImage() nextImage = currentImage; currentImage = prevImage; if (position > 0) - prevImage = loadImage(path + QLatin1Char('/') + files.at(position-1)); + prevImage = loadImage(files.at(position - 1)); else prevImage = QImage(); } @@ -234,12 +242,12 @@ void ImageWidget::goToImage(int index) position = index; if (index > 0) - prevImage = loadImage(path + QLatin1Char('/') + files.at(position-1)); + prevImage = loadImage(files.at(position - 1)); else prevImage = QImage(); - currentImage = loadImage(path + QLatin1Char('/') + files.at(position)); + currentImage = loadImage(files.at(position)); if (position+1 < files.size()) - nextImage = loadImage(path + QLatin1Char('/') + files.at(position+1)); + nextImage = loadImage(files.at(position + 1)); else nextImage = QImage(); update(); diff --git a/examples/widgets/gestures/imagegestures/imagewidget.h b/examples/widgets/gestures/imagegestures/imagewidget.h index 7e814244..b5bbc9ef 100644 --- a/examples/widgets/gestures/imagegestures/imagewidget.h +++ b/examples/widgets/gestures/imagegestures/imagewidget.h @@ -4,6 +4,7 @@ #ifndef IMAGEWIDGET_H #define IMAGEWIDGET_H +#include #include #include #include @@ -40,14 +41,14 @@ private: void swipeTriggered(QSwipeGesture*); //! [class definition begin] - QImage loadImage(const QString &fileName) const; + QImage loadImage(const QFileInfo &fileInfo) const; void loadImage(); void goNextImage(); void goPrevImage(); void goToImage(int index); QString path; - QStringList files; + QFileInfoList files; int position; QImage prevImage, nextImage; diff --git a/examples/widgets/graphicsview/CMakeLists.txt b/examples/widgets/graphicsview/CMakeLists.txt index e0d29131..4eddec0c 100644 --- a/examples/widgets/graphicsview/CMakeLists.txt +++ b/examples/widgets/graphicsview/CMakeLists.txt @@ -3,11 +3,9 @@ qt_internal_add_example(chip) qt_internal_add_example(elasticnodes) -qt_internal_add_example(embeddeddialogs) qt_internal_add_example(collidingmice) qt_internal_add_example(basicgraphicslayouts) qt_internal_add_example(diagramscene) -qt_internal_add_example(flowlayout) qt_internal_add_example(simpleanchorlayout) if(QT_FEATURE_cursor AND QT_FEATURE_draganddrop) qt_internal_add_example(dragdroprobot) diff --git a/examples/widgets/graphicsview/chip/main.cpp b/examples/widgets/graphicsview/chip/main.cpp index bf75db6a..4ccd66bb 100644 --- a/examples/widgets/graphicsview/chip/main.cpp +++ b/examples/widgets/graphicsview/chip/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(images); - QApplication app(argc, argv); app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); diff --git a/examples/widgets/graphicsview/diagramscene/main.cpp b/examples/widgets/graphicsview/diagramscene/main.cpp index 56310b17..699c33f0 100644 --- a/examples/widgets/graphicsview/diagramscene/main.cpp +++ b/examples/widgets/graphicsview/diagramscene/main.cpp @@ -7,8 +7,6 @@ int main(int argv, char *args[]) { - Q_INIT_RESOURCE(diagramscene); - QApplication app(argv, args); MainWindow mainWindow; mainWindow.setGeometry(100, 100, 800, 500); diff --git a/examples/widgets/graphicsview/graphicsview.pro b/examples/widgets/graphicsview/graphicsview.pro index b3e49050..d50f0b1a 100644 --- a/examples/widgets/graphicsview/graphicsview.pro +++ b/examples/widgets/graphicsview/graphicsview.pro @@ -2,12 +2,10 @@ TEMPLATE = subdirs SUBDIRS = \ chip \ elasticnodes \ - embeddeddialogs \ collidingmice \ basicgraphicslayouts \ diagramscene \ dragdroprobot \ - flowlayout \ simpleanchorlayout contains(DEFINES, QT_NO_CURSOR)|!qtConfig(draganddrop): SUBDIRS -= dragdroprobot diff --git a/examples/widgets/itemviews/CMakeLists.txt b/examples/widgets/itemviews/CMakeLists.txt index 96af14b5..9659dafa 100644 --- a/examples/widgets/itemviews/CMakeLists.txt +++ b/examples/widgets/itemviews/CMakeLists.txt @@ -3,26 +3,12 @@ qt_internal_add_example(addressbook) qt_internal_add_example(basicsortfiltermodel) -qt_internal_add_example(chart) qt_internal_add_example(coloreditorfactory) qt_internal_add_example(combowidgetmapper) qt_internal_add_example(customsortfiltermodel) -qt_internal_add_example(dirview) qt_internal_add_example(editabletreemodel) qt_internal_add_example(fetchmore) -qt_internal_add_example(flattreeview) qt_internal_add_example(frozencolumn) -qt_internal_add_example(interview) -qt_internal_add_example(pixelator) -qt_internal_add_example(simpletreemodel) -qt_internal_add_example(simplewidgetmapper) qt_internal_add_example(spinboxdelegate) qt_internal_add_example(spreadsheet) qt_internal_add_example(stardelegate) -qt_internal_add_example(storageview) -if(QT_FEATURE_draganddrop) - qt_internal_add_example(puzzle) -endif() -if(TARGET Qt6::Xml) - qt_internal_add_example(simpledommodel) -endif() diff --git a/examples/widgets/itemviews/editabletreemodel/main.cpp b/examples/widgets/itemviews/editabletreemodel/main.cpp index b7e7b3de..40a8fa10 100644 --- a/examples/widgets/itemviews/editabletreemodel/main.cpp +++ b/examples/widgets/itemviews/editabletreemodel/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(editabletreemodel); - QApplication app(argc, argv); MainWindow window; window.show(); diff --git a/examples/widgets/itemviews/flattreeview/CMakeLists.txt b/examples/widgets/itemviews/flattreeview/CMakeLists.txt deleted file mode 100644 index 2d987148..00000000 --- a/examples/widgets/itemviews/flattreeview/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(flattreeview LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/flattreeview") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(flattreeview - main.cpp -) - -set_target_properties(flattreeview PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(flattreeview PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS flattreeview - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/itemviews/flattreeview/flattreeview.pro b/examples/widgets/itemviews/flattreeview/flattreeview.pro deleted file mode 100644 index 05a6573d..00000000 --- a/examples/widgets/itemviews/flattreeview/flattreeview.pro +++ /dev/null @@ -1,7 +0,0 @@ -QT += widgets - -SOURCES = main.cpp - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/flattreeview -INSTALLS += target diff --git a/examples/widgets/itemviews/flattreeview/main.cpp b/examples/widgets/itemviews/flattreeview/main.cpp deleted file mode 100644 index f51e24da..00000000 --- a/examples/widgets/itemviews/flattreeview/main.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2017 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -/* - main.cpp - - A simple example that shows a multi-column list using QTreeView. - The data is not a tree, so the first column was made movable. -*/ - -#include -#include -#include -#include - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - QStandardItemModel model(4, 2); - QTreeView treeView; - treeView.setModel(&model); - treeView.setRootIsDecorated(false); - treeView.header()->setFirstSectionMovable(true); - treeView.header()->setStretchLastSection(true); - - for (int row = 0; row < 4; ++row) { - for (int column = 0; column < 2; ++column) { - QModelIndex index = model.index(row, column, QModelIndex()); - model.setData(index, QVariant((row + 1) * (column + 1))); - } - } - - treeView.setWindowTitle(QObject::tr("Flat Tree View")); - treeView.show(); - return app.exec(); -} diff --git a/examples/widgets/itemviews/frozencolumn/main.cpp b/examples/widgets/itemviews/frozencolumn/main.cpp index 901db76d..8cc4a1d7 100644 --- a/examples/widgets/itemviews/frozencolumn/main.cpp +++ b/examples/widgets/itemviews/frozencolumn/main.cpp @@ -10,8 +10,6 @@ int main(int argc, char* argv[]) { - Q_INIT_RESOURCE(grades); - QApplication app( argc, argv ); QStandardItemModel *model=new QStandardItemModel(); @@ -46,4 +44,3 @@ int main(int argc, char* argv[]) tableView->show(); return app.exec(); } - diff --git a/examples/widgets/itemviews/itemviews.pro b/examples/widgets/itemviews/itemviews.pro index b4a002c1..15ad2625 100644 --- a/examples/widgets/itemviews/itemviews.pro +++ b/examples/widgets/itemviews/itemviews.pro @@ -1,24 +1,13 @@ TEMPLATE = subdirs SUBDIRS = addressbook \ basicsortfiltermodel \ - chart \ coloreditorfactory \ combowidgetmapper \ customsortfiltermodel \ - dirview \ editabletreemodel \ fetchmore \ - flattreeview \ frozencolumn \ - interview \ - pixelator \ - puzzle \ - simpledommodel \ simpletreemodel \ - simplewidgetmapper \ spinboxdelegate \ spreadsheet \ - stardelegate \ - storageview -!qtConfig(draganddrop): SUBDIRS -= puzzle -!qtHaveModule(xml): SUBDIRS -= simpledommodel + stardelegate diff --git a/examples/widgets/itemviews/simpletreemodel/main.cpp b/examples/widgets/itemviews/simpletreemodel/main.cpp index 10075a18..ee8edb7c 100644 --- a/examples/widgets/itemviews/simpletreemodel/main.cpp +++ b/examples/widgets/itemviews/simpletreemodel/main.cpp @@ -9,8 +9,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(simpletreemodel); - QApplication app(argc, argv); QFile file(":/default.txt"); diff --git a/examples/widgets/itemviews/spreadsheet/main.cpp b/examples/widgets/itemviews/spreadsheet/main.cpp index 13bd0c93..3c2d676e 100644 --- a/examples/widgets/itemviews/spreadsheet/main.cpp +++ b/examples/widgets/itemviews/spreadsheet/main.cpp @@ -8,8 +8,6 @@ int main(int argc, char **argv) { - Q_INIT_RESOURCE(spreadsheet); - QApplication app(argc, argv); SpreadSheet sheet(10, 6); sheet.setWindowIcon(QPixmap(":/images/interview.png")); @@ -17,5 +15,3 @@ int main(int argc, char **argv) sheet.layout()->setSizeConstraint(QLayout::SetFixedSize); return app.exec(); } - - diff --git a/examples/widgets/layouts/CMakeLists.txt b/examples/widgets/layouts/CMakeLists.txt index 60299638..75355a07 100644 --- a/examples/widgets/layouts/CMakeLists.txt +++ b/examples/widgets/layouts/CMakeLists.txt @@ -2,6 +2,4 @@ # SPDX-License-Identifier: BSD-3-Clause qt_internal_add_example(basiclayouts) -qt_internal_add_example(borderlayout) -qt_internal_add_example(dynamiclayouts) qt_internal_add_example(flowlayout) diff --git a/examples/widgets/layouts/layouts.pro b/examples/widgets/layouts/layouts.pro index c641e8cf..c0b5453f 100644 --- a/examples/widgets/layouts/layouts.pro +++ b/examples/widgets/layouts/layouts.pro @@ -1,5 +1,3 @@ TEMPLATE = subdirs SUBDIRS = basiclayouts \ - borderlayout \ - dynamiclayouts \ flowlayout diff --git a/examples/widgets/mainwindows/CMakeLists.txt b/examples/widgets/mainwindows/CMakeLists.txt index f8457d50..8fec6844 100644 --- a/examples/widgets/mainwindows/CMakeLists.txt +++ b/examples/widgets/mainwindows/CMakeLists.txt @@ -1,8 +1,4 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -qt_internal_add_example(application) -qt_internal_add_example(dockwidgets) -qt_internal_add_example(mainwindow) -qt_internal_add_example(mdi) qt_internal_add_example(menus) diff --git a/examples/widgets/mainwindows/mainwindows.pro b/examples/widgets/mainwindows/mainwindows.pro index 7a53cc6f..75f664f6 100644 --- a/examples/widgets/mainwindows/mainwindows.pro +++ b/examples/widgets/mainwindows/mainwindows.pro @@ -1,6 +1,2 @@ TEMPLATE = subdirs -SUBDIRS = application \ - dockwidgets \ - mainwindow \ - mdi \ - menus +SUBDIRS = menus diff --git a/examples/widgets/painting/CMakeLists.txt b/examples/widgets/painting/CMakeLists.txt index df0bfe90..38ff34c5 100644 --- a/examples/widgets/painting/CMakeLists.txt +++ b/examples/widgets/painting/CMakeLists.txt @@ -11,4 +11,3 @@ qt_internal_add_example(pathstroke) qt_internal_add_example(imagecomposition) qt_internal_add_example(painterpaths) qt_internal_add_example(transformations) -qt_internal_add_example(fontsampler) diff --git a/examples/widgets/painting/affine/main.cpp b/examples/widgets/painting/affine/main.cpp index 3efd2125..1f9c2399 100644 --- a/examples/widgets/painting/affine/main.cpp +++ b/examples/widgets/painting/affine/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char **argv) { - Q_INIT_RESOURCE(affine); - QApplication app(argc, argv); XFormWidget xformWidget(nullptr); diff --git a/examples/widgets/painting/basicdrawing/main.cpp b/examples/widgets/painting/basicdrawing/main.cpp index 67a6d845..1d8fd919 100644 --- a/examples/widgets/painting/basicdrawing/main.cpp +++ b/examples/widgets/painting/basicdrawing/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(basicdrawing); - QApplication app(argc, argv); Window window; window.show(); diff --git a/examples/widgets/painting/deform/main.cpp b/examples/widgets/painting/deform/main.cpp index b81adc09..5ac5b4cc 100644 --- a/examples/widgets/painting/deform/main.cpp +++ b/examples/widgets/painting/deform/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char **argv) { - Q_INIT_RESOURCE(deform); - QApplication app(argc, argv); bool smallScreen = QApplication::arguments().contains("-small-screen"); diff --git a/examples/widgets/painting/gradients/main.cpp b/examples/widgets/painting/gradients/main.cpp index f3b75a74..c1e22975 100644 --- a/examples/widgets/painting/gradients/main.cpp +++ b/examples/widgets/painting/gradients/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(gradients); - QApplication app(argc, argv); GradientWidget gradientWidget; diff --git a/examples/widgets/painting/imagecomposition/main.cpp b/examples/widgets/painting/imagecomposition/main.cpp index cd5468f0..a3cf65a3 100644 --- a/examples/widgets/painting/imagecomposition/main.cpp +++ b/examples/widgets/painting/imagecomposition/main.cpp @@ -8,8 +8,6 @@ //! [0] int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(imagecomposition); - QApplication app(argc, argv); ImageComposer composer; composer.show(); diff --git a/examples/widgets/painting/painting.pro b/examples/widgets/painting/painting.pro index a9749a56..7d5c2e02 100644 --- a/examples/widgets/painting/painting.pro +++ b/examples/widgets/painting/painting.pro @@ -8,8 +8,7 @@ SUBDIRS = basicdrawing \ pathstroke \ imagecomposition \ painterpaths \ - transformations \ - fontsampler + transformations EXAMPLE_FILES = \ shared diff --git a/examples/widgets/painting/pathstroke/main.cpp b/examples/widgets/painting/pathstroke/main.cpp index a5ceb9e3..4f991e8a 100644 --- a/examples/widgets/painting/pathstroke/main.cpp +++ b/examples/widgets/painting/pathstroke/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char **argv) { - Q_INIT_RESOURCE(pathstroke); - QApplication app(argc, argv); bool smallScreen = QApplication::arguments().contains("-small-screen"); diff --git a/examples/widgets/qnx/foreignwindows/collector.cpp b/examples/widgets/qnx/foreignwindows/collector.cpp index 6717488d..8831aab3 100644 --- a/examples/widgets/qnx/foreignwindows/collector.cpp +++ b/examples/widgets/qnx/foreignwindows/collector.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 QNX Software Systems. All rights reserved. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include #include diff --git a/examples/widgets/qnx/foreignwindows/collector.h b/examples/widgets/qnx/foreignwindows/collector.h index a6cd00f9..4ee93cbc 100644 --- a/examples/widgets/qnx/foreignwindows/collector.h +++ b/examples/widgets/qnx/foreignwindows/collector.h @@ -1,5 +1,5 @@ // Copyright (C) 2018 QNX Software Systems. All rights reserved. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #ifndef COLLECTOR_H_ #define COLLECTOR_H_ diff --git a/examples/widgets/qnx/foreignwindows/main.cpp b/examples/widgets/qnx/foreignwindows/main.cpp index e5cc0ea3..55dfc98f 100644 --- a/examples/widgets/qnx/foreignwindows/main.cpp +++ b/examples/widgets/qnx/foreignwindows/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 QNX Software Systems. All rights reserved. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include diff --git a/examples/widgets/richtext/CMakeLists.txt b/examples/widgets/richtext/CMakeLists.txt index ea4165b7..a01296d6 100644 --- a/examples/widgets/richtext/CMakeLists.txt +++ b/examples/widgets/richtext/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -qt_internal_add_example(calendar) qt_internal_add_example(orderform) qt_internal_add_example(syntaxhighlighter) -qt_internal_add_example(textedit) diff --git a/examples/widgets/richtext/richtext.pro b/examples/widgets/richtext/richtext.pro index 499733ec..0d7f6c94 100644 --- a/examples/widgets/richtext/richtext.pro +++ b/examples/widgets/richtext/richtext.pro @@ -1,5 +1,3 @@ TEMPLATE = subdirs -SUBDIRS = calendar \ - orderform \ - syntaxhighlighter \ - textedit +SUBDIRS = orderform \ + syntaxhighlighter diff --git a/examples/widgets/tools/CMakeLists.txt b/examples/widgets/tools/CMakeLists.txt index edf951fe..1d0f35e1 100644 --- a/examples/widgets/tools/CMakeLists.txt +++ b/examples/widgets/tools/CMakeLists.txt @@ -11,8 +11,4 @@ qt_internal_add_example(undoframework) if(QT_FEATURE_library) qt_internal_add_example(echoplugin) - - if(QT_FEATURE_inputdialog) - qt_internal_add_example(plugandpaint) - endif() endif() diff --git a/examples/widgets/tools/completer/main.cpp b/examples/widgets/tools/completer/main.cpp index 4ea6bc1a..060dfe5b 100644 --- a/examples/widgets/tools/completer/main.cpp +++ b/examples/widgets/tools/completer/main.cpp @@ -7,8 +7,6 @@ //! [0] int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(completer); - QApplication app(argc, argv); MainWindow window; window.show(); diff --git a/examples/widgets/tools/customcompleter/main.cpp b/examples/widgets/tools/customcompleter/main.cpp index 13e8544b..060dfe5b 100644 --- a/examples/widgets/tools/customcompleter/main.cpp +++ b/examples/widgets/tools/customcompleter/main.cpp @@ -7,8 +7,6 @@ //! [0] int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(customcompleter); - QApplication app(argc, argv); MainWindow window; window.show(); diff --git a/examples/widgets/tools/echoplugin/CMakeLists.txt b/examples/widgets/tools/echoplugin/CMakeLists.txt index cfe76f4a..548c23fd 100644 --- a/examples/widgets/tools/echoplugin/CMakeLists.txt +++ b/examples/widgets/tools/echoplugin/CMakeLists.txt @@ -2,7 +2,7 @@ # SPDX-License-Identifier: BSD-3-Clause cmake_minimum_required(VERSION 3.16) -project(plugandpaint LANGUAGES CXX) +project(echoplugin LANGUAGES CXX) if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") diff --git a/examples/widgets/tools/settingseditor/mainwindow.cpp b/examples/widgets/tools/settingseditor/mainwindow.cpp index 68178a37..be9f19e8 100644 --- a/examples/widgets/tools/settingseditor/mainwindow.cpp +++ b/examples/widgets/tools/settingseditor/mainwindow.cpp @@ -151,7 +151,7 @@ void MainWindow::createActions() QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addAction(tr("&About"), this, &MainWindow::about); - helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit); + helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); } void MainWindow::setSettingsObject(const SettingsPtr &settings) diff --git a/examples/widgets/tools/tools.pro b/examples/widgets/tools/tools.pro index 4a9dce34..09b693dc 100644 --- a/examples/widgets/tools/tools.pro +++ b/examples/widgets/tools/tools.pro @@ -3,7 +3,6 @@ SUBDIRS = \ completer \ customcompleter \ echoplugin \ - plugandpaint \ regularexpression \ settingseditor \ styleplugin \ @@ -12,6 +11,5 @@ SUBDIRS = \ !qtConfig(library) { SUBDIRS -= \ - echoplugin \ - plugandpaint + echoplugin } diff --git a/examples/widgets/tools/treemodelcompleter/main.cpp b/examples/widgets/tools/treemodelcompleter/main.cpp index 50ca5731..060dfe5b 100644 --- a/examples/widgets/tools/treemodelcompleter/main.cpp +++ b/examples/widgets/tools/treemodelcompleter/main.cpp @@ -7,8 +7,6 @@ //! [0] int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(treemodelcompleter); - QApplication app(argc, argv); MainWindow window; window.show(); diff --git a/examples/widgets/tools/undoframework/main.cpp b/examples/widgets/tools/undoframework/main.cpp index c43b2fcc..8dfa3ffb 100644 --- a/examples/widgets/tools/undoframework/main.cpp +++ b/examples/widgets/tools/undoframework/main.cpp @@ -8,8 +8,6 @@ //! [0] int main(int argv, char *args[]) { - Q_INIT_RESOURCE(undoframework); - QApplication app(argv, args); MainWindow mainWindow; diff --git a/examples/widgets/touch/CMakeLists.txt b/examples/widgets/touch/CMakeLists.txt index 4cf78789..9d7ed621 100644 --- a/examples/widgets/touch/CMakeLists.txt +++ b/examples/widgets/touch/CMakeLists.txt @@ -4,7 +4,4 @@ if(NOT TARGET Qt6::Widgets) return() endif() -qt_internal_add_example(pinchzoom) -qt_internal_add_example(fingerpaint) qt_internal_add_example(knobs) -qt_internal_add_example(dials) diff --git a/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc b/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc index 3a41c500..fc6daa37 100644 --- a/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc +++ b/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc @@ -4,6 +4,7 @@ /*! \example touch/knobs \title Touch Knobs Example + \examplecategory {User Interface Components} \ingroup touchinputexamples \brief Shows how to create custom controls that accept touch input. diff --git a/examples/widgets/touch/touch.pro b/examples/widgets/touch/touch.pro index 018ec134..4fff58e0 100644 --- a/examples/widgets/touch/touch.pro +++ b/examples/widgets/touch/touch.pro @@ -1,4 +1,4 @@ requires(qtHaveModule(widgets)) TEMPLATE = subdirs -SUBDIRS = pinchzoom fingerpaint knobs dials +SUBDIRS = knobs diff --git a/examples/widgets/tutorials/CMakeLists.txt b/examples/widgets/tutorials/CMakeLists.txt index 02d196db..548c9627 100644 --- a/examples/widgets/tutorials/CMakeLists.txt +++ b/examples/widgets/tutorials/CMakeLists.txt @@ -1,8 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -add_subdirectory(addressbook) add_subdirectory(widgets) add_subdirectory(modelview) -add_subdirectory(gettingStarted) qt_internal_add_example(notepad) diff --git a/examples/widgets/tutorials/gettingStarted/CMakeLists.txt b/examples/widgets/tutorials/gettingStarted/CMakeLists.txt deleted file mode 100644 index 42cac47b..00000000 --- a/examples/widgets/tutorials/gettingStarted/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(gsQt) diff --git a/examples/widgets/tutorials/gettingStarted/gettingStarted.pro b/examples/widgets/tutorials/gettingStarted/gettingStarted.pro deleted file mode 100644 index 3e377254..00000000 --- a/examples/widgets/tutorials/gettingStarted/gettingStarted.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS += dir_gsqt - -dir_gsqt.file = gsQt/gsqt.pro diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/CMakeLists.txt b/examples/widgets/tutorials/gettingStarted/gsQt/CMakeLists.txt deleted file mode 100644 index a0fd3503..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -qt_internal_add_example(part1) -qt_internal_add_example(part2) -qt_internal_add_example(part3) -qt_internal_add_example(part4) -qt_internal_add_example(part5) diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/gsqt.pro b/examples/widgets/tutorials/gettingStarted/gsQt/gsqt.pro deleted file mode 100644 index 320f3c3e..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/gsqt.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS = part1 \ - part2 \ - part3 \ - part4 \ - part5 diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part1/CMakeLists.txt b/examples/widgets/tutorials/gettingStarted/gsQt/part1/CMakeLists.txt deleted file mode 100644 index d9db469b..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part1/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(getting_started_part1 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/gettingStarted/gsQt/part1") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(getting_started_part1 - main.cpp -) - -set_target_properties(getting_started_part1 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(getting_started_part1 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS getting_started_part1 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part1/part1.pro b/examples/widgets/tutorials/gettingStarted/gsQt/part1/part1.pro deleted file mode 100644 index 391606bf..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part1/part1.pro +++ /dev/null @@ -1,8 +0,0 @@ - -QT += widgets -SOURCES = main.cpp - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/gettingStarted/gsQt/part1 -INSTALLS += target - diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part2/CMakeLists.txt b/examples/widgets/tutorials/gettingStarted/gsQt/part2/CMakeLists.txt deleted file mode 100644 index 93749d31..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part2/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(getting_started_part2 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/gettingStarted/gsQt/part2") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(getting_started_part2 - main.cpp -) - -set_target_properties(getting_started_part2 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(getting_started_part2 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS getting_started_part2 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part2/main.cpp b/examples/widgets/tutorials/gettingStarted/gsQt/part2/main.cpp deleted file mode 100644 index 722d7889..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part2/main.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - QTextEdit *textEdit = new QTextEdit; - QPushButton *quitButton = new QPushButton("&Quit"); - - QObject::connect(quitButton, &QPushButton::clicked, - qApp, &QApplication::quit); - - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(textEdit); - layout->addWidget(quitButton); - - QWidget window; - window.setLayout(layout); - - window.show(); - - return app.exec(); -} - diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part2/part2.pro b/examples/widgets/tutorials/gettingStarted/gsQt/part2/part2.pro deleted file mode 100644 index e7422e4a..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part2/part2.pro +++ /dev/null @@ -1,8 +0,0 @@ - -QT += widgets -SOURCES = main.cpp - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/gettingStarted/gsQt/part2 -INSTALLS += target - diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part3/CMakeLists.txt b/examples/widgets/tutorials/gettingStarted/gsQt/part3/CMakeLists.txt deleted file mode 100644 index 28aee654..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part3/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(getting_started_part3 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/gettingStarted/gsQt/part3") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(getting_started_part3 - main.cpp -) - -set_target_properties(getting_started_part3 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(getting_started_part3 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS getting_started_part3 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part3/main.cpp b/examples/widgets/tutorials/gettingStarted/gsQt/part3/main.cpp deleted file mode 100644 index 5424dc3c..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part3/main.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include - -class Notepad : public QWidget -{ - Q_OBJECT - -public: - Notepad(); - -private slots: - void quit(); - -private: - QTextEdit *textEdit; - QPushButton *quitButton; - -}; - -Notepad::Notepad() -{ - textEdit = new QTextEdit; - quitButton = new QPushButton(tr("Quit")); - - connect(quitButton, &QPushButton::clicked, - this, &Notepad::quit); - - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(textEdit); - layout->addWidget(quitButton); - - setLayout(layout); - - setWindowTitle(tr("Notepad")); -} - -void Notepad::quit() -{ - QMessageBox messageBox; - messageBox.setWindowTitle(tr("Notepad")); - messageBox.setText(tr("Do you really want to quit?")); - messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - messageBox.setDefaultButton(QMessageBox::No); - if (messageBox.exec() == QMessageBox::Yes) - qApp->quit(); -} - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - Notepad notepad; - notepad.show(); - - return app.exec(); -} - -#include "main.moc" - diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part3/part3.pro b/examples/widgets/tutorials/gettingStarted/gsQt/part3/part3.pro deleted file mode 100644 index 1577848d..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part3/part3.pro +++ /dev/null @@ -1,8 +0,0 @@ - -QT += widgets -SOURCES = main.cpp - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/gettingStarted/gsQt/part3 -INSTALLS += target - diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part4/CMakeLists.txt b/examples/widgets/tutorials/gettingStarted/gsQt/part4/CMakeLists.txt deleted file mode 100644 index a64eca5a..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part4/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(getting_started_part4 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/gettingStarted/gsQt/part4") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(getting_started_part4 - main.cpp -) - -set_target_properties(getting_started_part4 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(getting_started_part4 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS getting_started_part4 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part4/main.cpp b/examples/widgets/tutorials/gettingStarted/gsQt/part4/main.cpp deleted file mode 100644 index de6436ad..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part4/main.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include - -class Notepad : public QMainWindow -{ - Q_OBJECT - -public: - Notepad(); - -private slots: - void load(); - void save(); - -private: - QTextEdit *textEdit; - - QAction *loadAction; - QAction *saveAction; - QAction *exitAction; - - QMenu *fileMenu; -}; - -Notepad::Notepad() -{ - loadAction = new QAction(tr("&Load"), this); - saveAction = new QAction(tr("&Save"), this); - exitAction = new QAction(tr("E&xit"), this); - - connect(loadAction, &QAction::triggered, - this, &Notepad::load); - connect(saveAction, &QAction::triggered, - this, &Notepad::save); - connect(exitAction, &QAction::triggered, - qApp, &QApplication::quit); - - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(loadAction); - fileMenu->addAction(saveAction); - fileMenu->addSeparator(); - fileMenu->addAction(exitAction); - - textEdit = new QTextEdit; - setCentralWidget(textEdit); - - setWindowTitle(tr("Notepad")); -} - -void Notepad::load() -{ - -} - -void Notepad::save() -{ - -} - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - Notepad notepad; - notepad.show(); - - return app.exec(); -}; - -#include "main.moc" - diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part4/part4.pro b/examples/widgets/tutorials/gettingStarted/gsQt/part4/part4.pro deleted file mode 100644 index 086fac69..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part4/part4.pro +++ /dev/null @@ -1,8 +0,0 @@ - -QT += widgets -SOURCES = main.cpp - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/gettingStarted/gsQt/part4 -INSTALLS += target - diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part5/CMakeLists.txt b/examples/widgets/tutorials/gettingStarted/gsQt/part5/CMakeLists.txt deleted file mode 100644 index 7d5a4f73..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part5/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.16) -project(getting_started_part5 LANGUAGES CXX) - -if(NOT DEFINED INSTALL_EXAMPLESDIR) - set(INSTALL_EXAMPLESDIR "examples") -endif() - -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tutorials/gettingStarted/gsQt/part5") - -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) - -qt_standard_project_setup() - -qt_add_executable(getting_started_part5 - main.cpp -) - -set_target_properties(getting_started_part5 PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) - -target_link_libraries(getting_started_part5 PRIVATE - Qt6::Core - Qt6::Gui - Qt6::Widgets -) - -install(TARGETS getting_started_part5 - RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" - BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" - LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" -) diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part5/main.cpp b/examples/widgets/tutorials/gettingStarted/gsQt/part5/main.cpp deleted file mode 100644 index 037f1771..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part5/main.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -#include - -class Notepad : public QMainWindow -{ - Q_OBJECT - -public: - Notepad(); - -private slots: - void open(); - void save(); - -private: - QTextEdit *textEdit; - - QAction *openAction; - QAction *saveAction; - QAction *exitAction; - - QMenu *fileMenu; -}; - -Notepad::Notepad() -{ - openAction = new QAction(tr("&Load"), this); - saveAction = new QAction(tr("&Save"), this); - exitAction = new QAction(tr("E&xit"), this); - - connect(openAction, &QAction::triggered, - this, &Notepad::open); - connect(saveAction, &QAction::triggered, - this, &Notepad::save); - connect(exitAction, &QAction::triggered, - qApp, &QApplication::quit); - - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(openAction); - fileMenu->addAction(saveAction); - fileMenu->addSeparator(); - fileMenu->addAction(exitAction); - - textEdit = new QTextEdit; - setCentralWidget(textEdit); - - setWindowTitle(tr("Notepad")); -} - -void Notepad::open() -{ - QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", - tr("Text Files (*.txt);;C++ Files (*.cpp *.h)")); - - if (!fileName.isEmpty()) { - QFile file(fileName); - if (!file.open(QIODevice::ReadOnly)) { - QMessageBox::critical(this, tr("Error"), tr("Could not open file")); - return; - } - QTextStream in(&file); - textEdit->setText(in.readAll()); - file.close(); - } -} - -void Notepad::save() -{ - - QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", - tr("Text Files (*.txt);;C++ Files (*.cpp *.h)")); - - if (!fileName.isEmpty()) { - QFile file(fileName); - if (!file.open(QIODevice::WriteOnly)) { - // error message - } else { - QTextStream stream(&file); - stream << textEdit->toPlainText(); - stream.flush(); - file.close(); - } - } -} - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - Notepad notepad; - notepad.show(); - - return app.exec(); -} - -#include "main.moc" - diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part5/part5.pro b/examples/widgets/tutorials/gettingStarted/gsQt/part5/part5.pro deleted file mode 100644 index 12378f30..00000000 --- a/examples/widgets/tutorials/gettingStarted/gsQt/part5/part5.pro +++ /dev/null @@ -1,8 +0,0 @@ -QT += widgets -requires(qtConfig(filedialog)) -SOURCES = main.cpp - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tutorials/gettingStarted/gsQt/part5 -INSTALLS += target - diff --git a/examples/widgets/tutorials/gettingstartedqt.qdoc b/examples/widgets/tutorials/notepad/gettingstartedqt.qdoc similarity index 99% rename from examples/widgets/tutorials/gettingstartedqt.qdoc rename to examples/widgets/tutorials/notepad/gettingstartedqt.qdoc index 152bf8c1..7979d591 100644 --- a/examples/widgets/tutorials/gettingstartedqt.qdoc +++ b/examples/widgets/tutorials/notepad/gettingstartedqt.qdoc @@ -4,6 +4,7 @@ /*! \example tutorials/notepad \title Getting Started Programming with Qt Widgets + \examplecategory {User Interface Components} \brief A tutorial for Qt Widgets based notepad application. In this topic, we teach basic Qt knowledge by implementing a simple @@ -486,10 +487,6 @@ \header \li About \li Here - \row - \li MDI applications - \li QMdiArea, - \l{MDI Example} \row \li Files and I/O devices \li QFile, QIODevice diff --git a/examples/widgets/tutorials/tutorials.pro b/examples/widgets/tutorials/tutorials.pro index 0aaa119d..d9dbbd28 100644 --- a/examples/widgets/tutorials/tutorials.pro +++ b/examples/widgets/tutorials/tutorials.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS += addressbook widgets modelview gettingStarted notepad +SUBDIRS += widgets modelview notepad diff --git a/examples/widgets/widgets.pro b/examples/widgets/widgets.pro index 2dbbefa1..88185821 100644 --- a/examples/widgets/widgets.pro +++ b/examples/widgets/widgets.pro @@ -8,7 +8,6 @@ SUBDIRS = \ desktop \ dialogs \ draganddrop \ - effects \ gallery \ gestures \ graphicsview \ @@ -17,15 +16,11 @@ SUBDIRS = \ mainwindows \ painting \ richtext \ - scroller \ tools \ touch \ tutorials \ widgets -qtHaveModule(gui):qtConfig(opengl): \ - SUBDIRS += windowcontainer - contains(DEFINES, QT_NO_CURSOR): SUBDIRS -= mainwindows !qtConfig(draganddrop): SUBDIRS -= draganddrop !qtConfig(animation): SUBDIRS -= animation diff --git a/examples/widgets/widgets/CMakeLists.txt b/examples/widgets/widgets/CMakeLists.txt index d852233c..6b6a7760 100644 --- a/examples/widgets/widgets/CMakeLists.txt +++ b/examples/widgets/widgets/CMakeLists.txt @@ -4,24 +4,13 @@ qt_internal_add_example(analogclock) qt_internal_add_example(calculator) qt_internal_add_example(calendarwidget) -qt_internal_add_example(charactermap) -qt_internal_add_example(digitalclock) qt_internal_add_example(groupbox) -qt_internal_add_example(icons) -qt_internal_add_example(imageviewer) qt_internal_add_example(lineedits) -if(QT_FEATURE_movie) - qt_internal_add_example(movie) -endif() qt_internal_add_example(scribble) qt_internal_add_example(shapedclock) qt_internal_add_example(shortcuteditor) qt_internal_add_example(sliders) qt_internal_add_example(spinboxes) -qt_internal_add_example(styles) -qt_internal_add_example(stylesheet) qt_internal_add_example(tablet) -qt_internal_add_example(tetrix) qt_internal_add_example(tooltips) -qt_internal_add_example(validators) qt_internal_add_example(windowflags) diff --git a/examples/widgets/widgets/shapedclock/shapedclock.cpp b/examples/widgets/widgets/shapedclock/shapedclock.cpp index 5cc4a540..25225eb5 100644 --- a/examples/widgets/widgets/shapedclock/shapedclock.cpp +++ b/examples/widgets/widgets/shapedclock/shapedclock.cpp @@ -78,7 +78,9 @@ void ShapedClock::paintEvent(QPaintEvent *) painter.setPen(Qt::NoPen); painter.setBrush(palette().window()); + painter.setOpacity(0.9); painter.drawEllipse(QPoint(0, 0), 98, 98); + painter.setOpacity(1.0); painter.setPen(Qt::NoPen); painter.setBrush(hourColor); @@ -114,18 +116,8 @@ void ShapedClock::paintEvent(QPaintEvent *) //! [3] //! [4] -void ShapedClock::resizeEvent(QResizeEvent * /* event */) -{ - int side = qMin(width(), height()); - QRegion maskedRegion(width() / 2 - side / 2, height() / 2 - side / 2, side, - side, QRegion::Ellipse); - setMask(maskedRegion); -} -//! [4] - -//! [5] QSize ShapedClock::sizeHint() const { return QSize(200, 200); } -//! [5] +//! [4] diff --git a/examples/widgets/widgets/shapedclock/shapedclock.h b/examples/widgets/widgets/shapedclock/shapedclock.h index c359a3a0..3dec93cc 100644 --- a/examples/widgets/widgets/shapedclock/shapedclock.h +++ b/examples/widgets/widgets/shapedclock/shapedclock.h @@ -19,7 +19,6 @@ protected: void mouseMoveEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void paintEvent(QPaintEvent *event) override; - void resizeEvent(QResizeEvent *event) override; private: QPoint dragPosition; diff --git a/examples/widgets/widgets/shortcuteditor/shortcuteditormodel.cpp b/examples/widgets/widgets/shortcuteditor/shortcuteditormodel.cpp index 4355f029..612f1fb7 100644 --- a/examples/widgets/widgets/shortcuteditor/shortcuteditormodel.cpp +++ b/examples/widgets/widgets/shortcuteditor/shortcuteditormodel.cpp @@ -257,11 +257,11 @@ bool ShortcutEditorModel::setData(const QModelIndex &index, const QVariant &valu QString keySequenceString = value.toString(); ShortcutEditorModelItem *item = static_cast(index.internalPointer()); QAction *itemAction = item->action(); - if (itemAction - && keySequenceString == itemAction->shortcut().toString(QKeySequence::NativeText)) - return true; - - itemAction->setShortcut(keySequenceString); + if (itemAction) { + if (keySequenceString == itemAction->shortcut().toString(QKeySequence::NativeText)) + return true; + itemAction->setShortcut(keySequenceString); + } Q_EMIT dataChanged(index, index); if (keySequenceString.isEmpty()) diff --git a/examples/widgets/widgets/tooltips/main.cpp b/examples/widgets/widgets/tooltips/main.cpp index 677d9ecd..1cc7f435 100644 --- a/examples/widgets/widgets/tooltips/main.cpp +++ b/examples/widgets/widgets/tooltips/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char *argv[]) { - Q_INIT_RESOURCE(tooltips); - QApplication app(argc, argv); SortingBox sortingBox; sortingBox.show(); diff --git a/examples/widgets/widgets/widgets.pro b/examples/widgets/widgets/widgets.pro index 36d42842..7384b697 100644 --- a/examples/widgets/widgets/widgets.pro +++ b/examples/widgets/widgets/widgets.pro @@ -2,21 +2,12 @@ TEMPLATE = subdirs SUBDIRS = analogclock \ calculator \ calendarwidget \ - charactermap \ - digitalclock \ groupbox \ - icons \ - imageviewer \ lineedits \ - movie \ scribble \ shapedclock \ sliders \ spinboxes \ - styles \ - stylesheet \ tablet \ - tetrix \ tooltips \ - validators \ windowflags diff --git a/examples/xml/dombookmarks/doc/images/dombookmarks-example.png b/examples/xml/dombookmarks/doc/images/dombookmarks-example.png deleted file mode 100644 index abacacbb..00000000 Binary files a/examples/xml/dombookmarks/doc/images/dombookmarks-example.png and /dev/null differ diff --git a/examples/xml/dombookmarks/doc/images/screenshot.png b/examples/xml/dombookmarks/doc/images/screenshot.png new file mode 100644 index 00000000..462052ce Binary files /dev/null and b/examples/xml/dombookmarks/doc/images/screenshot.png differ diff --git a/examples/xml/dombookmarks/doc/src/dombookmarks.qdoc b/examples/xml/dombookmarks/doc/src/dombookmarks.qdoc index 366b3d14..dc757f84 100644 --- a/examples/xml/dombookmarks/doc/src/dombookmarks.qdoc +++ b/examples/xml/dombookmarks/doc/src/dombookmarks.qdoc @@ -3,16 +3,94 @@ /*! \example dombookmarks - \title DOM Bookmarks Example - \examplecategory {Input/Output} + \title DOM Bookmarks Application + \examplecategory {Data Processing & I/O} \ingroup xml-examples + \meta tag {xml} \brief Provides a reader for XML Bookmark Exchange Language files. - The DOM Bookmarks example provides a reader for XML Bookmark Exchange Language (XBEL) - files that uses Qt's DOM-based XML API to read and parse the files. The SAX Bookmarks - example provides an alternative way to read this type of file. + The DOM Bookmarks Application provides a reader for XML Bookmark Exchange + Language (XBEL) files that uses Qt's DOM-based XML API to read and parse + the files. The {QXmlStream Bookmarks Example} provides an alternative + way to read this type of file. - \image dombookmarks-example.png + \image screenshot.png + + \section1 The XbelTree Class Definition + + The XbelTree class has functions for reading and writing to the filesystem. + It inherits from the QTreeWidget class, contains the model for the + displaying of the bookmarks, and allows it to be edited. + + \snippet dombookmarks/xbeltree.h 0 + + \section1 The XbelTree Class Implementation + + The \c XbelTree constructor accepts a QWidget within which it is placed. + The \c folderIcon is set to QIcon::Normal mode where the pixmap is only + displayed when the user is not interacting with the icon. The + QStyle::SP_DirClosedIcon, QStyle::SP_DirOpenIcon, and QStyle::SP_FileIcon + correspond to standard pixmaps that follow the style of your GUI. + + \snippet dombookmarks/xbeltree.cpp 0 + + The \c read() function opens the given QIODevice using + QDomDocument::setContent. If it succeeds opening the file and the top + level headers are verified, the contents of the class is cleared before + the file contents is parsed by iterating all the top level XML nodes and + calling \c parseFolderElement() on each of them. + + \snippet dombookmarks/xbeltree.cpp 1 + + The \c parseFolderElement() function handles the different element types + and calls itself recursively if the element is a subfolder. + + \snippet dombookmarks/xbeltree.cpp 3 + + The \c write() function saves the domDocument to the given QIODevice using + QDomDocument::save. + + \snippet dombookmarks/xbeltree.cpp 2 + + \section1 The MainWindow Class Definition + + The \c MainWindow class is a subclass of QMainWindow, with a + \c File menu and a \c Help menu. + + \snippet dombookmarks/mainwindow.h 0 + + \section1 The MainWindow Class Implementation + + The \c MainWindow constructor instantiates the member XbelTree object, + and sets its header with a QStringList object, \c labels. + The constructor also invokes \c createMenus() to set up the menus. + The \c statusBar() is used to display the message "Ready". + + \snippet dombookmarks/mainwindow.cpp 0 + + The \c createMenus() function populates the menus and sets keyboard + shortcuts. + + \snippet dombookmarks/mainwindow.cpp 4 + + The \c open() function enables the user to open an XBEL file using + QFileDialog. A warning message is displayed along + with the \c fileName and \c errorString if the file cannot be read or + if there is a parse error. If it succeeds it calls \c XbelTree::read(). + + \snippet dombookmarks/mainwindow.cpp 1 + + The \c saveAs() function displays a QFileDialog, prompting the user for + a \c fileName. Similar to the \c open() function, this function also + displays a warning message if the file cannot be written to. If this + succeeds it calls \c XbelTree::write(). + + \snippet dombookmarks/mainwindow.cpp 2 + + The \c about() function displays a QMessageBox with a brief description + of the example. + + \snippet dombookmarks/mainwindow.cpp 3 See the \l{http://pyxml.sourceforge.net/topics/xbel/}{XML Bookmark Exchange Language Resource Page} for more information about XBEL files. diff --git a/examples/xml/dombookmarks/dombookmarks.pro b/examples/xml/dombookmarks/dombookmarks.pro index 280207ee..f6cf6ffc 100644 --- a/examples/xml/dombookmarks/dombookmarks.pro +++ b/examples/xml/dombookmarks/dombookmarks.pro @@ -6,7 +6,7 @@ SOURCES = main.cpp \ QT += xml widgets requires(qtConfig(filedialog)) -EXAMPLE_FILES = frank.xbel jennifer.xbel +EXAMPLE_FILES = jennifer.xbel # install target.path = $$[QT_INSTALL_EXAMPLES]/xml/dombookmarks diff --git a/examples/xml/dombookmarks/jennifer.xbel b/examples/xml/dombookmarks/jennifer.xbel index 2501c118..d5042368 100644 --- a/examples/xml/dombookmarks/jennifer.xbel +++ b/examples/xml/dombookmarks/jennifer.xbel @@ -3,66 +3,66 @@ Qt Resources - + Qt home page - + Qt Partners - - Training + + Professional Services - - Qt 5 documentation - - - Frequently Asked Questions + + Qt Documentation Community Resources - + + The Qt Project + + Qt Centre - - QtForum.org + + Forum.Qt.org - + The Independent Qt Tutorial - + German Qt Forum - + Korean Qt Community Site - + Russian Qt Forum Online Dictionaries - + Dictionary.com - + Merriam-Webster Online - + Cambridge Dictionaries Online - + OneLook Dictionary Search - - TU Chemnitz German-English Dictionary + + BEOLINGUS, a service of TU Chemnitz Trésor de la Langue Française informatisé - + Dictionnaire de l'Académie Française diff --git a/examples/xml/dombookmarks/mainwindow.cpp b/examples/xml/dombookmarks/mainwindow.cpp index 6a03a57b..5e6c68ce 100644 --- a/examples/xml/dombookmarks/mainwindow.cpp +++ b/examples/xml/dombookmarks/mainwindow.cpp @@ -1,11 +1,21 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#include - #include "mainwindow.h" #include "xbeltree.h" +#include +#include +#include +#include +#include + +#include +#include + +using namespace Qt::StringLiterals; + +//! [0] MainWindow::MainWindow() { xbelTree = new XbelTree; @@ -19,19 +29,20 @@ MainWindow::MainWindow() const QSize availableSize = screen()->availableGeometry().size(); resize(availableSize.width() / 2, availableSize.height() / 3); } +//! [0] +//! [1] void MainWindow::open() { - QString fileName = - QFileDialog::getOpenFileName(this, tr("Open Bookmark File"), - QDir::currentPath(), - tr("XBEL Files (*.xbel *.xml)")); - if (fileName.isEmpty()) + QFileDialog fileDialog(this, tr("Open Bookmark File"), QDir::currentPath()); + fileDialog.setMimeTypeFilters({"application/x-xbel"_L1}); + if (fileDialog.exec() != QDialog::Accepted) return; + const QString fileName = fileDialog.selectedFiles().constFirst(); QFile file(fileName); if (!file.open(QFile::ReadOnly | QFile::Text)) { - QMessageBox::warning(this, tr("SAX Bookmarks"), + QMessageBox::warning(this, tr("DOM Bookmarks"), tr("Cannot read file %1:\n%2.") .arg(QDir::toNativeSeparators(fileName), file.errorString())); @@ -41,19 +52,22 @@ void MainWindow::open() if (xbelTree->read(&file)) statusBar()->showMessage(tr("File loaded"), 2000); } +//! [1] +//! [2] void MainWindow::saveAs() { - QString fileName = - QFileDialog::getSaveFileName(this, tr("Save Bookmark File"), - QDir::currentPath(), - tr("XBEL Files (*.xbel *.xml)")); - if (fileName.isEmpty()) + QFileDialog fileDialog(this, tr("Save Bookmark File"), QDir::currentPath()); + fileDialog.setAcceptMode(QFileDialog::AcceptSave); + fileDialog.setDefaultSuffix("xbel"_L1); + fileDialog.setMimeTypeFilters({"application/x-xbel"_L1}); + if (fileDialog.exec() != QDialog::Accepted) return; + const QString fileName = fileDialog.selectedFiles().constFirst(); QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { - QMessageBox::warning(this, tr("SAX Bookmarks"), + QMessageBox::warning(this, tr("DOM Bookmarks"), tr("Cannot write file %1:\n%2.") .arg(QDir::toNativeSeparators(fileName), file.errorString())); @@ -63,7 +77,9 @@ void MainWindow::saveAs() if (xbelTree->write(&file)) statusBar()->showMessage(tr("File saved"), 2000); } +//! [2] +//! [3] void MainWindow::about() { QMessageBox::about(this, tr("About DOM Bookmarks"), @@ -71,7 +87,9 @@ void MainWindow::about() "use Qt's DOM classes to read and write XML " "documents.")); } +//! [3] +//! [4] void MainWindow::createMenus() { QMenu *fileMenu = menuBar()->addMenu(tr("&File")); @@ -88,5 +106,6 @@ void MainWindow::createMenus() QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addAction(tr("&About"), this, &MainWindow::about); - helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit); + helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); } +//! [4] diff --git a/examples/xml/dombookmarks/mainwindow.h b/examples/xml/dombookmarks/mainwindow.h index 55b78c84..82e29012 100644 --- a/examples/xml/dombookmarks/mainwindow.h +++ b/examples/xml/dombookmarks/mainwindow.h @@ -8,6 +8,7 @@ class XbelTree; +//! [0] class MainWindow : public QMainWindow { Q_OBJECT @@ -25,5 +26,6 @@ private: XbelTree *xbelTree; }; +//! [0] #endif diff --git a/examples/xml/dombookmarks/xbeltree.cpp b/examples/xml/dombookmarks/xbeltree.cpp index 5d2e14f1..eff2fea8 100644 --- a/examples/xml/dombookmarks/xbeltree.cpp +++ b/examples/xml/dombookmarks/xbeltree.cpp @@ -1,30 +1,41 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#include - #include "xbeltree.h" +#include +#include +#include + +#include +#include +#if QT_CONFIG(clipboard) && QT_CONFIG(contextmenu) +# include +# include +#endif + +#include + +using namespace Qt::StringLiterals; + enum { DomElementRole = Qt::UserRole + 1 }; Q_DECLARE_METATYPE(QDomElement) -static inline QString titleElement() { return QStringLiteral("title"); } -static inline QString folderElement() { return QStringLiteral("folder"); } -static inline QString bookmarkElement() { return QStringLiteral("bookmark"); } +static const auto titleElement = u"title"_s; +static const auto folderElement = u"folder"_s; +static const auto bookmarkElement = u"bookmark"_s; -static inline QString versionAttribute() { return QStringLiteral("version"); } -static inline QString hrefAttribute() { return QStringLiteral("href"); } -static inline QString foldedAttribute() { return QStringLiteral("folded"); } +static const auto versionAttribute = u"version"_s; +static const auto hrefAttribute = u"href"_s; +static const auto foldedAttribute = u"folded"_s; +//! [0] XbelTree::XbelTree(QWidget *parent) : QTreeWidget(parent) { - QStringList labels; - labels << tr("Title") << tr("Location"); - header()->setSectionResizeMode(QHeaderView::Stretch); - setHeaderLabels(labels); + setHeaderLabels({tr("Title"), tr("Location")}); folderIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon), QIcon::Normal, QIcon::Off); @@ -32,8 +43,9 @@ XbelTree::XbelTree(QWidget *parent) QIcon::Normal, QIcon::On); bookmarkIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon)); } +//! [0] -#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) +#if QT_CONFIG(clipboard) && QT_CONFIG(contextmenu) void XbelTree::contextMenuEvent(QContextMenuEvent *event) { const QTreeWidgetItem *item = itemAt(event->pos()); @@ -49,8 +61,9 @@ void XbelTree::contextMenuEvent(QContextMenuEvent *event) else if (action == openAction) QDesktopServices::openUrl(QUrl(url)); } -#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD +#endif // QT_CONFIG(clipboard) && QT_CONFIG(contextmenu) +//! [1] bool XbelTree::read(QIODevice *device) { QDomDocument::ParseResult result = @@ -69,8 +82,8 @@ bool XbelTree::read(QIODevice *device) QMessageBox::information(window(), tr("DOM Bookmarks"), tr("The file is not an XBEL file.")); return false; - } else if (root.hasAttribute(versionAttribute()) - && root.attribute(versionAttribute()) != QLatin1String("1.0")) { + } else if (root.hasAttribute(versionAttribute) + && root.attribute(versionAttribute) != "1.0"_L1) { QMessageBox::information(window(), tr("DOM Bookmarks"), tr("The file is not an XBEL version 1.0 " "file.")); @@ -81,17 +94,19 @@ bool XbelTree::read(QIODevice *device) disconnect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement); - QDomElement child = root.firstChildElement(folderElement()); + QDomElement child = root.firstChildElement(folderElement); while (!child.isNull()) { parseFolderElement(child); - child = child.nextSiblingElement(folderElement()); + child = child.nextSiblingElement(folderElement); } connect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement); return true; } +//! [1] +//! [2] bool XbelTree::write(QIODevice *device) const { const int IndentSize = 4; @@ -100,65 +115,70 @@ bool XbelTree::write(QIODevice *device) const domDocument.save(out, IndentSize); return true; } +//! [2] void XbelTree::updateDomElement(const QTreeWidgetItem *item, int column) { QDomElement element = qvariant_cast(item->data(0, DomElementRole)); if (!element.isNull()) { if (column == 0) { - QDomElement oldTitleElement = element.firstChildElement(titleElement()); - QDomElement newTitleElement = domDocument.createElement(titleElement()); + QDomElement oldTitleElement = element.firstChildElement(titleElement); + QDomElement newTitleElement = domDocument.createElement(titleElement); QDomText newTitleText = domDocument.createTextNode(item->text(0)); newTitleElement.appendChild(newTitleText); element.replaceChild(newTitleElement, oldTitleElement); } else { - if (element.tagName() == bookmarkElement()) - element.setAttribute(hrefAttribute(), item->text(1)); + if (element.tagName() == bookmarkElement) + element.setAttribute(hrefAttribute, item->text(1)); } } } +//! [3] void XbelTree::parseFolderElement(const QDomElement &element, QTreeWidgetItem *parentItem) { QTreeWidgetItem *item = createItem(element, parentItem); - QString title = element.firstChildElement(titleElement()).text(); + QString title = element.firstChildElement(titleElement).text(); if (title.isEmpty()) - title = QObject::tr("Folder"); + title = tr("Folder"); item->setFlags(item->flags() | Qt::ItemIsEditable); item->setIcon(0, folderIcon); item->setText(0, title); - bool folded = (element.attribute(foldedAttribute()) != QLatin1String("no")); + bool folded = (element.attribute(foldedAttribute) != "no"_L1); item->setExpanded(!folded); + constexpr char16_t midDot = u'\xB7'; + static const QString dots = QString(30, midDot); QDomElement child = element.firstChildElement(); while (!child.isNull()) { - if (child.tagName() == folderElement()) { + if (child.tagName() == folderElement) { parseFolderElement(child, item); - } else if (child.tagName() == bookmarkElement()) { + } else if (child.tagName() == bookmarkElement) { QTreeWidgetItem *childItem = createItem(child, item); - QString title = child.firstChildElement(titleElement()).text(); + QString title = child.firstChildElement(titleElement).text(); if (title.isEmpty()) - title = QObject::tr("Folder"); + title = tr("Folder"); childItem->setFlags(item->flags() | Qt::ItemIsEditable); childItem->setIcon(0, bookmarkIcon); childItem->setText(0, title); - childItem->setText(1, child.attribute(hrefAttribute())); - } else if (child.tagName() == QLatin1String("separator")) { + childItem->setText(1, child.attribute(hrefAttribute)); + } else if (child.tagName() == "separator"_L1) { QTreeWidgetItem *childItem = createItem(child, item); childItem->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEditable)); - childItem->setText(0, QString(30, u'\xB7')); + childItem->setText(0, dots); } child = child.nextSiblingElement(); } } +//! [3] QTreeWidgetItem *XbelTree::createItem(const QDomElement &element, QTreeWidgetItem *parentItem) diff --git a/examples/xml/dombookmarks/xbeltree.h b/examples/xml/dombookmarks/xbeltree.h index d39caad5..caaf4c00 100644 --- a/examples/xml/dombookmarks/xbeltree.h +++ b/examples/xml/dombookmarks/xbeltree.h @@ -8,18 +8,19 @@ #include #include +//! [0] class XbelTree : public QTreeWidget { Q_OBJECT public: - XbelTree(QWidget *parent = nullptr); + explicit XbelTree(QWidget *parent = nullptr); bool read(QIODevice *device); bool write(QIODevice *device) const; protected: -#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) +#if QT_CONFIG(clipboard) && QT_CONFIG(contextmenu) void contextMenuEvent(QContextMenuEvent *event) override; #endif @@ -36,5 +37,6 @@ private: QIcon folderIcon; QIcon bookmarkIcon; }; +//! [0] #endif diff --git a/mkspecs/common/macx.conf b/mkspecs/common/macx.conf index 6760aa73..b891c293 100644 --- a/mkspecs/common/macx.conf +++ b/mkspecs/common/macx.conf @@ -9,7 +9,7 @@ QMAKE_MACOSX_DEPLOYMENT_TARGET = 11 QT_MAC_SDK_VERSION_MIN = 11 -QT_MAC_SDK_VERSION_MAX = 13 +QT_MAC_SDK_VERSION_MAX = 14 device.sdk = macosx device.target = device diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 3c4b284b..114c729f 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -249,15 +249,16 @@ for(ever) { } else { lib_bases = $$MODULE_MODULE$$qtPlatformTargetSuffix() darwin: lib_bases *= $$MODULE_MODULE + add_lib_to_pretargetdeps = false win32|contains(MODULE_CONFIG, staticlib) { lib_prefix = $$MODULE_LIBS/$$QMAKE_PREFIX_STATICLIB lib_suffixes = $$QMAKE_EXTENSION_STATICLIB lib_suffixes *= $$QMAKE_LIB_EXTENSIONS - add_lib_to_pretargetdeps = true + !xcodebuild: \ + add_lib_to_pretargetdeps = true } else { lib_prefix = $$MODULE_LIBS/$$QMAKE_PREFIX_SHLIB lib_suffixes = $$QMAKE_EXTENSION_SHLIB - add_lib_to_pretargetdeps = false } candidates = for(lib_base, lib_bases) { diff --git a/mkspecs/features/toolchain.prf b/mkspecs/features/toolchain.prf index 0040b6c4..bfad10d3 100644 --- a/mkspecs/features/toolchain.prf +++ b/mkspecs/features/toolchain.prf @@ -288,9 +288,12 @@ isEmpty($${target_prefix}.INCDIRS) { } } } - isEmpty(QMAKE_DEFAULT_LIBDIRS)|isEmpty(QMAKE_DEFAULT_INCDIRS): \ + isEmpty(QMAKE_DEFAULT_INCDIRS): \ !integrity: \ - error("failed to parse default search paths from compiler output") + error("failed to parse default include paths from compiler output") + isEmpty(QMAKE_DEFAULT_LIBDIRS): \ + !integrity:!darwin: \ + error("failed to parse default library paths from compiler output") QMAKE_DEFAULT_LIBDIRS = $$unique(QMAKE_DEFAULT_LIBDIRS) } else: ghs { cmd = $$QMAKE_CXX $$QMAKE_CXXFLAGS -$${LITERAL_HASH} -o /tmp/fake_output /tmp/fake_input.cpp @@ -411,7 +414,7 @@ isEmpty($${target_prefix}.INCDIRS) { QMAKE_DEFAULT_INCDIRS = $$split(INCLUDE, $$QMAKE_DIRLIST_SEP) } - unix:if(!cross_compile|host_build) { + unix:!darwin:if(!cross_compile|host_build) { isEmpty(QMAKE_DEFAULT_INCDIRS): QMAKE_DEFAULT_INCDIRS = /usr/include /usr/local/include isEmpty(QMAKE_DEFAULT_LIBDIRS): QMAKE_DEFAULT_LIBDIRS = /lib /usr/lib } diff --git a/qmake/CMakeLists.txt b/qmake/CMakeLists.txt index b61f6f69..d3e8f56a 100644 --- a/qmake/CMakeLists.txt +++ b/qmake/CMakeLists.txt @@ -16,14 +16,14 @@ qt_add_library(QtLibraryInfo OBJECT qmakelibraryinfo.cpp qmakelibraryinfo.h ) +# Make sure we use same parameters when building QtLibraryInfo and other Qt libraries, +# otherwise some compilers may have compilation errors, such as clang-cl. +target_link_libraries(QtLibraryInfo PUBLIC PlatformCommonInternal) + +target_link_libraries(QtLibraryInfo PUBLIC Qt::CorePrivate) + qt_internal_add_sync_header_dependencies(QtLibraryInfo Core) -set_target_properties(QtLibraryInfo PROPERTIES - COMPILE_OPTIONS $ - COMPILE_DEFINITIONS $ - INCLUDE_DIRECTORIES $ - INCLUDE_DIRECTORIES $ -) target_include_directories(QtLibraryInfo PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/library" @@ -41,21 +41,22 @@ target_compile_definitions(QtLibraryInfo PUBLIC PROEVALUATOR_FULL QT_BUILD_QMAKE QT_USE_QSTRINGBUILDER - QT_NO_FOREACH - QT_VERSION_STR="${PROJECT_VERSION}" QT_HOST_MKSPEC="${QT_QMAKE_HOST_MKSPEC}" QT_TARGET_MKSPEC="${QT_QMAKE_TARGET_MKSPEC}" QT_HOST_DATADIR="${hostdatadir}" ${deprecation_define} ) +qt_internal_set_exceptions_flags(QtLibraryInfo OFF) + if(NOT QT_FEATURE_qmake) return() endif() qt_get_tool_target_name(target_name qmake) qt_internal_add_tool(${target_name} - TOOLS_TARGET Core # special case + TRY_RUN + TOOLS_TARGET Core USER_FACING NO_UNITY_BUILD INSTALL_VERSIONED_LINK @@ -97,7 +98,6 @@ qt_internal_add_tool(${target_name} PRECOMPILED_HEADER "qmake_pch.h" LIBRARIES - Qt::CorePrivate QtLibraryInfo ) qt_internal_return_unless_building_tools() diff --git a/qmake/doc/snippets/code/doc_src_qmake-manual.pro b/qmake/doc/snippets/code/doc_src_qmake-manual.pro index 76f0eec2..bb803d11 100644 --- a/qmake/doc/snippets/code/doc_src_qmake-manual.pro +++ b/qmake/doc/snippets/code/doc_src_qmake-manual.pro @@ -961,3 +961,25 @@ translations_de.files = $$PWD/de.lproj/InfoPlist.strings QMAKE_BUNDLE_DATA += translations_en translations_de #! [189] + +#! [TR_EXCLUDE sources] +SOURCES += main.cpp \ + excluded.cpp \ + 3rdparty/sqlite3.h \ + 3rdparty/sqlite3.c +TR_EXCLUDE += excluded.cpp 3rdparty/* +#! [TR_EXCLUDE sources] + +#! [TR_EXCLUDE SUBDIRS] +SUBDIRS += \ + libs \ + apps \ + tests +TR_EXCLUDE += tests +#! [TR_EXCLUDE SUBDIRS] + +#! [TR_EXCLUDE include paths] +linux { + TR_EXCLUDE += /usr/include/boost/* +} +#! [TR_EXCLUDE include paths] diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index 424900b2..875a1ac5 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -118,6 +118,9 @@ For more information about the environment variables that qmake uses when configuring the build process, see \l{Configuring qmake}. + \note Add your project build directory to the list of excluded directories + of any anti-virus application that runs on your system. + \section1 Using Third Party Libraries The guide to \l{Third Party Libraries} shows you how to use simple third @@ -154,7 +157,6 @@ The following sections describe the different types of elements used in project files. - \target ProjectFileElementsVariables \section2 Variables In a project file, variables are used to hold lists of strings. In the @@ -272,9 +274,10 @@ line as the condition. More complex operations on variables that would usually require loops - are provided by built-in functions such as \l{findfunction}{find()}, - \l{unique}{unique()}, and \l{countfunction}{count()}. These functions, and - many others are provided to manipulate + are provided by built-in functions such as \l{find(variablename, substr)} + {find()}, \l{unique(variablename)}{unique()}, and + \l{count(variablename, number)}{count()}. + These functions, and many others are provided to manipulate strings and paths, support user input, and call external tools. For more information about using the functions, see \l{qmake Language}. For lists of all functions and their descriptions, see \l{Replace Functions} and @@ -321,7 +324,6 @@ The \c SUBDIRS variable is used to contain a list of all the subdirectories to be processed. - \target GeneralConfiguration \section1 General Configuration The \l{CONFIG} variable specifies the options and features that the project @@ -488,9 +490,9 @@ You can use the \c options to specify both general and mode-specific settings. Options that only apply to the Makefile mode are described in the - \l{#MakefileMode}{Makefile Mode Options} section, whereas options that influence the + \l{Makefile Mode Options} section, whereas options that influence the creation of project files are described in the - \l{#ProjectMode}{Project Mode Options} section. + \l{Project Mode Options} section. \section1 Files @@ -551,7 +553,6 @@ files. \endlist - \target MakefileMode \section1 Makefile Mode Options \snippet code/doc_src_qmake-manual.pro 9 @@ -593,7 +594,6 @@ is specified, all assignments on the command line after the \c -after option will be postponed until after the specified files are parsed. - \target ProjectMode \section1 Project Mode Options \snippet code/doc_src_qmake-manual.pro 12 @@ -884,7 +884,6 @@ to specify a list of libraries that each project needs to link against, and \c QMAKE_LIBS_X11 would be used to extend this list. - \target ANDROID_ABIS \section1 ANDROID_ABIS \note This variable applies only to Android targets. @@ -902,7 +901,6 @@ it is not recommended since it will override any ABIs specified on the \c qmake command line. - \target ANDROID_API_VERSION \section1 ANDROID_API_VERSION \note This variable applies only to Android targets. @@ -910,7 +908,6 @@ Specifies the Android API level number. For more information, see \l{Android: Build Numbers}{Android Build Numbers}. - \target ANDROID_APPLICATION_ARGUMENTS \section1 ANDROID_APPLICATION_ARGUMENTS \note This variable applies only to Android targets. @@ -923,7 +920,6 @@ ANDROID_APPLICATION_ARGUMENTS = "arg1 arg2 arg3" \endcode - \target ANDROID_BUNDLED_JAR_DEPENDENCIES \section1 ANDROID_BUNDLED_JAR_DEPENDENCIES \note This variable applies only to Android modules. @@ -935,7 +931,6 @@ ANDROID_BUNDLED_JAR_DEPENDENCIES += jar/Qt6Android.jar \endcode - \target ANDROID_DEPLOYMENT_DEPENDENCIES \section1 ANDROID_DEPLOYMENT_DEPENDENCIES \note This variable applies only to Android targets. @@ -954,7 +949,6 @@ provides a way to override the automatic detection entirely, so if a library is listed before its dependencies, it will fail to load on some devices. - \target ANDROID_DEPLOYMENT_SETTINGS_FILE \section1 ANDROID_DEPLOYMENT_SETTINGS_FILE \note This variable applies only to Android targets. @@ -964,7 +958,6 @@ the settings file generated by qmake, thus you have to make sure to provide a valid settings file. - \target ANDROID_EXTRA_LIBS \section1 ANDROID_EXTRA_LIBS \note This variable applies only to Android targets. @@ -987,7 +980,6 @@ for (abi, ANDROID_ABIS): ANDROID_EXTRA_LIBS += $$PWD/library_name_$${abi}.so \endcode - \target ANDROID_EXTRA_PLUGINS \section1 ANDROID_EXTRA_PLUGINS \note This variable applies only to Android targets. @@ -1028,7 +1020,6 @@ ANDROID_EXTRA_PLUGINS += $$top_builddir/plugins \endcode - \target ANDROID_FEATURES \section1 ANDROID_FEATURES \note This variable applies only to Android modules. @@ -1041,7 +1032,6 @@ For more information, see \l{Android: }{Android Docs}. - \target ANDROID_LIB_DEPENDENCIES \section1 ANDROID_LIB_DEPENDENCIES \note This variable applies only to Android modules. @@ -1054,7 +1044,6 @@ plugins/libplugins_platforms_qtforandroid.so \endcode - \target ANDROID_MIN_SDK_VERSION \section1 ANDROID_MIN_SDK_VERSION \note This variable applies only to Android targets. @@ -1062,7 +1051,6 @@ Specifies the minimum Android API level for the project. By default, this variable is set to API level 23. - \target ANDROID_PACKAGE_SOURCE_DIR \section1 ANDROID_PACKAGE_SOURCE_DIR \note This variable applies only to Android targets. @@ -1083,7 +1071,6 @@ instance, you can make a custom \c {AndroidManifest.xml} for your application, then place this directly into the directory specified by this variable. - \target ANDROID_PERMISSIONS \section1 ANDROID_PERMISSIONS \note This variable applies only to Android modules. @@ -1096,7 +1083,6 @@ For more information, see \l{Android: }{Android Docs}. - \target ANDROID_TARGET_SDK_VERSION \section1 ANDROID_TARGET_SDK_VERSION \note This variable applies only to Android targets. @@ -1104,7 +1090,6 @@ Specifies the target Android API level for the project. By default, this variable is set to API level 31. - \target ANDROID_VERSION_CODE \section1 ANDROID_VERSION_CODE \note This variable applies only to Android targets. @@ -1112,7 +1097,6 @@ Specifies the application's version number. For more information, see \l{Android: App Versioning}{Android App Versioning}. - \target ANDROID_VERSION_NAME \section1 ANDROID_VERSION_NAME \note This variable applies only to Android targets. @@ -1120,7 +1104,6 @@ Specifies the application's version in as a human readable string. For more information, see \l{Android: App Versioning}{Android App Versioning}. - \target CONFIG \section1 CONFIG Specifies project configuration and compiler options. The values are @@ -1280,11 +1263,11 @@ qmake to track these dependencies. When this option is enabled, qmake will create a file with the extension \c .prl which will save meta-information about the library - (see \l{LibDepend}{Library Dependencies} for more info). + (see \l{Library Dependencies} for more info). \row \li link_prl \li When this option is enabled, qmake will process all libraries linked to by the application and find their meta-information (see - \l{LibDepend}{Library Dependencies} for more info). + \l{Library Dependencies} for more info). \row \li no_install_prl \li This option disables the generation of installation rules for generated .prl files. \endtable @@ -1391,7 +1374,6 @@ \snippet code/doc_src_qmake-manual.pro 26 - \target DEFINES \section1 DEFINES qmake adds the values of this variable as @@ -1401,7 +1383,6 @@ \snippet code/doc_src_qmake-manual.pro 27 - \target DEFINES_DEBUG \section1 DEFINES_DEBUG Specifies preprocessor defines for the debug configuration. The values of @@ -1411,7 +1392,6 @@ This variable was introduced in Qt 5.13.2. - \target DEFINES_RELEASE \section1 DEFINES_RELEASE Specifies preprocessor defines for the release configuration. The values of @@ -1424,21 +1404,18 @@ This variable was introduced in Qt 5.13.2. - \target DEF_FILE \section1 DEF_FILE \note This variable is used only on Windows when using the \c app template. Specifies a \c .def file to be included in the project. - \target DEPENDPATH \section1 DEPENDPATH Specifies a list of directories for qmake to scan, to resolve dependencies. This variable is used when qmake crawls through the header files that you \c{#include} in your source code. - \target DESTDIR \section1 DESTDIR Specifies where to put the \l{#TARGET}{target} file. @@ -1451,7 +1428,6 @@ the used build tool. In particular, parentheses do not work with \c{make}. - \target DISTFILES \section1 DISTFILES Specifies a list of files to be included in the dist @@ -1461,14 +1437,12 @@ \snippet code/doc_src_qmake-manual.pro 31 - \target DLLDESTDIR \section1 DLLDESTDIR \note This variable applies only to Windows targets. Specifies where to copy the \l{#TARGET}{target} dll. - \target EXTRA_TRANSLATIONS \section1 EXTRA_TRANSLATIONS Specifies a list of translation (.ts) files that contain @@ -1486,7 +1460,6 @@ See the \l{Qt Linguist Manual} for more information about internationalization (i18n) and localization (l10n) with Qt. - \target FORMS \section1 FORMS Specifies the UI files (see \l{Qt Designer Manual}) to be processed by \c uic @@ -1497,7 +1470,6 @@ \snippet code/doc_src_qmake-manual.pro 32 - \target GUID \section1 GUID Specifies the GUID that is set inside a \c{.vcproj} file. The GUID is @@ -1507,7 +1479,6 @@ This variable is specific to \c{.vcproj} files only; it is ignored otherwise. - \target HEADERS \section1 HEADERS Defines the header files for the project. @@ -1522,20 +1493,17 @@ See also \l{#SOURCES}{SOURCES}. - \target ICON \section1 ICON This variable is used only on Mac OS to set the application icon. Please see \l{Setting the Application Icon}{the application icon documentation} for more information. - \target IDLSOURCES \section1 IDLSOURCES This variable is used only on Windows for the Visual Studio project generation to put the specified files in the Generated Files folder. - \target INCLUDEPATH \section1 INCLUDEPATH Specifies the #include directories which should be @@ -1550,7 +1518,6 @@ \snippet qmake/spaces.pro quoting include paths with spaces - \target INSTALLS \section1 INSTALLS Specifies a list of resources that will be installed when @@ -1604,28 +1571,24 @@ This variable is also used to specify which additional files will be deployed to embedded devices. - \target JAVA_HOME \section1 JAVA_HOME \note This variable is useful only to Android targets. Specifies the JDK/OpenJDK installation path used for building the project. - \target LEXIMPLS \section1 LEXIMPLS Specifies a list of Lex implementation files. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target LEXOBJECTS \section1 LEXOBJECTS Specifies the names of intermediate Lex object files. The value of this variable is typically handled by qmake and rarely needs to be modified. - \target LEXSOURCES \section1 LEXSOURCES Specifies a list of Lex source files. All @@ -1636,7 +1599,6 @@ \snippet code/doc_src_qmake-manual.pro 37 - \target LIBS \section1 LIBS Specifies a list of libraries to be linked into the project. @@ -1660,7 +1622,6 @@ \snippet code/doc_src_qmake-manual.pro 39 - \target LIBS_PRIVATE \section1 LIBS_PRIVATE Specifies a list of libraries to be linked privately into the project. @@ -1673,7 +1634,6 @@ directly, it needs to link to A explicitly. Put differently, libraries linked privately are not exposed transitively at build time. - \target LITERAL_HASH \section1 LITERAL_HASH This variable is used whenever a literal hash character (\c{#}) is needed in @@ -1687,14 +1647,12 @@ By using \c LITERAL_HASH in this way, the \c # character can be used to construct a URL for the \c message() function to print to the console. - \target MAKEFILE \section1 MAKEFILE Specifies the name of the generated Makefile. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target MAKEFILE_GENERATOR \section1 MAKEFILE_GENERATOR Specifies the name of the Makefile generator to use @@ -1702,13 +1660,11 @@ handled internally by qmake and rarely needs to be modified. - \target MSVCPROJ_* \section1 MSVCPROJ_* These variables are handled internally by qmake and should not be modified or utilized. - \target MOC_DIR \section1 MOC_DIR Specifies the directory where all intermediate moc @@ -1718,7 +1674,6 @@ \snippet code/doc_src_qmake-manual.pro 40 - \target OBJECTIVE_HEADERS \section1 OBJECTIVE_HEADERS Defines the Objective-C++ header files for the project. @@ -1732,7 +1687,6 @@ See also \l{#OBJECTIVE_SOURCES}{OBJECTIVE_SOURCES}. - \target OBJECTIVE_SOURCES \section1 OBJECTIVE_SOURCES Specifies the names of all Objective-C/C++ source files in the project. @@ -1742,14 +1696,12 @@ See also \l{#OBJECTIVE_HEADERS}{OBJECTIVE_HEADERS}. - \target OBJECTS \section1 OBJECTS This variable is automatically populated from the \l{SOURCES} variable. The extension of each source file is replaced by .o (Unix) or .obj (Win32). You can add objects to the list. - \target OBJECTS_DIR \section1 OBJECTS_DIR Specifies the directory where all intermediate @@ -1759,7 +1711,6 @@ \snippet code/doc_src_qmake-manual.pro 41 - \target POST_TARGETDEPS \section1 POST_TARGETDEPS Lists the libraries that the \l{#TARGET}{target} depends on. Some backends, @@ -1771,7 +1722,6 @@ This list is placed after all builtin (and \link #PRE_TARGETDEPS $$PRE_TARGETDEPS \endlink) dependencies. - \target PRE_TARGETDEPS \section1 PRE_TARGETDEPS Lists libraries that the \l{#TARGET}{target} depends on. Some backends, @@ -1782,7 +1732,6 @@ This list is placed before all builtin dependencies. - \target PRECOMPILED_HEADER \section1 PRECOMPILED_HEADER Indicates the header file for creating a precompiled @@ -1791,7 +1740,6 @@ (Windows - all MSVC project types, Apple - Xcode, Makefile, Unix - gcc 3.3 and up). - \target PWD \section1 PWD Specifies the full path leading to the directory @@ -1803,7 +1751,6 @@ \note Do not attempt to overwrite the value of this variable. - \target OUT_PWD \section1 OUT_PWD Specifies the full path leading to the directory where qmake places the @@ -1811,7 +1758,6 @@ \note Do not attempt to overwrite the value of this variable. - \target QM_FILES_RESOURCE_PREFIX \section1 QM_FILES_RESOURCE_PREFIX Specifies the directory in the resource system where \c .qm files will @@ -1819,14 +1765,12 @@ The default is \c{:/i18n/}. - \target QM_FILES_INSTALL_PATH \section1 QM_FILES_INSTALL_PATH Specifies the target directory \c .qm files generated by \l{CONFIG}{CONFIG += lrelease} will be installed to. Does not have any effect if \l{CONFIG}{CONFIG += embed_translations} is set. - \target QML_IMPORT_PATH \section1 QML_IMPORT_PATH This variable is only used by \l{Qt Creator Manual}{Qt Creator}. If you have @@ -1835,7 +1779,6 @@ See \l{Qt Creator: Using QML Modules with Plugins} for details. - \target QMLPATHS \section1 QMLPATHS Expects a list of import paths that point to root directories of trees of @@ -1853,17 +1796,15 @@ application. Rather, they are only used at build time. In particular, qmlimportscanner uses them to find any QML modules it may need to mark as imported by your application. - + \sa QQmlEngine::addImportPath() - \target QMAKE_systemvariable \section1 QMAKE Specifies the name of the qmake program itself and is placed in generated Makefiles. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKESPEC_systemvariable \section1 QMAKESPEC A system variable that contains the full path of the qmake configuration that is used @@ -1871,7 +1812,20 @@ \note Do not attempt to overwrite the value of this variable. - \target QMAKE_AR_CMD + \section1 QMAKE_APPLE_DEVICE_ARCHS + + \note This variable is used on \macos only. + + Specifies a list of architectures to build for. By default, a project is + built for the development machine's architecture. This variable allows to + override the default and build for a different architecture or to create + multi-architecture binaries. + + This variable is usually specified on the command line or in the project + file. + + See \l{Qt for macOS} for more information. + \section1 QMAKE_AR_CMD \note This variable is used on Unix platforms only. @@ -1879,7 +1833,6 @@ Specifies the command to execute when creating a shared library. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_BUNDLE_DATA \section1 QMAKE_BUNDLE_DATA \note This variable is used on \macos, iOS, tvOS, and watchOS only. @@ -1958,21 +1911,18 @@ adjusted by modifying the \c QMAKE_CFLAGS_DEBUG and \c QMAKE_CFLAGS_RELEASE variables, respectively. - \target QMAKE_CFLAGS_DEBUG \section1 QMAKE_CFLAGS_DEBUG Specifies the C compiler flags for debug builds. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CFLAGS_RELEASE \section1 QMAKE_CFLAGS_RELEASE Specifies the C compiler flags for release builds. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO \section1 QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO Specifies the C compiler flags for release builds where @@ -1980,7 +1930,6 @@ The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CFLAGS_SHLIB \section1 QMAKE_CFLAGS_SHLIB \note This variable is used on Unix platforms only. @@ -1990,7 +1939,6 @@ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CFLAGS_THREAD \section1 QMAKE_CFLAGS_THREAD Specifies the compiler flags for creating a multi-threaded @@ -1998,21 +1946,18 @@ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CFLAGS_WARN_OFF \section1 QMAKE_CFLAGS_WARN_OFF This variable is used only when the \c {warn_off} \l{#CONFIG}{CONFIG} option is set. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CFLAGS_WARN_ON \section1 QMAKE_CFLAGS_WARN_ON This variable is used only when the \c {warn_on} \l{#CONFIG}{CONFIG} option is set. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CLEAN \section1 QMAKE_CLEAN Specifies a list of generated files (by \l{moc} and \l{uic}, for example) and @@ -2034,21 +1979,18 @@ adjusted by modifying the \c QMAKE_CXXFLAGS_DEBUG and \c QMAKE_CXXFLAGS_RELEASE variables, respectively. - \target QMAKE_CXXFLAGS_DEBUG \section1 QMAKE_CXXFLAGS_DEBUG Specifies the C++ compiler flags for debug builds. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CXXFLAGS_RELEASE \section1 QMAKE_CXXFLAGS_RELEASE Specifies the C++ compiler flags for release builds. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO \section1 QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO Specifies the C++ compiler flags for release builds where @@ -2056,7 +1998,6 @@ The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CXXFLAGS_SHLIB \section1 QMAKE_CXXFLAGS_SHLIB Specifies the C++ compiler flags for creating a shared library. @@ -2064,14 +2005,12 @@ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CXXFLAGS_THREAD \section1 QMAKE_CXXFLAGS_THREAD Specifies the C++ compiler flags for creating a multi-threaded application. The value of this variable is typically handled by qmake or \l{#QMAKESPEC} {qmake.conf} and rarely needs to be modified. - \target QMAKE_CXXFLAGS_WARN_OFF \section1 QMAKE_CXXFLAGS_WARN_OFF Specifies the C++ compiler flags for suppressing compiler @@ -2079,7 +2018,6 @@ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_CXXFLAGS_WARN_ON \section1 QMAKE_CXXFLAGS_WARN_ON Specifies C++ compiler flags for generating compiler warnings. @@ -2087,7 +2025,6 @@ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_DEVELOPMENT_TEAM \section1 QMAKE_DEVELOPMENT_TEAM \note This variable is used on \macos, iOS, tvOS, and watchOS only. @@ -2095,12 +2032,10 @@ The identifier of a development team to use for signing certificates and provisioning profiles. - \target QMAKE_DISTCLEAN \section1 QMAKE_DISTCLEAN Specifies a list of files to be removed by \c{make distclean}. - \target QMAKE_EXTENSION_SHLIB \section1 QMAKE_EXTENSION_SHLIB Contains the extension for shared libraries. The value of @@ -2110,7 +2045,6 @@ \note Platform-specific variables that change the extension override the contents of this variable. - \target QMAKE_EXTENSION_STATICLIB \section1 QMAKE_EXTENSION_STATICLIB Contains the extension for shared static libraries. The value of @@ -2121,51 +2055,51 @@ Contains the extension used on included moc files. - See also \l{Configuring qmake#Extensions}{File Extensions}. + See also \l{Configuring qmake#File Extensions}{File Extensions}. \section1 QMAKE_EXT_UI Contains the extension used on \QD UI files. - See also \l{Configuring qmake#Extensions}{File Extensions}. + See also \l{Configuring qmake#File Extensions}{File Extensions}. \section1 QMAKE_EXT_PRL Contains the extension used on created PRL files. - See also \l{Configuring qmake#Extensions}{File Extensions}, - \l{LibDepend}{Library Dependencies}. + See also \l{Configuring qmake#File Extensions}{File Extensions}, + \l{Library Dependencies}. \section1 QMAKE_EXT_LEX Contains the extension used on files given to Lex. - See also \l{Configuring qmake#Extensions}{File Extensions}, + See also \l{Configuring qmake#File Extensions}{File Extensions}, \l{#LEXSOURCES}{LEXSOURCES}. \section1 QMAKE_EXT_YACC Contains the extension used on files given to Yacc. - See also \l{Configuring qmake#Extensions}{File Extensions}, + See also \l{Configuring qmake#File Extensions}{File Extensions}, \l{#YACCSOURCES}{YACCSOURCES}. \section1 QMAKE_EXT_OBJ Contains the extension used on generated object files. - See also \l{Configuring qmake#Extensions}{File Extensions}. + See also \l{Configuring qmake#File Extensions}{File Extensions}. \section1 QMAKE_EXT_CPP Contains suffixes for files that should be interpreted as C++ source code. - See also \l{Configuring qmake#Extensions}{File Extensions}. + See also \l{Configuring qmake#File Extensions}{File Extensions}. \section1 QMAKE_EXT_H Contains suffixes for files which should be interpreted as C header files. - See also \l{Configuring qmake#Extensions}{File Extensions}. + See also \l{Configuring qmake#File Extensions}{File Extensions}. \section1 QMAKE_EXTRA_COMPILERS @@ -2179,7 +2113,6 @@ See also \l{Adding Custom Targets}. - \target QMAKE_FAILED_REQUIREMENTS \section1 QMAKE_FAILED_REQUIREMENTS Contains the list of failed requirements. @@ -2200,7 +2133,6 @@ See \l{Creating Frameworks} for more information about creating frameworks and library bundles. - \target QMAKE_FRAMEWORK_VERSION \section1 QMAKE_FRAMEWORK_VERSION \note This variable is used on \macos, iOS, tvOS, and watchOS only. @@ -2214,7 +2146,6 @@ See \l{Creating Frameworks} for more information about creating frameworks. - \target QMAKE_HOST \section1 QMAKE_HOST Provides information about the host machine running qmake. @@ -2233,14 +2164,12 @@ \snippet code/doc_src_qmake-manual.pro 187 - \target QMAKE_INCDIR \section1 QMAKE_INCDIR Specifies the list of system header paths that are appended to \l{INCLUDEPATH}. The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_INCDIR_EGL \section1 QMAKE_INCDIR_EGL Specifies the location of EGL header files to be added to @@ -2249,7 +2178,6 @@ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_INCDIR_OPENGL \section1 QMAKE_INCDIR_OPENGL Specifies the location of OpenGL header files to be added @@ -2273,7 +2201,6 @@ If the OpenGL implementation uses EGL (most OpenGL/ES systems), then QMAKE_INCDIR_EGL may also need to be set. - \target QMAKE_INCDIR_OPENVG \section1 QMAKE_INCDIR_OPENVG Specifies the location of OpenVG header files to be added @@ -2285,7 +2212,6 @@ If the OpenVG implementation uses EGL then QMAKE_INCDIR_EGL may also need to be set. - \target QMAKE_INCDIR_X11 \section1 QMAKE_INCDIR_X11 \note This variable is used on Unix platforms only. @@ -2295,7 +2221,6 @@ is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_INFO_PLIST \section1 QMAKE_INFO_PLIST \note This variable is used on \macos, iOS, tvOS, and watchOS platforms only. @@ -2389,7 +2314,6 @@ platform or type of project, use one of the specialized variables for that purpose instead of this variable. - \target QMAKE_LFLAGS_CONSOLE \section1 QMAKE_LFLAGS_CONSOLE \note This variable is used on Windows only. @@ -2657,7 +2581,6 @@ value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_LRELEASE_FLAGS \section1 QMAKE_LRELEASE_FLAGS List of additional options passed to \l{Using lrelease}{lrelease} when @@ -2694,7 +2617,6 @@ files for IDEs. The default value is the target name. The value of this variable is typically handled by qmake and rarely needs to be modified. - \target QMAKE_PROVISIONING_PROFILE \section1 QMAKE_PROVISIONING_PROFILE \note This variable is used on \macos, iOS, tvOS, and watchOS only. @@ -2827,7 +2749,6 @@ variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target QMAKE_TARGET_COMPANY \section1 QMAKE_TARGET_COMPANY Windows only. Specifies the company for the project target; this is @@ -2835,7 +2756,6 @@ properties. This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set. - \target QMAKE_TARGET_DESCRIPTION \section1 QMAKE_TARGET_DESCRIPTION Windows only. Specifies the description for the project target; this is @@ -2843,7 +2763,6 @@ properties. This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set. - \target QMAKE_TARGET_COPYRIGHT \section1 QMAKE_TARGET_COPYRIGHT Windows only. Specifies the copyright information for the project target; @@ -2852,7 +2771,6 @@ \l{RC_ICONS} variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set. - \target QMAKE_TARGET_PRODUCT \section1 QMAKE_TARGET_PRODUCT Windows only. Specifies the product for the project target; this is used @@ -2860,7 +2778,6 @@ This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set. - \target QMAKE_TARGET_ORIGINAL_FILENAME \section1 QMAKE_TARGET_ORIGINAL_FILENAME Windows only. Specifies the original file name for the project target; @@ -2869,7 +2786,6 @@ \l{RC_ICONS} variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set. - \target QMAKE_TARGET_INTERNALNAME \section1 QMAKE_TARGET_INTERNALNAME Windows only. Specifies the internal name for the project target; this is @@ -2877,7 +2793,6 @@ properties. This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set. - \target QMAKE_TARGET_COMMENTS \section1 QMAKE_TARGET_COMMENTS Windows only. Specifies the comments for the project target; this is @@ -2885,7 +2800,6 @@ properties. This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set. - \target QMAKE_TARGET_TRADEMARKS \section1 QMAKE_TARGET_TRADEMARKS Windows only. Specifies the trademark information for the project target; @@ -2894,7 +2808,6 @@ \l{RC_ICONS} variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set. - \target QMAKE_MANIFEST \section1 QMAKE_MANIFEST Windows only. Specifies the manifest file for the project target. @@ -2995,22 +2908,18 @@ shared/dynamic build of Qt, or when linking libraries. It may be used for deployment of dynamic plugins at a later time. - \target QT_VERSION_variable \section1 QT_VERSION Contains the current version of Qt. - \target QT_MAJOR_VERSION \section1 QT_MAJOR_VERSION Contains the current major version of Qt. - \target QT_MINOR_VERSION \section1 QT_MINOR_VERSION Contains the current minor version of Qt. - \target QT_PATCH_VERSION \section1 QT_PATCH_VERSION Contains the current patch version of Qt. @@ -3020,14 +2929,12 @@ Windows only. Specifies the name of the Windows resource file (.rc) for the target. See \l{Adding Windows Resource Files}. - \target RC_CODEPAGE \section1 RC_CODEPAGE Windows only. Specifies the codepage that should be specified in a generated .rc file. This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set. - \target RC_DEFINES \section1 RC_DEFINES Windows only. qmake adds the values of this variable as RC preprocessor macros @@ -3035,7 +2942,6 @@ \snippet code/doc_src_qmake-manual.pro 186 - \target RC_ICONS \section1 RC_ICONS Windows only. Specifies the icons that should be included into a generated @@ -3043,7 +2949,6 @@ are not set. More details about the generation of .rc files can be found in the \l{Platform Notes}. - \target RC_LANG \section1 RC_LANG Windows only. Specifies the language that should be specified in a generated @@ -3054,7 +2959,6 @@ Specifies include paths that are passed to the Windows Resource Compiler. - \target RCC_DIR \section1 RCC_DIR Specifies the directory for Qt Resource Compiler output files. @@ -3063,7 +2967,6 @@ \snippet code/doc_src_qmake-manual.pro 48 - \target REQUIRES \section1 REQUIRES Specifies a list of values that are evaluated as conditions. If any of the conditions is false, @@ -3072,7 +2975,6 @@ \note We recommend using the \l{requires(condition)}{requires()} function instead if you want to skip projects or subprojects when building. - \target RESOURCES \section1 RESOURCES Specifies the name of the resource collection files (qrc) @@ -3088,7 +2990,6 @@ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target SOURCES \section1 SOURCES Specifies the names of all source files in the project. @@ -3099,7 +3000,6 @@ See also \l{#HEADERS}{HEADERS}. - \target SUBDIRS \section1 SUBDIRS This variable, when used with the \c subdirs \l{#TEMPLATE}{template} @@ -3161,7 +3061,6 @@ \snippet code/doc_src_qmake-manual.pro 149 - \target TARGET \section1 TARGET Specifies the name of the target file. Contains the base name of the project @@ -3194,7 +3093,6 @@ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. - \target TEMPLATE \section1 TEMPLATE Specifies the name of the template to use when generating the project. The @@ -3231,7 +3129,6 @@ determine how the project is built, it is necessary to declare TEMPLATE on the command line rather than use the \c -t option. - \target TRANSLATIONS \section1 TRANSLATIONS Specifies a list of translation (.ts) files that contain @@ -3249,7 +3146,25 @@ See the \l{Qt Linguist Manual} for more information about internationalization (i18n) and localization (l10n) with Qt. - \target UI_DIR + \section1 TR_EXCLUDE + + Specifies a list of paths (source files, subdirectories, and C++ include + paths) to be excluded from handling in \c{lupdate}. The paths may contain + wildcards. Relative paths are considered to be relative to + \l{_PRO_FILE_PWD_}. + + For example, to exclude source files: + + \snippet code/doc_src_qmake-manual.pro TR_EXCLUDE sources + + To exclude subdirectories of a \c SUBDIRS project: + + \snippet code/doc_src_qmake-manual.pro TR_EXCLUDE SUBDIRS + + To speed up lupdate's C++ parser, exclude include paths: + + \snippet code/doc_src_qmake-manual.pro TR_EXCLUDE include paths + \section1 UI_DIR Specifies the directory where all intermediate files from uic @@ -3259,7 +3174,6 @@ \snippet code/doc_src_qmake-manual.pro 54 - \target VERSION \section1 VERSION Specifies the version number of the application if the \c app @@ -3310,7 +3224,6 @@ See also \l{#DEPENDPATH}{DEPENDPATH}. - \target WINDOWS_TARGET_PLATFORM_VERSION \section1 WINDOWS_TARGET_PLATFORM_VERSION Specifies the targeted Windows version; this corresponds to the tag @@ -3319,7 +3232,6 @@ On desktop Windows, the default value is the value of the environment variable \c{WindowsSDKVersion}. - \target WINDOWS_TARGET_PLATFORM_MIN_VERSION \section1 WINDOWS_TARGET_PLATFORM_MIN_VERSION Specifies the minimum version of the Windows target platform; this @@ -3327,7 +3239,6 @@ Defaults to \c{WINDOWS_TARGET_PLATFORM_VERSION}. - \target YACCSOURCES \section1 YACCSOURCES Specifies a list of Yacc source files to be included @@ -3407,7 +3318,6 @@ \snippet code/doc_src_qmake-manual.pro 59 - \target qmake-cat \section2 cat(filename[, mode]) Returns the contents of \c filename. You can specify the following options @@ -3459,7 +3369,6 @@ \snippet code/doc_src_qmake-manual.pro 173 - \target findfunction \section2 find(variablename, substr) Returns all the values in \c variablename that match the regular expression @@ -3475,7 +3384,6 @@ Expands the specified wildcard pattern and returns a list of filenames. If \c recursive is true, this function descends into subdirectories. - \target fn_first \section2 first(variablename) Returns the first value of \c variablename. @@ -3484,9 +3392,9 @@ \snippet code/doc_src_qmake-manual.pro 161 - See also \l{take_first()}, \l{fn_last}{last()}. + See also \l{take_first(variablename)}{take_first()}, + \l{last(variablename)}{last()}. - \target format_number() \section2 format_number(number[, options...]) Returns \c number in the format specified by \c options. You can specify the @@ -3537,7 +3445,6 @@ to empty strings. If you need to encode spaces in \c glue, \c before, or \c after, you must quote them. - \target fn_last \section2 last(variablename) Returns the last value of \c variablename. @@ -3546,7 +3453,8 @@ \snippet code/doc_src_qmake-manual.pro 162 - See also \l{take_last()}, \l{fn_first}{first()}. + See also \l{take_last(variablename)}{take_last()}, + \l{first(variablename)}{first()}. \section2 list(arg1 [, arg2 ..., argn]) @@ -3567,7 +3475,6 @@ See also \l{upper(arg1 [, arg2 ..., argn])}{upper()}. - \target member() \section2 member(variablename [, start [, end]]) Returns the slice of the list value of \c variablename with the @@ -3594,9 +3501,8 @@ that an empty list will be returned only when an index is invalid (which is implied by the input variable being empty). - See also \l{str_member()}. + See also \l{str_member(arg [, start [, end]])}{str_member()}. - \target num_add() \section2 num_add(arg1 [, arg2 ..., argn]) Takes an arbitrary number of numeric arguments and adds them up, @@ -3728,12 +3634,11 @@ See also \l{system_quote(arg)}{system_quote()}. - \target fn_size \section2 size(variablename) Returns the number of values of \c variablename. - See also \l{str_size()}. + See also \l{str_size(arg)}{str_size()}. \section2 sort_depends(variablename, prefix) @@ -3747,7 +3652,8 @@ in ascending ASCII order. Numerical sorting can be accomplished by zero-padding the values to - a fixed length with the help of the \l{format_number()} function. + a fixed length with the help of the + \l{format_number(number[, options...])}{format_number()} function. This function was introduced in Qt 5.8. @@ -3765,12 +3671,11 @@ Replaces %1-%9 in \c string with the arguments passed in the comma-separated list of function \c arguments and returns the processed string. - \target str_member() \section2 str_member(arg [, start [, end]]) - This function is identical to \l{member()}, except that it operates - on a string value instead of a list variable, and consequently the - indices refer to character positions. + This function is identical to \l{member(variablename [, start [, end]])} + {member()}, except that it operates on a string value instead of a list + variable, and consequently the indices refer to character positions. This function can be used to implement many common string slicing operations: @@ -3795,20 +3700,19 @@ \note In these implementations, a zero \c len argument needs to be handled separately. - See also \l{member()}, \l{num_add()}. + See also \l{member(variablename [, start [, end]])}{member()}, + \l{num_add(arg1 [, arg2 ..., argn])}{num_add()}. This function was introduced in Qt 5.8. - \target str_size() \section2 str_size(arg) Returns the number of characters in the argument. - See also \l{fn_size}{size()}. + See also \l{size(variablename)}{size()}. This function was introduced in Qt 5.8. - \target system_replace \section2 system(command[, mode[, stsvar]]) You can use this variant of the \c system function to obtain stdout from the @@ -3818,9 +3722,10 @@ \snippet code/doc_src_qmake-manual.pro 72 - Like \l {qmake-cat}{$$cat()}, the \a mode argument takes \c blob, \c lines, - \c true, and \c false as value. However, the legacy word splitting rules - (i.e. empty or \c true, and \c false) differ subtly. + Like \l {cat(filename[, mode])}{$$cat()}, the \a mode argument takes + \c blob, \c lines, \c true, and \c false as value. However, the legacy + word splitting rules (i.e. empty or \c true, and \c false) differ + subtly. If you pass \c stsvar, the command's exit status will be stored in that variable. If the command crashes, the status will be -1, otherwise a @@ -3849,7 +3754,6 @@ See also \l{shell_quote(arg)}{shell_quote()}. - \target take_first() \section2 take_first(variablename) Returns the first value of \c variablename and removes it from the @@ -3859,9 +3763,9 @@ This function was introduced in Qt 5.8. - See also \l{take_last()}, \l{fn_first}{first()}. + See also \l{take_last(variablename)}{take_last()}, + \l{first(variablename)}{first()}. - \target take_last() \section2 take_last(variablename) Returns the last value of \c variablename and removes it from the @@ -3871,9 +3775,9 @@ This function was introduced in Qt 5.8. - See also \l{take_first()}, \l{fn_last}{last()}. + See also \l{take_first(variablename)}{take_first()}, + \l{last(variablename)}{last()}. - \target unique \section2 unique(variablename) Returns the list of values in \c variablename with duplicate entries removed. @@ -3951,7 +3855,6 @@ appropriate files are added to the \l{SOURCES} and \l{HEADERS} variables. - \target countfunction \section2 count(variablename, number) Succeeds if the variable \c variablename contains a list with the @@ -4030,7 +3933,6 @@ Exports the current value of \c variablename from the local context of a function to the global context. - \target forfunction \section2 for(iterate, list) Starts a loop that iterates over all values in \c list, setting \c iterate to each @@ -4175,9 +4077,9 @@ \snippet code/doc_src_qmake-manual.pro 71 - See also the replace variant of \l{system_replace}{system()}. + See also the replace variant of \l{system(command[, mode[, stsvar]])} + {system()}. - \target touchfunction \section2 touch(filename, reference_filename) Updates the time stamp of \c filename to match the time stamp of @@ -4396,7 +4298,6 @@ \snippet code/doc_src_qmake-manual.pro 78 - \target QMAKESPEC \section1 QMAKESPEC qmake requires a platform and compiler @@ -4420,7 +4321,6 @@ \note The \c QMAKESPEC path will be automatically added to the generated Makefile after the contents of the \l{INCLUDEPATH} system variable. - \target cache \section1 Cache File The cache file is a special file qmake reads to @@ -4433,7 +4333,6 @@ If qmake finds a \c{.qmake.cache} file then it will process this file first before it processes the project file. - \target Extensions \section1 File Extensions Under normal circumstances qmake will try to @@ -4454,7 +4353,7 @@ \li \l{QMAKE_EXT_UI} modifies the extension used for \QD UI files (usually in \l{FORMS}). \li \l{QMAKE_EXT_PRL} modifies the extension placed on - \l{LibDepend}{library dependency files}. + \l{Library Dependencies}{library dependency files}. \li \l{QMAKE_EXT_LEX} changes the suffix used in Lex files (usually in \l{LEXSOURCES}). \li \l{QMAKE_EXT_YACC} changes the suffix used in Yacc files (usually in @@ -4535,8 +4434,8 @@ \snippet code/doc_src_qmake-manual.pro 92 In the above line, \c USE_MY_STUFF will only be added to the list of pre-processor - defines if it is not already defined. Note that the \l{unique}{unique()} - function can also be used to ensure that a variable only contains one + defines if it is not already defined. Note that the \l{unique(variablename)} + {unique()} function can also be used to ensure that a variable only contains one instance of each value. \section2 Replacing Values @@ -4595,7 +4494,6 @@ \snippet code/doc_src_qmake-manual.pro 101 - \target Scopes \section1 Scopes Scopes are similar to \c if statements in procedural programming languages. @@ -4722,7 +4620,6 @@ You can test for any other platform-compiler combination as long as a specification exists for it in the \c mkspecs directory. - \target UsingVariables \section1 Variables Many of the variables used in project files are special variables that @@ -4755,7 +4652,6 @@ \snippet code/doc_src_qmake-manual.pro 100 - \target UsingReplaceFunctions \section1 Replace Functions qmake provides a selection of built-in @@ -4781,7 +4677,6 @@ \snippet qmake/replacefunction.pro 0 - \target UsingTestFunctions \section1 Test Functions qmake provides built-in functions that can be @@ -5100,7 +4995,6 @@ to be linked in. \endtable - \target LibDepend \section1 Library Dependencies Often when linking against a library, qmake @@ -5154,7 +5048,6 @@ \previouspage Advanced Usage \nextpage Configuring qmake - \target Introduction Precompiled headers (PCH) are a performance feature supported by some compilers to compile a stable body of code, and store the compiled @@ -5183,7 +5076,6 @@ \endlist \endlist - \target ADD_PCH \section1 Adding Precompiled Headers to Your Project The precompiled header must contain code which is \e stable @@ -5196,7 +5088,6 @@ C++ includes, since the precompiled header file for C files may not contain C++ code. - \target PROJECT_OPTIONS \section2 Project Options To make your project use precompiled headers, you only need to define the @@ -5236,7 +5127,6 @@ To avoid potential conflicts like these, give distinctive names to header files that will be precompiled. - \target EXAMPLE_PROJECT \section1 Example Project You can find the following source code in the @@ -5550,7 +5440,6 @@ Platform-specific variables are not described here. For more information, see \l{Qt for Windows - Deployment} and \l{Qt for macOS}. - \target Application \section1 Building an Application The \c app template tells qmake to generate a @@ -5670,7 +5559,6 @@ The only primary requirement is that the test program exit with a zero exit code on success, and a non-zero exit code on failure. - \target Library \section1 Building a Library The \c lib template tells qmake to generate a Makefile that will build a @@ -5699,7 +5587,6 @@ X11, \macos, and iOS, the library name will be prefixed by \c lib. On Windows, no prefix is added to the file name. - \target Plugin \section1 Building a Plugin Plugins are built using the \c lib template, as described in the previous diff --git a/qmake/propertyprinter.cpp b/qmake/propertyprinter.cpp index 4ba56327..10c94942 100644 --- a/qmake/propertyprinter.cpp +++ b/qmake/propertyprinter.cpp @@ -5,6 +5,10 @@ #include +#include +#include +#include + QT_BEGIN_NAMESPACE void qmakePropertyPrinter(const QList> &values) @@ -22,11 +26,12 @@ void qmakePropertyPrinter(const QList> &values) void jsonPropertyPrinter(const QList> &values) { - std::cout << "{\n"; - for (const auto &val : values) { - std::cout << "\"" << qPrintable(val.first) << "\":\"" << qPrintable(val.second) << "\",\n"; - } - std::cout << "}\n"; + QJsonObject object; + for (const auto &val : values) + object.insert(val.first, val.second); + + QJsonDocument document(object); + std::cout << document.toJson().constData(); } QT_END_NAMESPACE diff --git a/qt_cmdline.cmake b/qt_cmdline.cmake index 5450b256..372e6873 100644 --- a/qt_cmdline.cmake +++ b/qt_cmdline.cmake @@ -43,6 +43,8 @@ qt_commandline_option(avx TYPE boolean) qt_commandline_option(avx2 TYPE boolean) qt_commandline_option(avx512 TYPE boolean NAME avx512f) qt_commandline_option(c++std TYPE cxxstd) +qt_commandline_option(unity-build TYPE boolean NAME unity_build) +qt_commandline_option(unity-build-batch-size TYPE string NAME unity_build_batch_size) qt_commandline_option(ccache TYPE boolean NAME ccache) qt_commandline_option(commercial TYPE void) qt_commandline_option(confirm-license TYPE void) diff --git a/src/3rdparty/double-conversion/double-conversion/bignum.cc b/src/3rdparty/double-conversion/double-conversion/bignum.cc index d6745d75..5c74d70d 100644 --- a/src/3rdparty/double-conversion/double-conversion/bignum.cc +++ b/src/3rdparty/double-conversion/double-conversion/bignum.cc @@ -147,7 +147,7 @@ void Bignum::AssignHexString(Vector value) { } if (tmp > 0) { DOUBLE_CONVERSION_ASSERT(tmp <= kBigitMask); - RawBigit(used_bigits_++) = (tmp & kBigitMask); + RawBigit(used_bigits_++) = static_cast(tmp & kBigitMask); } Clamp(); } @@ -204,7 +204,7 @@ void Bignum::AddBignum(const Bignum& other) { carry = sum >> kBigitSize; ++bigit_pos; } - used_bigits_ = (std::max)(bigit_pos, static_cast(used_bigits_)); + used_bigits_ = static_cast(std::max(bigit_pos, static_cast(used_bigits_))); DOUBLE_CONVERSION_ASSERT(IsClamped()); } @@ -240,7 +240,7 @@ void Bignum::ShiftLeft(const int shift_amount) { if (used_bigits_ == 0) { return; } - exponent_ += (shift_amount / kBigitSize); + exponent_ += static_cast(shift_amount / kBigitSize); const int local_shift = shift_amount % kBigitSize; EnsureCapacity(used_bigits_ + 1); BigitsShiftLeft(local_shift); @@ -418,7 +418,7 @@ void Bignum::Square() { DOUBLE_CONVERSION_ASSERT(accumulator == 0); // Don't forget to update the used_digits and the exponent. - used_bigits_ = product_length; + used_bigits_ = static_cast(product_length); exponent_ *= 2; Clamp(); } @@ -739,8 +739,8 @@ void Bignum::Align(const Bignum& other) { for (int i = 0; i < zero_bigits; ++i) { RawBigit(i) = 0; } - used_bigits_ += zero_bigits; - exponent_ -= zero_bigits; + used_bigits_ += static_cast(zero_bigits); + exponent_ -= static_cast(zero_bigits); DOUBLE_CONVERSION_ASSERT(used_bigits_ >= 0); DOUBLE_CONVERSION_ASSERT(exponent_ >= 0); diff --git a/src/3rdparty/double-conversion/double-conversion/double-to-string.cc b/src/3rdparty/double-conversion/double-conversion/double-to-string.cc index bb369fe8..215eaa96 100644 --- a/src/3rdparty/double-conversion/double-conversion/double-to-string.cc +++ b/src/3rdparty/double-conversion/double-conversion/double-to-string.cc @@ -79,7 +79,14 @@ void DoubleToStringConverter::CreateExponentialRepresentation( StringBuilder* result_builder) const { DOUBLE_CONVERSION_ASSERT(length != 0); result_builder->AddCharacter(decimal_digits[0]); - if (length != 1) { + if (length == 1) { + if ((flags_ & EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL) != 0) { + result_builder->AddCharacter('.'); + if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT_IN_EXPONENTIAL) != 0) { + result_builder->AddCharacter('0'); + } + } + } else { result_builder->AddCharacter('.'); result_builder->AddSubstring(&decimal_digits[1], length-1); } diff --git a/src/3rdparty/double-conversion/double-conversion/double-to-string.h b/src/3rdparty/double-conversion/double-conversion/double-to-string.h index 04a4ac38..abe60e88 100644 --- a/src/3rdparty/double-conversion/double-conversion/double-to-string.h +++ b/src/3rdparty/double-conversion/double-conversion/double-to-string.h @@ -78,7 +78,9 @@ class DoubleToStringConverter { EMIT_TRAILING_DECIMAL_POINT = 2, EMIT_TRAILING_ZERO_AFTER_POINT = 4, UNIQUE_ZERO = 8, - NO_TRAILING_ZERO = 16 + NO_TRAILING_ZERO = 16, + EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL = 32, + EMIT_TRAILING_ZERO_AFTER_POINT_IN_EXPONENTIAL = 64 }; // Flags should be a bit-or combination of the possible Flags-enum. @@ -97,6 +99,13 @@ class DoubleToStringConverter { // of the result in precision mode. Matches printf's %g. // When EMIT_TRAILING_ZERO_AFTER_POINT is also given, one trailing zero is // preserved. + // - EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL: when the input number has + // exactly one significant digit and is converted into exponent form then a + // trailing decimal point is appended to the significand in shortest mode + // or in precision mode with one requested digit. + // - EMIT_TRAILING_ZERO_AFTER_POINT_IN_EXPONENTIAL: in addition to a trailing + // decimal point emits a trailing '0'-character. This flag requires the + // EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL flag. // // Infinity symbol and nan_symbol provide the string representation for these // special values. If the string is NULL and the special value is encountered @@ -132,6 +141,22 @@ class DoubleToStringConverter { // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. // + // When converting numbers with exactly one significant digit to exponent + // form in shortest mode or in precision mode with one requested digit, the + // EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT flags have + // no effect. Use the EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL flag to + // append a decimal point in this case and the + // EMIT_TRAILING_ZERO_AFTER_POINT_IN_EXPONENTIAL flag to also append a + // '0'-character in this case. + // Example with decimal_in_shortest_low = 0: + // ToShortest(0.0009) -> "9e-4" + // with EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL deactivated. + // ToShortest(0.0009) -> "9.e-4" + // with EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL activated. + // ToShortest(0.0009) -> "9.0e-4" + // with EMIT_TRAILING_DECIMAL_POINT_IN_EXPONENTIAL activated and + // EMIT_TRAILING_ZERO_AFTER_POINT_IN_EXPONENTIAL activated. + // // The min_exponent_width is used for exponential representations. // The converter adds leading '0's to the exponent until the exponent // is at least min_exponent_width digits long. diff --git a/src/3rdparty/double-conversion/qt_attribution.json b/src/3rdparty/double-conversion/qt_attribution.json index 21692f04..4166ccef 100644 --- a/src/3rdparty/double-conversion/qt_attribution.json +++ b/src/3rdparty/double-conversion/qt_attribution.json @@ -5,8 +5,8 @@ "QtUsage": "Used in Qt Core. Configure with -system-doubleconversion or -no-doubleconversion to avoid.", "Homepage": "https://github.com/google/double-conversion", - "Version": "3.2.1", - "DownloadLocation": "https://github.com/google/double-conversion/releases/tag/v3.2.1", + "Version": "3.3.0", + "DownloadLocation": "https://github.com/google/double-conversion/releases/tag/v3.3.0", "License": "BSD 3-clause \"New\" or \"Revised\" License", "LicenseId": "BSD-3-Clause", "LicenseFile": "LICENSE", diff --git a/src/3rdparty/freetype/README b/src/3rdparty/freetype/README index 327b94d8..cd4c1d7d 100644 --- a/src/3rdparty/freetype/README +++ b/src/3rdparty/freetype/README @@ -1,4 +1,4 @@ -FreeType 2.13.0 +FreeType 2.13.2 =============== Homepage: https://www.freetype.org @@ -32,9 +32,9 @@ sites. Go to and download one of the following files. - freetype-doc-2.13.0.tar.xz - freetype-doc-2.13.0.tar.gz - ftdoc2130.zip + freetype-doc-2.13.2.tar.xz + freetype-doc-2.13.2.tar.gz + ftdoc2132.zip To view the documentation online, go to diff --git a/src/3rdparty/freetype/docs/CHANGES b/src/3rdparty/freetype/docs/CHANGES index 3c6a8774..96cf607d 100644 --- a/src/3rdparty/freetype/docs/CHANGES +++ b/src/3rdparty/freetype/docs/CHANGES @@ -1,3 +1,57 @@ +CHANGES BETWEEN 2.13.1 and 2.13.2 (2023-Aug-25) + + I. MISCELLANEOUS + + - Better support for CFF2 variation fonts. + + - TrueType interpreter version 38 (also known as 'Infinality') has + been removed. + + - Improved OpenVMS support. + + +====================================================================== + +CHANGES BETWEEN 2.13.0 and 2.13.1 (2023-Jun-24) + + I. MISCELLANEOUS + + - New function `FT_Get_Default_Named_Instance` to get the index of + the default named instance of an OpenType Variation Font. + + - A new load flag `FT_LOAD_NO_SVG` to make FreeType ignore glyphs in + an 'SVG ' table. + + - New function `FT_GlyphSlot_AdjustWeight` to adjust the glyph + weight either horizontally or vertically. This is part of the + `ftsynth.h` header file, which is still considered to be in alpha + stage. + + - TrueType interpreter version 38 (also known as 'Infinality') has + been deactivated; the value of `TT_INTERPRETER_VERSION_38` is now + the same as `TT_INTERPRETER_VERSION_40`. + + - Updated OpenVMS support. + + - The base API documentation has been modularized for easier + handling. + + - Switching named instances on and off in Variation Fonts was buggy + if the design coordinates didn't change. + + - `ftbench` has a new command-line option `-a` to apply design + coordinates. + + - `ftview` can now flip SVG rendering on and off using the 'Z' key. + + - In `ftmulti` it is now possible to toggle the fill rule and + overlap flag used for rendering glyphs using the 'F3' and 'F4' + keys, respectively. Toggling the anti-aliased mode has been + changed to the 'TAB' key. + + +====================================================================== + CHANGES BETWEEN 2.12.1 and 2.13.0 (2023-Feb-09) I. IMPORTANT CHANGES @@ -12,7 +66,7 @@ CHANGES BETWEEN 2.12.1 and 2.13.0 (2023-Feb-09) https://learn.microsoft.com/en-us/typography/opentype/spec/colr - III. MISCELLANEOUS + II. MISCELLANEOUS - For OpenType Variable Fonts, `avar` table format 2.0 is now supported. The code was contributed by Behdad Esfahbod. @@ -75,6 +129,10 @@ CHANGES BETWEEN 2.12.1 and 2.13.0 (2023-Feb-09) af_debug_hints_ ``` + - The internal zlib library was updated to version 1.2.13. Note, + however, that FreeType is *not* affected by CVE-2022-37434 since + it doesn't use the `inflateGetHeader` function. + ====================================================================== @@ -2420,7 +2478,7 @@ CHANGES BETWEEN 2.3.8 and 2.3.7 is provided for x86 and ARM. See FT_CONFIG_OPTION_INLINE_MULFIX and FT_CONFIG_OPTION_NO_ASSEMBLER (in ftoption.h) for more. - - The handling of `tricky' fonts (this is, fonts which don't work + - The handling of `tricky' fonts (that is, fonts which don't work with the autohinter, needing the font format's hinting engine) has been generalized and changed slightly: @@ -2877,7 +2935,7 @@ CHANGES BETWEEN 2.2 and 2.1.10 II. IMPORTANT CHANGES - - Version 2.2 no longer exposes its internals, this is, the header + - Version 2.2 no longer exposes its internals, that is, the header files located in the `include/freetype/internal' directory of the source package are not copied anymore by the `make install' command. Consequently, a number of rogue clients which directly diff --git a/src/3rdparty/freetype/docs/DEBUG b/src/3rdparty/freetype/docs/DEBUG index 4a5ac3a4..7398df69 100644 --- a/src/3rdparty/freetype/docs/DEBUG +++ b/src/3rdparty/freetype/docs/DEBUG @@ -270,12 +270,12 @@ to access them. `FT2_DEBUG' environment variable. Use this function to override the value with `level'. Use value `NULL' to disable tracing. - FT_Trace_Set_Default_Level(): + FT_Trace_Set_Default_Level( void ) Reset the tracing levels to the default value, i.e., the value of the `FT2_DEBUG' environment variable or no tracing if not set. - FT_Set_Log_Handler( ft_custom_log_handler handler ): + FT_Set_Log_Handler( ft_custom_log_handler handler ) Use `handler' as a custom handler for formatting tracing and error messages. The `ft_custom_log_handler' typedef has the following @@ -290,7 +290,7 @@ to access them. first argument of `FT_TRACE' or `FT_ERROR', and `args' holds the remaining arguments. - FT_Set_Default_Log_Handler(): + FT_Set_Default_Log_Handler( void ) Reset the log handler to the default version. diff --git a/src/3rdparty/freetype/include/dlg/dlg.h b/src/3rdparty/freetype/include/dlg/dlg.h index 3a7abf8f..fa10730e 100644 --- a/src/3rdparty/freetype/include/dlg/dlg.h +++ b/src/3rdparty/freetype/include/dlg/dlg.h @@ -85,6 +85,13 @@ #endif #endif +// This macro is used when an assertion fails. It gets the source expression +// and can return an alternative (that must stay alive). +// Mainly useful to execute something on failed assertion. +#ifndef DLG_FAILED_ASSERTION_TEXT + #define DLG_FAILED_ASSERTION_TEXT(x) x +#endif + // - utility - // two methods needed since cplusplus does not support compound literals // and c does not support uniform initialization/initializer lists @@ -131,83 +138,12 @@ struct dlg_origin { // Type of the output handler, see dlg_set_handler. typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string, void* data); -#ifdef DLG_DISABLE +#ifndef DLG_DISABLE // Tagged/Untagged logging with variable level // Tags must always be in the format `("tag1", "tag2")` (including brackets) - #define dlg_log(level, ...) - #define dlg_logt(level, tags, ...) - - // Dynamic level assert macros in various versions for additional arguments - #define dlg_assertl(level, expr) // assert without tags/message - #define dlg_assertlt(level, tags, expr) // assert with tags - #define dlg_assertlm(level, expr, ...) // assert with message - #define dlg_assertltm(level, tags, expr, ...) // assert with tags & message - - // Sets the handler that is responsible for formatting and outputting log calls. - // This function is not thread safe and the handler is set globally. - // The handler itself must not change dlg tags or call a dlg macro (if it - // does so, the provided string or tags array in 'origin' might get invalid). - // The handler can also be used for various other things such as dealing - // with failed assertions or filtering calls based on the passed tags. - // The default handler is dlg_default_output (see its doc for more info). - // If using c++ make sure the registered handler cannot throw e.g. by - // wrapping everything into a try-catch blog. - inline void dlg_set_handler(dlg_handler handler, void* data) { - (void) handler; - (void) data; - } - - // Returns the currently active dlg handler and sets `data` to - // its user data pointer. `data` must not be NULL. - // Useful to create handler chains. - // This function is not threadsafe, i.e. retrieving the handler while - // changing it from another thread is unsafe. - // See `dlg_set_handler`. - inline dlg_handler dlg_get_handler(void** data) { - *data = NULL; - return NULL; - } - - // The default output handler. - // Only use this to reset the output handler, prefer to use - // dlg_generic_output (from output.h) which this function simply calls. - // It also flushes the stream used and correctly outputs even from multiple threads. - inline void dlg_default_output(const struct dlg_origin* o, const char* str, void* data) { - (void) o; - (void) str; - (void) data; - } - - // Adds the given tag associated with the given function to the thread specific list. - // If func is not NULL the tag will only applied to calls from the same function. - // Remove the tag again calling dlg_remove_tag (with exactly the same pointers!). - // Does not check if the tag is already present. - inline void dlg_add_tag(const char* tag, const char* func) { - (void) tag; - (void) func; - } - - // Removes a tag added with dlg_add_tag (has no effect for tags no present). - // The pointers must be exactly the same pointers that were supplied to dlg_add_tag, - // this function will not check using strcmp. When the same tag/func combination - // is added multiple times, this function remove exactly one candidate, it is - // undefined which. Returns whether a tag was found (and removed). - inline bool dlg_remove_tag(const char* tag, const char* func) { - (void) tag; - (void) func; - return true; - } - - // Returns the thread-specific buffer and its size for dlg. - // The buffer should only be used by formatting functions. - // The buffer can be reallocated and the size changed, just make sure - // to update both values correctly. - inline char** dlg_thread_buffer(size_t** size) { - (void) size; - return NULL; - } - -#else // DLG_DISABLE + // Example usages: + // dlg_log(dlg_level_warning, "test 1") + // dlg_logt(("tag1, "tag2"), dlg_level_debug, "test %d", 2) #define dlg_log(level, ...) if(level >= DLG_LOG_LEVEL) \ dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, \ DLG_FMT_FUNC(__VA_ARGS__), NULL) @@ -215,23 +151,31 @@ typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string, dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, \ DLG_FMT_FUNC(__VA_ARGS__), NULL) + // Dynamic level assert macros in various versions for additional arguments + // Example usages: + // dlg_assertl(dlg_level_warning, data != nullptr); + // dlg_assertlt(("tag1, "tag2"), dlg_level_trace, data != nullptr); + // dlg_asserttlm(("tag1), dlg_level_warning, data != nullptr, "Data must not be null"); + // dlg_assertlm(dlg_level_error, data != nullptr, "Data must not be null"); #define dlg_assertl(level, expr) if(level >= DLG_ASSERT_LEVEL && !(expr)) \ - dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, NULL, #expr) + dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, NULL, \ + DLG_FAILED_ASSERTION_TEXT(#expr)) #define dlg_assertlt(level, tags, expr) if(level >= DLG_ASSERT_LEVEL && !(expr)) \ - dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, NULL, #expr) + dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, NULL, \ + DLG_FAILED_ASSERTION_TEXT(#expr)) #define dlg_assertlm(level, expr, ...) if(level >= DLG_ASSERT_LEVEL && !(expr)) \ dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, \ - DLG_FMT_FUNC(__VA_ARGS__), #expr) + DLG_FMT_FUNC(__VA_ARGS__), DLG_FAILED_ASSERTION_TEXT(#expr)) #define dlg_assertltm(level, tags, expr, ...) if(level >= DLG_ASSERT_LEVEL && !(expr)) \ dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, \ - __func__, DLG_FMT_FUNC(__VA_ARGS__), #expr) + __func__, DLG_FMT_FUNC(__VA_ARGS__), DLG_FAILED_ASSERTION_TEXT(#expr)) - DLG_API void dlg_set_handler(dlg_handler handler, void* data); - DLG_API dlg_handler dlg_get_handler(void** data); - DLG_API void dlg_default_output(const struct dlg_origin*, const char* string, void*); - DLG_API void dlg_add_tag(const char* tag, const char* func); - DLG_API bool dlg_remove_tag(const char* tag, const char* func); - DLG_API char** dlg_thread_buffer(size_t** size); + #define dlg__assert_or(level, tags, expr, code, msg) if(!(expr)) {\ + if(level >= DLG_ASSERT_LEVEL) \ + dlg__do_log(level, tags, DLG_FILE, __LINE__, __func__, msg, \ + DLG_FAILED_ASSERTION_TEXT(#expr)); \ + code; \ + } (void) NULL // - Private interface: not part of the abi/api but needed in macros - // Formats the given format string and arguments as printf would, uses the thread buffer. @@ -239,8 +183,66 @@ typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string, DLG_API void dlg__do_log(enum dlg_level lvl, const char* const*, const char*, int, const char*, const char*, const char*); DLG_API const char* dlg__strip_root_path(const char* file, const char* base); + +#else // DLG_DISABLE + + #define dlg_log(level, ...) + #define dlg_logt(level, tags, ...) + + #define dlg_assertl(level, expr) // assert without tags/message + #define dlg_assertlt(level, tags, expr) // assert with tags + #define dlg_assertlm(level, expr, ...) // assert with message + #define dlg_assertltm(level, tags, expr, ...) // assert with tags & message + + #define dlg__assert_or(level, tags, expr, code, msg) if(!(expr)) { code; } (void) NULL #endif // DLG_DISABLE +// The API below is independent from DLG_DISABLE + +// Sets the handler that is responsible for formatting and outputting log calls. +// This function is not thread safe and the handler is set globally. +// The handler itself must not change dlg tags or call a dlg macro (if it +// does so, the provided string or tags array in 'origin' might get invalid). +// The handler can also be used for various other things such as dealing +// with failed assertions or filtering calls based on the passed tags. +// The default handler is dlg_default_output (see its doc for more info). +// If using c++ make sure the registered handler cannot throw e.g. by +// wrapping everything into a try-catch blog. +DLG_API void dlg_set_handler(dlg_handler handler, void* data); + +// The default output handler. +// Only use this to reset the output handler, prefer to use +// dlg_generic_output (from output.h) which this function simply calls. +// It also flushes the stream used and correctly outputs even from multiple threads. +DLG_API void dlg_default_output(const struct dlg_origin*, const char* string, void*); + +// Returns the currently active dlg handler and sets `data` to +// its user data pointer. `data` must not be NULL. +// Useful to create handler chains. +// This function is not threadsafe, i.e. retrieving the handler while +// changing it from another thread is unsafe. +// See `dlg_set_handler`. +DLG_API dlg_handler dlg_get_handler(void** data); + +// Adds the given tag associated with the given function to the thread specific list. +// If func is not NULL the tag will only applied to calls from the same function. +// Remove the tag again calling dlg_remove_tag (with exactly the same pointers!). +// Does not check if the tag is already present. +DLG_API void dlg_add_tag(const char* tag, const char* func); + +// Removes a tag added with dlg_add_tag (has no effect for tags no present). +// The pointers must be exactly the same pointers that were supplied to dlg_add_tag, +// this function will not check using strcmp. When the same tag/func combination +// is added multiple times, this function remove exactly one candidate, it is +// undefined which. Returns whether a tag was found (and removed). +DLG_API bool dlg_remove_tag(const char* tag, const char* func); + +// Returns the thread-specific buffer and its size for dlg. +// The buffer should only be used by formatting functions. +// The buffer can be reallocated and the size changed, just make sure +// to update both values correctly. +DLG_API char** dlg_thread_buffer(size_t** size); + // Untagged leveled logging #define dlg_trace(...) dlg_log(dlg_level_trace, __VA_ARGS__) #define dlg_debug(...) dlg_log(dlg_level_debug, __VA_ARGS__) @@ -263,6 +265,24 @@ typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string, #define dlg_assertm(expr, ...) dlg_assertlm(DLG_DEFAULT_ASSERT, expr, __VA_ARGS__) #define dlg_asserttm(tags, expr, ...) dlg_assertltm(DLG_DEFAULT_ASSERT, tags, expr, __VA_ARGS__) +// If (expr) does not evaluate to true, always executes 'code' (no matter what +// DLG_ASSERT_LEVEL is or if dlg is disabled or not). +// When dlg is enabled and the level is greater or equal to DLG_ASSERT_LEVEL, +// logs the failed assertion. +// Example usages: +// dlg_assertl_or(dlg_level_warn, data != nullptr, return); +// dlg_assertlm_or(dlg_level_fatal, data != nullptr, return, "Data must not be null"); +// dlg_assert_or(data != nullptr, logError(); return false); +#define dlg_assertltm_or(level, tags, expr, code, ...) dlg__assert_or(level, \ + DLG_CREATE_TAGS tags, expr, code, DLG_FMT_FUNC(__VA_ARGS__)) +#define dlg_assertlm_or(level, expr, code, ...) dlg__assert_or(level, \ + DLG_CREATE_TAGS(NULL), expr, code, DLG_FMT_FUNC(__VA_ARGS__)) +#define dlg_assertl_or(level, expr, code) dlg__assert_or(level, \ + DLG_CREATE_TAGS(NULL), expr, code, NULL) + +#define dlg_assert_or(expr, code) dlg_assertl_or(DLG_DEFAULT_ASSERT, expr, code) +#define dlg_assertm_or(expr, code, ...) dlg_assertlm_or(DLG_DEFAULT_ASSERT, expr, code, __VA_ARGS__) + #ifdef __cplusplus } #endif diff --git a/src/3rdparty/freetype/include/freetype/config/ftoption.h b/src/3rdparty/freetype/include/freetype/config/ftoption.h index 9e03e178..1976b33a 100644 --- a/src/3rdparty/freetype/include/freetype/config/ftoption.h +++ b/src/3rdparty/freetype/include/freetype/config/ftoption.h @@ -661,36 +661,12 @@ FT_BEGIN_HEADER * not) instructions in a certain way so that all TrueType fonts look like * they do in a Windows ClearType (DirectWrite) environment. See [1] for a * technical overview on what this means. See `ttinterp.h` for more - * details on the LEAN option. + * details on this option. * - * There are three possible values. - * - * Value 1: - * This value is associated with the 'Infinality' moniker, contributed by - * an individual nicknamed Infinality with the goal of making TrueType - * fonts render better than on Windows. A high amount of configurability - * and flexibility, down to rules for single glyphs in fonts, but also - * very slow. Its experimental and slow nature and the original - * developer losing interest meant that this option was never enabled in - * default builds. - * - * The corresponding interpreter version is v38. - * - * Value 2: - * The new default mode for the TrueType driver. The Infinality code - * base was stripped to the bare minimum and all configurability removed - * in the name of speed and simplicity. The configurability was mainly - * aimed at legacy fonts like 'Arial', 'Times New Roman', or 'Courier'. - * Legacy fonts are fonts that modify vertical stems to achieve clean - * black-and-white bitmaps. The new mode focuses on applying a minimal - * set of rules to all fonts indiscriminately so that modern and web - * fonts render well while legacy fonts render okay. - * - * The corresponding interpreter version is v40. - * - * Value 3: - * Compile both, making both v38 and v40 available (the latter is the - * default). + * The new default mode focuses on applying a minimal set of rules to all + * fonts indiscriminately so that modern and web fonts render well while + * legacy fonts render okay. The corresponding interpreter version is v40. + * The so-called Infinality mode (v38) is no longer available in FreeType. * * By undefining these, you get rendering behavior like on Windows without * ClearType, i.e., Windows XP without ClearType enabled and Win9x @@ -705,9 +681,7 @@ FT_BEGIN_HEADER * [1] * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */ -/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */ -#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2 -/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */ +#define TT_CONFIG_OPTION_SUBPIXEL_HINTING /************************************************************************** @@ -977,21 +951,14 @@ FT_BEGIN_HEADER /* - * The next three macros are defined if native TrueType hinting is + * The next two macros are defined if native TrueType hinting is * requested by the definitions above. Don't change this. */ #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER #define TT_USE_BYTECODE_INTERPRETER - #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING -#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1 -#define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY -#endif - -#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2 #define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL #endif -#endif #endif diff --git a/src/3rdparty/freetype/include/freetype/config/ftstdlib.h b/src/3rdparty/freetype/include/freetype/config/ftstdlib.h index 3c9d2ae5..f65148a9 100644 --- a/src/3rdparty/freetype/include/freetype/config/ftstdlib.h +++ b/src/3rdparty/freetype/include/freetype/config/ftstdlib.h @@ -111,13 +111,13 @@ #include -#define FT_FILE FILE -#define ft_fclose fclose -#define ft_fopen fopen -#define ft_fread fread -#define ft_fseek fseek -#define ft_ftell ftell -#define ft_sprintf sprintf +#define FT_FILE FILE +#define ft_fclose fclose +#define ft_fopen fopen +#define ft_fread fread +#define ft_fseek fseek +#define ft_ftell ftell +#define ft_snprintf snprintf /************************************************************************** diff --git a/src/3rdparty/freetype/include/freetype/freetype.h b/src/3rdparty/freetype/include/freetype/freetype.h index efff74fe..92acf379 100644 --- a/src/3rdparty/freetype/include/freetype/freetype.h +++ b/src/3rdparty/freetype/include/freetype/freetype.h @@ -102,61 +102,25 @@ FT_BEGIN_HEADER */ - - /*************************************************************************/ - /*************************************************************************/ - /* */ - /* B A S I C T Y P E S */ - /* */ - /*************************************************************************/ - /*************************************************************************/ - - /************************************************************************** * * @section: - * base_interface + * font_testing_macros * * @title: - * Base Interface + * Font Testing Macros * * @abstract: - * The FreeType~2 base font interface. + * Macros to test various properties of fonts. * * @description: - * This section describes the most important public high-level API - * functions of FreeType~2. + * Macros to test the most important font properties. + * + * It is recommended to use these high-level macros instead of directly + * testing the corresponding flags, which are scattered over various + * structures. * * @order: - * FT_Library - * FT_Face - * FT_Size - * FT_GlyphSlot - * FT_CharMap - * FT_Encoding - * FT_ENC_TAG - * - * FT_FaceRec - * - * FT_FACE_FLAG_SCALABLE - * FT_FACE_FLAG_FIXED_SIZES - * FT_FACE_FLAG_FIXED_WIDTH - * FT_FACE_FLAG_HORIZONTAL - * FT_FACE_FLAG_VERTICAL - * FT_FACE_FLAG_COLOR - * FT_FACE_FLAG_SFNT - * FT_FACE_FLAG_CID_KEYED - * FT_FACE_FLAG_TRICKY - * FT_FACE_FLAG_KERNING - * FT_FACE_FLAG_MULTIPLE_MASTERS - * FT_FACE_FLAG_VARIATION - * FT_FACE_FLAG_GLYPH_NAMES - * FT_FACE_FLAG_EXTERNAL_STREAM - * FT_FACE_FLAG_HINTER - * FT_FACE_FLAG_SVG - * FT_FACE_FLAG_SBIX - * FT_FACE_FLAG_SBIX_OVERLAY - * * FT_HAS_HORIZONTAL * FT_HAS_VERTICAL * FT_HAS_KERNING @@ -176,21 +140,59 @@ FT_BEGIN_HEADER * FT_IS_NAMED_INSTANCE * FT_IS_VARIATION * - * FT_STYLE_FLAG_BOLD - * FT_STYLE_FLAG_ITALIC + */ + + + /************************************************************************** * - * FT_SizeRec - * FT_Size_Metrics + * @section: + * library_setup * - * FT_GlyphSlotRec - * FT_Glyph_Metrics - * FT_SubGlyph + * @title: + * Library Setup * - * FT_Bitmap_Size + * @abstract: + * Functions to start and end the usage of the FreeType library. * + * @description: + * Functions to start and end the usage of the FreeType library. + * + * Note that @FT_Library_Version and @FREETYPE_XXX are of limited use + * because even a new release of FreeType with only documentation + * changes increases the version number. + * + * @order: + * FT_Library * FT_Init_FreeType * FT_Done_FreeType * + * FT_Library_Version + * FREETYPE_XXX + * + */ + + + /************************************************************************** + * + * @section: + * face_creation + * + * @title: + * Face Creation + * + * @abstract: + * Functions to manage fonts. + * + * @description: + * The functions and structures collected in this section operate on + * fonts globally. + * + * @order: + * FT_Face + * FT_FaceRec + * FT_FACE_FLAG_XXX + * FT_STYLE_FLAG_XXX + * * FT_New_Face * FT_Done_Face * FT_Reference_Face @@ -198,10 +200,36 @@ FT_BEGIN_HEADER * FT_Face_Properties * FT_Open_Face * FT_Open_Args + * FT_OPEN_XXX * FT_Parameter * FT_Attach_File * FT_Attach_Stream * + */ + + + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + * @title: + * Sizing and Scaling + * + * @abstract: + * Functions to manage font sizes. + * + * @description: + * The functions and structures collected in this section are related to + * selecting and manipulating the size of a font globally. + * + * @order: + * FT_Size + * FT_SizeRec + * FT_Size_Metrics + * + * FT_Bitmap_Size + * * FT_Set_Char_Size * FT_Set_Pixel_Sizes * FT_Request_Size @@ -209,44 +237,37 @@ FT_BEGIN_HEADER * FT_Size_Request_Type * FT_Size_RequestRec * FT_Size_Request + * * FT_Set_Transform * FT_Get_Transform + * + */ + + + /************************************************************************** + * + * @section: + * glyph_retrieval + * + * @title: + * Glyph Retrieval + * + * @abstract: + * Functions to manage glyphs. + * + * @description: + * The functions and structures collected in this section operate on + * single glyphs, of which @FT_Load_Glyph is most important. + * + * @order: + * FT_GlyphSlot + * FT_GlyphSlotRec + * FT_Glyph_Metrics + * * FT_Load_Glyph - * FT_Get_Char_Index - * FT_Get_First_Char - * FT_Get_Next_Char - * FT_Load_Char - * - * FT_OPEN_MEMORY - * FT_OPEN_STREAM - * FT_OPEN_PATHNAME - * FT_OPEN_DRIVER - * FT_OPEN_PARAMS - * - * FT_LOAD_DEFAULT - * FT_LOAD_RENDER - * FT_LOAD_MONOCHROME - * FT_LOAD_LINEAR_DESIGN - * FT_LOAD_NO_SCALE - * FT_LOAD_NO_HINTING - * FT_LOAD_NO_BITMAP - * FT_LOAD_SBITS_ONLY - * FT_LOAD_NO_AUTOHINT - * FT_LOAD_COLOR - * - * FT_LOAD_VERTICAL_LAYOUT - * FT_LOAD_IGNORE_TRANSFORM - * FT_LOAD_FORCE_AUTOHINT - * FT_LOAD_NO_RECURSE - * FT_LOAD_PEDANTIC - * - * FT_LOAD_TARGET_NORMAL - * FT_LOAD_TARGET_LIGHT - * FT_LOAD_TARGET_MONO - * FT_LOAD_TARGET_LCD - * FT_LOAD_TARGET_LCD_V - * + * FT_LOAD_XXX * FT_LOAD_TARGET_MODE + * FT_LOAD_TARGET_XXX * * FT_Render_Glyph * FT_Render_Mode @@ -254,34 +275,121 @@ FT_BEGIN_HEADER * FT_Kerning_Mode * FT_Get_Track_Kerning * + */ + + + /************************************************************************** + * + * @section: + * character_mapping + * + * @title: + * Character Mapping + * + * @abstract: + * Functions to manage character-to-glyph maps. + * + * @description: + * This section holds functions and structures that are related to + * mapping character input codes to glyph indices. + * + * Note that for many scripts the simplistic approach used by FreeType + * of mapping a single character to a single glyph is not valid or + * possible! In general, a higher-level library like HarfBuzz or ICU + * should be used for handling text strings. + * + * @order: + * FT_CharMap * FT_CharMapRec + * FT_Encoding + * FT_ENC_TAG + * * FT_Select_Charmap * FT_Set_Charmap * FT_Get_Charmap_Index * + * FT_Get_Char_Index + * FT_Get_First_Char + * FT_Get_Next_Char + * FT_Load_Char + * + */ + + + /************************************************************************** + * + * @section: + * information_retrieval + * + * @title: + * Information Retrieval + * + * @abstract: + * Functions to retrieve font and glyph information. + * + * @description: + * Functions to retrieve font and glyph information. Only some very + * basic data is covered; see also the chapter on the format-specific + * API for more. + * + * + * @order: * FT_Get_Name_Index * FT_Get_Glyph_Name * FT_Get_Postscript_Name * FT_Get_FSType_Flags + * FT_FSTYPE_XXX * FT_Get_SubGlyph_Info + * FT_SUBGLYPH_FLAG_XXX * + */ + + + /************************************************************************** + * + * @section: + * other_api_data + * + * @title: + * Other API Data + * + * @abstract: + * Other structures, enumerations, and macros. + * + * @description: + * Other structures, enumerations, and macros. Deprecated functions are + * also listed here. + * + * @order: * FT_Face_Internal * FT_Size_Internal * FT_Slot_Internal * - * FT_FACE_FLAG_XXX - * FT_STYLE_FLAG_XXX - * FT_OPEN_XXX - * FT_LOAD_XXX - * FT_LOAD_TARGET_XXX - * FT_SUBGLYPH_FLAG_XXX - * FT_FSTYPE_XXX + * FT_SubGlyph * * FT_HAS_FAST_GLYPHS + * FT_Face_CheckTrueTypePatents + * FT_Face_SetUnpatentedHinting * */ + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S I C T Y P E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @struct: @@ -349,6 +457,13 @@ FT_BEGIN_HEADER } FT_Glyph_Metrics; + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @struct: @@ -409,6 +524,13 @@ FT_BEGIN_HEADER /*************************************************************************/ /*************************************************************************/ + /************************************************************************** + * + * @section: + * library_setup + * + */ + /************************************************************************** * * @type: @@ -483,7 +605,7 @@ FT_BEGIN_HEADER /************************************************************************** * * @section: - * base_interface + * face_creation * */ @@ -519,6 +641,13 @@ FT_BEGIN_HEADER typedef struct FT_FaceRec_* FT_Face; + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @type: @@ -551,6 +680,13 @@ FT_BEGIN_HEADER typedef struct FT_SizeRec_* FT_Size; + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @type: @@ -570,6 +706,13 @@ FT_BEGIN_HEADER typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; + /************************************************************************** + * + * @section: + * character_mapping + * + */ + /************************************************************************** * * @type: @@ -877,6 +1020,13 @@ FT_BEGIN_HEADER /*************************************************************************/ + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @type: @@ -892,6 +1042,13 @@ FT_BEGIN_HEADER typedef struct FT_Face_InternalRec_* FT_Face_Internal; + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @struct: @@ -918,7 +1075,7 @@ FT_BEGIN_HEADER * If we have the third named instance of face~4, say, `face_index` is * set to 0x00030004. * - * Bit 31 is always zero (this is, `face_index` is always a positive + * Bit 31 is always zero (that is, `face_index` is always a positive * value). * * [Since 2.9] Changing the design coordinates with @@ -936,7 +1093,7 @@ FT_BEGIN_HEADER * * [Since 2.6.1] Bits 16-30 hold the number of named instances * available for the current face if we have a GX or OpenType variation - * (sub)font. Bit 31 is always zero (this is, `style_flags` is always + * (sub)font. Bit 31 is always zero (that is, `style_flags` is always * a positive value). Note that a variation font has always at least * one named instance, namely the default instance. * @@ -1002,7 +1159,7 @@ FT_BEGIN_HEADER * Note that the bounding box might be off by (at least) one pixel for * hinted fonts. See @FT_Size_Metrics for further discussion. * - * Note that the bounding box does not vary in OpenType variable fonts + * Note that the bounding box does not vary in OpenType variation fonts * and should only be used in relation to the default instance. * * units_per_EM :: @@ -1090,9 +1247,9 @@ FT_BEGIN_HEADER FT_Generic generic; - /*# The following member variables (down to `underline_thickness`) */ - /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ - /*# for bitmap fonts. */ + /* The following member variables (down to `underline_thickness`) */ + /* are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ + /* for bitmap fonts. */ FT_BBox bbox; FT_UShort units_per_EM; @@ -1110,7 +1267,7 @@ FT_BEGIN_HEADER FT_Size size; FT_CharMap charmap; - /*@private begin */ + /* private fields, internal to FreeType */ FT_Driver driver; FT_Memory memory; @@ -1123,8 +1280,6 @@ FT_BEGIN_HEADER FT_Face_Internal internal; - /*@private end */ - } FT_FaceRec; @@ -1207,13 +1362,13 @@ FT_BEGIN_HEADER * successfully; in all other cases you get an * `FT_Err_Invalid_Argument` error. * - * Note that CID-keyed fonts that are in an SFNT wrapper (this is, all + * Note that CID-keyed fonts that are in an SFNT wrapper (that is, all * OpenType/CFF fonts) don't have this flag set since the glyphs are * accessed in the normal way (using contiguous indices); the * 'CID-ness' isn't visible to the application. * * FT_FACE_FLAG_TRICKY :: - * The face is 'tricky', this is, it always needs the font format's + * The face is 'tricky', that is, it always needs the font format's * native hinting engine to get a reasonable result. A typical example * is the old Chinese font `mingli.ttf` (but not `mingliu.ttc`) that * uses TrueType bytecode instructions to move and scale all of its @@ -1235,8 +1390,8 @@ FT_BEGIN_HEADER * FT_FACE_FLAG_VARIATION :: * [Since 2.9] Set if the current face (or named instance) has been * altered with @FT_Set_MM_Design_Coordinates, - * @FT_Set_Var_Design_Coordinates, or @FT_Set_Var_Blend_Coordinates. - * This flag is unset by a call to @FT_Set_Named_Instance. + * @FT_Set_Var_Design_Coordinates, @FT_Set_Var_Blend_Coordinates, or + * @FT_Set_MM_WeightVector to select a non-default instance. * * FT_FACE_FLAG_SVG :: * [Since 2.12] The face has an 'SVG~' OpenType table. @@ -1272,6 +1427,13 @@ FT_BEGIN_HEADER #define FT_FACE_FLAG_SBIX_OVERLAY ( 1L << 18 ) + /************************************************************************** + * + * @section: + * font_testing_macros + * + */ + /************************************************************************** * * @macro: @@ -1381,6 +1543,13 @@ FT_BEGIN_HEADER ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES ) ) + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @macro: @@ -1393,6 +1562,13 @@ FT_BEGIN_HEADER #define FT_HAS_FAST_GLYPHS( face ) 0 + /************************************************************************** + * + * @section: + * font_testing_macros + * + */ + /************************************************************************** * * @macro: @@ -1451,8 +1627,8 @@ FT_BEGIN_HEADER * * @description: * A macro that returns true whenever a face object has been altered by - * @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, or - * @FT_Set_Var_Blend_Coordinates. + * @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, + * @FT_Set_Var_Blend_Coordinates, or @FT_Set_MM_WeightVector. * * @since: * 2.9 @@ -1628,6 +1804,13 @@ FT_BEGIN_HEADER ( !!( (face)->face_flags & FT_FACE_FLAG_SBIX_OVERLAY ) ) + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @enum: @@ -1654,6 +1837,13 @@ FT_BEGIN_HEADER #define FT_STYLE_FLAG_BOLD ( 1 << 1 ) + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @type: @@ -1666,6 +1856,13 @@ FT_BEGIN_HEADER typedef struct FT_Size_InternalRec_* FT_Size_Internal; + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @struct: @@ -1817,6 +2014,13 @@ FT_BEGIN_HEADER } FT_SizeRec; + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @struct: @@ -1848,6 +2052,13 @@ FT_BEGIN_HEADER typedef struct FT_Slot_InternalRec_* FT_Slot_Internal; + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @struct: @@ -2092,6 +2303,13 @@ FT_BEGIN_HEADER /*************************************************************************/ + /************************************************************************** + * + * @section: + * library_setup + * + */ + /************************************************************************** * * @function: @@ -2149,6 +2367,13 @@ FT_BEGIN_HEADER FT_Done_FreeType( FT_Library library ); + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @enum: @@ -2451,7 +2676,7 @@ FT_BEGIN_HEADER * Each new face object created with this function also owns a default * @FT_Size object, accessible as `face->size`. * - * One @FT_Library instance can have multiple face objects, this is, + * One @FT_Library instance can have multiple face objects, that is, * @FT_Open_Face and its siblings can be called multiple times using the * same `library` argument. * @@ -2650,6 +2875,13 @@ FT_BEGIN_HEADER FT_Done_Face( FT_Face face ); + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @function: @@ -2679,7 +2911,7 @@ FT_BEGIN_HEADER * silently uses outlines if there is no bitmap for a given glyph index. * * For GX and OpenType variation fonts, a bitmap strike makes sense only - * if the default instance is active (this is, no glyph variation takes + * if the default instance is active (that is, no glyph variation takes * place); otherwise, FreeType simply ignores bitmap strikes. The same * is true for all named instances that are different from the default * instance. @@ -2942,6 +3174,13 @@ FT_BEGIN_HEADER FT_UInt pixel_height ); + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @function: @@ -2976,7 +3215,7 @@ FT_BEGIN_HEADER * glyph may be transformed. See @FT_Set_Transform for the details. * * For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument` is returned - * for invalid CID values (this is, for CID values that don't have a + * for invalid CID values (that is, for CID values that don't have a * corresponding glyph in the font). See the discussion of the * @FT_FACE_FLAG_CID_KEYED flag for more details. * @@ -2990,6 +3229,13 @@ FT_BEGIN_HEADER FT_Int32 load_flags ); + /************************************************************************** + * + * @section: + * character_mapping + * + */ + /************************************************************************** * * @function: @@ -3033,6 +3279,13 @@ FT_BEGIN_HEADER FT_Int32 load_flags ); + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @enum: @@ -3172,10 +3425,11 @@ FT_BEGIN_HEADER * * [Since 2.12] If the glyph index maps to an entry in the face's * 'SVG~' table, load the associated SVG document from this table and - * set the `format` field of @FT_GlyphSlotRec to @FT_GLYPH_FORMAT_SVG. - * Note that FreeType itself can't render SVG documents; however, the - * library provides hooks to seamlessly integrate an external renderer. - * See sections @ot_svg_driver and @svg_fonts for more. + * set the `format` field of @FT_GlyphSlotRec to @FT_GLYPH_FORMAT_SVG + * ([since 2.13.1] provided @FT_LOAD_NO_SVG is not set). Note that + * FreeType itself can't render SVG documents; however, the library + * provides hooks to seamlessly integrate an external renderer. See + * sections @ot_svg_driver and @svg_fonts for more. * * [Since 2.10, experimental] If the glyph index maps to an entry in * the face's 'COLR' table with a 'CPAL' palette table (as defined in @@ -3189,6 +3443,9 @@ FT_BEGIN_HEADER * @FT_Palette_Select instead of setting @FT_LOAD_COLOR for rendering * so that the client application can handle blending by itself. * + * FT_LOAD_NO_SVG :: + * [Since 2.13.1] Ignore SVG glyph data when loading. + * * FT_LOAD_COMPUTE_METRICS :: * [Since 2.6.1] Compute glyph metrics from the glyph data, without the * use of bundled metrics tables (for example, the 'hdmx' table in @@ -3254,6 +3511,7 @@ FT_BEGIN_HEADER #define FT_LOAD_COLOR ( 1L << 20 ) #define FT_LOAD_COMPUTE_METRICS ( 1L << 21 ) #define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 ) +#define FT_LOAD_NO_SVG ( 1L << 24 ) /* */ @@ -3372,6 +3630,13 @@ FT_BEGIN_HEADER FT_STATIC_CAST( FT_Render_Mode, ( (x) >> 16 ) & 15 ) + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @function: @@ -3447,6 +3712,13 @@ FT_BEGIN_HEADER FT_Vector* delta ); + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @enum: @@ -3841,6 +4113,13 @@ FT_BEGIN_HEADER FT_Fixed* akerning ); + /************************************************************************** + * + * @section: + * character_mapping + * + */ + /************************************************************************** * * @function: @@ -4057,6 +4336,13 @@ FT_BEGIN_HEADER FT_UInt *agindex ); + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @function: @@ -4155,6 +4441,13 @@ FT_BEGIN_HEADER FT_Parameter* properties ); + /************************************************************************** + * + * @section: + * information_retrieval + * + */ + /************************************************************************** * * @function: @@ -4266,9 +4559,10 @@ FT_BEGIN_HEADER * * [Since 2.9] Special PostScript names for named instances are only * returned if the named instance is set with @FT_Set_Named_Instance (and - * the font has corresponding entries in its 'fvar' table). If - * @FT_IS_VARIATION returns true, the algorithmically derived PostScript - * name is provided, not looking up special entries for named instances. + * the font has corresponding entries in its 'fvar' table or is the + * default named instance). If @FT_IS_VARIATION returns true, the + * algorithmically derived PostScript name is provided, not looking up + * special entries for named instances. */ FT_EXPORT( const char* ) FT_Get_Postscript_Name( FT_Face face ); @@ -4900,32 +5194,10 @@ FT_BEGIN_HEADER /************************************************************************** * * @section: - * version - * - * @title: - * FreeType Version - * - * @abstract: - * Functions and macros related to FreeType versions. - * - * @description: - * Note that those functions and macros are of limited use because even a - * new release of FreeType with only documentation changes increases the - * version number. - * - * @order: - * FT_Library_Version - * - * FREETYPE_MAJOR - * FREETYPE_MINOR - * FREETYPE_PATCH - * - * FT_Face_CheckTrueTypePatents - * FT_Face_SetUnpatentedHinting + * library_setup * */ - /************************************************************************** * * @enum: @@ -4950,7 +5222,7 @@ FT_BEGIN_HEADER */ #define FREETYPE_MAJOR 2 #define FREETYPE_MINOR 13 -#define FREETYPE_PATCH 0 +#define FREETYPE_PATCH 2 /************************************************************************** @@ -4992,6 +5264,13 @@ FT_BEGIN_HEADER FT_Int *apatch ); + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @function: diff --git a/src/3rdparty/freetype/include/freetype/ftcache.h b/src/3rdparty/freetype/include/freetype/ftcache.h index c7686954..a2072e26 100644 --- a/src/3rdparty/freetype/include/freetype/ftcache.h +++ b/src/3rdparty/freetype/include/freetype/ftcache.h @@ -43,61 +43,61 @@ FT_BEGIN_HEADER * objects, as well as caching information like character maps and glyph * images while limiting their maximum memory usage. * - * Note that all types and functions begin with the `FTC_` prefix. + * Note that all types and functions begin with the `FTC_` prefix rather + * than the usual `FT_` prefix in the rest of FreeType. * - * The cache is highly portable and thus doesn't know anything about the - * fonts installed on your system, or how to access them. This implies - * the following scheme: + * The cache is highly portable and, thus, doesn't know anything about + * the fonts installed on your system, or how to access them. Therefore, + * it requires the following. * - * First, available or installed font faces are uniquely identified by - * @FTC_FaceID values, provided to the cache by the client. Note that - * the cache only stores and compares these values, and doesn't try to - * interpret them in any way. + * * @FTC_FaceID, an arbitrary non-zero value that uniquely identifies + * available or installed font faces, has to be provided to the + * cache by the client. Note that the cache only stores and compares + * these values and doesn't try to interpret them in any way, but they + * have to be persistent on the client side. * - * Second, the cache calls, only when needed, a client-provided function - * to convert an @FTC_FaceID into a new @FT_Face object. The latter is - * then completely managed by the cache, including its termination - * through @FT_Done_Face. To monitor termination of face objects, the - * finalizer callback in the `generic` field of the @FT_Face object can - * be used, which might also be used to store the @FTC_FaceID of the - * face. + * * @FTC_Face_Requester, a method to convert an @FTC_FaceID into a new + * @FT_Face object when necessary, has to be provided to the cache by + * the client. The @FT_Face object is completely managed by the cache, + * including its termination through @FT_Done_Face. To monitor + * termination of face objects, the finalizer callback in the `generic` + * field of the @FT_Face object can be used, which might also be used + * to store the @FTC_FaceID of the face. * - * Clients are free to map face IDs to anything else. The most simple - * usage is to associate them to a (pathname,face_index) pair that is - * used to call @FT_New_Face. However, more complex schemes are also - * possible. + * Clients are free to map face IDs to anything useful. The most simple + * usage is, for example, to associate them to a `{pathname,face_index}` + * pair that is then used by @FTC_Face_Requester to call @FT_New_Face. + * However, more complex schemes are also possible. * * Note that for the cache to work correctly, the face ID values must be * **persistent**, which means that the contents they point to should not * change at runtime, or that their value should not become invalid. - * * If this is unavoidable (e.g., when a font is uninstalled at runtime), - * you should call @FTC_Manager_RemoveFaceID as soon as possible, to let + * you should call @FTC_Manager_RemoveFaceID as soon as possible to let * the cache get rid of any references to the old @FTC_FaceID it may keep * internally. Failure to do so will lead to incorrect behaviour or even - * crashes. + * crashes in @FTC_Face_Requester. * * To use the cache, start with calling @FTC_Manager_New to create a new * @FTC_Manager object, which models a single cache instance. You can * then look up @FT_Face and @FT_Size objects with - * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively. + * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively, and + * use them in any FreeType work stream. You can also cache other + * FreeType objects as follows. * - * If you want to use the charmap caching, call @FTC_CMapCache_New, then - * later use @FTC_CMapCache_Lookup to perform the equivalent of - * @FT_Get_Char_Index, only much faster. + * * If you want to use the charmap caching, call @FTC_CMapCache_New, + * then later use @FTC_CMapCache_Lookup to perform the equivalent of + * @FT_Get_Char_Index, only much faster. * - * If you want to use the @FT_Glyph caching, call @FTC_ImageCache_New, - * then later use @FTC_ImageCache_Lookup to retrieve the corresponding - * @FT_Glyph objects from the cache. - * - * If you need lots of small bitmaps, it is much more memory efficient to - * call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This - * returns @FTC_SBitRec structures, which are used to store small bitmaps - * directly. (A small bitmap is one whose metrics and dimensions all fit - * into 8-bit integers). - * - * We hope to also provide a kerning cache in the near future. + * * If you want to use the @FT_Glyph caching, call @FTC_ImageCache_New, + * then later use @FTC_ImageCache_Lookup to retrieve the corresponding + * @FT_Glyph objects from the cache. * + * * If you need lots of small bitmaps, it is much more memory-efficient + * to call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This + * returns @FTC_SBitRec structures, which are used to store small + * bitmaps directly. (A small bitmap is one whose metrics and + * dimensions all fit into 8-bit integers). * * @order: * FTC_Manager diff --git a/src/3rdparty/freetype/include/freetype/ftchapters.h b/src/3rdparty/freetype/include/freetype/ftchapters.h index 6a9733ad..7566fbd1 100644 --- a/src/3rdparty/freetype/include/freetype/ftchapters.h +++ b/src/3rdparty/freetype/include/freetype/ftchapters.h @@ -31,9 +31,28 @@ * Core API * * @sections: - * version * basic_types - * base_interface + * library_setup + * face_creation + * font_testing_macros + * sizing_and_scaling + * glyph_retrieval + * character_mapping + * information_retrieval + * other_api_data + * + */ + + + /************************************************************************** + * + * @chapter: + * extended_api + * + * @title: + * Extended API + * + * @sections: * glyph_variants * color_management * layer_management diff --git a/src/3rdparty/freetype/include/freetype/ftdriver.h b/src/3rdparty/freetype/include/freetype/ftdriver.h index f90946fd..7af7465b 100644 --- a/src/3rdparty/freetype/include/freetype/ftdriver.h +++ b/src/3rdparty/freetype/include/freetype/ftdriver.h @@ -134,7 +134,7 @@ FT_BEGIN_HEADER * each being rounded to the nearest pixel edge, taking care of overshoot * suppression at small sizes, stem darkening, and scaling. * - * Hstems (this is, hint values defined in the font to help align + * Hstems (that is, hint values defined in the font to help align * horizontal features) that fall within a blue zone are said to be * 'captured' and are aligned to that zone. Uncaptured stems are moved * in one of four ways, top edge up or down, bottom edge up or down. @@ -446,7 +446,7 @@ FT_BEGIN_HEADER * at smaller sizes. * * For the auto-hinter, stem-darkening is experimental currently and thus - * switched off by default (this is, `no-stem-darkening` is set to TRUE + * switched off by default (that is, `no-stem-darkening` is set to TRUE * by default). Total consistency with the CFF driver is not achieved * right now because the emboldening method differs and glyphs must be * scaled down on the Y-axis to keep outline points inside their @@ -651,11 +651,8 @@ FT_BEGIN_HEADER * Windows~98; only grayscale and B/W rasterizing is supported. * * TT_INTERPRETER_VERSION_38 :: - * Version~38 corresponds to MS rasterizer v.1.9; it is roughly - * equivalent to the hinting provided by DirectWrite ClearType (as can - * be found, for example, in the Internet Explorer~9 running on - * Windows~7). It is used in FreeType to select the 'Infinality' - * subpixel hinting code. The code may be removed in a future version. + * Version~38 is the same Version~40. The original 'Infinality' code is + * no longer available. * * TT_INTERPRETER_VERSION_40 :: * Version~40 corresponds to MS rasterizer v.2.1; it is roughly diff --git a/src/3rdparty/freetype/include/freetype/ftimage.h b/src/3rdparty/freetype/include/freetype/ftimage.h index 2e8e6734..6baa8125 100644 --- a/src/3rdparty/freetype/include/freetype/ftimage.h +++ b/src/3rdparty/freetype/include/freetype/ftimage.h @@ -19,7 +19,7 @@ /************************************************************************** * * Note: A 'raster' is simply a scan-line converter, used to render - * FT_Outlines into FT_Bitmaps. + * `FT_Outline`s into `FT_Bitmap`s. * */ @@ -256,6 +256,12 @@ FT_BEGIN_HEADER * palette :: * A typeless pointer to the bitmap palette; this field is intended for * paletted pixel modes. Not used currently. + * + * @note: + * `width` and `rows` refer to the *physical* size of the bitmap, not the + * *logical* one. For example, if @FT_Pixel_Mode is set to + * `FT_PIXEL_MODE_LCD`, the logical width is a just a third of the + * physical one. */ typedef struct FT_Bitmap_ { @@ -856,7 +862,7 @@ FT_BEGIN_HEADER * @FT_SpanFunc that takes the y~coordinate of the span as a parameter. * * The anti-aliased rasterizer produces coverage values from 0 to 255, - * this is, from completely transparent to completely opaque. + * that is, from completely transparent to completely opaque. */ typedef struct FT_Span_ { diff --git a/src/3rdparty/freetype/include/freetype/ftlogging.h b/src/3rdparty/freetype/include/freetype/ftlogging.h index 2246dc83..53b8b896 100644 --- a/src/3rdparty/freetype/include/freetype/ftlogging.h +++ b/src/3rdparty/freetype/include/freetype/ftlogging.h @@ -62,7 +62,7 @@ FT_BEGIN_HEADER * component. * * ``` - * FT_Trace_Set_Level( "any:7 memory:0 ); + * FT_Trace_Set_Level( "any:7 memory:0" ); * ``` * * @note: diff --git a/src/3rdparty/freetype/include/freetype/ftmm.h b/src/3rdparty/freetype/include/freetype/ftmm.h index e381ef3d..d145128a 100644 --- a/src/3rdparty/freetype/include/freetype/ftmm.h +++ b/src/3rdparty/freetype/include/freetype/ftmm.h @@ -153,7 +153,7 @@ FT_BEGIN_HEADER * @note: * The fields `minimum`, `def`, and `maximum` are 16.16 fractional values * for TrueType GX and OpenType variation fonts. For Adobe MM fonts, the - * values are integers. + * values are whole numbers (i.e., the fractional part is zero). */ typedef struct FT_Var_Axis_ { @@ -399,8 +399,8 @@ FT_BEGIN_HEADER * * @note: * The design coordinates are 16.16 fractional values for TrueType GX and - * OpenType variation fonts. For Adobe MM fonts, the values are - * integers. + * OpenType variation fonts. For Adobe MM fonts, the values are supposed + * to be whole numbers (i.e., the fractional part is zero). * * [Since 2.8.1] To reset all axes to the default values, call the * function with `num_coords` set to zero and `coords` set to `NULL`. @@ -446,8 +446,8 @@ FT_BEGIN_HEADER * * @note: * The design coordinates are 16.16 fractional values for TrueType GX and - * OpenType variation fonts. For Adobe MM fonts, the values are - * integers. + * OpenType variation fonts. For Adobe MM fonts, the values are whole + * numbers (i.e., the fractional part is zero). * * @since: * 2.7.1 @@ -602,10 +602,12 @@ FT_BEGIN_HEADER * * @note: * Adobe Multiple Master fonts limit the number of designs, and thus the - * length of the weight vector to~16. + * length of the weight vector to 16~elements. * - * If `len` is zero and `weightvector` is `NULL`, the weight vector array - * is reset to the default values. + * If `len` is larger than zero, this function sets the + * @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field (i.e., + * @FT_IS_VARIATION will return true). If `len` is zero, this bit flag + * is unset and the weight vector array is reset to the default values. * * The Adobe documentation also states that the values in the * WeightVector array must total 1.0 +/-~0.001. In practice this does @@ -753,6 +755,45 @@ FT_BEGIN_HEADER FT_Set_Named_Instance( FT_Face face, FT_UInt instance_index ); + + /************************************************************************** + * + * @function: + * FT_Get_Default_Named_Instance + * + * @description: + * Retrieve the index of the default named instance, to be used with + * @FT_Set_Named_Instance. + * + * The default instance of a variation font is that instance for which + * the nth axis coordinate is equal to `axis[n].def` (as specified in the + * @FT_MM_Var structure), with~n covering all axes. + * + * FreeType synthesizes a named instance for the default instance if the + * font does not contain such an entry. + * + * @input: + * face :: + * A handle to the source face. + * + * @output: + * instance_index :: + * The index of the default named instance. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * For Adobe MM fonts (which don't have named instances) this function + * always returns zero for `instance_index`. + * + * @since: + * 2.13.1 + */ + FT_EXPORT( FT_Error ) + FT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ); + /* */ diff --git a/src/3rdparty/freetype/include/freetype/ftoutln.h b/src/3rdparty/freetype/include/freetype/ftoutln.h index 54434b25..f9329ca4 100644 --- a/src/3rdparty/freetype/include/freetype/ftoutln.h +++ b/src/3rdparty/freetype/include/freetype/ftoutln.h @@ -118,7 +118,7 @@ FT_BEGIN_HEADER * attachement. * * Similarly, the function returns success for an empty outline also - * (doing nothing, this is, not calling any emitter); if necessary, you + * (doing nothing, that is, not calling any emitter); if necessary, you * should filter this out, too. */ FT_EXPORT( FT_Error ) diff --git a/src/3rdparty/freetype/include/freetype/ftrender.h b/src/3rdparty/freetype/include/freetype/ftrender.h index a8576dab..0b6fad32 100644 --- a/src/3rdparty/freetype/include/freetype/ftrender.h +++ b/src/3rdparty/freetype/include/freetype/ftrender.h @@ -158,7 +158,7 @@ FT_BEGIN_HEADER FT_Renderer_GetCBoxFunc get_glyph_cbox; FT_Renderer_SetModeFunc set_mode; - FT_Raster_Funcs* raster_class; + const FT_Raster_Funcs* raster_class; } FT_Renderer_Class; diff --git a/src/3rdparty/freetype/include/freetype/ftsynth.h b/src/3rdparty/freetype/include/freetype/ftsynth.h index 5d196976..af90967d 100644 --- a/src/3rdparty/freetype/include/freetype/ftsynth.h +++ b/src/3rdparty/freetype/include/freetype/ftsynth.h @@ -68,6 +68,18 @@ FT_BEGIN_HEADER FT_EXPORT( void ) FT_GlyphSlot_Embolden( FT_GlyphSlot slot ); + /* Precisely adjust the glyph weight either horizontally or vertically. */ + /* The `xdelta` and `ydelta` values are fractions of the face Em size */ + /* (in fixed-point format). Considering that a regular face would have */ + /* stem widths on the order of 0.1 Em, a delta of 0.05 (0x0CCC) should */ + /* be very noticeable. To increase or decrease the weight, use positive */ + /* or negative values, respectively. */ + FT_EXPORT( void ) + FT_GlyphSlot_AdjustWeight( FT_GlyphSlot slot, + FT_Fixed xdelta, + FT_Fixed ydelta ); + + /* Slant an outline glyph to the right by about 12 degrees. */ FT_EXPORT( void ) FT_GlyphSlot_Oblique( FT_GlyphSlot slot ); diff --git a/src/3rdparty/freetype/include/freetype/ftsystem.h b/src/3rdparty/freetype/include/freetype/ftsystem.h index a995b078..3a08f491 100644 --- a/src/3rdparty/freetype/include/freetype/ftsystem.h +++ b/src/3rdparty/freetype/include/freetype/ftsystem.h @@ -229,8 +229,7 @@ FT_BEGIN_HEADER * A handle to the source stream. * * offset :: - * The offset from the start of the stream to seek to if this is a seek - * operation (see note). + * The offset from the start of the stream to seek to. * * buffer :: * The address of the read buffer. @@ -239,16 +238,9 @@ FT_BEGIN_HEADER * The number of bytes to read from the stream. * * @return: - * The number of bytes effectively read by the stream. - * - * @note: - * This function performs a seek *or* a read operation depending on the - * argument values. If `count` is zero, the operation is a seek to - * `offset` bytes. If `count` is >~0, the operation is a read of `count` - * bytes from the current position in the stream, and the `offset` value - * should be ignored. - * - * For seek operations, a non-zero return value indicates an error. + * If count >~0, return the number of bytes effectively read by the + * stream (after seeking to `offset`). If count ==~0, return the status + * of the seek operation (non-zero indicates an error). * */ typedef unsigned long diff --git a/src/3rdparty/freetype/include/freetype/internal/compiler-macros.h b/src/3rdparty/freetype/include/freetype/internal/compiler-macros.h index 7883317f..6f676509 100644 --- a/src/3rdparty/freetype/include/freetype/internal/compiler-macros.h +++ b/src/3rdparty/freetype/include/freetype/internal/compiler-macros.h @@ -41,8 +41,11 @@ FT_BEGIN_HEADER # if ( defined( __STDC_VERSION__ ) && __STDC_VERSION__ > 201710L ) || \ ( defined( __cplusplus ) && __cplusplus > 201402L ) # define FALL_THROUGH [[__fallthrough__]] -# elif ( defined( __GNUC__ ) && __GNUC__ >= 7 ) || \ - ( defined( __clang__ ) && __clang_major__ >= 10 ) +# elif ( defined( __GNUC__ ) && __GNUC__ >= 7 ) || \ + ( defined( __clang__ ) && \ + ( defined( __apple_build_version__ ) \ + ? __apple_build_version__ >= 12000000 \ + : __clang_major__ >= 10 ) ) # define FALL_THROUGH __attribute__(( __fallthrough__ )) # else # define FALL_THROUGH ( (void)0 ) diff --git a/src/3rdparty/freetype/include/freetype/internal/ftcalc.h b/src/3rdparty/freetype/include/freetype/internal/ftcalc.h index d1baa392..d9aea236 100644 --- a/src/3rdparty/freetype/include/freetype/internal/ftcalc.h +++ b/src/3rdparty/freetype/include/freetype/internal/ftcalc.h @@ -332,9 +332,9 @@ FT_BEGIN_HEADER * Based on geometric considerations we use the following inequality to * identify a degenerate matrix. * - * 50 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2 + * 32 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2 * - * Value 50 is heuristic. + * Value 32 is heuristic. */ FT_BASE( FT_Bool ) FT_Matrix_Check( const FT_Matrix* matrix ); diff --git a/src/3rdparty/freetype/include/freetype/internal/ftdrv.h b/src/3rdparty/freetype/include/freetype/internal/ftdrv.h index f78912ca..9001c07a 100644 --- a/src/3rdparty/freetype/include/freetype/internal/ftdrv.h +++ b/src/3rdparty/freetype/include/freetype/internal/ftdrv.h @@ -157,6 +157,7 @@ FT_BEGIN_HEADER * A handle to a function used to select a new fixed size. It is used * only if @FT_FACE_FLAG_FIXED_SIZES is set. Can be set to 0 if the * scaling done in the base layer suffices. + * * @note: * Most function pointers, with the exception of `load_glyph`, can be set * to 0 to indicate a default behaviour. diff --git a/src/3rdparty/freetype/include/freetype/internal/ftmmtypes.h b/src/3rdparty/freetype/include/freetype/internal/ftmmtypes.h index b7c66c35..c4b21d61 100644 --- a/src/3rdparty/freetype/include/freetype/internal/ftmmtypes.h +++ b/src/3rdparty/freetype/include/freetype/internal/ftmmtypes.h @@ -28,13 +28,19 @@ FT_BEGIN_HEADER typedef struct GX_ItemVarDataRec_ { - FT_UInt itemCount; /* number of delta sets per item */ - FT_UInt regionIdxCount; /* number of region indices */ - FT_UInt* regionIndices; /* array of `regionCount' indices; */ - /* these index `varRegionList' */ - FT_ItemVarDelta* deltaSet; /* array of `itemCount' deltas */ - /* use `innerIndex' for this array */ - + FT_UInt itemCount; /* Number of delta sets per item. */ + FT_UInt regionIdxCount; /* Number of region indices. */ + FT_UInt* regionIndices; /* Array of `regionCount` indices; */ + /* these index `varRegionList`. */ + FT_Byte* deltaSet; /* Array of `itemCount` deltas; */ + /* use `innerIndex` for this array. */ + FT_UShort wordDeltaCount; /* Number of the first 32-bit ints */ + /* or 16-bit ints of `deltaSet` */ + /* depending on `longWords`. */ + FT_Bool longWords; /* If true, `deltaSet` is a 32-bit */ + /* array followed by a 16-bit */ + /* array, otherwise a 16-bit array */ + /* followed by an 8-bit array. */ } GX_ItemVarDataRec, *GX_ItemVarData; diff --git a/src/3rdparty/freetype/include/freetype/internal/services/svmetric.h b/src/3rdparty/freetype/include/freetype/internal/services/svmetric.h index e588ea48..167617eb 100644 --- a/src/3rdparty/freetype/include/freetype/internal/services/svmetric.h +++ b/src/3rdparty/freetype/include/freetype/internal/services/svmetric.h @@ -77,6 +77,9 @@ FT_BEGIN_HEADER typedef void (*FT_Metrics_Adjust_Func)( FT_Face face ); + typedef FT_Error + (*FT_Size_Reset_Func)( FT_Size size ); + FT_DEFINE_SERVICE( MetricsVariations ) { @@ -90,6 +93,7 @@ FT_BEGIN_HEADER FT_VOrg_Adjust_Func vorg_adjust; FT_Metrics_Adjust_Func metrics_adjust; + FT_Size_Reset_Func size_reset; }; @@ -101,7 +105,8 @@ FT_BEGIN_HEADER tsb_adjust_, \ bsb_adjust_, \ vorg_adjust_, \ - metrics_adjust_ ) \ + metrics_adjust_, \ + size_reset_ ) \ static const FT_Service_MetricsVariationsRec class_ = \ { \ hadvance_adjust_, \ @@ -111,7 +116,8 @@ FT_BEGIN_HEADER tsb_adjust_, \ bsb_adjust_, \ vorg_adjust_, \ - metrics_adjust_ \ + metrics_adjust_, \ + size_reset_ \ }; /* */ diff --git a/src/3rdparty/freetype/include/freetype/internal/services/svmm.h b/src/3rdparty/freetype/include/freetype/internal/services/svmm.h index d9420423..7e76ab83 100644 --- a/src/3rdparty/freetype/include/freetype/internal/services/svmm.h +++ b/src/3rdparty/freetype/include/freetype/internal/services/svmm.h @@ -60,9 +60,9 @@ FT_BEGIN_HEADER /* use return value -1 to indicate that the new coordinates */ /* are equal to the current ones; no changes are thus needed */ typedef FT_Error - (*FT_Set_MM_Blend_Func)( FT_Face face, - FT_UInt num_coords, - FT_Long* coords ); + (*FT_Set_MM_Blend_Func)( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); typedef FT_Error (*FT_Get_Var_Design_Func)( FT_Face face, @@ -70,13 +70,17 @@ FT_BEGIN_HEADER FT_Fixed* coords ); typedef FT_Error - (*FT_Set_Instance_Func)( FT_Face face, - FT_UInt instance_index ); + (*FT_Set_Named_Instance_Func)( FT_Face face, + FT_UInt instance_index ); typedef FT_Error - (*FT_Get_MM_Blend_Func)( FT_Face face, - FT_UInt num_coords, - FT_Long* coords ); + (*FT_Get_Default_Named_Instance_Func)( FT_Face face, + FT_UInt *instance_index ); + + typedef FT_Error + (*FT_Get_MM_Blend_Func)( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); typedef FT_Error (*FT_Get_Var_Blend_Func)( FT_Face face, @@ -86,7 +90,7 @@ FT_BEGIN_HEADER FT_MM_Var* *mm_var ); typedef void - (*FT_Done_Blend_Func)( FT_Face ); + (*FT_Done_Blend_Func)( FT_Face face ); typedef FT_Error (*FT_Set_MM_WeightVector_Func)( FT_Face face, @@ -98,6 +102,9 @@ FT_BEGIN_HEADER FT_UInt* len, FT_Fixed* weight_vector ); + typedef void + (*FT_Construct_PS_Name_Func)( FT_Face face ); + typedef FT_Error (*FT_Var_Load_Delta_Set_Idx_Map_Func)( FT_Face face, FT_ULong offset, @@ -134,11 +141,13 @@ FT_BEGIN_HEADER FT_Get_MM_Var_Func get_mm_var; FT_Set_Var_Design_Func set_var_design; FT_Get_Var_Design_Func get_var_design; - FT_Set_Instance_Func set_instance; + FT_Set_Named_Instance_Func set_named_instance; + FT_Get_Default_Named_Instance_Func get_default_named_instance; FT_Set_MM_WeightVector_Func set_mm_weightvector; FT_Get_MM_WeightVector_Func get_mm_weightvector; /* for internal use; only needed for code sharing between modules */ + FT_Construct_PS_Name_Func construct_ps_name; FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map; FT_Var_Load_Item_Var_Store_Func load_item_var_store; FT_Var_Get_Item_Delta_Func get_item_delta; @@ -149,43 +158,49 @@ FT_BEGIN_HEADER }; -#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \ - get_mm_, \ - set_mm_design_, \ - set_mm_blend_, \ - get_mm_blend_, \ - get_mm_var_, \ - set_var_design_, \ - get_var_design_, \ - set_instance_, \ - set_weightvector_, \ - get_weightvector_, \ - load_delta_set_idx_map_, \ - load_item_var_store_, \ - get_item_delta_, \ - done_item_var_store_, \ - done_delta_set_idx_map_, \ - get_var_blend_, \ - done_blend_ ) \ - static const FT_Service_MultiMastersRec class_ = \ - { \ - get_mm_, \ - set_mm_design_, \ - set_mm_blend_, \ - get_mm_blend_, \ - get_mm_var_, \ - set_var_design_, \ - get_var_design_, \ - set_instance_, \ - set_weightvector_, \ - get_weightvector_, \ - load_delta_set_idx_map_, \ - load_item_var_store_, \ - get_item_delta_, \ - done_item_var_store_, \ - done_delta_set_idx_map_, \ - get_var_blend_, \ - done_blend_ \ +#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \ + get_mm_, \ + set_mm_design_, \ + set_mm_blend_, \ + get_mm_blend_, \ + get_mm_var_, \ + set_var_design_, \ + get_var_design_, \ + set_named_instance_, \ + get_default_named_instance_, \ + set_mm_weightvector_, \ + get_mm_weightvector_, \ + \ + construct_ps_name_, \ + load_delta_set_idx_map_, \ + load_item_var_store_, \ + get_item_delta_, \ + done_item_var_store_, \ + done_delta_set_idx_map_, \ + get_var_blend_, \ + done_blend_ ) \ + static const FT_Service_MultiMastersRec class_ = \ + { \ + get_mm_, \ + set_mm_design_, \ + set_mm_blend_, \ + get_mm_blend_, \ + get_mm_var_, \ + set_var_design_, \ + get_var_design_, \ + set_named_instance_, \ + get_default_named_instance_, \ + set_mm_weightvector_, \ + get_mm_weightvector_, \ + \ + construct_ps_name_, \ + load_delta_set_idx_map_, \ + load_item_var_store_, \ + get_item_delta_, \ + done_item_var_store_, \ + done_delta_set_idx_map_, \ + get_var_blend_, \ + done_blend_ \ }; /* */ diff --git a/src/3rdparty/freetype/include/freetype/internal/services/svpscmap.h b/src/3rdparty/freetype/include/freetype/internal/services/svpscmap.h index fd99d857..6e599f3a 100644 --- a/src/3rdparty/freetype/include/freetype/internal/services/svpscmap.h +++ b/src/3rdparty/freetype/include/freetype/internal/services/svpscmap.h @@ -97,7 +97,7 @@ FT_BEGIN_HEADER (*PS_Unicodes_CharIndexFunc)( PS_Unicodes unicodes, FT_UInt32 unicode ); - typedef FT_UInt32 + typedef FT_UInt (*PS_Unicodes_CharNextFunc)( PS_Unicodes unicodes, FT_UInt32 *unicode ); diff --git a/src/3rdparty/freetype/include/freetype/internal/t1types.h b/src/3rdparty/freetype/include/freetype/internal/t1types.h index 5a105c58..b9c94398 100644 --- a/src/3rdparty/freetype/include/freetype/internal/t1types.h +++ b/src/3rdparty/freetype/include/freetype/internal/t1types.h @@ -201,30 +201,30 @@ FT_BEGIN_HEADER typedef struct T1_FaceRec_ { - FT_FaceRec root; - T1_FontRec type1; - const void* psnames; - const void* psaux; - const void* afm_data; - FT_CharMapRec charmaprecs[2]; - FT_CharMap charmaps[2]; + FT_FaceRec root; + T1_FontRec type1; + const void* psnames; + const void* psaux; + const void* afm_data; + FT_CharMapRec charmaprecs[2]; + FT_CharMap charmaps[2]; /* support for Multiple Masters fonts */ - PS_Blend blend; + PS_Blend blend; /* undocumented, optional: indices of subroutines that express */ /* the NormalizeDesignVector and the ConvertDesignVector procedure, */ /* respectively, as Type 2 charstrings; -1 if keywords not present */ - FT_Int ndv_idx; - FT_Int cdv_idx; + FT_Int ndv_idx; + FT_Int cdv_idx; /* undocumented, optional: has the same meaning as len_buildchar */ /* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */ - FT_UInt len_buildchar; - FT_Long* buildchar; + FT_UInt len_buildchar; + FT_Long* buildchar; /* since version 2.1 - interface to PostScript hinter */ - const void* pshinter; + const void* pshinter; } T1_FaceRec; diff --git a/src/3rdparty/freetype/include/freetype/internal/tttypes.h b/src/3rdparty/freetype/include/freetype/internal/tttypes.h index 3b521924..b9788c78 100644 --- a/src/3rdparty/freetype/include/freetype/internal/tttypes.h +++ b/src/3rdparty/freetype/include/freetype/internal/tttypes.h @@ -779,13 +779,15 @@ FT_BEGIN_HEADER /************************************************************************** * * @struct: - * TT_Post_20Rec + * TT_Post_NamesRec * * @description: - * Postscript names sub-table, format 2.0. Stores the PS name of each - * glyph in the font face. + * Postscript names table, either format 2.0 or 2.5. * * @fields: + * loaded :: + * A flag to indicate whether the PS names are loaded. + * * num_glyphs :: * The number of named glyphs in the table. * @@ -798,68 +800,13 @@ FT_BEGIN_HEADER * glyph_names :: * The PS names not in Mac Encoding. */ - typedef struct TT_Post_20Rec_ + typedef struct TT_Post_NamesRec_ { + FT_Bool loaded; FT_UShort num_glyphs; FT_UShort num_names; FT_UShort* glyph_indices; - FT_Char** glyph_names; - - } TT_Post_20Rec, *TT_Post_20; - - - /************************************************************************** - * - * @struct: - * TT_Post_25Rec - * - * @description: - * Postscript names sub-table, format 2.5. Stores the PS name of each - * glyph in the font face. - * - * @fields: - * num_glyphs :: - * The number of glyphs in the table. - * - * offsets :: - * An array of signed offsets in a normal Mac Postscript name encoding. - */ - typedef struct TT_Post_25_ - { - FT_UShort num_glyphs; - FT_Char* offsets; - - } TT_Post_25Rec, *TT_Post_25; - - - /************************************************************************** - * - * @struct: - * TT_Post_NamesRec - * - * @description: - * Postscript names table, either format 2.0 or 2.5. - * - * @fields: - * loaded :: - * A flag to indicate whether the PS names are loaded. - * - * format_20 :: - * The sub-table used for format 2.0. - * - * format_25 :: - * The sub-table used for format 2.5. - */ - typedef struct TT_Post_NamesRec_ - { - FT_Bool loaded; - - union - { - TT_Post_20Rec format_20; - TT_Post_25Rec format_25; - - } names; + FT_Byte** glyph_names; } TT_Post_NamesRec, *TT_Post_Names; @@ -1253,12 +1200,16 @@ FT_BEGIN_HEADER * mm :: * A pointer to the Multiple Masters service. * - * var :: - * A pointer to the Metrics Variations service. + * tt_var :: + * A pointer to the Metrics Variations service for the "truetype" + * driver. * - * hdmx :: - * The face's horizontal device metrics ('hdmx' table). This table is - * optional in TrueType/OpenType fonts. + * face_var :: + * A pointer to the Metrics Variations service for this `TT_Face`'s + * driver. + * + * psaux :: + * A pointer to the PostScript Auxiliary service. * * gasp :: * The grid-fitting and scaling properties table ('gasp'). This table @@ -1364,6 +1315,12 @@ FT_BEGIN_HEADER * var_postscript_prefix_len :: * The length of the `var_postscript_prefix` string. * + * var_default_named_instance :: + * The index of the default named instance. + * + * non_var_style_name :: + * The non-variation style name, used as a backup. + * * horz_metrics_size :: * The size of the 'hmtx' table. * @@ -1410,14 +1367,6 @@ FT_BEGIN_HEADER * A mapping between the strike indices exposed by the API and the * indices used in the font's sbit table. * - * cpal :: - * A pointer to data related to the 'CPAL' table. `NULL` if the table - * is not available. - * - * colr :: - * A pointer to data related to the 'COLR' table. `NULL` if the table - * is not available. - * * kern_table :: * A pointer to the 'kern' table. * @@ -1445,19 +1394,23 @@ FT_BEGIN_HEADER * vert_metrics_offset :: * The file offset of the 'vmtx' table. * - * sph_found_func_flags :: - * Flags identifying special bytecode functions (used by the v38 - * implementation of the bytecode interpreter). - * - * sph_compatibility_mode :: - * This flag is set if we are in ClearType backward compatibility mode - * (used by the v38 implementation of the bytecode interpreter). - * * ebdt_start :: * The file offset of the sbit data table (CBDT, bdat, etc.). * * ebdt_size :: * The size of the sbit data table. + * + * cpal :: + * A pointer to data related to the 'CPAL' table. `NULL` if the table + * is not available. + * + * colr :: + * A pointer to data related to the 'COLR' table. `NULL` if the table + * is not available. + * + * svg :: + * A pointer to data related to the 'SVG' table. `NULL` if the table + * is not available. */ typedef struct TT_FaceRec_ { @@ -1508,8 +1461,14 @@ FT_BEGIN_HEADER void* mm; /* a typeless pointer to the FT_Service_MetricsVariationsRec table */ - /* used to handle the HVAR, VVAR, and MVAR OpenType tables */ - void* var; + /* used to handle the HVAR, VVAR, and MVAR OpenType tables by the */ + /* "truetype" driver */ + void* tt_var; + + /* a typeless pointer to the FT_Service_MetricsVariationsRec table */ + /* used to handle the HVAR, VVAR, and MVAR OpenType tables by this */ + /* TT_Face's driver */ + void* face_var; /* since 2.13.1 */ #endif /* a typeless pointer to the PostScript Aux service */ @@ -1591,6 +1550,9 @@ FT_BEGIN_HEADER const char* var_postscript_prefix; /* since 2.7.2 */ FT_UInt var_postscript_prefix_len; /* since 2.7.2 */ + FT_UInt var_default_named_instance; /* since 2.13.1 */ + + const char* non_var_style_name; /* since 2.13.1 */ #endif /* since version 2.2 */ @@ -1627,13 +1589,6 @@ FT_BEGIN_HEADER FT_ULong horz_metrics_offset; FT_ULong vert_metrics_offset; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* since 2.4.12 */ - FT_ULong sph_found_func_flags; /* special functions found */ - /* for this face */ - FT_Bool sph_compatibility_mode; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS /* since 2.7 */ FT_ULong ebdt_start; /* either `CBDT', `EBDT', or `bdat' */ diff --git a/src/3rdparty/freetype/qt_attribution.json b/src/3rdparty/freetype/qt_attribution.json index 407cdd3b..4b1c6a76 100644 --- a/src/3rdparty/freetype/qt_attribution.json +++ b/src/3rdparty/freetype/qt_attribution.json @@ -8,11 +8,11 @@ "Description": "FreeType is a freely available software library to render fonts.", "Homepage": "http://www.freetype.org", - "Version": "2.13.0", - "DownloadLocation": "https://download.savannah.gnu.org/releases/freetype/freetype-2.13.0.tar.gz", + "Version": "2.13.2", + "DownloadLocation": "https://download.savannah.gnu.org/releases/freetype/freetype-2.13.2.tar.gz", "License": "Freetype Project License or GNU General Public License v2.0 only", - "LicenseId": "FTL OR GPL-2.0", + "LicenseId": "FTL OR GPL-2.0-only", "LicenseFile": "LICENSE.txt", "Copyright": "Copyright (c) 2007-2014 Adobe Systems Incorporated Copyright (c) 2004-2023 Albert Chin-A-Young diff --git a/src/3rdparty/freetype/src/autofit/afblue.dat b/src/3rdparty/freetype/src/autofit/afblue.dat index b7efe8be..8299baa2 100644 --- a/src/3rdparty/freetype/src/autofit/afblue.dat +++ b/src/3rdparty/freetype/src/autofit/afblue.dat @@ -89,7 +89,7 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: "ت ث ط ظ ك" // We don't necessarily have access to medial forms via Unicode in case // Arabic presentational forms are missing. The only character that is - // guaranteed to have the same vertical position with joining (this is, + // guaranteed to have the same vertical position with joining (that is, // non-isolated) forms is U+0640, ARABIC TATWEEL, which must join both // round and flat curves. AF_BLUE_STRING_ARABIC_JOIN diff --git a/src/3rdparty/freetype/src/autofit/afcjk.c b/src/3rdparty/freetype/src/autofit/afcjk.c index 5daefff3..f414289a 100644 --- a/src/3rdparty/freetype/src/autofit/afcjk.c +++ b/src/3rdparty/freetype/src/autofit/afcjk.c @@ -417,16 +417,14 @@ { FT_Int nn; - FT_Int first = 0; - FT_Int last = -1; + FT_Int pp, first, last; - for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ ) + last = -1; + for ( nn = 0; nn < outline.n_contours; nn++ ) { - FT_Int pp; - - - last = outline.contours[nn]; + first = last + 1; + last = outline.contours[nn]; /* Avoid single-point contours since they are never rasterized. */ /* In some fonts, they correspond to mark attachment points */ @@ -569,8 +567,8 @@ af_cjk_metrics_check_digits( AF_CJKMetrics metrics, FT_Face face ) { - FT_Bool started = 0, same_width = 1; - FT_Fixed advance = 0, old_advance = 0; + FT_Bool started = 0, same_width = 1; + FT_Long advance = 0, old_advance = 0; /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ @@ -635,10 +633,11 @@ /* Initialize global metrics. */ FT_LOCAL_DEF( FT_Error ) - af_cjk_metrics_init( AF_CJKMetrics metrics, - FT_Face face ) + af_cjk_metrics_init( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Face face ) { - FT_CharMap oldmap = face->charmap; + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + FT_CharMap oldmap = face->charmap; metrics->units_per_em = face->units_per_EM; @@ -756,9 +755,12 @@ /* Scale global values in both directions. */ FT_LOCAL_DEF( void ) - af_cjk_metrics_scale( AF_CJKMetrics metrics, - AF_Scaler scaler ) + af_cjk_metrics_scale( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + AF_Scaler scaler ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + /* we copy the whole structure since the x and y scaling values */ /* are not modified, contrary to e.g. the `latin' auto-hinter */ metrics->root.scaler = *scaler; @@ -771,11 +773,14 @@ /* Extract standard_width from writing system/script specific */ /* metrics class. */ - FT_LOCAL_DEF( void ) - af_cjk_get_standard_widths( AF_CJKMetrics metrics, - FT_Pos* stdHW, - FT_Pos* stdVW ) + FT_CALLBACK_DEF( void ) + af_cjk_get_standard_widths( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Pos* stdHW, + FT_Pos* stdVW ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + if ( stdHW ) *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; @@ -1376,9 +1381,10 @@ /* Initalize hinting engine. */ FT_LOCAL_DEF( FT_Error ) - af_cjk_hints_init( AF_GlyphHints hints, - AF_CJKMetrics metrics ) + af_cjk_hints_init( AF_GlyphHints hints, + AF_StyleMetrics metrics_ ) /* AF_CJKMetrics */ { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; FT_Render_Mode mode; FT_UInt32 scaler_flags, other_flags; @@ -1628,7 +1634,7 @@ stem_edge->pos = base_edge->pos + fitted_width; - FT_TRACE5(( " CJKLINK: edge %ld @%d (opos=%.2f) linked to %.2f," + FT_TRACE5(( " CJKLINK: edge %td @%d (opos=%.2f) linked to %.2f," " dist was %.2f, now %.2f\n", stem_edge - hints->axis[dim].edges, stem_edge->fpos, (double)stem_edge->opos / 64, @@ -1852,7 +1858,7 @@ continue; #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( " CJKBLUE: edge %ld @%d (opos=%.2f) snapped to %.2f," + FT_TRACE5(( " CJKBLUE: edge %td @%d (opos=%.2f) snapped to %.2f," " was %.2f\n", edge1 - edges, edge1->fpos, (double)edge1->opos / 64, (double)blue->fit / 64, (double)edge1->pos / 64 )); @@ -1916,7 +1922,7 @@ /* this should not happen, but it's better to be safe */ if ( edge2->blue_edge ) { - FT_TRACE5(( "ASSERTION FAILED for edge %ld\n", edge2-edges )); + FT_TRACE5(( "ASSERTION FAILED for edge %td\n", edge2 - edges )); af_cjk_align_linked_edge( hints, dim, edge2, edge ); edge->flags |= AF_EDGE_DONE; @@ -2268,11 +2274,13 @@ /* Apply the complete hinting algorithm to a CJK glyph. */ FT_LOCAL_DEF( FT_Error ) - af_cjk_hints_apply( FT_UInt glyph_index, - AF_GlyphHints hints, - FT_Outline* outline, - AF_CJKMetrics metrics ) + af_cjk_hints_apply( FT_UInt glyph_index, + AF_GlyphHints hints, + FT_Outline* outline, + AF_StyleMetrics metrics_ ) /* AF_CJKMetrics */ { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + FT_Error error; int dim; diff --git a/src/3rdparty/freetype/src/autofit/afcjk.h b/src/3rdparty/freetype/src/autofit/afcjk.h index bd7b81b3..f380ef6e 100644 --- a/src/3rdparty/freetype/src/autofit/afcjk.h +++ b/src/3rdparty/freetype/src/autofit/afcjk.h @@ -103,22 +103,22 @@ FT_BEGIN_HEADER #ifdef AF_CONFIG_OPTION_CJK FT_LOCAL( FT_Error ) - af_cjk_metrics_init( AF_CJKMetrics metrics, - FT_Face face ); + af_cjk_metrics_init( AF_StyleMetrics metrics, + FT_Face face ); FT_LOCAL( void ) - af_cjk_metrics_scale( AF_CJKMetrics metrics, - AF_Scaler scaler ); + af_cjk_metrics_scale( AF_StyleMetrics metrics, + AF_Scaler scaler ); FT_LOCAL( FT_Error ) - af_cjk_hints_init( AF_GlyphHints hints, - AF_CJKMetrics metrics ); + af_cjk_hints_init( AF_GlyphHints hints, + AF_StyleMetrics metrics ); FT_LOCAL( FT_Error ) - af_cjk_hints_apply( FT_UInt glyph_index, - AF_GlyphHints hints, - FT_Outline* outline, - AF_CJKMetrics metrics ); + af_cjk_hints_apply( FT_UInt glyph_index, + AF_GlyphHints hints, + FT_Outline* outline, + AF_StyleMetrics metrics ); /* shared; called from afindic.c */ FT_LOCAL( void ) diff --git a/src/3rdparty/freetype/src/autofit/afglobal.c b/src/3rdparty/freetype/src/autofit/afglobal.c index ede27eb1..b1957570 100644 --- a/src/3rdparty/freetype/src/autofit/afglobal.c +++ b/src/3rdparty/freetype/src/autofit/afglobal.c @@ -376,8 +376,11 @@ FT_LOCAL_DEF( void ) - af_face_globals_free( AF_FaceGlobals globals ) + af_face_globals_free( void* globals_ ) { + AF_FaceGlobals globals = (AF_FaceGlobals)globals_; + + if ( globals ) { FT_Memory memory = globals->face->memory; diff --git a/src/3rdparty/freetype/src/autofit/afglobal.h b/src/3rdparty/freetype/src/autofit/afglobal.h index 83a7c2ff..66170e41 100644 --- a/src/3rdparty/freetype/src/autofit/afglobal.h +++ b/src/3rdparty/freetype/src/autofit/afglobal.h @@ -156,7 +156,7 @@ FT_BEGIN_HEADER AF_StyleMetrics *ametrics ); FT_LOCAL( void ) - af_face_globals_free( AF_FaceGlobals globals ); + af_face_globals_free( void* globals ); FT_LOCAL( FT_Bool ) af_face_globals_is_digit( AF_FaceGlobals globals, diff --git a/src/3rdparty/freetype/src/autofit/afhints.c b/src/3rdparty/freetype/src/autofit/afhints.c index 6515af9f..e4a378fb 100644 --- a/src/3rdparty/freetype/src/autofit/afhints.c +++ b/src/3rdparty/freetype/src/autofit/afhints.c @@ -320,8 +320,9 @@ static char* - af_print_idx( char* p, - int idx ) + af_print_idx( char* p, + size_t n, + int idx ) { if ( idx == -1 ) { @@ -330,7 +331,7 @@ p[2] = '\0'; } else - ft_sprintf( p, "%d", idx ); + ft_snprintf( p, n, "%d", idx ); return p; } @@ -457,12 +458,12 @@ " %5d %5d %7.2f %7.2f %7.2f %7.2f" " %5s %5s %5s %5s\n", point_idx, - af_print_idx( buf1, + af_print_idx( buf1, 16, af_get_edge_index( hints, segment_idx_1, 1 ) ), - af_print_idx( buf2, segment_idx_1 ), - af_print_idx( buf3, + af_print_idx( buf2, 16, segment_idx_1 ), + af_print_idx( buf3, 16, af_get_edge_index( hints, segment_idx_0, 0 ) ), - af_print_idx( buf4, segment_idx_0 ), + af_print_idx( buf4, 16, segment_idx_0 ), ( point->flags & AF_FLAG_NEAR ) ? " near " : ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) @@ -476,18 +477,22 @@ (double)point->x / 64, (double)point->y / 64, - af_print_idx( buf5, af_get_strong_edge_index( hints, - point->before, - 1 ) ), - af_print_idx( buf6, af_get_strong_edge_index( hints, - point->after, - 1 ) ), - af_print_idx( buf7, af_get_strong_edge_index( hints, - point->before, - 0 ) ), - af_print_idx( buf8, af_get_strong_edge_index( hints, - point->after, - 0 ) ) )); + af_print_idx( buf5, 16, + af_get_strong_edge_index( hints, + point->before, + 1 ) ), + af_print_idx( buf6, 16, + af_get_strong_edge_index( hints, + point->after, + 1 ) ), + af_print_idx( buf7, 16, + af_get_strong_edge_index( hints, + point->before, + 0 ) ), + af_print_idx( buf8, 16, + af_get_strong_edge_index( hints, + point->after, + 0 ) ) )); } AF_DUMP(( "\n" )); } @@ -574,9 +579,12 @@ AF_INDEX_NUM( seg->first, points ), AF_INDEX_NUM( seg->last, points ), - af_print_idx( buf1, AF_INDEX_NUM( seg->link, segments ) ), - af_print_idx( buf2, AF_INDEX_NUM( seg->serif, segments ) ), - af_print_idx( buf3, AF_INDEX_NUM( seg->edge, edges ) ), + af_print_idx( buf1, 16, + AF_INDEX_NUM( seg->link, segments ) ), + af_print_idx( buf2, 16, + AF_INDEX_NUM( seg->serif, segments ) ), + af_print_idx( buf3, 16, + AF_INDEX_NUM( seg->edge, edges ) ), seg->height, seg->height - ( seg->max_coord - seg->min_coord ), @@ -716,8 +724,10 @@ AF_INDEX_NUM( edge, edges ), (double)(int)edge->opos / 64, af_dir_str( (AF_Direction)edge->dir ), - af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ), - af_print_idx( buf2, AF_INDEX_NUM( edge->serif, edges ) ), + af_print_idx( buf1, 16, + AF_INDEX_NUM( edge->link, edges ) ), + af_print_idx( buf2, 16, + AF_INDEX_NUM( edge->serif, edges ) ), edge->blue_edge ? 'y' : 'n', (double)edge->opos / 64, diff --git a/src/3rdparty/freetype/src/autofit/afindic.c b/src/3rdparty/freetype/src/autofit/afindic.c index 289a09d7..7fb12c63 100644 --- a/src/3rdparty/freetype/src/autofit/afindic.c +++ b/src/3rdparty/freetype/src/autofit/afindic.c @@ -28,9 +28,12 @@ static FT_Error - af_indic_metrics_init( AF_CJKMetrics metrics, - FT_Face face ) + af_indic_metrics_init( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Face face ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + /* skip blue zone init in CJK routines */ FT_CharMap oldmap = face->charmap; @@ -55,8 +58,8 @@ static void - af_indic_metrics_scale( AF_CJKMetrics metrics, - AF_Scaler scaler ) + af_indic_metrics_scale( AF_StyleMetrics metrics, + AF_Scaler scaler ) { /* use CJK routines */ af_cjk_metrics_scale( metrics, scaler ); @@ -64,8 +67,8 @@ static FT_Error - af_indic_hints_init( AF_GlyphHints hints, - AF_CJKMetrics metrics ) + af_indic_hints_init( AF_GlyphHints hints, + AF_StyleMetrics metrics ) { /* use CJK routines */ return af_cjk_hints_init( hints, metrics ); @@ -73,10 +76,10 @@ static FT_Error - af_indic_hints_apply( FT_UInt glyph_index, - AF_GlyphHints hints, - FT_Outline* outline, - AF_CJKMetrics metrics ) + af_indic_hints_apply( FT_UInt glyph_index, + AF_GlyphHints hints, + FT_Outline* outline, + AF_StyleMetrics metrics ) { /* use CJK routines */ return af_cjk_hints_apply( glyph_index, hints, outline, metrics ); @@ -87,10 +90,13 @@ /* metrics class. */ static void - af_indic_get_standard_widths( AF_CJKMetrics metrics, - FT_Pos* stdHW, - FT_Pos* stdVW ) + af_indic_get_standard_widths( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Pos* stdHW, + FT_Pos* stdVW ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + if ( stdHW ) *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; diff --git a/src/3rdparty/freetype/src/autofit/aflatin.c b/src/3rdparty/freetype/src/autofit/aflatin.c index 4b3c59b3..b86367aa 100644 --- a/src/3rdparty/freetype/src/autofit/aflatin.c +++ b/src/3rdparty/freetype/src/autofit/aflatin.c @@ -496,23 +496,20 @@ /* now compute min or max point indices and coordinates */ points = outline.points; best_point = -1; + best_contour_first = -1; + best_contour_last = -1; best_y = 0; /* make compiler happy */ - best_contour_first = 0; /* ditto */ - best_contour_last = 0; /* ditto */ { FT_Int nn; - FT_Int first = 0; - FT_Int last = -1; + FT_Int pp, first, last; - for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ ) + last = -1; + for ( nn = 0; nn < outline.n_contours; nn++ ) { - FT_Int old_best_point = best_point; - FT_Int pp; - - - last = outline.contours[nn]; + first = last + 1; + last = outline.contours[nn]; /* Avoid single-point contours since they are never */ /* rasterized. In some fonts, they correspond to mark */ @@ -551,7 +548,7 @@ } } - if ( best_point != old_best_point ) + if ( best_point > best_contour_last ) { best_contour_first = first; best_contour_last = last; @@ -1025,7 +1022,7 @@ { *a = *b; FT_TRACE5(( "blue zone overlap:" - " adjusting %s %ld to %ld\n", + " adjusting %s %td to %ld\n", a_is_top ? "overshoot" : "reference", blue_sorted[i] - axis->blues, *a )); @@ -1068,8 +1065,8 @@ af_latin_metrics_check_digits( AF_LatinMetrics metrics, FT_Face face ) { - FT_Bool started = 0, same_width = 1; - FT_Fixed advance = 0, old_advance = 0; + FT_Bool started = 0, same_width = 1; + FT_Long advance = 0, old_advance = 0; /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ @@ -1134,9 +1131,11 @@ /* Initialize global metrics. */ FT_LOCAL_DEF( FT_Error ) - af_latin_metrics_init( AF_LatinMetrics metrics, + af_latin_metrics_init( AF_StyleMetrics metrics_, /* AF_LatinMetrics */ FT_Face face ) { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + FT_Error error = FT_Err_Ok; FT_CharMap oldmap = face->charmap; @@ -1489,9 +1488,12 @@ /* Scale global values in both directions. */ FT_LOCAL_DEF( void ) - af_latin_metrics_scale( AF_LatinMetrics metrics, + af_latin_metrics_scale( AF_StyleMetrics metrics_, /* AF_LatinMetrics */ AF_Scaler scaler ) { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + + metrics->root.scaler.render_mode = scaler->render_mode; metrics->root.scaler.face = scaler->face; metrics->root.scaler.flags = scaler->flags; @@ -1504,11 +1506,14 @@ /* Extract standard_width from writing system/script specific */ /* metrics class. */ - FT_LOCAL_DEF( void ) - af_latin_get_standard_widths( AF_LatinMetrics metrics, + FT_CALLBACK_DEF( void ) + af_latin_get_standard_widths( AF_StyleMetrics metrics_, /* AF_LatinMetrics */ FT_Pos* stdHW, FT_Pos* stdVW ) { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + + if ( stdHW ) *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; @@ -2041,7 +2046,7 @@ max = seg2->max_coord; /* compute maximum coordinate difference of the two segments */ - /* (this is, how much they overlap) */ + /* (that is, how much they overlap) */ len = max - min; if ( len >= len_threshold ) { @@ -2610,8 +2615,10 @@ static FT_Error af_latin_hints_init( AF_GlyphHints hints, - AF_LatinMetrics metrics ) + AF_StyleMetrics metrics_ ) /* AF_LatinMetrics */ { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + FT_Render_Mode mode; FT_UInt32 scaler_flags, other_flags; FT_Face face = metrics->root.scaler.face; @@ -2953,7 +2960,7 @@ stem_edge->pos = base_edge->pos + fitted_width; - FT_TRACE5(( " LINK: edge %ld (opos=%.2f) linked to %.2f," + FT_TRACE5(( " LINK: edge %td (opos=%.2f) linked to %.2f," " dist was %.2f, now %.2f\n", stem_edge - hints->axis[dim].edges, (double)stem_edge->opos / 64, (double)stem_edge->pos / 64, @@ -3078,13 +3085,13 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( !anchor ) - FT_TRACE5(( " BLUE_ANCHOR: edge %ld (opos=%.2f) snapped to %.2f," - " was %.2f (anchor=edge %ld)\n", + FT_TRACE5(( " BLUE_ANCHOR: edge %td (opos=%.2f) snapped to %.2f," + " was %.2f (anchor=edge %td)\n", edge1 - edges, (double)edge1->opos / 64, (double)blue->fit / 64, (double)edge1->pos / 64, edge - edges )); else - FT_TRACE5(( " BLUE: edge %ld (opos=%.2f) snapped to %.2f," + FT_TRACE5(( " BLUE: edge %td (opos=%.2f) snapped to %.2f," " was %.2f\n", edge1 - edges, (double)edge1->opos / 64, (double)blue->fit / 64, @@ -3134,7 +3141,7 @@ /* this should not happen, but it's better to be safe */ if ( edge2->blue_edge ) { - FT_TRACE5(( " ASSERTION FAILED for edge %ld\n", edge2 - edges )); + FT_TRACE5(( " ASSERTION FAILED for edge %td\n", edge2 - edges )); af_latin_align_linked_edge( hints, dim, edge2, edge ); edge->flags |= AF_EDGE_DONE; @@ -3202,7 +3209,7 @@ anchor = edge; edge->flags |= AF_EDGE_DONE; - FT_TRACE5(( " ANCHOR: edge %ld (opos=%.2f) and %ld (opos=%.2f)" + FT_TRACE5(( " ANCHOR: edge %td (opos=%.2f) and %td (opos=%.2f)" " snapped to %.2f and %.2f\n", edge - edges, (double)edge->opos / 64, edge2 - edges, (double)edge2->opos / 64, @@ -3231,7 +3238,7 @@ if ( edge2->flags & AF_EDGE_DONE ) { - FT_TRACE5(( " ADJUST: edge %ld (pos=%.2f) moved to %.2f\n", + FT_TRACE5(( " ADJUST: edge %td (pos=%.2f) moved to %.2f\n", edge - edges, (double)edge->pos / 64, (double)( edge2->pos - cur_len ) / 64 )); @@ -3272,7 +3279,7 @@ edge->pos = cur_pos1 - cur_len / 2; edge2->pos = cur_pos1 + cur_len / 2; - FT_TRACE5(( " STEM: edge %ld (opos=%.2f) linked to %ld (opos=%.2f)" + FT_TRACE5(( " STEM: edge %td (opos=%.2f) linked to %td (opos=%.2f)" " snapped to %.2f and %.2f\n", edge - edges, (double)edge->opos / 64, edge2 - edges, (double)edge2->opos / 64, @@ -3303,7 +3310,7 @@ edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2; edge2->pos = edge->pos + cur_len; - FT_TRACE5(( " STEM: edge %ld (opos=%.2f) linked to %ld (opos=%.2f)" + FT_TRACE5(( " STEM: edge %td (opos=%.2f) linked to %td (opos=%.2f)" " snapped to %.2f and %.2f\n", edge - edges, (double)edge->opos / 64, edge2 - edges, (double)edge2->opos / 64, @@ -3326,7 +3333,7 @@ if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 ) { #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n", + FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n", edge - edges, (double)edge->pos / 64, (double)edge[-1].pos / 64 )); @@ -3428,7 +3435,7 @@ if ( delta < 64 + 16 ) { af_latin_align_serif_edge( hints, edge->serif, edge ); - FT_TRACE5(( " SERIF: edge %ld (opos=%.2f) serif to %ld (opos=%.2f)" + FT_TRACE5(( " SERIF: edge %td (opos=%.2f) serif to %td (opos=%.2f)" " aligned to %.2f\n", edge - edges, (double)edge->opos / 64, edge->serif - edges, (double)edge->serif->opos / 64, @@ -3438,9 +3445,9 @@ { edge->pos = FT_PIX_ROUND( edge->opos ); anchor = edge; - FT_TRACE5(( " SERIF_ANCHOR: edge %ld (opos=%.2f)" + FT_TRACE5(( " SERIF_ANCHOR: edge %td (opos=%.2f)" " snapped to %.2f\n", - edge-edges, + edge - edges, (double)edge->opos / 64, (double)edge->pos / 64 )); } else @@ -3467,8 +3474,8 @@ after->pos - before->pos, after->opos - before->opos ); - FT_TRACE5(( " SERIF_LINK1: edge %ld (opos=%.2f) snapped to %.2f" - " from %ld (opos=%.2f)\n", + FT_TRACE5(( " SERIF_LINK1: edge %td (opos=%.2f) snapped to %.2f" + " from %td (opos=%.2f)\n", edge - edges, (double)edge->opos / 64, (double)edge->pos / 64, before - edges, (double)before->opos / 64 )); @@ -3477,7 +3484,7 @@ { edge->pos = anchor->pos + ( ( edge->opos - anchor->opos + 16 ) & ~31 ); - FT_TRACE5(( " SERIF_LINK2: edge %ld (opos=%.2f)" + FT_TRACE5(( " SERIF_LINK2: edge %td (opos=%.2f)" " snapped to %.2f\n", edge - edges, (double)edge->opos / 64, (double)edge->pos / 64 )); @@ -3498,7 +3505,7 @@ if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 ) { #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n", + FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n", edge - edges, (double)edge->pos / 64, (double)edge[-1].pos / 64 )); @@ -3519,7 +3526,7 @@ if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 ) { #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n", + FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n", edge - edges, (double)edge->pos / 64, (double)edge[1].pos / 64 )); @@ -3547,8 +3554,10 @@ af_latin_hints_apply( FT_UInt glyph_index, AF_GlyphHints hints, FT_Outline* outline, - AF_LatinMetrics metrics ) + AF_StyleMetrics metrics_ ) /* AF_LatinMetrics */ { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + FT_Error error; int dim; diff --git a/src/3rdparty/freetype/src/autofit/aflatin.h b/src/3rdparty/freetype/src/autofit/aflatin.h index 3c6a7ee4..31aa91d3 100644 --- a/src/3rdparty/freetype/src/autofit/aflatin.h +++ b/src/3rdparty/freetype/src/autofit/aflatin.h @@ -116,11 +116,11 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - af_latin_metrics_init( AF_LatinMetrics metrics, + af_latin_metrics_init( AF_StyleMetrics metrics, FT_Face face ); FT_LOCAL( void ) - af_latin_metrics_scale( AF_LatinMetrics metrics, + af_latin_metrics_scale( AF_StyleMetrics metrics, AF_Scaler scaler ); FT_LOCAL( void ) diff --git a/src/3rdparty/freetype/src/autofit/afloader.c b/src/3rdparty/freetype/src/autofit/afloader.c index c8082796..7c47d562 100644 --- a/src/3rdparty/freetype/src/autofit/afloader.c +++ b/src/3rdparty/freetype/src/autofit/afloader.c @@ -55,10 +55,8 @@ error = af_face_globals_new( face, &loader->globals, module ); if ( !error ) { - face->autohint.data = - (FT_Pointer)loader->globals; - face->autohint.finalizer = - (FT_Generic_Finalizer)af_face_globals_free; + face->autohint.data = (FT_Pointer)loader->globals; + face->autohint.finalizer = af_face_globals_free; } } diff --git a/src/3rdparty/freetype/src/autofit/afmodule.c b/src/3rdparty/freetype/src/autofit/afmodule.c index 92e5156a..20a6b96b 100644 --- a/src/3rdparty/freetype/src/autofit/afmodule.c +++ b/src/3rdparty/freetype/src/autofit/afmodule.c @@ -89,10 +89,8 @@ error = af_face_globals_new( face, &globals, module ); if ( !error ) { - face->autohint.data = - (FT_Pointer)globals; - face->autohint.finalizer = - (FT_Generic_Finalizer)af_face_globals_free; + face->autohint.data = (FT_Pointer)globals; + face->autohint.finalizer = af_face_globals_free; } } @@ -374,8 +372,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( af_service_properties, - (FT_Properties_SetFunc)af_property_set, /* set_property */ - (FT_Properties_GetFunc)af_property_get ) /* get_property */ + af_property_set, /* FT_Properties_SetFunc set_property */ + af_property_get /* FT_Properties_GetFunc get_property */ + ) FT_DEFINE_SERVICEDESCREC1( @@ -430,12 +429,14 @@ FT_CALLBACK_DEF( FT_Error ) - af_autofitter_load_glyph( AF_Module module, - FT_GlyphSlot slot, - FT_Size size, - FT_UInt glyph_index, - FT_Int32 load_flags ) + af_autofitter_load_glyph( FT_AutoHinter module_, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) { + AF_Module module = (AF_Module)module_; + FT_Error error = FT_Err_Ok; FT_Memory memory = module->root.library->memory; @@ -499,10 +500,10 @@ FT_DEFINE_AUTOHINTER_INTERFACE( af_autofitter_interface, - NULL, /* reset_face */ - NULL, /* get_global_hints */ - NULL, /* done_global_hints */ - (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph /* load_glyph */ + NULL, /* FT_AutoHinter_GlobalResetFunc reset_face */ + NULL, /* FT_AutoHinter_GlobalGetFunc get_global_hints */ + NULL, /* FT_AutoHinter_GlobalDoneFunc done_global_hints */ + af_autofitter_load_glyph /* FT_AutoHinter_GlyphLoadFunc load_glyph */ ) FT_DEFINE_MODULE( @@ -517,9 +518,9 @@ (const void*)&af_autofitter_interface, - (FT_Module_Constructor)af_autofitter_init, /* module_init */ - (FT_Module_Destructor) af_autofitter_done, /* module_done */ - (FT_Module_Requester) af_get_interface /* get_interface */ + af_autofitter_init, /* FT_Module_Constructor module_init */ + af_autofitter_done, /* FT_Module_Destructor module_done */ + af_get_interface /* FT_Module_Requester get_interface */ ) diff --git a/src/3rdparty/freetype/src/autofit/afshaper.c b/src/3rdparty/freetype/src/autofit/afshaper.c index 1b8b870e..abc6f1d2 100644 --- a/src/3rdparty/freetype/src/autofit/afshaper.c +++ b/src/3rdparty/freetype/src/autofit/afshaper.c @@ -258,7 +258,7 @@ /* * We now check whether we can construct blue zones, using glyphs * covered by the feature only. In case there is not a single zone - * (this is, not a single character is covered), we skip this coverage. + * (that is, not a single character is covered), we skip this coverage. * */ if ( style_class->coverage != AF_COVERAGE_DEFAULT ) @@ -313,9 +313,9 @@ * hinted and usually rendered glyph. * * Consider the superscript feature of font `pala.ttf': Some of the - * glyphs are `real', this is, they have a zero vertical offset, but + * glyphs are `real', that is, they have a zero vertical offset, but * most of them are small caps glyphs shifted up to the superscript - * position (this is, the `sups' feature is present in both the GSUB and + * position (that is, the `sups' feature is present in both the GSUB and * GPOS tables). The code for blue zones computation actually uses a * feature's y offset so that the `real' glyphs get correct hints. But * later on it is impossible to decide whether a glyph index belongs to, diff --git a/src/3rdparty/freetype/src/autofit/ft-hb.c b/src/3rdparty/freetype/src/autofit/ft-hb.c index 09a8401c..71aee045 100644 --- a/src/3rdparty/freetype/src/autofit/ft-hb.c +++ b/src/3rdparty/freetype/src/autofit/ft-hb.c @@ -108,7 +108,7 @@ hb_ft_font_create_ (FT_Face ft_face, #else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ /* ANSI C doesn't like empty source files */ -typedef int _ft_hb_dummy; +typedef int ft_hb_dummy_; #endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ diff --git a/src/3rdparty/freetype/src/base/ftbbox.c b/src/3rdparty/freetype/src/base/ftbbox.c index 7dd71882..385fea40 100644 --- a/src/3rdparty/freetype/src/base/ftbbox.c +++ b/src/3rdparty/freetype/src/base/ftbbox.c @@ -82,10 +82,13 @@ * @Return: * Always 0. Needed for the interface only. */ - static int - BBox_Move_To( FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Move_To( const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + FT_UPDATE_BBOX( to, user->bbox ); user->last = *to; @@ -116,10 +119,13 @@ * @Return: * Always 0. Needed for the interface only. */ - static int - BBox_Line_To( FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Line_To( const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + user->last = *to; return 0; @@ -205,11 +211,14 @@ * In the case of a non-monotonous arc, we compute directly the * extremum coordinates, as it is sufficiently fast. */ - static int - BBox_Conic_To( FT_Vector* control, - FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Conic_To( const FT_Vector* control, + const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + /* in case `to' is implicit and not included in bbox yet */ FT_UPDATE_BBOX( to, user->bbox ); @@ -410,12 +419,15 @@ * In the case of a non-monotonous arc, we don't compute directly * extremum coordinates, we subdivide instead. */ - static int - BBox_Cubic_To( FT_Vector* control1, - FT_Vector* control2, - FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Cubic_To( const FT_Vector* control1, + const FT_Vector* control2, + const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + /* We don't need to check `to' since it is always an on-point, */ /* thus within the bbox. Only segments with an off-point outside */ /* the bbox can possibly reach new extreme values. */ diff --git a/src/3rdparty/freetype/src/base/ftcalc.c b/src/3rdparty/freetype/src/base/ftcalc.c index 13e74f33..c5bc7e3b 100644 --- a/src/3rdparty/freetype/src/base/ftcalc.c +++ b/src/3rdparty/freetype/src/base/ftcalc.c @@ -749,65 +749,43 @@ FT_BASE_DEF( FT_Bool ) FT_Matrix_Check( const FT_Matrix* matrix ) { - FT_Matrix m; - FT_Fixed val[4]; - FT_Fixed nonzero_minval, maxval; - FT_Fixed temp1, temp2; - FT_UInt i; + FT_Fixed xx, xy, yx, yy; + FT_Fixed val; + FT_Int shift; + FT_ULong temp1, temp2; if ( !matrix ) return 0; - val[0] = FT_ABS( matrix->xx ); - val[1] = FT_ABS( matrix->xy ); - val[2] = FT_ABS( matrix->yx ); - val[3] = FT_ABS( matrix->yy ); + xx = matrix->xx; + xy = matrix->xy; + yx = matrix->yx; + yy = matrix->yy; + val = FT_ABS( xx ) | FT_ABS( xy ) | FT_ABS( yx ) | FT_ABS( yy ); - /* - * To avoid overflow, we ensure that each value is not larger than - * - * int(sqrt(2^31 / 4)) = 23170 ; - * - * we also check that no value becomes zero if we have to scale. - */ - - maxval = 0; - nonzero_minval = FT_LONG_MAX; - - for ( i = 0; i < 4; i++ ) - { - if ( val[i] > maxval ) - maxval = val[i]; - if ( val[i] && val[i] < nonzero_minval ) - nonzero_minval = val[i]; - } - - /* we only handle 32bit values */ - if ( maxval > 0x7FFFFFFFL ) + /* we only handle non-zero 32-bit values */ + if ( !val || val > 0x7FFFFFFFL ) return 0; - if ( maxval > 23170 ) + /* Scale matrix to avoid the temp1 overflow, which is */ + /* more stringent than avoiding the temp2 overflow. */ + + shift = FT_MSB( val ) - 12; + + if ( shift > 0 ) { - FT_Fixed scale = FT_DivFix( maxval, 23170 ); - - - if ( !FT_DivFix( nonzero_minval, scale ) ) - return 0; /* value range too large */ - - m.xx = FT_DivFix( matrix->xx, scale ); - m.xy = FT_DivFix( matrix->xy, scale ); - m.yx = FT_DivFix( matrix->yx, scale ); - m.yy = FT_DivFix( matrix->yy, scale ); + xx >>= shift; + xy >>= shift; + yx >>= shift; + yy >>= shift; } - else - m = *matrix; - temp1 = FT_ABS( m.xx * m.yy - m.xy * m.yx ); - temp2 = m.xx * m.xx + m.xy * m.xy + m.yx * m.yx + m.yy * m.yy; + temp1 = 32U * (FT_ULong)FT_ABS( xx * yy - xy * yx ); + temp2 = (FT_ULong)( xx * xx ) + (FT_ULong)( xy * xy ) + + (FT_ULong)( yx * yx ) + (FT_ULong)( yy * yy ); - if ( temp1 == 0 || - temp2 / temp1 > 50 ) + if ( temp1 <= temp2 ) return 0; return 1; @@ -1061,7 +1039,7 @@ /* */ /* This approach has the advantage that the angle between */ /* `in' and `out' is not checked. In case one of the two */ - /* vectors is `dominant', this is, much larger than the */ + /* vectors is `dominant', that is, much larger than the */ /* other vector, we thus always have a flat corner. */ /* */ /* hypotenuse */ @@ -1092,9 +1070,6 @@ { FT_UInt i; FT_Int64 temp; -#ifndef FT_INT64 - FT_Int64 halfUnit; -#endif #ifdef FT_INT64 @@ -1103,7 +1078,7 @@ for ( i = 0; i < count; ++i ) temp += (FT_Int64)s[i] * f[i]; - return ( temp + 0x8000 ) >> 16; + return (FT_Int32)( ( temp + 0x8000 ) >> 16 ); #else temp.hi = 0; temp.lo = 0; @@ -1139,13 +1114,10 @@ FT_Add64( &temp, &multResult, &temp ); } - /* Round value. */ - halfUnit.hi = 0; - halfUnit.lo = 0x8000; - FT_Add64( &temp, &halfUnit, &temp ); + /* Shift and round value. */ + return (FT_Int32)( ( ( temp.hi << 16 ) | ( temp.lo >> 16 ) ) + + ( 1 & ( temp.lo >> 15 ) ) ); - return (FT_Int32)( ( (FT_Int32)( temp.hi & 0xFFFF ) << 16 ) | - ( temp.lo >> 16 ) ); #endif /* !FT_INT64 */ diff --git a/src/3rdparty/freetype/src/base/ftdbgmem.c b/src/3rdparty/freetype/src/base/ftdbgmem.c index 6730c4c8..8fab50dd 100644 --- a/src/3rdparty/freetype/src/base/ftdbgmem.c +++ b/src/3rdparty/freetype/src/base/ftdbgmem.c @@ -963,7 +963,7 @@ #else /* !FT_DEBUG_MEMORY */ /* ANSI C doesn't like empty source files */ - typedef int _debug_mem_dummy; + typedef int debug_mem_dummy_; #endif /* !FT_DEBUG_MEMORY */ diff --git a/src/3rdparty/freetype/src/base/ftmac.c b/src/3rdparty/freetype/src/base/ftmac.c index de34e834..492d0553 100644 --- a/src/3rdparty/freetype/src/base/ftmac.c +++ b/src/3rdparty/freetype/src/base/ftmac.c @@ -1082,7 +1082,7 @@ #else /* !FT_MACINTOSH */ /* ANSI C doesn't like empty source files */ - typedef int _ft_mac_dummy; + typedef int ft_mac_dummy_; #endif /* !FT_MACINTOSH */ diff --git a/src/3rdparty/freetype/src/base/ftmm.c b/src/3rdparty/freetype/src/base/ftmm.c index a2b4bd03..9e2dd7ee 100644 --- a/src/3rdparty/freetype/src/base/ftmm.c +++ b/src/3rdparty/freetype/src/base/ftmm.c @@ -185,6 +185,14 @@ error = FT_ERR( Invalid_Argument ); if ( service->set_mm_design ) error = service->set_mm_design( face, num_coords, coords ); + + if ( !error ) + { + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + } } /* enforce recomputation of auto-hinting data */ @@ -220,6 +228,14 @@ error = FT_ERR( Invalid_Argument ); if ( service->set_mm_weightvector ) error = service->set_mm_weightvector( face, len, weightvector ); + + if ( !error ) + { + if ( len ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + } } /* enforce recomputation of auto-hinting data */ @@ -283,6 +299,30 @@ if ( service_mm->set_var_design ) error = service_mm->set_var_design( face, num_coords, coords ); + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + /* internal error code -1 means `no change'; we can exit immediately */ if ( error == -1 ) return FT_Err_Ok; @@ -359,6 +399,30 @@ if ( service_mm->set_mm_blend ) error = service_mm->set_mm_blend( face, num_coords, coords ); + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + /* internal error code -1 means `no change'; we can exit immediately */ if ( error == -1 ) return FT_Err_Ok; @@ -410,6 +474,30 @@ if ( service_mm->set_mm_blend ) error = service_mm->set_mm_blend( face, num_coords, coords ); + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + /* internal error code -1 means `no change'; we can exit immediately */ if ( error == -1 ) return FT_Err_Ok; @@ -535,8 +623,35 @@ if ( !error ) { error = FT_ERR( Invalid_Argument ); - if ( service_mm->set_instance ) - error = service_mm->set_instance( face, instance_index ); + if ( service_mm->set_named_instance ) + error = service_mm->set_named_instance( face, instance_index ); + + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + face->face_index = ( instance_index << 16 ) | + ( face->face_index & 0xFFFFL ); + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + + /* internal error code -1 means `no change'; we can exit immediately */ + if ( error == -1 ) + return FT_Err_Ok; } if ( !error ) @@ -554,11 +669,32 @@ face->autohint.data = NULL; } + return error; + } + + + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ) + { + FT_Error error; + + FT_Service_MultiMasters service_mm = NULL; + + + /* check of `face' delayed to `ft_face_get_mm_service' */ + + error = ft_face_get_mm_service( face, &service_mm ); if ( !error ) { - face->face_index = ( instance_index << 16 ) | - ( face->face_index & 0xFFFFL ); - face->face_flags &= ~FT_FACE_FLAG_VARIATION; + /* no error if `get_default_named_instance` is not available */ + if ( service_mm->get_default_named_instance ) + error = service_mm->get_default_named_instance( face, + instance_index ); + else + error = FT_Err_Ok; } return error; diff --git a/src/3rdparty/freetype/src/base/ftobjs.c b/src/3rdparty/freetype/src/base/ftobjs.c index ad6ef0ae..89a25bc7 100644 --- a/src/3rdparty/freetype/src/base/ftobjs.c +++ b/src/3rdparty/freetype/src/base/ftobjs.c @@ -1019,7 +1019,8 @@ /* elegant. */ /* try to load SVG documents if available */ - if ( FT_HAS_SVG( face ) ) + if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && + FT_HAS_SVG( face ) ) { error = driver->clazz->load_glyph( slot, face->size, glyph_index, @@ -1245,9 +1246,13 @@ /* destructor for sizes list */ static void destroy_size( FT_Memory memory, - FT_Size size, - FT_Driver driver ) + void* size_, + void* driver_ ) { + FT_Size size = (FT_Size)size_; + FT_Driver driver = (FT_Driver)driver_; + + /* finalize client-specific data */ if ( size->generic.finalizer ) size->generic.finalizer( size ); @@ -1293,10 +1298,12 @@ /* destructor for faces list */ static void destroy_face( FT_Memory memory, - FT_Face face, - FT_Driver driver ) + void* face_, + void* driver_ ) { - FT_Driver_Class clazz = driver->clazz; + FT_Face face = (FT_Face)face_; + FT_Driver driver = (FT_Driver)driver_; + FT_Driver_Class clazz = driver->clazz; /* discard auto-hinting data */ @@ -1310,7 +1317,7 @@ /* discard all sizes for this face */ FT_List_Finalize( &face->sizes_list, - (FT_List_Destructor)destroy_size, + destroy_size, memory, driver ); face->size = NULL; @@ -1346,7 +1353,7 @@ Destroy_Driver( FT_Driver driver ) { FT_List_Finalize( &driver->faces_list, - (FT_List_Destructor)destroy_face, + destroy_face, driver->root.memory, driver ); } @@ -1740,7 +1747,8 @@ FT_Memory memory = library->memory; - args.flags = 0; + args.driver = NULL; + args.flags = 0; if ( driver_name ) { diff --git a/src/3rdparty/freetype/src/base/ftoutln.c b/src/3rdparty/freetype/src/base/ftoutln.c index 30ff21ff..134f39d2 100644 --- a/src/3rdparty/freetype/src/base/ftoutln.c +++ b/src/3rdparty/freetype/src/base/ftoutln.c @@ -58,7 +58,9 @@ FT_Error error; FT_Int n; /* index of contour in outline */ - FT_UInt first; /* index of first point in contour */ + FT_Int first; /* index of first point in contour */ + FT_Int last; /* index of last point in contour */ + FT_Int tag; /* current point's state */ FT_Int shift; @@ -73,18 +75,17 @@ shift = func_interface->shift; delta = func_interface->delta; - first = 0; + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { - FT_Int last; /* index of last point in contour */ + FT_TRACE5(( "FT_Outline_Decompose: Contour %d\n", n )); - - FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); - - last = outline->contours[n]; - if ( last < 0 ) + first = last + 1; + last = outline->contours[n]; + if ( last < first ) goto Invalid_Outline; + limit = outline->points + last; v_start = outline->points[first]; @@ -282,8 +283,6 @@ Close: if ( error ) goto Exit; - - first = (FT_UInt)last + 1; } FT_TRACE5(( "FT_Outline_Decompose: Done\n" )); @@ -368,7 +367,7 @@ if ( n_points <= 0 || n_contours <= 0 ) goto Bad; - end0 = end = -1; + end0 = -1; for ( n = 0; n < n_contours; n++ ) { end = outline->contours[n]; @@ -380,7 +379,7 @@ end0 = end; } - if ( end != n_points - 1 ) + if ( end0 != n_points - 1 ) goto Bad; /* XXX: check the tags array */ @@ -388,7 +387,7 @@ } Bad: - return FT_THROW( Invalid_Argument ); + return FT_THROW( Invalid_Outline ); } @@ -550,10 +549,12 @@ if ( !outline ) return; - first = 0; - + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { + /* keep the first contour point as is and swap points around it */ + /* to guarantee that the cubic arches stay valid after reverse */ + first = last + 2; last = outline->contours[n]; /* reverse point table */ @@ -591,8 +592,6 @@ q--; } } - - first = last + 1; } outline->flags ^= FT_OUTLINE_REVERSE_FILL; @@ -941,7 +940,7 @@ points = outline->points; - first = 0; + last = -1; for ( c = 0; c < outline->n_contours; c++ ) { FT_Vector in, out, anchor, shift; @@ -949,8 +948,9 @@ FT_Int i, j, k; - l_in = 0; - last = outline->contours[c]; + first = last + 1; + last = outline->contours[c]; + l_in = 0; /* pacify compiler */ in.x = in.y = anchor.x = anchor.y = 0; @@ -1037,8 +1037,6 @@ in = out; l_in = l_out; } - - first = last + 1; } return FT_Err_Ok; @@ -1054,7 +1052,7 @@ FT_Int xshift, yshift; FT_Vector* points; FT_Vector v_prev, v_cur; - FT_Int c, n, first; + FT_Int c, n, first, last; FT_Pos area = 0; @@ -1086,11 +1084,11 @@ points = outline->points; - first = 0; + last = -1; for ( c = 0; c < outline->n_contours; c++ ) { - FT_Int last = outline->contours[c]; - + first = last + 1; + last = outline->contours[c]; v_prev.x = points[last].x >> xshift; v_prev.y = points[last].y >> yshift; @@ -1106,8 +1104,6 @@ v_prev = v_cur; } - - first = last + 1; } if ( area > 0 ) diff --git a/src/3rdparty/freetype/src/base/ftstream.c b/src/3rdparty/freetype/src/base/ftstream.c index 05c56375..64826ace 100644 --- a/src/3rdparty/freetype/src/base/ftstream.c +++ b/src/3rdparty/freetype/src/base/ftstream.c @@ -141,7 +141,9 @@ if ( read_bytes > count ) read_bytes = count; - FT_MEM_COPY( buffer, stream->base + pos, read_bytes ); + /* Allow "reading" zero bytes without UB even if buffer is NULL */ + if ( count ) + FT_MEM_COPY( buffer, stream->base + pos, read_bytes ); } stream->pos = pos + read_bytes; @@ -178,7 +180,9 @@ if ( read_bytes > count ) read_bytes = count; - FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes ); + /* Allow "reading" zero bytes without UB even if buffer is NULL */ + if ( count ) + FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes ); } stream->pos += read_bytes; diff --git a/src/3rdparty/freetype/src/base/ftstroke.c b/src/3rdparty/freetype/src/base/ftstroke.c index db358e77..92f1e430 100644 --- a/src/3rdparty/freetype/src/base/ftstroke.c +++ b/src/3rdparty/freetype/src/base/ftstroke.c @@ -2055,7 +2055,9 @@ FT_Error error; FT_Int n; /* index of contour in outline */ - FT_UInt first; /* index of first point in contour */ + FT_Int first; /* index of first point in contour */ + FT_Int last; /* index of last point in contour */ + FT_Int tag; /* current point's state */ @@ -2067,22 +2069,17 @@ FT_Stroker_Rewind( stroker ); - first = 0; - + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { - FT_UInt last; /* index of last point in contour */ - - - last = (FT_UInt)outline->contours[n]; - limit = outline->points + last; + first = last + 1; + last = outline->contours[n]; /* skip empty points; we don't stroke these */ if ( last <= first ) - { - first = last + 1; continue; - } + + limit = outline->points + last; v_start = outline->points[first]; v_last = outline->points[last]; @@ -2231,8 +2228,6 @@ if ( error ) goto Exit; } - - first = last + 1; } return FT_Err_Ok; diff --git a/src/3rdparty/freetype/src/base/ftsynth.c b/src/3rdparty/freetype/src/base/ftsynth.c index 6ec25e13..f32edd33 100644 --- a/src/3rdparty/freetype/src/base/ftsynth.c +++ b/src/3rdparty/freetype/src/base/ftsynth.c @@ -97,9 +97,18 @@ FT_EXPORT_DEF( void ) FT_GlyphSlot_Embolden( FT_GlyphSlot slot ) + { + FT_GlyphSlot_AdjustWeight( slot, 0x0AAA, 0x0AAA ); + } + + + FT_EXPORT_DEF( void ) + FT_GlyphSlot_AdjustWeight( FT_GlyphSlot slot, + FT_Fixed xdelta, + FT_Fixed ydelta ) { FT_Library library; - FT_Face face; + FT_Size size; FT_Error error; FT_Pos xstr, ystr; @@ -108,16 +117,15 @@ return; library = slot->library; - face = slot->face; + size = slot->face->size; if ( slot->format != FT_GLYPH_FORMAT_OUTLINE && slot->format != FT_GLYPH_FORMAT_BITMAP ) return; - /* some reasonable strength */ - xstr = FT_MulFix( face->units_per_EM, - face->size->metrics.y_scale ) / 24; - ystr = xstr; + /* express deltas in pixels in 26.6 format */ + xstr = (FT_Pos)size->metrics.x_ppem * xdelta / 1024; + ystr = (FT_Pos)size->metrics.y_ppem * ydelta / 1024; if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) FT_Outline_EmboldenXY( &slot->outline, xstr, ystr ); diff --git a/src/3rdparty/freetype/src/base/ftsystem.c b/src/3rdparty/freetype/src/base/ftsystem.c index fcd289d1..61c99e36 100644 --- a/src/3rdparty/freetype/src/base/ftsystem.c +++ b/src/3rdparty/freetype/src/base/ftsystem.c @@ -206,7 +206,7 @@ * The number of bytes to read from the stream. * * @Return: - * The number of bytes actually read. If `count' is zero (this is, + * The number of bytes actually read. If `count' is zero (that is, * the function is used for seeking), a non-zero return value * indicates an error. */ @@ -219,7 +219,7 @@ FT_FILE* file; - if ( !count && offset > stream->size ) + if ( offset > stream->size && !count ) return 1; file = STREAM_FILE( stream ); @@ -227,6 +227,11 @@ if ( stream->pos != offset ) ft_fseek( file, (long)offset, SEEK_SET ); + /* Avoid calling `fread` with `buffer=NULL` and `count=0`, */ + /* which is undefined behaviour. */ + if ( !count ) + return 0; + return (unsigned long)ft_fread( buffer, 1, count, file ); } diff --git a/src/3rdparty/freetype/src/base/ftver.rc b/src/3rdparty/freetype/src/base/ftver.rc index f113cb89..137a6334 100644 --- a/src/3rdparty/freetype/src/base/ftver.rc +++ b/src/3rdparty/freetype/src/base/ftver.rc @@ -18,8 +18,8 @@ #include -#define FT_VERSION 2,13,0,0 -#define FT_VERSION_STR "2.13.0" +#define FT_VERSION 2,13,2,0 +#define FT_VERSION_STR "2.13.2" VS_VERSION_INFO VERSIONINFO FILEVERSION FT_VERSION diff --git a/src/3rdparty/freetype/src/bdf/bdf.h b/src/3rdparty/freetype/src/bdf/bdf.h index 5acbd5f2..e2cb52c1 100644 --- a/src/3rdparty/freetype/src/bdf/bdf.h +++ b/src/3rdparty/freetype/src/bdf/bdf.h @@ -239,10 +239,6 @@ FT_BEGIN_HEADER FT_LOCAL( void ) bdf_free_font( bdf_font_t* font ); - FT_LOCAL( bdf_property_t * ) - bdf_get_property( char* name, - bdf_font_t* font ); - FT_LOCAL( bdf_property_t * ) bdf_get_font_property( bdf_font_t* font, const char* name ); diff --git a/src/3rdparty/freetype/src/bdf/bdfdrivr.c b/src/3rdparty/freetype/src/bdf/bdfdrivr.c index d7e8e0ef..e02a1609 100644 --- a/src/3rdparty/freetype/src/bdf/bdfdrivr.c +++ b/src/3rdparty/freetype/src/bdf/bdfdrivr.c @@ -311,9 +311,9 @@ THE SOFTWARE. FT_CALLBACK_DEF( void ) - BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */ + BDF_Face_Done( FT_Face face ) /* BDF_Face */ { - BDF_Face face = (BDF_Face)bdfface; + BDF_Face bdfface = (BDF_Face)face; FT_Memory memory; @@ -322,31 +322,31 @@ THE SOFTWARE. memory = FT_FACE_MEMORY( face ); - bdf_free_font( face->bdffont ); + bdf_free_font( bdfface->bdffont ); - FT_FREE( face->en_table ); + FT_FREE( bdfface->en_table ); - FT_FREE( face->charset_encoding ); - FT_FREE( face->charset_registry ); - FT_FREE( bdfface->family_name ); - FT_FREE( bdfface->style_name ); + FT_FREE( bdfface->charset_encoding ); + FT_FREE( bdfface->charset_registry ); + FT_FREE( face->family_name ); + FT_FREE( face->style_name ); - FT_FREE( bdfface->available_sizes ); + FT_FREE( face->available_sizes ); - FT_FREE( face->bdffont ); + FT_FREE( bdfface->bdffont ); } FT_CALLBACK_DEF( FT_Error ) BDF_Face_Init( FT_Stream stream, - FT_Face bdfface, /* BDF_Face */ + FT_Face face, /* BDF_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { - FT_Error error = FT_Err_Ok; - BDF_Face face = (BDF_Face)bdfface; - FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Error error = FT_Err_Ok; + BDF_Face bdfface = (BDF_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); bdf_font_t* font = NULL; bdf_options_t options; @@ -375,7 +375,7 @@ THE SOFTWARE. goto Exit; /* we have a bdf font: let's construct the face object */ - face->bdffont = font; + bdfface->bdffont = font; /* BDF cannot have multiple faces in a single font file. * XXX: non-zero face_index is already invalid argument, but @@ -386,7 +386,7 @@ THE SOFTWARE. if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 ) { FT_ERROR(( "BDF_Face_Init: invalid face index\n" )); - BDF_Face_Done( bdfface ); + BDF_Face_Done( face ); return FT_THROW( Invalid_Argument ); } @@ -401,18 +401,18 @@ THE SOFTWARE. font->unencoded_size, font->unencoded_used )); - bdfface->num_faces = 1; - bdfface->face_index = 0; + face->num_faces = 1; + face->face_index = 0; - bdfface->face_flags |= FT_FACE_FLAG_FIXED_SIZES | - FT_FACE_FLAG_HORIZONTAL; + face->face_flags |= FT_FACE_FLAG_FIXED_SIZES | + FT_FACE_FLAG_HORIZONTAL; prop = bdf_get_font_property( font, "SPACING" ); if ( prop && prop->format == BDF_ATOM && prop->value.atom && ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' || *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) ) - bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + face->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */ /* FZ XXX: I need a font to implement this */ @@ -420,26 +420,27 @@ THE SOFTWARE. prop = bdf_get_font_property( font, "FAMILY_NAME" ); if ( prop && prop->value.atom ) { - if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) ) + if ( FT_STRDUP( face->family_name, prop->value.atom ) ) goto Exit; } else - bdfface->family_name = NULL; + face->family_name = NULL; - if ( FT_SET_ERROR( bdf_interpret_style( face ) ) ) + if ( FT_SET_ERROR( bdf_interpret_style( bdfface ) ) ) goto Exit; /* the number of glyphs (with one slot for the undefined glyph */ /* at position 0 and all unencoded glyphs) */ - bdfface->num_glyphs = (FT_Long)( font->glyphs_size + 1 ); + face->num_glyphs = (FT_Long)( font->glyphs_size + 1 ); - bdfface->num_fixed_sizes = 1; - if ( FT_NEW( bdfface->available_sizes ) ) + face->num_fixed_sizes = 1; + if ( FT_NEW( face->available_sizes ) ) goto Exit; { - FT_Bitmap_Size* bsize = bdfface->available_sizes; - FT_Short resolution_x = 0, resolution_y = 0; + FT_Bitmap_Size* bsize = face->available_sizes; + FT_Short resolution_x = 0; + FT_Short resolution_y = 0; long value; @@ -598,20 +599,20 @@ THE SOFTWARE. unsigned long n; - if ( FT_QNEW_ARRAY( face->en_table, font->glyphs_size ) ) + if ( FT_QNEW_ARRAY( bdfface->en_table, font->glyphs_size ) ) goto Exit; - face->default_glyph = 0; + bdfface->default_glyph = 0; for ( n = 0; n < font->glyphs_size; n++ ) { - (face->en_table[n]).enc = cur[n].encoding; + (bdfface->en_table[n]).enc = cur[n].encoding; FT_TRACE4(( " idx %ld, val 0x%lX\n", n, cur[n].encoding )); - (face->en_table[n]).glyph = (FT_UShort)n; + (bdfface->en_table[n]).glyph = (FT_UShort)n; if ( cur[n].encoding == font->default_char ) { if ( n < FT_UINT_MAX ) - face->default_glyph = (FT_UInt)n; + bdfface->default_glyph = (FT_UInt)n; else FT_TRACE1(( "BDF_Face_Init:" " idx %ld is too large for this system\n", n )); @@ -639,27 +640,27 @@ THE SOFTWARE. const char* s; - if ( FT_STRDUP( face->charset_encoding, + if ( FT_STRDUP( bdfface->charset_encoding, charset_encoding->value.atom ) || - FT_STRDUP( face->charset_registry, + FT_STRDUP( bdfface->charset_registry, charset_registry->value.atom ) ) goto Exit; /* Uh, oh, compare first letters manually to avoid dependency */ /* on locales. */ - s = face->charset_registry; + s = bdfface->charset_registry; if ( ( s[0] == 'i' || s[0] == 'I' ) && ( s[1] == 's' || s[1] == 'S' ) && ( s[2] == 'o' || s[2] == 'O' ) ) { s += 3; - if ( !ft_strcmp( s, "10646" ) || - ( !ft_strcmp( s, "8859" ) && - !ft_strcmp( face->charset_encoding, "1" ) ) ) + if ( !ft_strcmp( s, "10646" ) || + ( !ft_strcmp( s, "8859" ) && + !ft_strcmp( bdfface->charset_encoding, "1" ) ) ) unicode_charmap = 1; /* another name for ASCII */ - else if ( !ft_strcmp( s, "646.1991" ) && - !ft_strcmp( face->charset_encoding, "IRV" ) ) + else if ( !ft_strcmp( s, "646.1991" ) && + !ft_strcmp( bdfface->charset_encoding, "IRV" ) ) unicode_charmap = 1; } @@ -667,7 +668,7 @@ THE SOFTWARE. FT_CharMapRec charmap; - charmap.face = FT_FACE( face ); + charmap.face = face; charmap.encoding = FT_ENCODING_NONE; /* initial platform/encoding should indicate unset status? */ charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; @@ -693,7 +694,7 @@ THE SOFTWARE. FT_CharMapRec charmap; - charmap.face = FT_FACE( face ); + charmap.face = face; charmap.encoding = FT_ENCODING_ADOBE_STANDARD; charmap.platform_id = TT_PLATFORM_ADOBE; charmap.encoding_id = TT_ADOBE_ID_STANDARD; @@ -701,8 +702,8 @@ THE SOFTWARE. error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); /* Select default charmap */ - if ( bdfface->num_charmaps ) - bdfface->charmap = bdfface->charmaps[0]; + if ( face->num_charmaps ) + face->charmap = face->charmaps[0]; } } } @@ -711,7 +712,7 @@ THE SOFTWARE. return error; Fail: - BDF_Face_Done( bdfface ); + BDF_Face_Done( face ); return FT_THROW( Unknown_File_Format ); } @@ -868,17 +869,18 @@ THE SOFTWARE. * */ - static FT_Error - bdf_get_bdf_property( BDF_Face face, + FT_CALLBACK_DEF( FT_Error ) + bdf_get_bdf_property( FT_Face face, /* BDF_Face */ const char* prop_name, BDF_PropertyRec *aproperty ) { + BDF_Face bdfface = (BDF_Face)face; bdf_property_t* prop; - FT_ASSERT( face && face->bdffont ); + FT_ASSERT( bdfface && bdfface->bdffont ); - prop = bdf_get_font_property( face->bdffont, prop_name ); + prop = bdf_get_font_property( bdfface->bdffont, prop_name ); if ( prop ) { switch ( prop->format ) @@ -921,13 +923,16 @@ THE SOFTWARE. } - static FT_Error - bdf_get_charset_id( BDF_Face face, + FT_CALLBACK_DEF( FT_Error ) + bdf_get_charset_id( FT_Face face, /* BDF_Face */ const char* *acharset_encoding, const char* *acharset_registry ) { - *acharset_encoding = face->charset_encoding; - *acharset_registry = face->charset_registry; + BDF_Face bdfface = (BDF_Face)face; + + + *acharset_encoding = bdfface->charset_encoding; + *acharset_registry = bdfface->charset_registry; return 0; } @@ -964,7 +969,6 @@ THE SOFTWARE. } - FT_CALLBACK_TABLE_DEF const FT_Driver_ClassRec bdf_driver_class = { diff --git a/src/3rdparty/freetype/src/bdf/bdflib.c b/src/3rdparty/freetype/src/bdf/bdflib.c index 2224698f..0fa7e0a8 100644 --- a/src/3rdparty/freetype/src/bdf/bdflib.c +++ b/src/3rdparty/freetype/src/bdf/bdflib.c @@ -51,6 +51,9 @@ #define FT_COMPONENT bdflib +#define BUFSIZE 128 + + /************************************************************************** * * Default BDF font options. @@ -378,7 +381,7 @@ *alen = 0; if ( list == NULL || list->used == 0 ) - return 0; + return NULL; dp = list->field[0]; for ( i = j = 0; i < list->used; i++ ) @@ -887,18 +890,18 @@ } - FT_LOCAL_DEF( bdf_property_t* ) - bdf_get_property( char* name, + static bdf_property_t* + bdf_get_property( const char* name, bdf_font_t* font ) { size_t* propid; if ( name == NULL || *name == 0 ) - return 0; + return NULL; if ( ( propid = ft_hash_str_lookup( name, &(font->proptbl) ) ) == NULL ) - return 0; + return NULL; if ( *propid >= num_bdf_properties_ ) return font->user_props + ( *propid - num_bdf_properties_ ); @@ -944,7 +947,7 @@ static FT_Error bdf_add_comment_( bdf_font_t* font, - char* comment, + const char* comment, unsigned long len ) { char* cp; @@ -1053,27 +1056,24 @@ bdf_property_t* p; - *name = sp = ep = line; + sp = ep = line; while ( *ep && *ep != ' ' && *ep != '\t' ) ep++; - hold = -1; - if ( *ep ) - { - hold = *ep; - *ep = 0; - } + hold = *ep; + *ep = '\0'; p = bdf_get_property( sp, font ); - /* Restore the character that was saved before any return can happen. */ - if ( hold != -1 ) - *ep = (char)hold; - /* If the property exists and is not an atom, just return here. */ if ( p && p->format != BDF_ATOM ) + { + *ep = (char)hold; /* Undo NUL-termination. */ return 0; + } + + *name = sp; /* The property is an atom. Trim all leading and trailing whitespace */ /* and double quotes for the atom value. */ @@ -1081,25 +1081,26 @@ ep = line + linelen; /* Trim the leading whitespace if it exists. */ - if ( *sp ) - *sp++ = 0; - while ( *sp && - ( *sp == ' ' || *sp == '\t' ) ) - sp++; + if ( sp < ep ) + do + sp++; + while ( *sp == ' ' || *sp == '\t' ); /* Trim the leading double quote if it exists. */ if ( *sp == '"' ) sp++; + *value = sp; /* Trim the trailing whitespace if it exists. */ - while ( ep > sp && - ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) ) - *--ep = 0; + if ( sp < ep ) + do + *ep-- = '\0'; + while ( *ep == ' ' || *ep == '\t' ); /* Trim the trailing double quote if it exists. */ - if ( ep > sp && *( ep - 1 ) == '"' ) - *--ep = 0; + if ( *ep == '"' ) + *ep = '\0'; return 1; } @@ -1775,7 +1776,7 @@ bdf_parse_t_* p; char* name; char* value; - char nbuf[128]; + char nbuf[BUFSIZE]; FT_Error error = FT_Err_Ok; FT_UNUSED( lineno ); @@ -1796,7 +1797,7 @@ if ( bdf_get_font_property( p->font, "FONT_ASCENT" ) == 0 ) { p->font->font_ascent = p->font->bbx.ascent; - ft_sprintf( nbuf, "%hd", p->font->bbx.ascent ); + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.ascent ); error = bdf_add_property_( p->font, "FONT_ASCENT", nbuf, lineno ); if ( error ) @@ -1808,7 +1809,7 @@ if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 ) { p->font->font_descent = p->font->bbx.descent; - ft_sprintf( nbuf, "%hd", p->font->bbx.descent ); + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.descent ); error = bdf_add_property_( p->font, "FONT_DESCENT", nbuf, lineno ); if ( error ) @@ -2116,7 +2117,7 @@ /* Check for the CHARS field -- font properties are optional */ if ( _bdf_strncmp( line, "CHARS", 5 ) == 0 ) { - char nbuf[128]; + char nbuf[BUFSIZE]; if ( !( p->flags & BDF_FONT_BBX_ ) ) @@ -2130,7 +2131,7 @@ /* Add the two standard X11 properties which are required */ /* for compiling fonts. */ p->font->font_ascent = p->font->bbx.ascent; - ft_sprintf( nbuf, "%hd", p->font->bbx.ascent ); + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.ascent ); error = bdf_add_property_( p->font, "FONT_ASCENT", nbuf, lineno ); if ( error ) @@ -2138,7 +2139,7 @@ FT_TRACE2(( "bdf_parse_properties_: " ACMSG1, p->font->bbx.ascent )); p->font->font_descent = p->font->bbx.descent; - ft_sprintf( nbuf, "%hd", p->font->bbx.descent ); + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.descent ); error = bdf_add_property_( p->font, "FONT_DESCENT", nbuf, lineno ); if ( error ) diff --git a/src/3rdparty/freetype/src/bzip2/ftbzip2.c b/src/3rdparty/freetype/src/bzip2/ftbzip2.c index 6cf10678..ad342bd0 100644 --- a/src/3rdparty/freetype/src/bzip2/ftbzip2.c +++ b/src/3rdparty/freetype/src/bzip2/ftbzip2.c @@ -62,10 +62,12 @@ static void* - ft_bzip2_alloc( FT_Memory memory, - int items, - int size ) + ft_bzip2_alloc( void* memory_, /* FT_Memory */ + int items, + int size ) { + FT_Memory memory = (FT_Memory)memory_; + FT_ULong sz = (FT_ULong)size * (FT_ULong)items; FT_Error error; FT_Pointer p = NULL; @@ -77,9 +79,12 @@ static void - ft_bzip2_free( FT_Memory memory, - void* address ) + ft_bzip2_free( void* memory_, /* FT_Memory */ + void* address ) { + FT_Memory memory = (FT_Memory)memory_; + + FT_MEM_FREE( address ); } @@ -170,8 +175,8 @@ } /* initialize bzlib */ - bzstream->bzalloc = (alloc_func)ft_bzip2_alloc; - bzstream->bzfree = (free_func) ft_bzip2_free; + bzstream->bzalloc = ft_bzip2_alloc; + bzstream->bzfree = ft_bzip2_free; bzstream->opaque = zip->memory; bzstream->avail_in = 0; diff --git a/src/3rdparty/freetype/src/cache/ftcbasic.c b/src/3rdparty/freetype/src/cache/ftcbasic.c index 4c6d41b2..24a56c8d 100644 --- a/src/3rdparty/freetype/src/cache/ftcbasic.c +++ b/src/3rdparty/freetype/src/cache/ftcbasic.c @@ -337,7 +337,7 @@ #if 1 /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_GNode_Compare, + ftc_gnode_compare, hash, gindex, &query, node, @@ -411,7 +411,7 @@ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_GNode_Compare, + ftc_gnode_compare, hash, gindex, &query, node, @@ -537,7 +537,7 @@ #if 1 /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_SNode_Compare, + ftc_snode_compare, hash, gindex, &query, node, @@ -613,7 +613,7 @@ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_SNode_Compare, + ftc_snode_compare, hash, gindex, &query, node, diff --git a/src/3rdparty/freetype/src/cache/ftccache.c b/src/3rdparty/freetype/src/cache/ftccache.c index d54e68ca..e0698557 100644 --- a/src/3rdparty/freetype/src/cache/ftccache.c +++ b/src/3rdparty/freetype/src/cache/ftccache.c @@ -94,8 +94,8 @@ idx = hash & cache->mask; - if ( idx < cache->p ) - idx = hash & ( 2 * cache->mask + 1 ); + if ( idx >= cache->p ) + idx = hash & ( cache->mask >> 1 ); return cache->buckets + idx; } @@ -113,9 +113,9 @@ for (;;) { FTC_Node node, *pnode; - FT_UFast p = cache->p; - FT_UFast mask = cache->mask; - FT_UFast count = mask + p + 1; /* number of buckets */ + FT_UFast p = cache->p; + FT_UFast size = cache->mask + 1; /* available size */ + FT_UFast half = size >> 1; /* do we need to expand the buckets array? */ @@ -127,20 +127,22 @@ /* try to expand the buckets array _before_ splitting * the bucket lists */ - if ( p >= mask ) + if ( p == size ) { FT_Memory memory = cache->memory; FT_Error error; /* if we can't expand the array, leave immediately */ - if ( FT_RENEW_ARRAY( cache->buckets, - ( mask + 1 ) * 2, ( mask + 1 ) * 4 ) ) + if ( FT_QRENEW_ARRAY( cache->buckets, size, size * 2 ) ) break; + + cache->mask = 2 * size - 1; + half = size; } - /* split a single bucket */ - pnode = cache->buckets + p; + /* the bucket to split */ + pnode = cache->buckets + p - half; for (;;) { @@ -148,7 +150,7 @@ if ( !node ) break; - if ( node->hash & ( mask + 1 ) ) + if ( node->hash & half ) { *pnode = node->link; node->link = new_list; @@ -158,56 +160,50 @@ pnode = &node->link; } - cache->buckets[p + mask + 1] = new_list; + cache->buckets[p] = new_list; cache->slack += FTC_HASH_MAX_LOAD; + cache->p = p + 1; - if ( p >= mask ) - { - cache->mask = 2 * mask + 1; - cache->p = 0; - } - else - cache->p = p + 1; + FT_TRACE2(( "ftc_cache_resize: cache %u increased to %u hashes\n", + cache->index, cache->p )); } /* do we need to shrink the buckets array? */ - else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD ) + else if ( cache->slack > (FT_Long)p * FTC_HASH_SUB_LOAD ) { - FT_UFast old_index = p + mask; - FTC_Node* pold; + FTC_Node old_list = cache->buckets[--p]; - if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE ) + if ( p < FTC_HASH_INITIAL_SIZE ) break; - if ( p == 0 ) + if ( p == half ) { FT_Memory memory = cache->memory; FT_Error error; /* if we can't shrink the array, leave immediately */ - if ( FT_QRENEW_ARRAY( cache->buckets, - ( mask + 1 ) * 2, mask + 1 ) ) + if ( FT_QRENEW_ARRAY( cache->buckets, size, half ) ) break; - cache->mask >>= 1; - p = cache->mask; + cache->mask = half - 1; } - else - p--; - pnode = cache->buckets + p; + /* the bucket to merge */ + pnode = cache->buckets + p - half; + while ( *pnode ) pnode = &(*pnode)->link; - pold = cache->buckets + old_index; - *pnode = *pold; - *pold = NULL; + *pnode = old_list; cache->slack -= FTC_HASH_MAX_LOAD; cache->p = p; + + FT_TRACE2(( "ftc_cache_resize: cache %u decreased to %u hashes\n", + cache->index, cache->p )); } /* otherwise, the hash table is balanced */ @@ -239,7 +235,7 @@ if ( node == node0 ) break; - pnode = &(*pnode)->link; + pnode = &node->link; } *pnode = node0->link; @@ -322,13 +318,6 @@ /*************************************************************************/ - FT_LOCAL_DEF( FT_Error ) - FTC_Cache_Init( FTC_Cache cache ) - { - return ftc_cache_init( cache ); - } - - FT_LOCAL_DEF( FT_Error ) ftc_cache_init( FTC_Cache cache ) { @@ -336,27 +325,35 @@ FT_Error error; - cache->p = 0; + cache->p = FTC_HASH_INITIAL_SIZE; cache->mask = FTC_HASH_INITIAL_SIZE - 1; cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD; - FT_MEM_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 ); + FT_MEM_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE ); return error; } - static void - FTC_Cache_Clear( FTC_Cache cache ) + FT_LOCAL_DEF( FT_Error ) + FTC_Cache_Init( FTC_Cache cache ) { - if ( cache && cache->buckets ) + return ftc_cache_init( cache ); + } + + + FT_LOCAL_DEF( void ) + ftc_cache_done( FTC_Cache cache ) + { + FT_Memory memory = cache->memory; + + + if ( cache->buckets ) { FTC_Manager manager = cache->manager; + FT_UFast count = cache->p; FT_UFast i; - FT_UFast count; - count = cache->p + cache->mask + 1; - for ( i = 0; i < count; i++ ) { FTC_Node node = cache->buckets[i], next; @@ -376,30 +373,14 @@ cache->clazz.node_free( node, cache ); node = next; } - cache->buckets[i] = NULL; } - ftc_cache_resize( cache ); } - } + FT_FREE( cache->buckets ); - FT_LOCAL_DEF( void ) - ftc_cache_done( FTC_Cache cache ) - { - if ( cache->memory ) - { - FT_Memory memory = cache->memory; - - - FTC_Cache_Clear( cache ); - - FT_FREE( cache->buckets ); - cache->mask = 0; - cache->p = 0; - cache->slack = 0; - - cache->memory = NULL; - } + cache->p = 0; + cache->mask = 0; + cache->slack = 0; } @@ -562,12 +543,12 @@ FTC_Cache_RemoveFaceID( FTC_Cache cache, FTC_FaceID face_id ) { - FT_UFast i, count; FTC_Manager manager = cache->manager; FTC_Node frees = NULL; + FT_UFast count = cache->p; + FT_UFast i; - count = cache->p + cache->mask + 1; for ( i = 0; i < count; i++ ) { FTC_Node* pnode = cache->buckets + i; diff --git a/src/3rdparty/freetype/src/cache/ftccache.h b/src/3rdparty/freetype/src/cache/ftccache.h index 23bcb658..850d2554 100644 --- a/src/3rdparty/freetype/src/cache/ftccache.h +++ b/src/3rdparty/freetype/src/cache/ftccache.h @@ -72,11 +72,12 @@ FT_BEGIN_HEADER #define FTC_NODE_NEXT( x ) FTC_NODE( (x)->mru.next ) #define FTC_NODE_PREV( x ) FTC_NODE( (x)->mru.prev ) + /* address the hash table entries */ #ifdef FTC_INLINE -#define FTC_NODE_TOP_FOR_HASH( cache, hash ) \ - ( ( cache )->buckets + \ - ( ( ( ( hash ) & ( cache )->mask ) < ( cache )->p ) \ - ? ( ( hash ) & ( ( cache )->mask * 2 + 1 ) ) \ +#define FTC_NODE_TOP_FOR_HASH( cache, hash ) \ + ( ( cache )->buckets + \ + ( ( ( ( hash ) & ( cache )->mask ) >= ( cache )->p ) \ + ? ( ( hash ) & ( ( cache )->mask >> 1 ) ) \ : ( ( hash ) & ( cache )->mask ) ) ) #else FT_LOCAL( FTC_Node* ) @@ -139,11 +140,13 @@ FT_BEGIN_HEADER } FTC_CacheClassRec; - /* each cache really implements a dynamic hash table to manage its nodes */ + /* each cache really implements a hash table to manage its nodes */ + /* the number of the table entries (buckets) can change dynamically */ + /* each bucket contains a linked lists of nodes for a given hash */ typedef struct FTC_CacheRec_ { - FT_UFast p; - FT_UFast mask; + FT_UFast p; /* hash table counter */ + FT_UFast mask; /* hash table index range */ FT_Long slack; FTC_Node* buckets; diff --git a/src/3rdparty/freetype/src/cache/ftcglyph.c b/src/3rdparty/freetype/src/cache/ftcglyph.c index b3fb2f21..d344733f 100644 --- a/src/3rdparty/freetype/src/cache/ftcglyph.c +++ b/src/3rdparty/freetype/src/cache/ftcglyph.c @@ -79,20 +79,6 @@ } -#ifdef FTC_INLINE - - FT_LOCAL_DEF( FT_Bool ) - FTC_GNode_Compare( FTC_GNode gnode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed ) - { - return ftc_gnode_compare( FTC_NODE( gnode ), gquery, - cache, list_changed ); - } - -#endif - /*************************************************************************/ /*************************************************************************/ /***** *****/ @@ -115,22 +101,22 @@ FT_LOCAL_DEF( FT_Error ) - ftc_gcache_init( FTC_Cache ftccache ) + ftc_gcache_init( FTC_Cache cache ) { - FTC_GCache cache = (FTC_GCache)ftccache; + FTC_GCache gcache = (FTC_GCache)cache; FT_Error error; - error = FTC_Cache_Init( FTC_CACHE( cache ) ); + error = FTC_Cache_Init( cache ); if ( !error ) { - FTC_GCacheClass clazz = (FTC_GCacheClass)FTC_CACHE( cache )->org_class; + FTC_GCacheClass clazz = (FTC_GCacheClass)cache->org_class; - FTC_MruList_Init( &cache->families, + FTC_MruList_Init( &gcache->families, clazz->family_class, 0, /* no maximum here! */ cache, - FTC_CACHE( cache )->memory ); + cache->memory ); } return error; @@ -140,31 +126,31 @@ #if 0 FT_LOCAL_DEF( FT_Error ) - FTC_GCache_Init( FTC_GCache cache ) + FTC_GCache_Init( FTC_GCache gcache ) { - return ftc_gcache_init( FTC_CACHE( cache ) ); + return ftc_gcache_init( FTC_CACHE( gcache ) ); } #endif /* 0 */ FT_LOCAL_DEF( void ) - ftc_gcache_done( FTC_Cache ftccache ) + ftc_gcache_done( FTC_Cache cache ) { - FTC_GCache cache = (FTC_GCache)ftccache; + FTC_GCache gcache = (FTC_GCache)cache; - FTC_Cache_Done( (FTC_Cache)cache ); - FTC_MruList_Done( &cache->families ); + FTC_Cache_Done( cache ); + FTC_MruList_Done( &gcache->families ); } #if 0 FT_LOCAL_DEF( void ) - FTC_GCache_Done( FTC_GCache cache ) + FTC_GCache_Done( FTC_GCache gcache ) { - ftc_gcache_done( FTC_CACHE( cache ) ); + ftc_gcache_done( FTC_CACHE( gcache ) ); } #endif /* 0 */ @@ -183,7 +169,7 @@ #ifndef FTC_INLINE FT_LOCAL_DEF( FT_Error ) - FTC_GCache_Lookup( FTC_GCache cache, + FTC_GCache_Lookup( FTC_GCache gcache, FT_Offset hash, FT_UInt gindex, FTC_GQuery query, @@ -204,7 +190,7 @@ /* out-of-memory condition occurs during glyph node initialization. */ family->num_nodes++; - error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, anode ); + error = FTC_Cache_Lookup( FTC_CACHE( gcache ), hash, query, anode ); if ( --family->num_nodes == 0 ) FTC_FAMILY_FREE( family, cache ); diff --git a/src/3rdparty/freetype/src/cache/ftcglyph.h b/src/3rdparty/freetype/src/cache/ftcglyph.h index 728d4db1..0181e981 100644 --- a/src/3rdparty/freetype/src/cache/ftcglyph.h +++ b/src/3rdparty/freetype/src/cache/ftcglyph.h @@ -58,7 +58,7 @@ * - FTC_GNode sub-class, e.g. MyNode, with relevant methods: * my_node_new (must call FTC_GNode_Init) * my_node_free (must call FTC_GNode_Done) - * my_node_compare (must call FTC_GNode_Compare) + * my_node_compare (must call ftc_gnode_compare) * my_node_remove_faceid (must call ftc_gnode_unselect in case * of match) * @@ -179,19 +179,6 @@ FT_BEGIN_HEADER FT_UInt gindex, /* glyph index for node */ FTC_Family family ); -#ifdef FTC_INLINE - - /* returns TRUE iff the query's glyph index correspond to the node; */ - /* this assumes that the `family' and `hash' fields of the query are */ - /* already correctly set */ - FT_LOCAL( FT_Bool ) - FTC_GNode_Compare( FTC_GNode gnode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed ); - -#endif - /* call this function to clear a node's family -- this is necessary */ /* to implement the `node_remove_faceid' cache method correctly */ FT_LOCAL( void ) diff --git a/src/3rdparty/freetype/src/cache/ftcmanag.c b/src/3rdparty/freetype/src/cache/ftcmanag.c index 6c843391..94f8469c 100644 --- a/src/3rdparty/freetype/src/cache/ftcmanag.c +++ b/src/3rdparty/freetype/src/cache/ftcmanag.c @@ -426,7 +426,7 @@ memory = manager->memory; /* now discard all caches */ - for (idx = manager->num_caches; idx-- > 0; ) + for ( idx = manager->num_caches; idx-- > 0; ) { FTC_Cache cache = manager->caches[idx]; @@ -537,7 +537,7 @@ FT_LOCAL_DEF( void ) FTC_Manager_Compress( FTC_Manager manager ) { - FTC_Node node, first; + FTC_Node node, prev, first; if ( !manager ) @@ -557,20 +557,16 @@ return; /* go to last node -- it's a circular list */ - node = FTC_NODE_PREV( first ); + prev = FTC_NODE_PREV( first ); do { - FTC_Node prev; - - - prev = ( node == first ) ? NULL : FTC_NODE_PREV( node ); + node = prev; + prev = FTC_NODE_PREV( node ); if ( node->ref_count <= 0 ) ftc_node_destroy( node, manager ); - node = prev; - - } while ( node && manager->cur_weight > manager->max_weight ); + } while ( node != first && manager->cur_weight > manager->max_weight ); } @@ -633,20 +629,20 @@ FT_UInt count ) { FTC_Node first = manager->nodes_list; - FTC_Node node; - FT_UInt result; + FTC_Node prev, node; + FT_UInt result = 0; /* try to remove `count' nodes from the list */ - if ( !first ) /* empty list! */ - return 0; + if ( !first || !count ) + return result; - /* go to last node - it's a circular list */ - node = FTC_NODE_PREV(first); - for ( result = 0; result < count; ) + /* go to last node -- it's a circular list */ + prev = FTC_NODE_PREV( first ); + do { - FTC_Node prev = FTC_NODE_PREV( node ); - + node = prev; + prev = FTC_NODE_PREV( node ); /* don't touch locked nodes */ if ( node->ref_count <= 0 ) @@ -654,13 +650,9 @@ ftc_node_destroy( node, manager ); result++; } + } while ( node != first && result < count ); - if ( node == first ) - break; - - node = prev; - } - return result; + return result; } diff --git a/src/3rdparty/freetype/src/cache/ftcmru.c b/src/3rdparty/freetype/src/cache/ftcmru.c index 67227033..ad10a06b 100644 --- a/src/3rdparty/freetype/src/cache/ftcmru.c +++ b/src/3rdparty/freetype/src/cache/ftcmru.c @@ -329,29 +329,23 @@ FTC_MruNode_CompareFunc selection, FT_Pointer key ) { - FTC_MruNode first, node, next; + FTC_MruNode first = list->nodes; + FTC_MruNode prev, node; - first = list->nodes; - while ( first && ( !selection || selection( first, key ) ) ) + if ( !first || !selection ) + return; + + prev = first->prev; + do { - FTC_MruList_Remove( list, first ); - first = list->nodes; - } + node = prev; + prev = node->prev; - if ( first ) - { - node = first->next; - while ( node != first ) - { - next = node->next; + if ( selection( node, key ) ) + FTC_MruList_Remove( list, node ); - if ( selection( node, key ) ) - FTC_MruList_Remove( list, node ); - - node = next; - } - } + } while ( node != first ); } diff --git a/src/3rdparty/freetype/src/cache/ftcsbits.c b/src/3rdparty/freetype/src/cache/ftcsbits.c index ee9dab26..9929a0bc 100644 --- a/src/3rdparty/freetype/src/cache/ftcsbits.c +++ b/src/3rdparty/freetype/src/cache/ftcsbits.c @@ -342,7 +342,7 @@ FT_Bool result; - if (list_changed) + if ( list_changed ) *list_changed = FALSE; result = FT_BOOL( gnode->family == gquery->family && gindex - gnode->gindex < snode->count ); @@ -411,19 +411,4 @@ return result; } - -#ifdef FTC_INLINE - - FT_LOCAL_DEF( FT_Bool ) - FTC_SNode_Compare( FTC_SNode snode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed ) - { - return ftc_snode_compare( FTC_NODE( snode ), gquery, - cache, list_changed ); - } - -#endif - /* END */ diff --git a/src/3rdparty/freetype/src/cache/ftcsbits.h b/src/3rdparty/freetype/src/cache/ftcsbits.h index 3473923f..e833cb5c 100644 --- a/src/3rdparty/freetype/src/cache/ftcsbits.h +++ b/src/3rdparty/freetype/src/cache/ftcsbits.h @@ -81,17 +81,6 @@ FT_BEGIN_HEADER FTC_SNode_Weight( FTC_SNode inode ); #endif - -#ifdef FTC_INLINE - - FT_LOCAL( FT_Bool ) - FTC_SNode_Compare( FTC_SNode snode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed); - -#endif - /* */ FT_END_HEADER diff --git a/src/3rdparty/freetype/src/cff/cffcmap.c b/src/3rdparty/freetype/src/cff/cffcmap.c index 6ed31432..10d287bc 100644 --- a/src/3rdparty/freetype/src/cff/cffcmap.c +++ b/src/3rdparty/freetype/src/cff/cffcmap.c @@ -32,9 +32,10 @@ /*************************************************************************/ FT_CALLBACK_DEF( FT_Error ) - cff_cmap_encoding_init( CFF_CMapStd cmap, - FT_Pointer pointer ) + cff_cmap_encoding_init( FT_CMap cmap, + FT_Pointer pointer ) { + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); CFF_Font cff = (CFF_Font)face->extra.data; CFF_Encoding encoding = &cff->encoding; @@ -42,63 +43,56 @@ FT_UNUSED( pointer ); - cmap->gids = encoding->codes; + cffcmap->gids = encoding->codes; return 0; } FT_CALLBACK_DEF( void ) - cff_cmap_encoding_done( CFF_CMapStd cmap ) + cff_cmap_encoding_done( FT_CMap cmap ) { - cmap->gids = NULL; + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; + + + cffcmap->gids = NULL; } FT_CALLBACK_DEF( FT_UInt ) - cff_cmap_encoding_char_index( CFF_CMapStd cmap, - FT_UInt32 char_code ) + cff_cmap_encoding_char_index( FT_CMap cmap, + FT_UInt32 char_code ) { - FT_UInt result = 0; + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; + FT_UInt result = 0; if ( char_code < 256 ) - result = cmap->gids[char_code]; + result = cffcmap->gids[char_code]; return result; } - FT_CALLBACK_DEF( FT_UInt32 ) - cff_cmap_encoding_char_next( CFF_CMapStd cmap, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + cff_cmap_encoding_char_next( FT_CMap cmap, + FT_UInt32 *pchar_code ) { - FT_UInt result = 0; - FT_UInt32 char_code = *pchar_code; + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code; - *pchar_code = 0; - - if ( char_code < 255 ) + while ( char_code < 255 ) { - FT_UInt code = (FT_UInt)( char_code + 1 ); - - - for (;;) + result = cffcmap->gids[++char_code]; + if ( result ) { - if ( code >= 256 ) - break; - - result = cmap->gids[code]; - if ( result != 0 ) - { - *pchar_code = code; - break; - } - - code++; + *pchar_code = char_code; + break; } } + return result; } @@ -130,9 +124,10 @@ /*************************************************************************/ FT_CALLBACK_DEF( const char* ) - cff_sid_to_glyph_name( TT_Face face, + cff_sid_to_glyph_name( void* face_, /* TT_Face */ FT_UInt idx ) { + TT_Face face = (TT_Face)face_; CFF_Font cff = (CFF_Font)face->extra.data; CFF_Charset charset = &cff->charset; FT_UInt sid = charset->sids[idx]; @@ -143,14 +138,15 @@ FT_CALLBACK_DEF( FT_Error ) - cff_cmap_unicode_init( PS_Unicodes unicodes, + cff_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ FT_Pointer pointer ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - CFF_Font cff = (CFF_Font)face->extra.data; - CFF_Charset charset = &cff->charset; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + CFF_Font cff = (CFF_Font)face->extra.data; + CFF_Charset charset = &cff->charset; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; FT_UNUSED( pointer ); @@ -166,17 +162,18 @@ return psnames->unicodes_init( memory, unicodes, cff->num_glyphs, - (PS_GetGlyphNameFunc)&cff_sid_to_glyph_name, + &cff_sid_to_glyph_name, (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } FT_CALLBACK_DEF( void ) - cff_cmap_unicode_done( PS_Unicodes unicodes ) + cff_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Unicodes unicodes = (PS_Unicodes)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( unicodes->maps ); @@ -185,25 +182,27 @@ FT_CALLBACK_DEF( FT_UInt ) - cff_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) + cff_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 char_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + CFF_Font cff = (CFF_Font)face->extra.data; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; return psnames->unicodes_char_index( unicodes, char_code ); } - FT_CALLBACK_DEF( FT_UInt32 ) - cff_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + cff_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 *pchar_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + CFF_Font cff = (CFF_Font)face->extra.data; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; return psnames->unicodes_char_next( unicodes, pchar_code ); diff --git a/src/3rdparty/freetype/src/cff/cffdrivr.c b/src/3rdparty/freetype/src/cff/cffdrivr.c index 4e2e0e00..9898d625 100644 --- a/src/3rdparty/freetype/src/cff/cffdrivr.c +++ b/src/3rdparty/freetype/src/cff/cffdrivr.c @@ -108,20 +108,20 @@ * They can be implemented by format-specific interfaces. */ FT_CALLBACK_DEF( FT_Error ) - cff_get_kerning( FT_Face ttface, /* TT_Face */ + cff_get_kerning( FT_Face face, /* CFF_Face */ FT_UInt left_glyph, FT_UInt right_glyph, FT_Vector* kerning ) { - TT_Face face = (TT_Face)ttface; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + CFF_Face cffface = (CFF_Face)face; + SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; kerning->x = 0; kerning->y = 0; if ( sfnt ) - kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); + kerning->x = sfnt->get_kerning( cffface, left_glyph, right_glyph ); return FT_Err_Ok; } @@ -158,23 +158,23 @@ * FreeType error code. 0 means success. */ FT_CALLBACK_DEF( FT_Error ) - cff_glyph_load( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */ - FT_Size cffsize, /* CFF_Size */ + cff_glyph_load( FT_GlyphSlot slot, /* CFF_GlyphSlot */ + FT_Size size, /* CFF_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { FT_Error error; - CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot; - CFF_Size size = (CFF_Size)cffsize; + CFF_GlyphSlot cffslot = (CFF_GlyphSlot)slot; + CFF_Size cffsize = (CFF_Size)size; - if ( !slot ) + if ( !cffslot ) return FT_THROW( Invalid_Slot_Handle ); FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index )); /* check whether we want a scaled outline or bitmap */ - if ( !size ) + if ( !cffsize ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; /* reset the size object if necessary */ @@ -184,12 +184,12 @@ if ( size ) { /* these two objects must have the same parent */ - if ( cffsize->face != cffslot->face ) + if ( size->face != slot->face ) return FT_THROW( Invalid_Face_Handle ); } /* now load the glyph outline if necessary */ - error = cff_slot_load( slot, size, glyph_index, load_flags ); + error = cff_slot_load( cffslot, cffsize, glyph_index, load_flags ); /* force drop-out mode to 2 - irrelevant now */ /* slot->outline.dropout_mode = 2; */ @@ -216,7 +216,7 @@ /* it is no longer necessary that those values are identical to */ /* the values in the `CFF' table */ - TT_Face ttface = (TT_Face)face; + CFF_Face cffface = (CFF_Face)face; FT_Short dummy; @@ -225,7 +225,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without VVAR table */ if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && - !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + !( cffface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -233,7 +233,7 @@ /* otherwise we extract the info from the CFF glyphstrings */ /* (instead of synthesizing a global value using the `OS/2' */ /* table) */ - if ( !ttface->vertical_info ) + if ( !cffface->vertical_info ) goto Missing_Table; for ( nn = 0; nn < count; nn++ ) @@ -241,11 +241,11 @@ FT_UShort ah; - ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, - 1, - start + nn, - &dummy, - &ah ); + ( (SFNT_Service)cffface->sfnt )->get_metrics( cffface, + 1, + start + nn, + &dummy, + &ah ); FT_TRACE5(( " idx %d: advance height %d font unit%s\n", start + nn, @@ -259,12 +259,12 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without HVAR table */ if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && - !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + !( cffface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif /* check whether we have data from the `hmtx' table at all */ - if ( !ttface->horizontal.number_Of_HMetrics ) + if ( !cffface->horizontal.number_Of_HMetrics ) goto Missing_Table; for ( nn = 0; nn < count; nn++ ) @@ -272,11 +272,11 @@ FT_UShort aw; - ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, - 0, - start + nn, - &dummy, - &aw ); + ( (SFNT_Service)cffface->sfnt )->get_metrics( cffface, + 0, + start + nn, + &dummy, + &aw ); FT_TRACE5(( " idx %d: advance width %d font unit%s\n", start + nn, @@ -312,13 +312,14 @@ * */ - static FT_Error - cff_get_glyph_name( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_glyph_name( FT_Face face, /* CFF_Face */ FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ) { - CFF_Font font = (CFF_Font)face->extra.data; + CFF_Face cffface = (CFF_Face)face; + CFF_Font font = (CFF_Font)cffface->extra.data; FT_String* gname; FT_UShort sid; FT_Error error; @@ -338,10 +339,7 @@ if ( service && service->get_name ) - return service->get_name( FT_FACE( face ), - glyph_index, - buffer, - buffer_max ); + return service->get_name( face, glyph_index, buffer, buffer_max ); else { FT_ERROR(( "cff_get_glyph_name:" @@ -366,7 +364,7 @@ /* first, locate the sid in the charset table */ sid = font->charset.sids[glyph_index]; - /* now, lookup the name itself */ + /* now, look up the name itself */ gname = cff_index_get_sid_string( font, sid ); if ( gname ) @@ -379,21 +377,19 @@ } - static FT_UInt - cff_get_name_index( CFF_Face face, + FT_CALLBACK_DEF( FT_UInt ) + cff_get_name_index( FT_Face face, /* CFF_Face */ const FT_String* glyph_name ) { - CFF_Font cff; - CFF_Charset charset; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + CFF_Charset charset = &cff->charset; FT_Service_PsCMaps psnames; FT_String* name; FT_UShort sid; FT_UInt i; - cff = (CFF_FontRec *)face->extra.data; - charset = &cff->charset; - /* CFF2 table does not have glyph names; */ /* we need to use `post' table method */ if ( cff->version_major == 2 ) @@ -408,7 +404,7 @@ if ( service && service->name_index ) - return service->name_index( FT_FACE( face ), glyph_name ); + return service->name_index( face, glyph_name ); else { FT_ERROR(( "cff_get_name_index:" @@ -446,8 +442,8 @@ FT_DEFINE_SERVICE_GLYPHDICTREC( cff_service_glyph_dict, - (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, /* get_name */ - (FT_GlyphDict_NameIndexFunc)cff_get_name_index /* name_index */ + cff_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ + cff_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ ) @@ -456,25 +452,32 @@ * */ - static FT_Int + FT_CALLBACK_DEF( FT_Int ) cff_ps_has_glyph_names( FT_Face face ) { return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0; } - static FT_Error - cff_ps_get_font_info( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_ps_get_font_info( FT_Face face, /* CFF_Face */ PS_FontInfoRec* afont_info ) { - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + FT_Error error = FT_Err_Ok; + if ( cffface->is_cff2 ) + { + error = FT_THROW( Invalid_Argument ); + goto Fail; + } + if ( cff && !cff->font_info ) { CFF_FontRecDict dict = &cff->top_font.font_dict; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); PS_FontInfoRec* font_info = NULL; @@ -507,18 +510,19 @@ } - static FT_Error - cff_ps_get_font_extra( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_ps_get_font_extra( FT_Face face, /* CFF_Face */ PS_FontExtraRec* afont_extra ) { - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + FT_Error error = FT_Err_Ok; if ( cff && !cff->font_extra ) { CFF_FontRecDict dict = &cff->top_font.font_dict; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); PS_FontExtraRec* font_extra = NULL; FT_String* embedded_postscript; @@ -588,13 +592,13 @@ FT_DEFINE_SERVICE_PSINFOREC( cff_service_ps_info, - (PS_GetFontInfoFunc) cff_ps_get_font_info, /* ps_get_font_info */ - (PS_GetFontExtraFunc) cff_ps_get_font_extra, /* ps_get_font_extra */ - (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, /* ps_has_glyph_names */ + cff_ps_get_font_info, /* PS_GetFontInfoFunc ps_get_font_info */ + cff_ps_get_font_extra, /* PS_GetFontExtraFunc ps_get_font_extra */ + cff_ps_has_glyph_names, /* PS_HasGlyphNamesFunc ps_has_glyph_names */ /* unsupported with CFF fonts */ - (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ + NULL, /* PS_GetFontPrivateFunc ps_get_font_private */ /* not implemented */ - (PS_GetFontValueFunc) NULL /* ps_get_font_value */ + NULL /* PS_GetFontValueFunc ps_get_font_value */ ) @@ -603,17 +607,18 @@ * */ - static const char* - cff_get_ps_name( CFF_Face face ) + FT_CALLBACK_DEF( const char* ) + cff_get_ps_name( FT_Face face ) /* CFF_Face */ { - CFF_Font cff = (CFF_Font)face->extra.data; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; /* following the OpenType specification 1.7, we return the name stored */ /* in the `name' table for a CFF wrapped into an SFNT container */ - if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt ) + if ( FT_IS_SFNT( face ) && sfnt ) { FT_Library library = FT_FACE_LIBRARY( face ); FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); @@ -625,17 +630,17 @@ if ( service && service->get_ps_font_name ) - return service->get_ps_font_name( FT_FACE( face ) ); + return service->get_ps_font_name( face ); } - return (const char*)cff->font_name; + return cff ? (const char*)cff->font_name : NULL; } FT_DEFINE_SERVICE_PSFONTNAMEREC( cff_service_ps_name, - (FT_PsName_GetFunc)cff_get_ps_name /* get_ps_font_name */ + cff_get_ps_name /* FT_PsName_GetFunc get_ps_font_name */ ) @@ -649,7 +654,7 @@ * Otherwise call the service function in the sfnt module. * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) cff_get_cmap_info( FT_CharMap charmap, TT_CMapInfo *cmap_info ) { @@ -683,7 +688,7 @@ FT_DEFINE_SERVICE_TTCMAPSREC( cff_service_get_cmap_info, - (TT_CMap_Info_GetFunc)cff_get_cmap_info /* get_cmap_info */ + cff_get_cmap_info /* TT_CMap_Info_GetFunc get_cmap_info */ ) @@ -691,14 +696,15 @@ * CID INFO SERVICE * */ - static FT_Error - cff_get_ros( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_ros( FT_Face face, /* FT_Face */ const char* *registry, const char* *ordering, FT_Int *supplement ) { - FT_Error error = FT_Err_Ok; - CFF_Font cff = (CFF_Font)face->extra.data; + FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; if ( cff ) @@ -748,12 +754,13 @@ } - static FT_Error - cff_get_is_cid( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_is_cid( FT_Face face, /* CFF_Face */ FT_Bool *is_cid ) { - FT_Error error = FT_Err_Ok; - CFF_Font cff = (CFF_Font)face->extra.data; + FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; *is_cid = 0; @@ -771,17 +778,16 @@ } - static FT_Error - cff_get_cid_from_glyph_index( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_cid_from_glyph_index( FT_Face face, /* CFF_Face */ FT_UInt glyph_index, FT_UInt *cid ) { - FT_Error error = FT_Err_Ok; - CFF_Font cff; + FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; - cff = (CFF_Font)face->extra.data; - if ( cff ) { FT_UInt c; @@ -814,12 +820,12 @@ FT_DEFINE_SERVICE_CIDREC( cff_service_cid_info, - (FT_CID_GetRegistryOrderingSupplementFunc) - cff_get_ros, /* get_ros */ - (FT_CID_GetIsInternallyCIDKeyedFunc) - cff_get_is_cid, /* get_is_cid */ - (FT_CID_GetCIDFromGlyphIndexFunc) - cff_get_cid_from_glyph_index /* get_cid_from_glyph_index */ + cff_get_ros, + /* FT_CID_GetRegistryOrderingSupplementFunc get_ros */ + cff_get_is_cid, + /* FT_CID_GetIsInternallyCIDKeyedFunc get_is_cid */ + cff_get_cid_from_glyph_index + /* FT_CID_GetCIDFromGlyphIndexFunc get_cid_from_glyph_index */ ) @@ -831,9 +837,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( cff_service_properties, - (FT_Properties_SetFunc)ps_property_set, /* set_property */ - (FT_Properties_GetFunc)ps_property_get ) /* get_property */ - + ps_property_set, /* FT_Properties_SetFunc set_property */ + ps_property_get /* FT_Properties_GetFunc get_property */ + ) #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT @@ -842,160 +848,195 @@ * */ - static FT_Error - cff_set_mm_blend( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_set_mm_blend( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_mm_blend( FT_FACE( face ), num_coords, coords ); + return mm->set_mm_blend( face, num_coords, coords ); } - static FT_Error - cff_get_mm_blend( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_mm_blend( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_mm_blend( FT_FACE( face ), num_coords, coords ); + return mm->get_mm_blend( face, num_coords, coords ); } - static FT_Error - cff_set_mm_weightvector( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_set_mm_weightvector( FT_Face face, /* CFF_Face */ FT_UInt len, FT_Fixed* weightvector ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_mm_weightvector( FT_FACE( face ), len, weightvector ); + return mm->set_mm_weightvector( face, len, weightvector ); } - static FT_Error - cff_get_mm_weightvector( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_mm_weightvector( FT_Face face, /* CFF_Face */ FT_UInt* len, FT_Fixed* weightvector ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_mm_weightvector( FT_FACE( face ), len, weightvector ); + return mm->get_mm_weightvector( face, len, weightvector ); } - static FT_Error - cff_get_mm_var( CFF_Face face, + FT_CALLBACK_DEF( void ) + cff_construct_ps_name( FT_Face face ) /* CFF_Face */ + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + mm->construct_ps_name( face ); + } + + + FT_CALLBACK_DEF( FT_Error ) + cff_get_mm_var( FT_Face face, /* CFF_Face */ FT_MM_Var* *master ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_mm_var( FT_FACE( face ), master ); + return mm->get_mm_var( face, master ); } - static FT_Error - cff_set_var_design( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_set_var_design( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_var_design( FT_FACE( face ), num_coords, coords ); + return mm->set_var_design( face, num_coords, coords ); } - static FT_Error - cff_get_var_design( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_var_design( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_var_design( FT_FACE( face ), num_coords, coords ); + return mm->get_var_design( face, num_coords, coords ); } - static FT_Error - cff_set_instance( CFF_Face face, - FT_UInt instance_index ) + FT_CALLBACK_DEF( FT_Error ) + cff_set_named_instance( FT_Face face, /* CFF_Face */ + FT_UInt instance_index ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_instance( FT_FACE( face ), instance_index ); + return mm->set_named_instance( face, instance_index ); } - static FT_Error - cff_load_item_variation_store( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_default_named_instance( FT_Face face, /* CFF_Face */ + FT_UInt *instance_index ) + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + return mm->get_default_named_instance( face, instance_index ); + } + + + FT_CALLBACK_DEF( FT_Error ) + cff_load_item_variation_store( FT_Face face, /* CFF_Face */ FT_ULong offset, GX_ItemVarStore itemStore ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->load_item_var_store( FT_FACE(face), offset, itemStore ); + return mm->load_item_var_store( face, offset, itemStore ); } - static FT_Error - cff_load_delta_set_index_mapping( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_load_delta_set_index_mapping( FT_Face face, /* CFF_Face */ FT_ULong offset, GX_DeltaSetIdxMap map, GX_ItemVarStore itemStore, FT_ULong table_len ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->load_delta_set_idx_map( FT_FACE( face ), offset, map, + return mm->load_delta_set_idx_map( face, offset, map, itemStore, table_len ); } - static FT_Int - cff_get_item_delta( CFF_Face face, + FT_CALLBACK_DEF( FT_Int ) + cff_get_item_delta( FT_Face face, /* CFF_Face */ GX_ItemVarStore itemStore, FT_UInt outerIndex, FT_UInt innerIndex ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_item_delta( FT_FACE( face ), itemStore, - outerIndex, innerIndex ); + return mm->get_item_delta( face, itemStore, outerIndex, innerIndex ); } - static void - cff_done_item_variation_store( CFF_Face face, + FT_CALLBACK_DEF( void ) + cff_done_item_variation_store( FT_Face face, /* CFF_Face */ GX_ItemVarStore itemStore ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - mm->done_item_var_store( FT_FACE( face ), itemStore ); + mm->done_item_var_store( face, itemStore ); } - static void - cff_done_delta_set_index_map( CFF_Face face, + FT_CALLBACK_DEF( void ) + cff_done_delta_set_index_map( FT_Face face, /* CFF_Face */ GX_DeltaSetIdxMap deltaSetIdxMap ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - mm->done_delta_set_idx_map( FT_FACE ( face ), deltaSetIdxMap ); + mm->done_delta_set_idx_map( face, deltaSetIdxMap ); } @@ -1003,36 +1044,35 @@ FT_DEFINE_SERVICE_MULTIMASTERSREC( cff_service_multi_masters, - (FT_Get_MM_Func) NULL, /* get_mm */ - (FT_Set_MM_Design_Func) NULL, /* set_mm_design */ - (FT_Set_MM_Blend_Func) cff_set_mm_blend, /* set_mm_blend */ - (FT_Get_MM_Blend_Func) cff_get_mm_blend, /* get_mm_blend */ - (FT_Get_MM_Var_Func) cff_get_mm_var, /* get_mm_var */ - (FT_Set_Var_Design_Func)cff_set_var_design, /* set_var_design */ - (FT_Get_Var_Design_Func)cff_get_var_design, /* get_var_design */ - (FT_Set_Instance_Func) cff_set_instance, /* set_instance */ - (FT_Set_MM_WeightVector_Func) - cff_set_mm_weightvector, - /* set_mm_weightvector */ - (FT_Get_MM_WeightVector_Func) - cff_get_mm_weightvector, - /* get_mm_weightvector */ - (FT_Var_Load_Delta_Set_Idx_Map_Func) - cff_load_delta_set_index_mapping, - /* load_delta_set_idx_map */ - (FT_Var_Load_Item_Var_Store_Func) - cff_load_item_variation_store, - /* load_item_variation_store */ - (FT_Var_Get_Item_Delta_Func) - cff_get_item_delta, /* get_item_delta */ - (FT_Var_Done_Item_Var_Store_Func) - cff_done_item_variation_store, - /* done_item_variation_store */ - (FT_Var_Done_Delta_Set_Idx_Map_Func) - cff_done_delta_set_index_map, - /* done_delta_set_index_map */ - (FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */ - (FT_Done_Blend_Func) cff_done_blend /* done_blend */ + NULL, /* FT_Get_MM_Func get_mm */ + NULL, /* FT_Set_MM_Design_Func set_mm_design */ + cff_set_mm_blend, /* FT_Set_MM_Blend_Func set_mm_blend */ + cff_get_mm_blend, /* FT_Get_MM_Blend_Func get_mm_blend */ + cff_get_mm_var, /* FT_Get_MM_Var_Func get_mm_var */ + cff_set_var_design, /* FT_Set_Var_Design_Func set_var_design */ + cff_get_var_design, /* FT_Get_Var_Design_Func get_var_design */ + cff_set_named_instance, + /* FT_Set_Named_Instance_Func set_named_instance */ + cff_get_default_named_instance, + /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ + cff_set_mm_weightvector, + /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ + cff_get_mm_weightvector, + /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ + cff_construct_ps_name, + /* FT_Construct_PS_Name_Func construct_ps_name */ + cff_load_delta_set_index_mapping, + /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ + cff_load_item_variation_store, + /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ + cff_get_item_delta, + /* FT_Var_Get_Item_Delta_Func get_item_delta */ + cff_done_item_variation_store, + /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ + cff_done_delta_set_index_map, + /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ + cff_get_var_blend, /* FT_Get_Var_Blend_Func get_var_blend */ + cff_done_blend /* FT_Done_Blend_Func done_blend */ ) @@ -1041,41 +1081,46 @@ * */ - static FT_Error - cff_hadvance_adjust( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_hadvance_adjust( FT_Face face, /* CFF_Face */ FT_UInt gindex, FT_Int *avalue ) { - FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MetricsVariations + var = (FT_Service_MetricsVariations)cffface->tt_var; - return var->hadvance_adjust( FT_FACE( face ), gindex, avalue ); + return var->hadvance_adjust( face, gindex, avalue ); } - static void - cff_metrics_adjust( CFF_Face face ) + FT_CALLBACK_DEF( void ) + cff_metrics_adjust( FT_Face face ) /* CFF_Face */ { - FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MetricsVariations + var = (FT_Service_MetricsVariations)cffface->tt_var; - var->metrics_adjust( FT_FACE( face ) ); + var->metrics_adjust( face ); } FT_DEFINE_SERVICE_METRICSVARIATIONSREC( cff_service_metrics_variations, - (FT_HAdvance_Adjust_Func)cff_hadvance_adjust, /* hadvance_adjust */ - (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ - (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ + cff_hadvance_adjust, /* FT_HAdvance_Adjust_Func hadvance_adjust */ + NULL, /* FT_LSB_Adjust_Func lsb_adjust */ + NULL, /* FT_RSB_Adjust_Func rsb_adjust */ - (FT_VAdvance_Adjust_Func)NULL, /* vadvance_adjust */ - (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ - (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ - (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ + NULL, /* FT_VAdvance_Adjust_Func vadvance_adjust */ + NULL, /* FT_TSB_Adjust_Func tsb_adjust */ + NULL, /* FT_BSB_Adjust_Func bsb_adjust */ + NULL, /* FT_VOrg_Adjust_Func vorg_adjust */ - (FT_Metrics_Adjust_Func) cff_metrics_adjust /* metrics_adjust */ + cff_metrics_adjust, /* FT_Metrics_Adjust_Func metrics_adjust */ + NULL /* FT_Size_Reset_Func size_reset */ ) #endif @@ -1088,11 +1133,11 @@ FT_DEFINE_SERVICE_CFFLOADREC( cff_service_cff_load, - (FT_Get_Standard_Encoding_Func)cff_get_standard_encoding, - (FT_Load_Private_Dict_Func) cff_load_private_dict, - (FT_FD_Select_Get_Func) cff_fd_select_get, - (FT_Blend_Check_Vector_Func) cff_blend_check_vector, - (FT_Blend_Build_Vector_Func) cff_blend_build_vector + cff_get_standard_encoding, /* FT_Get_Standard_Encoding_Func get_standard_encoding */ + cff_load_private_dict, /* FT_Load_Private_Dict_Func load_private_dict */ + cff_fd_select_get, /* FT_FD_Select_Get_Func fd_select_get */ + cff_blend_check_vector, /* FT_Blend_Check_Vector_Func blend_check_vector */ + cff_blend_build_vector /* FT_Blend_Build_Vector_Func blend_build_vector */ ) diff --git a/src/3rdparty/freetype/src/cff/cffgload.c b/src/3rdparty/freetype/src/cff/cffgload.c index cfa0aaf2..c483d1d1 100644 --- a/src/3rdparty/freetype/src/cff/cffgload.c +++ b/src/3rdparty/freetype/src/cff/cffgload.c @@ -356,14 +356,16 @@ #ifdef FT_CONFIG_OPTION_SVG /* check for OT-SVG */ - if ( ( load_flags & FT_LOAD_COLOR ) && face->svg ) + if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && + ( load_flags & FT_LOAD_COLOR ) && + face->svg ) { /* * We load the SVG document and try to grab the advances from the * table. For the bearings we rely on the presetting hook to do that. */ - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)face->sfnt; if ( size && (size->root.metrics.x_ppem < 1 || diff --git a/src/3rdparty/freetype/src/cff/cffload.c b/src/3rdparty/freetype/src/cff/cffload.c index 4b8c6e16..af79082e 100644 --- a/src/3rdparty/freetype/src/cff/cffload.c +++ b/src/3rdparty/freetype/src/cff/cffload.c @@ -400,7 +400,7 @@ /* Allocate a table containing pointers to an index's elements. */ /* The `pool' argument makes this function convert the index */ - /* entries to C-style strings (this is, null-terminated). */ + /* entries to C-style strings (that is, null-terminated). */ static FT_Error cff_index_get_pointers( CFF_Index idx, FT_Byte*** table, @@ -1361,14 +1361,15 @@ for ( i = 0; i < numBlends; i++ ) { const FT_Int32* weight = &blend->BV[1]; - FT_UInt32 sum; + FT_Fixed sum; - /* convert inputs to 16.16 fixed-point */ - sum = cff_parse_num( parser, &parser->stack[i + base] ) * 0x10000; + /* convert inputs to 16.16 fixed point */ + sum = cff_parse_fixed( parser, &parser->stack[i + base] ); for ( j = 1; j < blend->lenBV; j++ ) - sum += cff_parse_num( parser, &parser->stack[delta++] ) * *weight++; + sum += FT_MulFix( cff_parse_fixed( parser, &parser->stack[delta++] ), + *weight++ ); /* point parser stack to new value on blend_stack */ parser->stack[i + base] = subFont->blend_top; @@ -1589,16 +1590,17 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_LOCAL_DEF( FT_Error ) - cff_get_var_blend( CFF_Face face, + cff_get_var_blend( FT_Face face, /* CFF_Face */ FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_var_blend( FT_FACE( face ), + return mm->get_var_blend( face, num_coords, coords, normalizedcoords, @@ -1607,13 +1609,14 @@ FT_LOCAL_DEF( void ) - cff_done_blend( CFF_Face face ) + cff_done_blend( FT_Face face ) /* CFF_Face */ { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - if (mm) - mm->done_blend( FT_FACE( face ) ); + if ( mm ) + mm->done_blend( face ); } #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ @@ -1650,13 +1653,6 @@ goto Exit; } - /* Zero out the code to gid/sid mappings. */ - for ( j = 0; j < 256; j++ ) - { - encoding->sids [j] = 0; - encoding->codes[j] = 0; - } - /* Note: The encoding table in a CFF font is indexed by glyph index; */ /* the first encoded glyph index is 1. Hence, we read the character */ /* code (`glyph_code') at index j and make the assignment: */ @@ -1671,6 +1667,10 @@ if ( offset > 1 ) { + /* Zero out the code to gid/sid mappings. */ + FT_ARRAY_ZERO( encoding->sids, 256 ); + FT_ARRAY_ZERO( encoding->codes, 256 ); + encoding->offset = base_offset + offset; /* we need to parse the table to determine its size */ @@ -2012,7 +2012,7 @@ /* Top and Font DICTs are not allowed to have blend operators. */ error = cff_parser_init( &parser, code, - &subfont->font_dict, + top, font->library, stackSize, 0, diff --git a/src/3rdparty/freetype/src/cff/cffload.h b/src/3rdparty/freetype/src/cff/cffload.h index 5a41cdeb..b5286b0c 100644 --- a/src/3rdparty/freetype/src/cff/cffload.h +++ b/src/3rdparty/freetype/src/cff/cffload.h @@ -105,14 +105,14 @@ FT_BEGIN_HEADER #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_LOCAL( FT_Error ) - cff_get_var_blend( CFF_Face face, + cff_get_var_blend( FT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); FT_LOCAL( void ) - cff_done_blend( CFF_Face face ); + cff_done_blend( FT_Face face ); #endif diff --git a/src/3rdparty/freetype/src/cff/cffobjs.c b/src/3rdparty/freetype/src/cff/cffobjs.c index 40cd9bf9..6d08620c 100644 --- a/src/3rdparty/freetype/src/cff/cffobjs.c +++ b/src/3rdparty/freetype/src/cff/cffobjs.c @@ -69,8 +69,8 @@ FT_Module module; - module = FT_Get_Module( size->root.face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( font->library, "pshinter" ); + return ( module && pshinter && pshinter->get_globals_funcs ) ? pshinter->get_globals_funcs( module ) : 0; @@ -182,8 +182,7 @@ goto Exit; cff_make_private_dict( &font->top_font, &priv ); - error = funcs->create( cffsize->face->memory, &priv, - &internal->topfont ); + error = funcs->create( memory, &priv, &internal->topfont ); if ( error ) goto Exit; @@ -193,8 +192,7 @@ cff_make_private_dict( sub, &priv ); - error = funcs->create( cffsize->face->memory, &priv, - &internal->subfonts[i - 1] ); + error = funcs->create( memory, &priv, &internal->subfonts[i - 1] ); if ( error ) goto Exit; } @@ -381,8 +379,7 @@ FT_Module module; - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( slot->library, "pshinter" ); if ( module ) { T2_Hints_Funcs funcs; @@ -722,22 +719,15 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; - FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; - FT_UInt instance_index = (FT_UInt)face_index >> 16; if ( FT_HAS_MULTIPLE_MASTERS( cffface ) && - mm && instance_index > 0 ) { - error = mm->set_instance( cffface, instance_index ); + error = FT_Set_Named_Instance( cffface, instance_index ); if ( error ) goto Exit; - - if ( var ) - var->metrics_adjust( cffface ); } } #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ @@ -1160,7 +1150,7 @@ } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - cff_done_blend( face ); + cff_done_blend( cffface ); face->blend = NULL; #endif } diff --git a/src/3rdparty/freetype/src/cff/cffparse.c b/src/3rdparty/freetype/src/cff/cffparse.c index e16206fd..3b076704 100644 --- a/src/3rdparty/freetype/src/cff/cffparse.c +++ b/src/3rdparty/freetype/src/cff/cffparse.c @@ -63,10 +63,7 @@ /* allocate the stack buffer */ if ( FT_QNEW_ARRAY( parser->stack, stackSize ) ) - { - FT_FREE( parser->stack ); goto Exit; - } parser->stackSize = stackSize; parser->top = parser->stack; /* empty stack */ @@ -76,23 +73,6 @@ } -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - static void - finalize_t2_strings( FT_Memory memory, - void* data, - void* user ) - { - CFF_T2_String t2 = (CFF_T2_String)data; - - - FT_UNUSED( user ); - - memory->free( memory, t2->start ); - memory->free( memory, data ); - } -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - - FT_LOCAL_DEF( void ) cff_parser_done( CFF_Parser parser ) { @@ -102,63 +82,19 @@ FT_FREE( parser->stack ); #ifdef CFF_CONFIG_OPTION_OLD_ENGINE - FT_List_Finalize( &parser->t2_strings, - finalize_t2_strings, - memory, - NULL ); + FT_List_Finalize( &parser->t2_strings, NULL, memory, NULL ); #endif } - /* Assuming `first >= last'. */ - - static FT_Error - cff_parser_within_limits( CFF_Parser parser, - FT_Byte* first, - FT_Byte* last ) - { -#ifndef CFF_CONFIG_OPTION_OLD_ENGINE - - /* Fast path for regular FreeType builds with the "new" engine; */ - /* `first >= parser->start' can be assumed. */ - - FT_UNUSED( first ); - - return last < parser->limit ? FT_Err_Ok : FT_THROW( Invalid_Argument ); - -#else /* CFF_CONFIG_OPTION_OLD_ENGINE */ - - FT_ListNode node; - - - if ( first >= parser->start && - last < parser->limit ) - return FT_Err_Ok; - - node = parser->t2_strings.head; - - while ( node ) - { - CFF_T2_String t2 = (CFF_T2_String)node->data; - - - if ( first >= t2->start && - last < t2->limit ) - return FT_Err_Ok; - - node = node->next; - } - - return FT_THROW( Invalid_Argument ); - -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - } - + /* The parser limit checks in the next two functions are supposed */ + /* to detect the immediate crossing of the stream boundary. They */ + /* shall not be triggered from the distant t2_strings buffers. */ /* read an integer */ static FT_Long - cff_parse_integer( CFF_Parser parser, - FT_Byte* start ) + cff_parse_integer( FT_Byte* start, + FT_Byte* limit ) { FT_Byte* p = start; FT_Int v = *p++; @@ -167,14 +103,14 @@ if ( v == 28 ) { - if ( cff_parser_within_limits( parser, p, p + 1 ) ) + if ( p + 2 > limit && limit >= p ) goto Bad; val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] ); } else if ( v == 29 ) { - if ( cff_parser_within_limits( parser, p, p + 3 ) ) + if ( p + 4 > limit && limit >= p ) goto Bad; val = (FT_Long)( ( (FT_ULong)p[0] << 24 ) | @@ -188,14 +124,14 @@ } else if ( v < 251 ) { - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; val = ( v - 247 ) * 256 + p[0] + 108; } else { - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; val = -( v - 251 ) * 256 - p[0] - 108; @@ -244,10 +180,10 @@ /* read a real */ static FT_Fixed - cff_parse_real( CFF_Parser parser, - FT_Byte* start, - FT_Long power_ten, - FT_Long* scaling ) + cff_parse_real( FT_Byte* start, + FT_Byte* limit, + FT_Long power_ten, + FT_Long* scaling ) { FT_Byte* p = start; FT_Int nib; @@ -282,7 +218,7 @@ p++; /* Make sure we don't read past the end. */ - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -319,7 +255,7 @@ p++; /* Make sure we don't read past the end. */ - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -358,7 +294,7 @@ p++; /* Make sure we don't read past the end. */ - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -525,7 +461,7 @@ if ( **d == 30 ) { /* binary-coded decimal is truncated to integer */ - return cff_parse_real( parser, *d, 0, NULL ) >> 16; + return cff_parse_real( *d, parser->limit, 0, NULL ) >> 16; } else if ( **d == 255 ) @@ -551,7 +487,7 @@ } else - return cff_parse_integer( parser, *d ); + return cff_parse_integer( *d, parser->limit ); } @@ -562,15 +498,33 @@ FT_Long scaling ) { if ( **d == 30 ) - return cff_parse_real( parser, *d, scaling, NULL ); - else + return cff_parse_real( *d, parser->limit, scaling, NULL ); + else if ( **d == 255 ) { - FT_Long val = cff_parse_integer( parser, *d ); - + FT_Fixed val = ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) | + ( (FT_UInt32)*( d[0] + 2 ) << 16 ) | + ( (FT_UInt32)*( d[0] + 3 ) << 8 ) | + (FT_UInt32)*( d[0] + 4 ) ) ); if ( scaling ) { if ( FT_ABS( val ) > power_ten_limits[scaling] ) + { + FT_TRACE4(( "!!!OVERFLOW:!!!" )); + return val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL; + } + val *= power_tens[scaling]; + } + return val; + } + else + { + FT_Long val = cff_parse_integer( *d, parser->limit ); + + + if ( scaling ) + { + if ( ( FT_ABS( val ) << 16 ) > power_ten_limits[scaling] ) { val = val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL; goto Overflow; @@ -600,7 +554,7 @@ /* read a floating point number, either integer or real */ - static FT_Fixed + FT_LOCAL_DEF( FT_Fixed ) cff_parse_fixed( CFF_Parser parser, FT_Byte** d ) { @@ -630,14 +584,14 @@ FT_ASSERT( scaling ); if ( **d == 30 ) - return cff_parse_real( parser, *d, 0, scaling ); + return cff_parse_real( *d, parser->limit, 0, scaling ); else { FT_Long number; FT_Int integer_length; - number = cff_parse_integer( parser, d[0] ); + number = cff_parse_integer( *d, parser->limit ); if ( number > 0x7FFFL ) { @@ -686,7 +640,7 @@ dict->has_font_matrix = TRUE; - /* We expect a well-formed font matrix, this is, the matrix elements */ + /* We expect a well-formed font matrix, that is, the matrix elements */ /* `xx' and `yy' are of approximately the same magnitude. To avoid */ /* loss of precision, we use the magnitude of the largest matrix */ /* element to scale all other elements. The scaling factor is then */ @@ -1264,11 +1218,8 @@ FT_Byte* charstring_base; FT_ULong charstring_len; - FT_Fixed* stack; - FT_ListNode node; - CFF_T2_String t2; - FT_Fixed t2_size; - FT_Byte* q; + FT_Fixed* stack; + FT_Byte* q = NULL; charstring_base = ++p; @@ -1309,39 +1260,18 @@ /* Now copy the stack data in the temporary decoder object, */ /* converting it back to charstring number representations */ /* (this is ugly, I know). */ + /* The maximum required size is 5 bytes per stack element. */ + if ( FT_QALLOC( q, (FT_Long)( 2 * sizeof ( FT_ListNode ) ) + + 5 * ( decoder.top - decoder.stack ) ) ) + goto Exit; - node = (FT_ListNode)memory->alloc( memory, - sizeof ( FT_ListNodeRec ) ); - if ( !node ) - goto Out_Of_Memory_Error; + FT_List_Add( &parser->t2_strings, (FT_ListNode)q ); - FT_List_Add( &parser->t2_strings, node ); + q += 2 * sizeof ( FT_ListNode ); - t2 = (CFF_T2_String)memory->alloc( memory, - sizeof ( CFF_T2_StringRec ) ); - if ( !t2 ) - goto Out_Of_Memory_Error; - - node->data = t2; - - /* `5' is the conservative upper bound of required bytes per stack */ - /* element. */ - - t2_size = 5 * ( decoder.top - decoder.stack ); - - q = (FT_Byte*)memory->alloc( memory, t2_size ); - if ( !q ) - goto Out_Of_Memory_Error; - - t2->start = q; - t2->limit = q + t2_size; - - stack = decoder.stack; - - while ( stack < decoder.top ) + for ( stack = decoder.stack; stack < decoder.top; stack++ ) { - FT_ULong num; - FT_Bool neg; + FT_Long num = *stack; if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize ) @@ -1349,69 +1279,37 @@ *parser->top++ = q; - if ( *stack < 0 ) - { - num = (FT_ULong)NEG_LONG( *stack ); - neg = 1; - } - else - { - num = (FT_ULong)*stack; - neg = 0; - } - if ( num & 0xFFFFU ) { - if ( neg ) - num = (FT_ULong)-num; - *q++ = 255; - *q++ = ( num & 0xFF000000U ) >> 24; - *q++ = ( num & 0x00FF0000U ) >> 16; - *q++ = ( num & 0x0000FF00U ) >> 8; - *q++ = num & 0x000000FFU; + *q++ = (FT_Byte)( ( num >> 24 ) & 0xFF ); + *q++ = (FT_Byte)( ( num >> 16 ) & 0xFF ); + *q++ = (FT_Byte)( ( num >> 8 ) & 0xFF ); + *q++ = (FT_Byte)( ( num ) & 0xFF ); } else { num >>= 16; - if ( neg ) + if ( -107 <= num && num <= 107 ) + *q++ = (FT_Byte)( num + 139 ); + else if ( 108 <= num && num <= 1131 ) { - if ( num <= 107 ) - *q++ = (FT_Byte)( 139 - num ); - else if ( num <= 1131 ) - { - *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 251 ); - *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); - } - else - { - num = (FT_ULong)-num; - - *q++ = 28; - *q++ = (FT_Byte)( num >> 8 ); - *q++ = (FT_Byte)( num & 0xFF ); - } + *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 ); + *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); + } + else if ( -1131 <= num && num <= -108 ) + { + *q++ = (FT_Byte)( ( ( -num - 108 ) >> 8 ) + 251 ); + *q++ = (FT_Byte)( ( -num - 108) & 0xFF ); } else { - if ( num <= 107 ) - *q++ = (FT_Byte)( num + 139 ); - else if ( num <= 1131 ) - { - *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 ); - *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); - } - else - { - *q++ = 28; - *q++ = (FT_Byte)( num >> 8 ); - *q++ = (FT_Byte)( num & 0xFF ); - } + *q++ = 28; + *q++ = (FT_Byte)( num >> 8 ); + *q++ = (FT_Byte)( num & 0xFF ); } } - - stack++; } } #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ @@ -1598,12 +1496,6 @@ Exit: return error; -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - Out_Of_Memory_Error: - error = FT_THROW( Out_Of_Memory ); - goto Exit; -#endif - Stack_Overflow: error = FT_THROW( Invalid_Argument ); goto Exit; diff --git a/src/3rdparty/freetype/src/cff/cffparse.h b/src/3rdparty/freetype/src/cff/cffparse.h index 58d59fa4..418caacc 100644 --- a/src/3rdparty/freetype/src/cff/cffparse.h +++ b/src/3rdparty/freetype/src/cff/cffparse.h @@ -76,6 +76,10 @@ FT_BEGIN_HEADER cff_parse_num( CFF_Parser parser, FT_Byte** d ); + FT_LOCAL( FT_Fixed ) + cff_parse_fixed( CFF_Parser parser, + FT_Byte** d ); + FT_LOCAL( FT_Error ) cff_parser_init( CFF_Parser parser, FT_UInt code, @@ -133,15 +137,6 @@ FT_BEGIN_HEADER FT_END_HEADER -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - typedef struct CFF_T2_String_ - { - FT_Byte* start; - FT_Byte* limit; - - } CFF_T2_StringRec, *CFF_T2_String; -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - #endif /* CFFPARSE_H_ */ diff --git a/src/3rdparty/freetype/src/cid/cidgload.c b/src/3rdparty/freetype/src/cid/cidgload.c index ba4b7565..eaca765a 100644 --- a/src/3rdparty/freetype/src/cid/cidgload.c +++ b/src/3rdparty/freetype/src/cid/cidgload.c @@ -40,6 +40,117 @@ #define FT_COMPONENT cidgload + /* + * A helper function to compute FD number (`fd_select`), the offset to the + * head of the glyph data (`off1`), and the offset to the and of the glyph + * data (`off2`). + * + * The number how many times `cid_get_offset` is invoked can be controlled + * by the number of non-NULL arguments. If `fd_select` is non-NULL but + * `off1` and `off2` are NULL, `cid_get_offset` is invoked only for + * `fd_select`; `off1` and `off2` are not validated. + * + */ + FT_LOCAL_DEF( FT_Error ) + cid_compute_fd_and_offsets( CID_Face face, + FT_UInt glyph_index, + FT_ULong* fd_select_p, + FT_ULong* off1_p, + FT_ULong* off2_p ) + { + FT_Error error = FT_Err_Ok; + + CID_FaceInfo cid = &face->cid; + FT_Stream stream = face->cid_stream; + FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes; + + FT_Byte* p; + FT_Bool need_frame_exit = 0; + FT_ULong fd_select, off1, off2; + + + /* For ordinary fonts, read the CID font dictionary index */ + /* and charstring offset from the CIDMap. */ + + if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + + glyph_index * entry_len ) || + FT_FRAME_ENTER( 2 * entry_len ) ) + goto Exit; + + need_frame_exit = 1; + + p = (FT_Byte*)stream->cursor; + fd_select = cid_get_offset( &p, cid->fd_bytes ); + off1 = cid_get_offset( &p, cid->gd_bytes ); + + p += cid->fd_bytes; + off2 = cid_get_offset( &p, cid->gd_bytes ); + + if ( fd_select_p ) + *fd_select_p = fd_select; + if ( off1_p ) + *off1_p = off1; + if ( off2_p ) + *off2_p = off2; + + if ( fd_select >= cid->num_dicts ) + { + /* + * fd_select == 0xFF is often used to indicate that the CID + * has no charstring to be rendered, similar to GID = 0xFFFF + * in TrueType fonts. + */ + if ( ( cid->fd_bytes == 1 && fd_select == 0xFFU ) || + ( cid->fd_bytes == 2 && fd_select == 0xFFFFU ) ) + { + FT_TRACE1(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE1(( " FD number %ld is the maximum\n", + fd_select )); + FT_TRACE1(( " integer fitting into %d byte%s\n", + cid->fd_bytes, cid->fd_bytes == 1 ? "" : "s" )); + } + else + { + FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE0(( " FD number %ld is larger\n", + fd_select )); + FT_TRACE0(( " than number of dictionaries (%d)\n", + cid->num_dicts )); + } + + error = FT_THROW( Invalid_Offset ); + goto Exit; + } + else if ( off2 > stream->size ) + { + FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE0(( " end of the glyph data\n" )); + FT_TRACE0(( " is beyond the data stream\n" )); + + error = FT_THROW( Invalid_Offset ); + goto Exit; + } + else if ( off1 > off2 ) + { + FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE0(( " the end position of glyph data\n" )); + FT_TRACE0(( " is set before the start position\n" )); + + error = FT_THROW( Invalid_Offset ); + } + + Exit: + if ( need_frame_exit ) + FT_FRAME_EXIT(); + + return error; + } + + FT_CALLBACK_DEF( FT_Error ) cid_load_glyph( T1_Decoder decoder, FT_UInt glyph_index ) @@ -97,35 +208,15 @@ else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - /* For ordinary fonts read the CID font dictionary index */ - /* and charstring offset from the CIDMap. */ { - FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes; FT_ULong off1, off2; - if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + - glyph_index * entry_len ) || - FT_FRAME_ENTER( 2 * entry_len ) ) + error = cid_compute_fd_and_offsets( face, glyph_index, + &fd_select, &off1, &off2 ); + if ( error ) goto Exit; - p = (FT_Byte*)stream->cursor; - fd_select = cid_get_offset( &p, cid->fd_bytes ); - off1 = cid_get_offset( &p, cid->gd_bytes ); - p += cid->fd_bytes; - off2 = cid_get_offset( &p, cid->gd_bytes ); - FT_FRAME_EXIT(); - - if ( fd_select >= cid->num_dicts || - off2 > stream->size || - off1 > off2 ) - { - FT_TRACE0(( "cid_load_glyph: invalid glyph stream offsets\n" )); - error = FT_THROW( Invalid_Offset ); - goto Exit; - } - glyph_length = off2 - off1; if ( glyph_length == 0 || @@ -161,7 +252,9 @@ cs_offset = decoder->lenIV >= 0 ? (FT_UInt)decoder->lenIV : 0; if ( cs_offset > glyph_length ) { - FT_TRACE0(( "cid_load_glyph: invalid glyph stream offsets\n" )); + FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, " + "offset to the charstring is beyond glyph length\n", + glyph_index )); error = FT_THROW( Invalid_Offset ); goto Exit; } diff --git a/src/3rdparty/freetype/src/cid/cidgload.h b/src/3rdparty/freetype/src/cid/cidgload.h index 97954d41..edd62292 100644 --- a/src/3rdparty/freetype/src/cid/cidgload.h +++ b/src/3rdparty/freetype/src/cid/cidgload.h @@ -42,6 +42,14 @@ FT_BEGIN_HEADER FT_Int32 load_flags ); + FT_LOCAL( FT_Error ) + cid_compute_fd_and_offsets( CID_Face face, + FT_UInt glyph_index, + FT_ULong* fd_select_p, + FT_ULong* off1_p, + FT_ULong* off2_p ); + + FT_END_HEADER #endif /* CIDGLOAD_H_ */ diff --git a/src/3rdparty/freetype/src/cid/cidload.c b/src/3rdparty/freetype/src/cid/cidload.c index 26daa5da..a7da8ea3 100644 --- a/src/3rdparty/freetype/src/cid/cidload.c +++ b/src/3rdparty/freetype/src/cid/cidload.c @@ -155,23 +155,24 @@ FT_CALLBACK_DEF( void ) - cid_parse_font_matrix( CID_Face face, - CID_Parser* parser ) + cid_parse_font_matrix( FT_Face face, /* CID_Face */ + void* parser_ ) { + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; CID_FaceDict dict; - FT_Face root = (FT_Face)&face->root; FT_Fixed temp[6]; FT_Fixed temp_scale; - if ( parser->num_dict < face->cid.num_dicts ) + if ( parser->num_dict < cidface->cid.num_dicts ) { FT_Matrix* matrix; FT_Vector* offset; FT_Int result; - dict = face->cid.font_dicts + parser->num_dict; + dict = cidface->cid.font_dicts + parser->num_dict; matrix = &dict->font_matrix; offset = &dict->font_offset; @@ -204,7 +205,7 @@ if ( temp_scale != 0x10000L ) { /* set units per EM based on FontMatrix values */ - root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); + face->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); temp[0] = FT_DivFix( temp[0], temp_scale ); temp[1] = FT_DivFix( temp[1], temp_scale ); @@ -237,13 +238,15 @@ FT_CALLBACK_DEF( void ) - parse_fd_array( CID_Face face, - CID_Parser* parser ) + parse_fd_array( FT_Face face, /* CID_Face */ + void* parser_ ) { - CID_FaceInfo cid = &face->cid; - FT_Memory memory = face->root.memory; - FT_Stream stream = parser->stream; - FT_Error error = FT_Err_Ok; + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; + CID_FaceInfo cid = &cidface->cid; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Stream stream = parser->stream; + FT_Error error = FT_Err_Ok; FT_Long num_dicts, max_dicts; @@ -313,18 +316,20 @@ /* By mistake, `expansion_factor' appears both in PS_PrivateRec */ /* and CID_FaceDictRec (both are public header files and can't */ - /* changed). We simply copy the value. */ + /* be thus changed). We simply copy the value. */ FT_CALLBACK_DEF( void ) - parse_expansion_factor( CID_Face face, - CID_Parser* parser ) + parse_expansion_factor( FT_Face face, /* CID_Face */ + void* parser_ ) { + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; CID_FaceDict dict; - if ( parser->num_dict < face->cid.num_dicts ) + if ( parser->num_dict < cidface->cid.num_dicts ) { - dict = face->cid.font_dicts + parser->num_dict; + dict = cidface->cid.font_dicts + parser->num_dict; dict->expansion_factor = cid_parser_to_fixed( parser, 0 ); dict->private_dict.expansion_factor = dict->expansion_factor; @@ -341,11 +346,15 @@ /* to catch it for producing better trace output. */ FT_CALLBACK_DEF( void ) - parse_font_name( CID_Face face, - CID_Parser* parser ) + parse_font_name( FT_Face face, /* CID_Face */ + void* parser_ ) { #ifdef FT_DEBUG_LEVEL_TRACE - if ( parser->num_dict < face->cid.num_dicts ) + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; + + + if ( parser->num_dict < cidface->cid.num_dicts ) { T1_TokenRec token; FT_UInt len; @@ -361,7 +370,7 @@ } #else FT_UNUSED( face ); - FT_UNUSED( parser ); + FT_UNUSED( parser_ ); #endif return; diff --git a/src/3rdparty/freetype/src/cid/cidobjs.c b/src/3rdparty/freetype/src/cid/cidobjs.c index 06b2139a..f698a419 100644 --- a/src/3rdparty/freetype/src/cid/cidobjs.c +++ b/src/3rdparty/freetype/src/cid/cidobjs.c @@ -69,8 +69,7 @@ FT_Module module; - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( slot->library, "pshinter" ); if ( module ) { T1_Hints_Funcs funcs; @@ -268,7 +267,8 @@ * * @Input: * stream :: - * The source font stream. + * Dummy argument for compatibility with the `FT_Face_InitFunc` API. + * Ignored. The stream should be passed through `face->root.stream`. * * face_index :: * The index of the font face in the resource. @@ -375,6 +375,14 @@ if ( info->is_fixed_pitch ) cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + /* + * For the sfnt-wrapped CID fonts for MacOS, currently, + * its `cmap' tables are ignored, and the content in + * its `CID ' table is treated the same as naked CID-keyed + * font. See ft_lookup_PS_in_sfnt_stream(). + */ + cidface->face_flags |= FT_FACE_FLAG_CID_KEYED; + /* XXX: TODO: add kerning with .afm support */ /* get style name -- be careful, some broken fonts only */ diff --git a/src/3rdparty/freetype/src/cid/cidparse.c b/src/3rdparty/freetype/src/cid/cidparse.c index 16889db9..171a8862 100644 --- a/src/3rdparty/freetype/src/cid/cidparse.c +++ b/src/3rdparty/freetype/src/cid/cidparse.c @@ -214,18 +214,24 @@ cur <= limit - STARTDATA_LEN && ft_strncmp( (char*)cur, STARTDATA, STARTDATA_LEN ) == 0 ) { - if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) + T1_TokenRec type_token; + FT_Long binary_length; + + + parser->root.cursor = arg1; + cid_parser_to_token( parser, &type_token ); + if ( type_token.limit - type_token.start == 5 && + ft_memcmp( (char*)type_token.start, "(Hex)", 5 ) == 0 ) { - FT_Long tmp = ft_strtol( (const char *)arg2, NULL, 10 ); - - - if ( tmp < 0 ) + parser->root.cursor = arg2; + binary_length = cid_parser_to_int( parser ); + if ( binary_length < 0 ) { FT_ERROR(( "cid_parser_new: invalid length of hex data\n" )); error = FT_THROW( Invalid_File_Format ); } else - parser->binary_length = (FT_ULong)tmp; + parser->binary_length = (FT_ULong)binary_length; } goto Exit; diff --git a/src/3rdparty/freetype/src/cid/cidriver.c b/src/3rdparty/freetype/src/cid/cidriver.c index f7499237..99e7b118 100644 --- a/src/3rdparty/freetype/src/cid/cidriver.c +++ b/src/3rdparty/freetype/src/cid/cidriver.c @@ -48,10 +48,11 @@ * */ - static const char* - cid_get_postscript_name( CID_Face face ) + FT_CALLBACK_DEF( const char* ) + cid_get_postscript_name( FT_Face face ) /* CID_Face */ { - const char* result = face->cid.cid_font_name; + CID_Face cidface = (CID_Face)face; + const char* result = cidface->cid.cid_font_name; if ( result && result[0] == '/' ) @@ -72,34 +73,36 @@ * */ - static FT_Error - cid_ps_get_font_info( FT_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_ps_get_font_info( FT_Face face, /* CID_Face */ PS_FontInfoRec* afont_info ) { - *afont_info = ((CID_Face)face)->cid.font_info; + *afont_info = ( (CID_Face)face )->cid.font_info; return FT_Err_Ok; } - static FT_Error - cid_ps_get_font_extra( FT_Face face, - PS_FontExtraRec* afont_extra ) + + FT_CALLBACK_DEF( FT_Error ) + cid_ps_get_font_extra( FT_Face face, /* CID_Face */ + PS_FontExtraRec* afont_extra ) { - *afont_extra = ((CID_Face)face)->font_extra; + *afont_extra = ( (CID_Face)face )->font_extra; return FT_Err_Ok; } + static const FT_Service_PsInfoRec cid_service_ps_info = { - (PS_GetFontInfoFunc) cid_ps_get_font_info, /* ps_get_font_info */ - (PS_GetFontExtraFunc) cid_ps_get_font_extra, /* ps_get_font_extra */ + cid_ps_get_font_info, /* PS_GetFontInfoFunc ps_get_font_info */ + cid_ps_get_font_extra, /* PS_GetFontExtraFunc ps_get_font_extra */ /* unsupported with CID fonts */ - (PS_HasGlyphNamesFunc) NULL, /* ps_has_glyph_names */ + NULL, /* PS_HasGlyphNamesFunc ps_has_glyph_names */ /* unsupported */ - (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ + NULL, /* PS_GetFontPrivateFunc ps_get_font_private */ /* not implemented */ - (PS_GetFontValueFunc) NULL /* ps_get_font_value */ + NULL /* PS_GetFontValueFunc ps_get_font_value */ }; @@ -107,13 +110,14 @@ * CID INFO SERVICE * */ - static FT_Error - cid_get_ros( CID_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_get_ros( FT_Face face, /* CID_Face */ const char* *registry, const char* *ordering, FT_Int *supplement ) { - CID_FaceInfo cid = &face->cid; + CID_Face cidface = (CID_Face)face; + CID_FaceInfo cid = &cidface->cid; if ( registry ) @@ -129,32 +133,48 @@ } - static FT_Error - cid_get_is_cid( CID_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_get_is_cid( FT_Face face, /* CID_Face */ FT_Bool *is_cid ) { FT_Error error = FT_Err_Ok; FT_UNUSED( face ); + /* + * XXX: If the ROS is Adobe-Identity-H or -V, + * the font has no reliable information about + * its glyph collection. Should we not set + * *is_cid in such cases? + */ if ( is_cid ) - *is_cid = 1; /* cid driver is only used for CID keyed fonts */ + *is_cid = 1; return error; } - static FT_Error - cid_get_cid_from_glyph_index( CID_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_get_cid_from_glyph_index( FT_Face face, /* CID_Face */ FT_UInt glyph_index, FT_UInt *cid ) { - FT_Error error = FT_Err_Ok; - FT_UNUSED( face ); + FT_Error error = FT_Err_Ok; + CID_Face cidface = (CID_Face)face; - if ( cid ) - *cid = glyph_index; /* identity mapping */ + /* + * Currently, FreeType does not support incrementally-defined, CID-keyed + * fonts that store the glyph description data in a `/GlyphDirectory` + * array or dictionary. Fonts loaded by the incremental loading feature + * are thus not handled here. + */ + error = cid_compute_fd_and_offsets( cidface, glyph_index, + NULL, NULL, NULL ); + if ( error ) + *cid = 0; + else + *cid = glyph_index; return error; } @@ -162,12 +182,12 @@ static const FT_Service_CIDRec cid_service_cid_info = { - (FT_CID_GetRegistryOrderingSupplementFunc) - cid_get_ros, /* get_ros */ - (FT_CID_GetIsInternallyCIDKeyedFunc) - cid_get_is_cid, /* get_is_cid */ - (FT_CID_GetCIDFromGlyphIndexFunc) - cid_get_cid_from_glyph_index /* get_cid_from_glyph_index */ + cid_get_ros, + /* FT_CID_GetRegistryOrderingSupplementFunc get_ros */ + cid_get_is_cid, + /* FT_CID_GetIsInternallyCIDKeyedFunc get_is_cid */ + cid_get_cid_from_glyph_index + /* FT_CID_GetCIDFromGlyphIndexFunc get_cid_from_glyph_index */ }; @@ -179,9 +199,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( cid_service_properties, - (FT_Properties_SetFunc)ps_property_set, /* set_property */ - (FT_Properties_GetFunc)ps_property_get ) /* get_property */ - + ps_property_set, /* FT_Properties_SetFunc set_property */ + ps_property_get /* FT_Properties_GetFunc get_property */ + ) /* * SERVICE LIST @@ -209,7 +229,6 @@ } - FT_CALLBACK_TABLE_DEF const FT_Driver_ClassRec t1cid_driver_class = { diff --git a/src/3rdparty/freetype/src/dlg/dlgwrap.c b/src/3rdparty/freetype/src/dlg/dlgwrap.c index 271241f0..e9dc3410 100644 --- a/src/3rdparty/freetype/src/dlg/dlgwrap.c +++ b/src/3rdparty/freetype/src/dlg/dlgwrap.c @@ -25,7 +25,7 @@ #include "dlg.c" #else /* ANSI C doesn't like empty source files */ - typedef int _dlg_dummy; + typedef int dlg_dummy_; #endif diff --git a/src/3rdparty/freetype/src/gxvalid/gxvfgen.c b/src/3rdparty/freetype/src/gxvalid/gxvfgen.c index 11535422..cf98bb36 100644 --- a/src/3rdparty/freetype/src/gxvalid/gxvfgen.c +++ b/src/3rdparty/freetype/src/gxvalid/gxvfgen.c @@ -97,7 +97,8 @@ #define EMPTYFEAT {0, 0, {NULL}} - static GX_Feature_RegistryRec featreg_table[] = { + static GX_Feature_RegistryRec featreg_table[] = + { { /* 0 */ "All Typographic Features", 0, diff --git a/src/3rdparty/freetype/src/gzip/README.freetype b/src/3rdparty/freetype/src/gzip/README.freetype index e0c8ced1..76298b06 100644 --- a/src/3rdparty/freetype/src/gzip/README.freetype +++ b/src/3rdparty/freetype/src/gzip/README.freetype @@ -1,7 +1,7 @@ Name: zlib Short Name: zlib URL: http://zlib.net/ -Version: 1.2.12 +Version: 1.2.13 License: see `zlib.h` Description: diff --git a/src/3rdparty/freetype/src/gzip/ftgzip.c b/src/3rdparty/freetype/src/gzip/ftgzip.c index 48da6ff9..ca6a2aab 100644 --- a/src/3rdparty/freetype/src/gzip/ftgzip.c +++ b/src/3rdparty/freetype/src/gzip/ftgzip.c @@ -70,10 +70,9 @@ /* so that configuration with `FT_CONFIG_OPTION_SYSTEM_ZLIB' might */ /* include the wrong `zconf.h' file, leading to errors. */ -#if defined( __GNUC__ ) || defined( __clang__ ) #define ZEXPORT -#define ZEXTERN static -#endif + /* prevent zlib functions from being visible outside their object files */ +#define ZEXTERN static #define HAVE_MEMCPY 1 #define Z_SOLO 1 diff --git a/src/3rdparty/freetype/src/gzip/infback.c b/src/3rdparty/freetype/src/gzip/infback.c deleted file mode 100644 index 264c14e0..00000000 --- a/src/3rdparty/freetype/src/gzip/infback.c +++ /dev/null @@ -1,644 +0,0 @@ -/* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2022 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - This code is largely copied from inflate.c. Normally either infback.o or - inflate.o would be linked into an application--not both. The interface - with inffast.c is retained so that optimized assembler-coded versions of - inflate_fast() can be used with either inflate.c or infback.c. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); - -/* - strm provides memory allocation functions in zalloc and zfree, or - Z_NULL to use the library memory allocation functions. - - windowBits is in the range 8..15, and window is a user-supplied - window and output buffer that is 2**windowBits bytes. - */ -int ZEXPORT inflateBackInit_( - z_streamp strm, - int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size) -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL || window == Z_NULL || - windowBits < 8 || windowBits > 15) - return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - state = (struct inflate_state FAR *)ZALLOC(strm, 1, - sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->dmax = 32768U; - state->wbits = (uInt)windowBits; - state->wsize = 1U << windowBits; - state->window = window; - state->wnext = 0; - state->whave = 0; - state->sane = 1; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables( - struct inflate_state FAR *state) -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -/* Macros for inflateBack(): */ - -/* Load returned state from inflate_fast() */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Set state from registers for inflate_fast() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Assure that some input is available. If input is requested, but denied, - then return a Z_BUF_ERROR from inflateBack(). */ -#define PULL() \ - do { \ - if (have == 0) { \ - have = in(in_desc, &next); \ - if (have == 0) { \ - next = Z_NULL; \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflateBack() - with an error if there is no input available. */ -#define PULLBYTE() \ - do { \ - PULL(); \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflateBack() with - an error. */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Assure that some output space is available, by writing out the window - if it's full. If the write fails, return from inflateBack() with a - Z_BUF_ERROR. */ -#define ROOM() \ - do { \ - if (left == 0) { \ - put = state->window; \ - left = state->wsize; \ - state->whave = left; \ - if (out(out_desc, put, left)) { \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* - strm provides the memory allocation functions and window buffer on input, - and provides information on the unused input on return. For Z_DATA_ERROR - returns, strm will also provide an error message. - - in() and out() are the call-back input and output functions. When - inflateBack() needs more input, it calls in(). When inflateBack() has - filled the window with output, or when it completes with data in the - window, it calls out() to write out the data. The application must not - change the provided input until in() is called again or inflateBack() - returns. The application must not change the window/output buffer until - inflateBack() returns. - - in() and out() are called with a descriptor parameter provided in the - inflateBack() call. This parameter can be a structure that provides the - information required to do the read or write, as well as accumulated - information on the input and output such as totals and check values. - - in() should return zero on failure. out() should return non-zero on - failure. If either in() or out() fails, than inflateBack() returns a - Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it - was in() or out() that caused in the error. Otherwise, inflateBack() - returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format - error, or Z_MEM_ERROR if it could not allocate memory for the state. - inflateBack() can also return Z_STREAM_ERROR if the input parameters - are not correct, i.e. strm is Z_NULL or the state was not initialized. - */ -int ZEXPORT inflateBack( - z_streamp strm, - in_func in, - void FAR *in_desc, - out_func out, - void FAR *out_desc) -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* Check that the strm exists and that the state was initialized */ - if (strm == Z_NULL || strm->state == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* Reset the state */ - strm->msg = Z_NULL; - state->mode = TYPE; - state->last = 0; - state->whave = 0; - next = strm->next_in; - have = next != Z_NULL ? strm->avail_in : 0; - hold = 0; - bits = 0; - put = state->window; - left = state->wsize; - - /* Inflate until end of block marked as last */ - for (;;) - switch (state->mode) { - case TYPE: - /* determine and dispatch block type */ - if (state->last) { - BYTEBITS(); - state->mode = DONE; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - - /* copy stored block from input to output */ - while (state->length != 0) { - copy = state->length; - PULL(); - ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - - /* get code length code lengths (not a typo) */ - state->have = 0; - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - - /* get length and distance code code lengths */ - state->have = 0; - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = (unsigned)(state->lens[state->have - 1]); - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - /* fallthrough */ - - case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= 6 && left >= 258) { - RESTORE(); - if (state->whave < state->wsize) - state->whave = state->wsize - left; - inflate_fast(strm, state->wsize); - LOAD(); - break; - } - - /* get a literal, length, or end-of-block code */ - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - state->length = (unsigned)here.val; - - /* process literal */ - if (here.op == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - ROOM(); - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - } - - /* process end of block */ - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - - /* invalid code */ - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - - /* length code -- get extra bits, if any */ - state->extra = (unsigned)(here.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - - /* get distance code */ - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)here.val; - - /* get distance extra bits, if any */ - state->extra = (unsigned)(here.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } - if (state->offset > state->wsize - (state->whave < state->wsize ? - left : 0)) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - - /* copy match from window to output */ - do { - ROOM(); - copy = state->wsize - state->offset; - if (copy < left) { - from = put + copy; - copy = left - copy; - } - else { - from = put - state->offset; - copy = left; - } - if (copy > state->length) copy = state->length; - state->length -= copy; - left -= copy; - do { - *put++ = *from++; - } while (--copy); - } while (state->length != 0); - break; - - case DONE: - /* inflate stream terminated properly */ - ret = Z_STREAM_END; - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - default: - /* can't happen, but makes compilers happy */ - ret = Z_STREAM_ERROR; - goto inf_leave; - } - - /* Write leftover output and return unused input */ - inf_leave: - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left) && - ret == Z_STREAM_END) - ret = Z_BUF_ERROR; - } - strm->next_in = next; - strm->avail_in = have; - return ret; -} - -int ZEXPORT inflateBackEnd( - z_streamp strm) -{ - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} diff --git a/src/3rdparty/freetype/src/gzip/rules.mk b/src/3rdparty/freetype/src/gzip/rules.mk index 6feb6f51..c76eacb1 100644 --- a/src/3rdparty/freetype/src/gzip/rules.mk +++ b/src/3rdparty/freetype/src/gzip/rules.mk @@ -36,25 +36,23 @@ endif # # All source and header files get loaded by `ftgzip.c' only if SYSTEM_ZLIB # is not defined (regardless whether we have a `single' or a `multi' build). -# However, it doesn't harm if we add everything as a dependency -# unconditionally. # -GZIP_DRV_SRCS := $(GZIP_DIR)/adler32.c \ - $(GZIP_DIR)/crc32.c \ - $(GZIP_DIR)/crc32.h \ - $(GZIP_DIR)/ftzconf.h \ - $(GZIP_DIR)/infback.c \ - $(GZIP_DIR)/inffast.c \ - $(GZIP_DIR)/inffast.h \ - $(GZIP_DIR)/inffixed.h \ - $(GZIP_DIR)/inflate.c \ - $(GZIP_DIR)/inflate.h \ - $(GZIP_DIR)/inftrees.c \ - $(GZIP_DIR)/inftrees.h \ - $(GZIP_DIR)/zlib.h \ - $(GZIP_DIR)/zutil.c \ - $(GZIP_DIR)/zutil.h - +ifeq ($(SYSTEM_ZLIB),) + GZIP_DRV_SRCS := $(GZIP_DIR)/adler32.c \ + $(GZIP_DIR)/crc32.c \ + $(GZIP_DIR)/crc32.h \ + $(GZIP_DIR)/ftzconf.h \ + $(GZIP_DIR)/inffast.c \ + $(GZIP_DIR)/inffast.h \ + $(GZIP_DIR)/inffixed.h \ + $(GZIP_DIR)/inflate.c \ + $(GZIP_DIR)/inflate.h \ + $(GZIP_DIR)/inftrees.c \ + $(GZIP_DIR)/inftrees.h \ + $(GZIP_DIR)/zlib.h \ + $(GZIP_DIR)/zutil.c \ + $(GZIP_DIR)/zutil.h +endif # gzip driver object(s) # diff --git a/src/3rdparty/freetype/src/pcf/pcfdrivr.c b/src/3rdparty/freetype/src/pcf/pcfdrivr.c index bfa6eacc..f1dba024 100644 --- a/src/3rdparty/freetype/src/pcf/pcfdrivr.c +++ b/src/3rdparty/freetype/src/pcf/pcfdrivr.c @@ -75,36 +75,36 @@ THE SOFTWARE. FT_CALLBACK_DEF( FT_Error ) - pcf_cmap_init( FT_CMap pcfcmap, /* PCF_CMap */ + pcf_cmap_init( FT_CMap cmap, /* PCF_CMap */ FT_Pointer init_data ) { - PCF_CMap cmap = (PCF_CMap)pcfcmap; - PCF_Face face = (PCF_Face)FT_CMAP_FACE( pcfcmap ); + PCF_CMap pcfcmap = (PCF_CMap)cmap; + PCF_Face face = (PCF_Face)FT_CMAP_FACE( cmap ); FT_UNUSED( init_data ); - cmap->enc = &face->enc; + pcfcmap->enc = &face->enc; return FT_Err_Ok; } FT_CALLBACK_DEF( void ) - pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */ + pcf_cmap_done( FT_CMap cmap ) /* PCF_CMap */ { - PCF_CMap cmap = (PCF_CMap)pcfcmap; + PCF_CMap pcfcmap = (PCF_CMap)cmap; - cmap->enc = NULL; + pcfcmap->enc = NULL; } FT_CALLBACK_DEF( FT_UInt ) - pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */ + pcf_cmap_char_index( FT_CMap cmap, /* PCF_CMap */ FT_UInt32 charcode ) { - PCF_Enc enc = ( (PCF_CMap)pcfcmap )->enc; + PCF_Enc enc = ( (PCF_CMap)cmap )->enc; FT_UInt32 i = ( charcode >> 8 ) - enc->firstRow; FT_UInt32 j = ( charcode & 0xFF ) - enc->firstCol; @@ -121,10 +121,10 @@ THE SOFTWARE. FT_CALLBACK_DEF( FT_UInt ) - pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */ + pcf_cmap_char_next( FT_CMap cmap, /* PCF_CMap */ FT_UInt32 *acharcode ) { - PCF_Enc enc = ( (PCF_CMap)pcfcmap )->enc; + PCF_Enc enc = ( (PCF_CMap)cmap )->enc; FT_UInt32 charcode = *acharcode + 1; FT_UInt32 i = ( charcode >> 8 ) - enc->firstRow; @@ -170,9 +170,9 @@ THE SOFTWARE. FT_CALLBACK_DEF( void ) - PCF_Face_Done( FT_Face pcfface ) /* PCF_Face */ + PCF_Face_Done( FT_Face face ) /* PCF_Face */ { - PCF_Face face = (PCF_Face)pcfface; + PCF_Face pcfface = (PCF_Face)face; FT_Memory memory; @@ -181,18 +181,18 @@ THE SOFTWARE. memory = FT_FACE_MEMORY( face ); - FT_FREE( face->metrics ); - FT_FREE( face->enc.offset ); + FT_FREE( pcfface->metrics ); + FT_FREE( pcfface->enc.offset ); /* free properties */ - if ( face->properties ) + if ( pcfface->properties ) { FT_Int i; - for ( i = 0; i < face->nprops; i++ ) + for ( i = 0; i < pcfface->nprops; i++ ) { - PCF_Property prop = &face->properties[i]; + PCF_Property prop = &pcfface->properties[i]; if ( prop ) @@ -203,33 +203,33 @@ THE SOFTWARE. } } - FT_FREE( face->properties ); + FT_FREE( pcfface->properties ); } - FT_FREE( face->toc.tables ); - FT_FREE( pcfface->family_name ); - FT_FREE( pcfface->style_name ); - FT_FREE( pcfface->available_sizes ); - FT_FREE( face->charset_encoding ); - FT_FREE( face->charset_registry ); + FT_FREE( pcfface->toc.tables ); + FT_FREE( face->family_name ); + FT_FREE( face->style_name ); + FT_FREE( face->available_sizes ); + FT_FREE( pcfface->charset_encoding ); + FT_FREE( pcfface->charset_registry ); /* close compressed stream if any */ - if ( pcfface->stream == &face->comp_stream ) + if ( face->stream == &pcfface->comp_stream ) { - FT_Stream_Close( &face->comp_stream ); - pcfface->stream = face->comp_source; + FT_Stream_Close( &pcfface->comp_stream ); + face->stream = pcfface->comp_source; } } FT_CALLBACK_DEF( FT_Error ) PCF_Face_Init( FT_Stream stream, - FT_Face pcfface, /* PCF_Face */ + FT_Face face, /* PCF_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { - PCF_Face face = (PCF_Face)pcfface; + PCF_Face pcfface = (PCF_Face)face; FT_Error error; FT_UNUSED( num_params ); @@ -238,10 +238,10 @@ THE SOFTWARE. FT_TRACE2(( "PCF driver\n" )); - error = pcf_load_font( stream, face, face_index ); + error = pcf_load_font( stream, pcfface, face_index ); if ( error ) { - PCF_Face_Done( pcfface ); + PCF_Face_Done( face ); #if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \ defined( FT_CONFIG_OPTION_USE_LZW ) || \ @@ -254,7 +254,7 @@ THE SOFTWARE. /* this didn't work, try gzip support! */ FT_TRACE2(( " ... try gzip stream\n" )); - error2 = FT_Stream_OpenGzip( &face->comp_stream, stream ); + error2 = FT_Stream_OpenGzip( &pcfface->comp_stream, stream ); if ( FT_ERR_EQ( error2, Unimplemented_Feature ) ) goto Fail; @@ -270,7 +270,7 @@ THE SOFTWARE. /* this didn't work, try LZW support! */ FT_TRACE2(( " ... try LZW stream\n" )); - error3 = FT_Stream_OpenLZW( &face->comp_stream, stream ); + error3 = FT_Stream_OpenLZW( &pcfface->comp_stream, stream ); if ( FT_ERR_EQ( error3, Unimplemented_Feature ) ) goto Fail; @@ -286,7 +286,7 @@ THE SOFTWARE. /* this didn't work, try Bzip2 support! */ FT_TRACE2(( " ... try Bzip2 stream\n" )); - error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream ); + error4 = FT_Stream_OpenBzip2( &pcfface->comp_stream, stream ); if ( FT_ERR_EQ( error4, Unimplemented_Feature ) ) goto Fail; @@ -297,12 +297,12 @@ THE SOFTWARE. if ( error ) goto Fail; - face->comp_source = stream; - pcfface->stream = &face->comp_stream; + pcfface->comp_source = stream; + face->stream = &pcfface->comp_stream; - stream = pcfface->stream; + stream = face->stream; - error = pcf_load_font( stream, face, face_index ); + error = pcf_load_font( stream, pcfface, face_index ); if ( error ) goto Fail; @@ -326,14 +326,14 @@ THE SOFTWARE. else if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 ) { FT_ERROR(( "PCF_Face_Init: invalid face index\n" )); - PCF_Face_Done( pcfface ); + PCF_Face_Done( face ); return FT_THROW( Invalid_Argument ); } /* set up charmap */ { - FT_String *charset_registry = face->charset_registry; - FT_String *charset_encoding = face->charset_encoding; + FT_String *charset_registry = pcfface->charset_registry; + FT_String *charset_encoding = pcfface->charset_encoding; FT_Bool unicode_charmap = 0; @@ -349,13 +349,13 @@ THE SOFTWARE. ( s[2] == 'o' || s[2] == 'O' ) ) { s += 3; - if ( !ft_strcmp( s, "10646" ) || - ( !ft_strcmp( s, "8859" ) && - !ft_strcmp( face->charset_encoding, "1" ) ) ) + if ( !ft_strcmp( s, "10646" ) || + ( !ft_strcmp( s, "8859" ) && + !ft_strcmp( pcfface->charset_encoding, "1" ) ) ) unicode_charmap = 1; /* another name for ASCII */ - else if ( !ft_strcmp( s, "646.1991" ) && - !ft_strcmp( face->charset_encoding, "IRV" ) ) + else if ( !ft_strcmp( s, "646.1991" ) && + !ft_strcmp( pcfface->charset_encoding, "IRV" ) ) unicode_charmap = 1; } } @@ -364,7 +364,7 @@ THE SOFTWARE. FT_CharMapRec charmap; - charmap.face = FT_FACE( face ); + charmap.face = face; charmap.encoding = FT_ENCODING_NONE; /* initial platform/encoding should indicate unset status? */ charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; @@ -386,7 +386,7 @@ THE SOFTWARE. Fail: FT_TRACE2(( " not a PCF file\n" )); - PCF_Face_Done( pcfface ); + PCF_Face_Done( face ); error = FT_THROW( Unknown_File_Format ); /* error */ goto Exit; } @@ -569,15 +569,16 @@ THE SOFTWARE. * */ - static FT_Error - pcf_get_bdf_property( PCF_Face face, + FT_CALLBACK_DEF( FT_Error ) + pcf_get_bdf_property( FT_Face face, /* PCF_Face */ const char* prop_name, BDF_PropertyRec *aproperty ) { + PCF_Face pcfface = (PCF_Face)face; PCF_Property prop; - prop = pcf_find_property( face, prop_name ); + prop = pcf_find_property( pcfface, prop_name ); if ( prop ) { if ( prop->isString ) @@ -611,13 +612,16 @@ THE SOFTWARE. } - static FT_Error - pcf_get_charset_id( PCF_Face face, + FT_CALLBACK_DEF( FT_Error ) + pcf_get_charset_id( FT_Face face, /* PCF_Face */ const char* *acharset_encoding, const char* *acharset_registry ) { - *acharset_encoding = face->charset_encoding; - *acharset_registry = face->charset_registry; + PCF_Face pcfface = (PCF_Face)face; + + + *acharset_encoding = pcfface->charset_encoding; + *acharset_registry = pcfface->charset_registry; return FT_Err_Ok; } @@ -634,7 +638,7 @@ THE SOFTWARE. * PROPERTY SERVICE * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) pcf_property_set( FT_Module module, /* PCF_Driver */ const char* property_name, const void* value, @@ -695,10 +699,10 @@ THE SOFTWARE. } - static FT_Error + FT_CALLBACK_DEF( FT_Error ) pcf_property_get( FT_Module module, /* PCF_Driver */ const char* property_name, - const void* value ) + void* value ) { #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES diff --git a/src/3rdparty/freetype/src/pfr/pfrcmap.c b/src/3rdparty/freetype/src/pfr/pfrcmap.c index 312a9ffe..08fe41d5 100644 --- a/src/3rdparty/freetype/src/pfr/pfrcmap.c +++ b/src/3rdparty/freetype/src/pfr/pfrcmap.c @@ -24,17 +24,18 @@ FT_CALLBACK_DEF( FT_Error ) - pfr_cmap_init( PFR_CMap cmap, + pfr_cmap_init( FT_CMap cmap, /* PFR_CMap */ FT_Pointer pointer ) { - FT_Error error = FT_Err_Ok; - PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); + PFR_CMap pfrcmap = (PFR_CMap)cmap; + FT_Error error = FT_Err_Ok; + PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); FT_UNUSED( pointer ); - cmap->num_chars = face->phy_font.num_chars; - cmap->chars = face->phy_font.chars; + pfrcmap->num_chars = face->phy_font.num_chars; + pfrcmap->chars = face->phy_font.chars; /* just for safety, check that the character entries are correctly */ /* sorted in increasing character code order */ @@ -42,9 +43,9 @@ FT_UInt n; - for ( n = 1; n < cmap->num_chars; n++ ) + for ( n = 1; n < pfrcmap->num_chars; n++ ) { - if ( cmap->chars[n - 1].char_code >= cmap->chars[n].char_code ) + if ( pfrcmap->chars[n - 1].char_code >= pfrcmap->chars[n].char_code ) { error = FT_THROW( Invalid_Table ); goto Exit; @@ -58,26 +59,30 @@ FT_CALLBACK_DEF( void ) - pfr_cmap_done( PFR_CMap cmap ) + pfr_cmap_done( FT_CMap cmap ) /* PFR_CMap */ { - cmap->chars = NULL; - cmap->num_chars = 0; + PFR_CMap pfrcmap = (PFR_CMap)cmap; + + + pfrcmap->chars = NULL; + pfrcmap->num_chars = 0; } FT_CALLBACK_DEF( FT_UInt ) - pfr_cmap_char_index( PFR_CMap cmap, + pfr_cmap_char_index( FT_CMap cmap, /* PFR_CMap */ FT_UInt32 char_code ) { - FT_UInt min = 0; - FT_UInt max = cmap->num_chars; - FT_UInt mid = min + ( max - min ) / 2; + PFR_CMap pfrcmap = (PFR_CMap)cmap; + FT_UInt min = 0; + FT_UInt max = pfrcmap->num_chars; + FT_UInt mid = min + ( max - min ) / 2; PFR_Char gchar; while ( min < max ) { - gchar = cmap->chars + mid; + gchar = pfrcmap->chars + mid; if ( gchar->char_code == char_code ) return mid + 1; @@ -96,10 +101,11 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - pfr_cmap_char_next( PFR_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + pfr_cmap_char_next( FT_CMap cmap, /* PFR_CMap */ FT_UInt32 *pchar_code ) { + PFR_CMap pfrcmap = (PFR_CMap)cmap; FT_UInt result = 0; FT_UInt32 char_code = *pchar_code + 1; @@ -107,14 +113,14 @@ Restart: { FT_UInt min = 0; - FT_UInt max = cmap->num_chars; + FT_UInt max = pfrcmap->num_chars; FT_UInt mid = min + ( max - min ) / 2; PFR_Char gchar; while ( min < max ) { - gchar = cmap->chars + mid; + gchar = pfrcmap->chars + mid; if ( gchar->char_code == char_code ) { @@ -143,9 +149,9 @@ /* we didn't find it, but we have a pair just above it */ char_code = 0; - if ( min < cmap->num_chars ) + if ( min < pfrcmap->num_chars ) { - gchar = cmap->chars + min; + gchar = pfrcmap->chars + min; result = min; if ( result != 0 ) { diff --git a/src/3rdparty/freetype/src/pfr/pfrdrivr.c b/src/3rdparty/freetype/src/pfr/pfrdrivr.c index 78c6c688..0048f524 100644 --- a/src/3rdparty/freetype/src/pfr/pfrdrivr.c +++ b/src/3rdparty/freetype/src/pfr/pfrdrivr.c @@ -27,16 +27,16 @@ FT_CALLBACK_DEF( FT_Error ) - pfr_get_kerning( FT_Face pfrface, /* PFR_Face */ + pfr_get_kerning( FT_Face face, /* PFR_Face */ FT_UInt left, FT_UInt right, FT_Vector *avector ) { - PFR_Face face = (PFR_Face)pfrface; - PFR_PhyFont phys = &face->phy_font; + PFR_Face pfrface = (PFR_Face)face; + PFR_PhyFont phys = &pfrface->phy_font; - (void)pfr_face_get_kerning( pfrface, left, right, avector ); + (void)pfr_face_get_kerning( face, left, right, avector ); /* convert from metrics to outline units when necessary */ if ( phys->outline_resolution != phys->metrics_resolution ) @@ -62,12 +62,12 @@ */ FT_CALLBACK_DEF( FT_Error ) - pfr_get_advance( FT_Face pfrface, /* PFR_Face */ + pfr_get_advance( FT_Face face, /* PFR_Face */ FT_UInt gindex, FT_Pos *anadvance ) { - PFR_Face face = (PFR_Face)pfrface; - FT_Error error = FT_ERR( Invalid_Argument ); + PFR_Face pfrface = (PFR_Face)face; + FT_Error error = FT_ERR( Invalid_Argument ); *anadvance = 0; @@ -77,9 +77,9 @@ gindex--; - if ( face ) + if ( pfrface ) { - PFR_PhyFont phys = &face->phy_font; + PFR_PhyFont phys = &pfrface->phy_font; if ( gindex < phys->num_chars ) @@ -95,16 +95,16 @@ FT_CALLBACK_DEF( FT_Error ) - pfr_get_metrics( FT_Face pfrface, /* PFR_Face */ + pfr_get_metrics( FT_Face face, /* PFR_Face */ FT_UInt *anoutline_resolution, FT_UInt *ametrics_resolution, FT_Fixed *ametrics_x_scale, FT_Fixed *ametrics_y_scale ) { - PFR_Face face = (PFR_Face)pfrface; - PFR_PhyFont phys = &face->phy_font; + PFR_Face pfrface = (PFR_Face)face; + PFR_PhyFont phys = &pfrface->phy_font; FT_Fixed x_scale, y_scale; - FT_Size size = face->root.size; + FT_Size size = pfrface->root.size; if ( anoutline_resolution ) diff --git a/src/3rdparty/freetype/src/pfr/pfrgload.c b/src/3rdparty/freetype/src/pfr/pfrgload.c index 14f2ec37..48cf27ec 100644 --- a/src/3rdparty/freetype/src/pfr/pfrgload.c +++ b/src/3rdparty/freetype/src/pfr/pfrgload.c @@ -560,8 +560,7 @@ FT_Byte* limit ) { FT_Error error = FT_Err_Ok; - FT_GlyphLoader loader = glyph->loader; - FT_Memory memory = loader->memory; + FT_Memory memory = glyph->loader->memory; PFR_SubGlyph subglyph; FT_UInt flags, i, count, org_count; FT_Int x_pos, y_pos; diff --git a/src/3rdparty/freetype/src/pfr/pfrload.c b/src/3rdparty/freetype/src/pfr/pfrload.c index de85ee6a..856a5942 100644 --- a/src/3rdparty/freetype/src/pfr/pfrload.c +++ b/src/3rdparty/freetype/src/pfr/pfrload.c @@ -449,15 +449,16 @@ /* load bitmap strikes lists */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_bitmap_info( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_bitmap_info( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { - FT_Memory memory = phy_font->memory; - PFR_Strike strike; - FT_UInt flags0; - FT_UInt n, count, size1; - FT_Error error = FT_Err_Ok; + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; + FT_Memory memory = phy_font->memory; + PFR_Strike strike; + FT_UInt flags0; + FT_UInt n, count, size1; + FT_Error error = FT_Err_Ok; PFR_CHECK( 5 ); @@ -549,13 +550,14 @@ * family. */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_font_id( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_font_id( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { - FT_Error error = FT_Err_Ok; - FT_Memory memory = phy_font->memory; - FT_UInt len = (FT_UInt)( limit - p ); + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; + FT_Error error = FT_Err_Ok; + FT_Memory memory = phy_font->memory; + FT_UInt len = (FT_UInt)( limit - p ); if ( phy_font->font_id ) @@ -575,14 +577,15 @@ /* load stem snap tables */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_stem_snaps( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_stem_snaps( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { - FT_UInt count, num_vert, num_horz; - FT_Int* snaps = NULL; - FT_Error error = FT_Err_Ok; - FT_Memory memory = phy_font->memory; + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; + FT_UInt count, num_vert, num_horz; + FT_Int* snaps = NULL; + FT_Error error = FT_Err_Ok; + FT_Memory memory = phy_font->memory; if ( phy_font->vertical.stem_snaps ) @@ -619,10 +622,11 @@ /* load kerning pair data */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_kerning_pairs( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_kerning_pairs( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; PFR_KernItem item = NULL; FT_Error error = FT_Err_Ok; FT_Memory memory = phy_font->memory; @@ -715,10 +719,10 @@ static const PFR_ExtraItemRec pfr_phy_font_extra_items[] = { - { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info }, - { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id }, - { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps }, - { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs }, + { 1, pfr_extra_item_load_bitmap_info }, + { 2, pfr_extra_item_load_font_id }, + { 3, pfr_extra_item_load_stem_snaps }, + { 4, pfr_extra_item_load_kerning_pairs }, { 0, NULL } }; diff --git a/src/3rdparty/freetype/src/pfr/pfrobjs.c b/src/3rdparty/freetype/src/pfr/pfrobjs.c index 3db8f0a0..8ef17c66 100644 --- a/src/3rdparty/freetype/src/pfr/pfrobjs.c +++ b/src/3rdparty/freetype/src/pfr/pfrobjs.c @@ -50,14 +50,14 @@ if ( !face ) return; - memory = pfrface->driver->root.memory; + memory = pfrface->memory; /* we don't want dangling pointers */ pfrface->family_name = NULL; pfrface->style_name = NULL; /* finalize the physical font record */ - pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) ); + pfr_phy_font_done( &face->phy_font, memory ); /* no need to finalize the logical font or the header */ FT_FREE( pfrface->available_sizes ); @@ -214,7 +214,7 @@ FT_UInt n, count = phy_font->num_strikes; FT_Bitmap_Size* size; PFR_Strike strike; - FT_Memory memory = pfrface->stream->memory; + FT_Memory memory = pfrface->memory; if ( FT_QNEW_ARRAY( pfrface->available_sizes, count ) ) diff --git a/src/3rdparty/freetype/src/psaux/afmparse.c b/src/3rdparty/freetype/src/psaux/afmparse.c index 68f95698..db08941d 100644 --- a/src/3rdparty/freetype/src/psaux/afmparse.c +++ b/src/3rdparty/freetype/src/psaux/afmparse.c @@ -1086,7 +1086,7 @@ #else /* T1_CONFIG_OPTION_NO_AFM */ /* ANSI C doesn't like empty source files */ - typedef int _afm_parse_dummy; + typedef int afm_parse_dummy_; #endif /* T1_CONFIG_OPTION_NO_AFM */ diff --git a/src/3rdparty/freetype/src/psaux/cffdecode.c b/src/3rdparty/freetype/src/psaux/cffdecode.c index 2cd91c96..562d17d2 100644 --- a/src/3rdparty/freetype/src/psaux/cffdecode.c +++ b/src/3rdparty/freetype/src/psaux/cffdecode.c @@ -2153,7 +2153,7 @@ decoder->locals_bias ); - FT_TRACE4(( " callsubr (idx %d, entering level %ld)\n", + FT_TRACE4(( " callsubr (idx %d, entering level %td)\n", idx, zone - decoder->zones + 1 )); @@ -2197,7 +2197,7 @@ decoder->globals_bias ); - FT_TRACE4(( " callgsubr (idx %d, entering level %ld)\n", + FT_TRACE4(( " callgsubr (idx %d, entering level %td)\n", idx, zone - decoder->zones + 1 )); @@ -2236,7 +2236,7 @@ break; case cff_op_return: - FT_TRACE4(( " return (leaving level %ld)\n", + FT_TRACE4(( " return (leaving level %td)\n", decoder->zone - decoder->zones )); if ( decoder->zone <= decoder->zones ) diff --git a/src/3rdparty/freetype/src/psaux/pshints.c b/src/3rdparty/freetype/src/psaux/pshints.c index 6f44d0ad..7bd08a9c 100644 --- a/src/3rdparty/freetype/src/psaux/pshints.c +++ b/src/3rdparty/freetype/src/psaux/pshints.c @@ -310,7 +310,7 @@ CF2_Hint hint = &hintmap->edge[i]; - FT_TRACE6(( " %3ld %7.2f %7.2f %5d %s%s%s%s\n", + FT_TRACE6(( " %3zu %7.2f %7.2f %5d %s%s%s%s\n", hint->index, hint->csCoord / 65536.0, hint->dsCoord / ( hint->scale * 1.0 ), diff --git a/src/3rdparty/freetype/src/psaux/t1cmap.c b/src/3rdparty/freetype/src/psaux/t1cmap.c index bf0a393b..c4bcf599 100644 --- a/src/3rdparty/freetype/src/psaux/t1cmap.c +++ b/src/3rdparty/freetype/src/psaux/t1cmap.c @@ -50,8 +50,11 @@ FT_CALLBACK_DEF( void ) - t1_cmap_std_done( T1_CMapStd cmap ) + t1_cmap_std_done( FT_CMap cmap_ ) /* T1_CMapStd */ { + T1_CMapStd cmap = (T1_CMapStd)cmap_; + + cmap->num_glyphs = 0; cmap->glyph_names = NULL; cmap->sid_to_string = NULL; @@ -60,10 +63,11 @@ FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_std_char_index( T1_CMapStd cmap, - FT_UInt32 char_code ) + t1_cmap_std_char_index( FT_CMap cmap, /* T1_CMapStd */ + FT_UInt32 char_code ) { - FT_UInt result = 0; + T1_CMapStd t1cmap = (T1_CMapStd)cmap; + FT_UInt result = 0; if ( char_code < 256 ) @@ -73,13 +77,13 @@ /* convert character code to Adobe SID string */ - code = cmap->code_to_sid[char_code]; - glyph_name = cmap->sid_to_string( code ); + code = t1cmap->code_to_sid[char_code]; + glyph_name = t1cmap->sid_to_string( code ); /* look for the corresponding glyph name */ - for ( n = 0; n < cmap->num_glyphs; n++ ) + for ( n = 0; n < t1cmap->num_glyphs; n++ ) { - const char* gname = cmap->glyph_names[n]; + const char* gname = t1cmap->glyph_names[n]; if ( gname && gname[0] == glyph_name[0] && @@ -95,9 +99,9 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_std_char_next( T1_CMapStd cmap, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_std_char_next( FT_CMap cmap, + FT_UInt32 *pchar_code ) { FT_UInt result = 0; FT_UInt32 char_code = *pchar_code + 1; @@ -120,13 +124,14 @@ FT_CALLBACK_DEF( FT_Error ) - t1_cmap_standard_init( T1_CMapStd cmap, + t1_cmap_standard_init( FT_CMap cmap, /* T1_CMapStd */ FT_Pointer pointer ) { + T1_CMapStd t1cmap = (T1_CMapStd)cmap; FT_UNUSED( pointer ); - t1_cmap_std_init( cmap, 0 ); + t1_cmap_std_init( t1cmap, 0 ); return 0; } @@ -150,13 +155,14 @@ FT_CALLBACK_DEF( FT_Error ) - t1_cmap_expert_init( T1_CMapStd cmap, + t1_cmap_expert_init( FT_CMap cmap, /* T1_CMapStd */ FT_Pointer pointer ) { + T1_CMapStd t1cmap = (T1_CMapStd)cmap; FT_UNUSED( pointer ); - t1_cmap_std_init( cmap, 1 ); + t1_cmap_std_init( t1cmap, 1 ); return 0; } @@ -188,20 +194,21 @@ FT_CALLBACK_DEF( FT_Error ) - t1_cmap_custom_init( T1_CMapCustom cmap, - FT_Pointer pointer ) + t1_cmap_custom_init( FT_CMap cmap, /* T1_CMapCustom */ + FT_Pointer pointer ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); - T1_Encoding encoding = &face->type1.encoding; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + T1_Encoding encoding = &face->type1.encoding; FT_UNUSED( pointer ); - cmap->first = (FT_UInt)encoding->code_first; - cmap->count = (FT_UInt)encoding->code_last - cmap->first; - cmap->indices = encoding->char_index; + t1cmap->first = (FT_UInt)encoding->code_first; + t1cmap->count = (FT_UInt)encoding->code_last - t1cmap->first; + t1cmap->indices = encoding->char_index; - FT_ASSERT( cmap->indices ); + FT_ASSERT( t1cmap->indices ); FT_ASSERT( encoding->code_first <= encoding->code_last ); return 0; @@ -209,45 +216,50 @@ FT_CALLBACK_DEF( void ) - t1_cmap_custom_done( T1_CMapCustom cmap ) + t1_cmap_custom_done( FT_CMap cmap ) /* T1_CMapCustom */ { - cmap->indices = NULL; - cmap->first = 0; - cmap->count = 0; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + + + t1cmap->indices = NULL; + t1cmap->first = 0; + t1cmap->count = 0; } FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_custom_char_index( T1_CMapCustom cmap, - FT_UInt32 char_code ) + t1_cmap_custom_char_index( FT_CMap cmap, /* T1_CMapCustom */ + FT_UInt32 char_code ) { - FT_UInt result = 0; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + FT_UInt result = 0; - if ( ( char_code >= cmap->first ) && - ( char_code < ( cmap->first + cmap->count ) ) ) - result = cmap->indices[char_code]; + if ( char_code >= t1cmap->first && + char_code < ( t1cmap->first + t1cmap->count ) ) + result = t1cmap->indices[char_code]; return result; } - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_custom_char_next( T1_CMapCustom cmap, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_custom_char_next( FT_CMap cmap, /* T1_CMapCustom */ + FT_UInt32 *pchar_code ) { - FT_UInt result = 0; - FT_UInt32 char_code = *pchar_code; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code; char_code++; - if ( char_code < cmap->first ) - char_code = cmap->first; + if ( char_code < t1cmap->first ) + char_code = t1cmap->first; - for ( ; char_code < ( cmap->first + cmap->count ); char_code++ ) + for ( ; char_code < ( t1cmap->first + t1cmap->count ); char_code++ ) { - result = cmap->indices[char_code]; + result = t1cmap->indices[char_code]; if ( result != 0 ) goto Exit; } @@ -287,20 +299,24 @@ /*************************************************************************/ FT_CALLBACK_DEF( const char * ) - psaux_get_glyph_name( T1_Face face, + psaux_get_glyph_name( void* face_, FT_UInt idx ) { + T1_Face face = (T1_Face)face_; + + return face->type1.glyph_names[idx]; } FT_CALLBACK_DEF( FT_Error ) - t1_cmap_unicode_init( PS_Unicodes unicodes, - FT_Pointer pointer ) + t1_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ + FT_Pointer pointer ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; FT_UNUSED( pointer ); @@ -311,17 +327,18 @@ return psnames->unicodes_init( memory, unicodes, (FT_UInt)face->type1.num_glyphs, - (PS_GetGlyphNameFunc)&psaux_get_glyph_name, + &psaux_get_glyph_name, (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } FT_CALLBACK_DEF( void ) - t1_cmap_unicode_done( PS_Unicodes unicodes ) + t1_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Unicodes unicodes = (PS_Unicodes)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( unicodes->maps ); @@ -330,23 +347,25 @@ FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) + t1_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 char_code ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_index( unicodes, char_code ); } - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 *pchar_code ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_next( unicodes, pchar_code ); diff --git a/src/3rdparty/freetype/src/psaux/t1decode.c b/src/3rdparty/freetype/src/psaux/t1decode.c index bfed45b5..4b6b969b 100644 --- a/src/3rdparty/freetype/src/psaux/t1decode.c +++ b/src/3rdparty/freetype/src/psaux/t1decode.c @@ -520,7 +520,7 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( bol ) { - FT_TRACE5(( " (%ld)", decoder->top - decoder->stack )); + FT_TRACE5(( " (%td)", decoder->top - decoder->stack )); bol = FALSE; } #endif @@ -1165,7 +1165,7 @@ if ( top - decoder->stack != num_args ) FT_TRACE0(( "t1_decoder_parse_charstrings:" " too much operands on the stack" - " (seen %ld, expected %d)\n", + " (seen %td, expected %d)\n", top - decoder->stack, num_args )); break; } diff --git a/src/3rdparty/freetype/src/pshinter/pshalgo.c b/src/3rdparty/freetype/src/pshinter/pshalgo.c index a7f32129..4f622e1e 100644 --- a/src/3rdparty/freetype/src/pshinter/pshalgo.c +++ b/src/3rdparty/freetype/src/pshinter/pshalgo.c @@ -516,7 +516,7 @@ if ( !psh_hint_is_fitted( parent ) ) psh_hint_align( parent, globals, dimension, glyph ); - /* keep original relation between hints, this is, use the */ + /* keep original relation between hints, that is, use the */ /* scaled distance between the centers of the hints to */ /* compute the new position */ par_org_center = parent->org_pos + ( parent->org_len >> 1 ); diff --git a/src/3rdparty/freetype/src/pshinter/pshmod.c b/src/3rdparty/freetype/src/pshinter/pshmod.c index a12e4856..974a99e0 100644 --- a/src/3rdparty/freetype/src/pshinter/pshmod.c +++ b/src/3rdparty/freetype/src/pshinter/pshmod.c @@ -37,8 +37,11 @@ /* finalize module */ FT_CALLBACK_DEF( void ) - ps_hinter_done( PS_Hinter_Module module ) + ps_hinter_done( FT_Module module_ ) /* PS_Hinter_Module */ { + PS_Hinter_Module module = (PS_Hinter_Module)module_; + + module->t1_funcs.hints = NULL; module->t2_funcs.hints = NULL; @@ -48,8 +51,10 @@ /* initialize module, create hints recorder and the interface */ FT_CALLBACK_DEF( FT_Error ) - ps_hinter_init( PS_Hinter_Module module ) + ps_hinter_init( FT_Module module_ ) /* PS_Hinter_Module */ { + PS_Hinter_Module module = (PS_Hinter_Module)module_; + FT_Memory memory = module->root.memory; void* ph = &module->ps_hints; diff --git a/src/3rdparty/freetype/src/pshinter/pshrec.c b/src/3rdparty/freetype/src/pshinter/pshrec.c index 58c8cf1b..680e6d01 100644 --- a/src/3rdparty/freetype/src/pshinter/pshrec.c +++ b/src/3rdparty/freetype/src/pshinter/pshrec.c @@ -851,10 +851,11 @@ /* add one Type1 counter stem to the current hints table */ static void - ps_hints_t1stem3( PS_Hints hints, + ps_hints_t1stem3( T1_Hints hints_, /* PS_Hints */ FT_UInt dimension, FT_Fixed* stems ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error = FT_Err_Ok; @@ -914,9 +915,10 @@ /* reset hints (only with Type 1 hints) */ static void - ps_hints_t1reset( PS_Hints hints, + ps_hints_t1reset( T1_Hints hints_, /* PS_Hints */ FT_UInt end_point ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error = FT_Err_Ok; @@ -953,11 +955,12 @@ /* Type2 "hintmask" operator, add a new hintmask to each direction */ static void - ps_hints_t2mask( PS_Hints hints, + ps_hints_t2mask( T2_Hints hints_, /* PS_Hints */ FT_UInt end_point, FT_UInt bit_count, const FT_Byte* bytes ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error; @@ -999,10 +1002,11 @@ static void - ps_hints_t2counter( PS_Hints hints, + ps_hints_t2counter( T2_Hints hints_, /* PS_Hints */ FT_UInt bit_count, const FT_Byte* bytes ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error; @@ -1087,6 +1091,13 @@ ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 ); } + static FT_Error + t1_hints_close( T1_Hints hints, + FT_UInt end_point ) + { + return ps_hints_close( (PS_Hints)hints, end_point ); + } + static void t1_hints_stem( T1_Hints hints, FT_UInt dimension, @@ -1102,17 +1113,27 @@ } + static FT_Error + t1_hints_apply( T1_Hints hints, + FT_Outline* outline, + PSH_Globals globals, + FT_Render_Mode hint_mode ) + { + return ps_hints_apply( (PS_Hints)hints, outline, globals, hint_mode ); + } + + FT_LOCAL_DEF( void ) t1_hints_funcs_init( T1_Hints_FuncsRec* funcs ) { FT_ZERO( funcs ); funcs->open = (T1_Hints_OpenFunc) t1_hints_open; - funcs->close = (T1_Hints_CloseFunc) ps_hints_close; + funcs->close = (T1_Hints_CloseFunc) t1_hints_close; funcs->stem = (T1_Hints_SetStemFunc) t1_hints_stem; funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3; funcs->reset = (T1_Hints_ResetFunc) ps_hints_t1reset; - funcs->apply = (T1_Hints_ApplyFunc) ps_hints_apply; + funcs->apply = (T1_Hints_ApplyFunc) t1_hints_apply; } @@ -1131,6 +1152,14 @@ } + static FT_Error + t2_hints_close( T2_Hints hints, + FT_UInt end_point ) + { + return ps_hints_close( (PS_Hints)hints, end_point ); + } + + static void t2_hints_stems( T2_Hints hints, FT_UInt dimension, @@ -1168,17 +1197,27 @@ } + static FT_Error + t2_hints_apply( T2_Hints hints, + FT_Outline* outline, + PSH_Globals globals, + FT_Render_Mode hint_mode ) + { + return ps_hints_apply( (PS_Hints)hints, outline, globals, hint_mode ); + } + + FT_LOCAL_DEF( void ) t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ) { FT_ZERO( funcs ); - funcs->open = (T2_Hints_OpenFunc) t2_hints_open; - funcs->close = (T2_Hints_CloseFunc) ps_hints_close; - funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems; - funcs->hintmask= (T2_Hints_MaskFunc) ps_hints_t2mask; - funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter; - funcs->apply = (T2_Hints_ApplyFunc) ps_hints_apply; + funcs->open = (T2_Hints_OpenFunc) t2_hints_open; + funcs->close = (T2_Hints_CloseFunc) t2_hints_close; + funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems; + funcs->hintmask = (T2_Hints_MaskFunc) ps_hints_t2mask; + funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter; + funcs->apply = (T2_Hints_ApplyFunc) t2_hints_apply; } diff --git a/src/3rdparty/freetype/src/psnames/psmodule.c b/src/3rdparty/freetype/src/psnames/psmodule.c index db454e55..8203a046 100644 --- a/src/3rdparty/freetype/src/psnames/psmodule.c +++ b/src/3rdparty/freetype/src/psnames/psmodule.c @@ -57,7 +57,7 @@ /* the name, as in `A.swash' or `e.final'; in this case, the */ /* VARIANT_BIT is set in the return value. */ /* */ - static FT_UInt32 + FT_CALLBACK_DEF( FT_UInt32 ) ps_unicode_value( const char* glyph_name ) { /* If the name begins with `uni', then the glyph name may be a */ @@ -309,7 +309,7 @@ /* Build a table that maps Unicode values to glyph indices. */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) ps_unicodes_init( FT_Memory memory, PS_Unicodes table, FT_UInt num_glyphs, @@ -408,7 +408,7 @@ } - static FT_UInt + FT_CALLBACK_DEF( FT_UInt ) ps_unicodes_char_index( PS_Unicodes table, FT_UInt32 unicode ) { @@ -453,7 +453,7 @@ } - static FT_UInt32 + FT_CALLBACK_DEF( FT_UInt ) ps_unicodes_char_next( PS_Unicodes table, FT_UInt32 *unicode ) { @@ -518,7 +518,7 @@ #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ - static const char* + FT_CALLBACK_DEF( const char* ) ps_get_macintosh_name( FT_UInt name_index ) { if ( name_index >= FT_NUM_MAC_NAMES ) @@ -528,7 +528,7 @@ } - static const char* + FT_CALLBACK_DEF( const char* ) ps_get_standard_strings( FT_UInt sid ) { if ( sid >= FT_NUM_SID_NAMES ) @@ -543,13 +543,13 @@ FT_DEFINE_SERVICE_PSCMAPSREC( pscmaps_interface, - (PS_Unicode_ValueFunc) ps_unicode_value, /* unicode_value */ - (PS_Unicodes_InitFunc) ps_unicodes_init, /* unicodes_init */ - (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, /* unicodes_char_index */ - (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, /* unicodes_char_next */ + ps_unicode_value, /* PS_Unicode_ValueFunc unicode_value */ + ps_unicodes_init, /* PS_Unicodes_InitFunc unicodes_init */ + ps_unicodes_char_index, /* PS_Unicodes_CharIndexFunc unicodes_char_index */ + ps_unicodes_char_next, /* PS_Unicodes_CharNextFunc unicodes_char_next */ - (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */ - (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */ + ps_get_macintosh_name, /* PS_Macintosh_NameFunc macintosh_name */ + ps_get_standard_strings, /* PS_Adobe_Std_StringsFunc adobe_std_strings */ t1_standard_encoding, /* adobe_std_encoding */ t1_expert_encoding /* adobe_expert_encoding */ @@ -560,13 +560,13 @@ FT_DEFINE_SERVICE_PSCMAPSREC( pscmaps_interface, - NULL, /* unicode_value */ - NULL, /* unicodes_init */ - NULL, /* unicodes_char_index */ - NULL, /* unicodes_char_next */ + NULL, /* PS_Unicode_ValueFunc unicode_value */ + NULL, /* PS_Unicodes_InitFunc unicodes_init */ + NULL, /* PS_Unicodes_CharIndexFunc unicodes_char_index */ + NULL, /* PS_Unicodes_CharNextFunc unicodes_char_next */ - (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */ - (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */ + ps_get_macintosh_name, /* PS_Macintosh_NameFunc macintosh_name */ + ps_get_standard_strings, /* PS_Adobe_Std_StringsFunc adobe_std_strings */ t1_standard_encoding, /* adobe_std_encoding */ t1_expert_encoding /* adobe_expert_encoding */ @@ -612,9 +612,9 @@ PUT_PS_NAMES_SERVICE( (void*)&pscmaps_interface ), /* module specific interface */ - (FT_Module_Constructor)NULL, /* module_init */ - (FT_Module_Destructor) NULL, /* module_done */ - (FT_Module_Requester) PUT_PS_NAMES_SERVICE( psnames_get_service ) /* get_interface */ + NULL, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + PUT_PS_NAMES_SERVICE( psnames_get_service ) /* FT_Module_Requester get_interface */ ) diff --git a/src/3rdparty/freetype/src/raster/ftraster.c b/src/3rdparty/freetype/src/raster/ftraster.c index 67cbfd5d..192ca070 100644 --- a/src/3rdparty/freetype/src/raster/ftraster.c +++ b/src/3rdparty/freetype/src/raster/ftraster.c @@ -1742,9 +1742,9 @@ * SUCCESS on success, FAILURE on error. */ static Bool - Decompose_Curve( RAS_ARGS UShort first, - UShort last, - Int flipped ) + Decompose_Curve( RAS_ARGS Int first, + Int last, + Int flipped ) { FT_Vector v_last; FT_Vector v_control; @@ -1969,8 +1969,8 @@ static Bool Convert_Glyph( RAS_ARGS Int flipped ) { - Int i; - UInt start; + Int i; + Int first, last; ras.fProfile = NULL; @@ -1985,8 +1985,7 @@ ras.cProfile->offset = ras.top; ras.num_Profs = 0; - start = 0; - + last = -1; for ( i = 0; i < ras.outline.n_contours; i++ ) { PProfile lastProfile; @@ -1996,12 +1995,11 @@ ras.state = Unknown_State; ras.gProfile = NULL; - if ( Decompose_Curve( RAS_VARS (UShort)start, - (UShort)ras.outline.contours[i], - flipped ) ) - return FAILURE; + first = last + 1; + last = ras.outline.contours[i]; - start = (UShort)ras.outline.contours[i] + 1; + if ( Decompose_Curve( RAS_VARS first, last, flipped ) ) + return FAILURE; /* we must now check whether the extreme arcs join or not */ if ( FRAC( ras.lastY ) == 0 && @@ -3167,9 +3165,12 @@ static int - ft_black_new( FT_Memory memory, - black_PRaster *araster ) + ft_black_new( void* memory_, /* FT_Memory */ + FT_Raster *araster_ ) /* black_PRaster */ { + FT_Memory memory = (FT_Memory)memory_; + black_PRaster *araster = (black_PRaster*)araster_; + FT_Error error; black_PRaster raster = NULL; @@ -3184,9 +3185,10 @@ static void - ft_black_done( black_PRaster raster ) + ft_black_done( FT_Raster raster_ ) /* black_PRaster */ { - FT_Memory memory = (FT_Memory)raster->memory; + black_PRaster raster = (black_PRaster)raster_; + FT_Memory memory = (FT_Memory)raster->memory; FT_FREE( raster ); @@ -3281,11 +3283,11 @@ FT_GLYPH_FORMAT_OUTLINE, - (FT_Raster_New_Func) ft_black_new, /* raster_new */ - (FT_Raster_Reset_Func) ft_black_reset, /* raster_reset */ - (FT_Raster_Set_Mode_Func)ft_black_set_mode, /* raster_set_mode */ - (FT_Raster_Render_Func) ft_black_render, /* raster_render */ - (FT_Raster_Done_Func) ft_black_done /* raster_done */ + ft_black_new, /* FT_Raster_New_Func raster_new */ + ft_black_reset, /* FT_Raster_Reset_Func raster_reset */ + ft_black_set_mode, /* FT_Raster_Set_Mode_Func raster_set_mode */ + ft_black_render, /* FT_Raster_Render_Func raster_render */ + ft_black_done /* FT_Raster_Done_Func raster_done */ ) diff --git a/src/3rdparty/freetype/src/raster/ftrend1.c b/src/3rdparty/freetype/src/raster/ftrend1.c index 0b5d8671..6d442b1f 100644 --- a/src/3rdparty/freetype/src/raster/ftrend1.c +++ b/src/3rdparty/freetype/src/raster/ftrend1.c @@ -27,8 +27,11 @@ /* initialize renderer -- init its raster */ static FT_Error - ft_raster1_init( FT_Renderer render ) + ft_raster1_init( FT_Module module ) /* FT_Renderer */ { + FT_Renderer render = (FT_Renderer)module; + + render->clazz->raster_class->raster_reset( render->raster, NULL, 0 ); return FT_Err_Ok; @@ -188,18 +191,18 @@ NULL, /* module specific interface */ - (FT_Module_Constructor)ft_raster1_init, /* module_init */ - (FT_Module_Destructor) NULL, /* module_done */ - (FT_Module_Requester) NULL, /* get_interface */ + ft_raster1_init, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + NULL, /* FT_Module_Requester get_interface */ FT_GLYPH_FORMAT_OUTLINE, - (FT_Renderer_RenderFunc) ft_raster1_render, /* render_glyph */ - (FT_Renderer_TransformFunc)ft_raster1_transform, /* transform_glyph */ - (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox, /* get_glyph_cbox */ - (FT_Renderer_SetModeFunc) ft_raster1_set_mode, /* set_mode */ + ft_raster1_render, /* FT_Renderer_RenderFunc render_glyph */ + ft_raster1_transform, /* FT_Renderer_TransformFunc transform_glyph */ + ft_raster1_get_cbox, /* FT_Renderer_GetCBoxFunc get_glyph_cbox */ + ft_raster1_set_mode, /* FT_Renderer_SetModeFunc set_mode */ - (FT_Raster_Funcs*)&ft_standard_raster /* raster_class */ + &ft_standard_raster /* FT_Raster_Funcs* raster_class */ ) diff --git a/src/3rdparty/freetype/src/sdf/ftbsdf.c b/src/3rdparty/freetype/src/sdf/ftbsdf.c index 901d8b74..e4727383 100644 --- a/src/3rdparty/freetype/src/sdf/ftbsdf.c +++ b/src/3rdparty/freetype/src/sdf/ftbsdf.c @@ -1173,9 +1173,12 @@ /* called when adding a new module through @FT_Add_Module */ static FT_Error - bsdf_raster_new( FT_Memory memory, - BSDF_PRaster* araster ) + bsdf_raster_new( void* memory_, /* FT_Memory */ + FT_Raster* araster_ ) /* BSDF_PRaster* */ { + FT_Memory memory = (FT_Memory)memory_; + BSDF_PRaster* araster = (BSDF_PRaster*)araster_; + FT_Error error; BSDF_PRaster raster = NULL; diff --git a/src/3rdparty/freetype/src/sdf/ftsdf.c b/src/3rdparty/freetype/src/sdf/ftsdf.c index 26a6d00e..bc4625d9 100644 --- a/src/3rdparty/freetype/src/sdf/ftsdf.c +++ b/src/3rdparty/freetype/src/sdf/ftsdf.c @@ -2371,11 +2371,11 @@ * ``` * * (6) Our task is to find a value of `t` such that the above equation - * `Q(t)` becomes zero, this is, the point-to-curve vector makes + * `Q(t)` becomes zero, that is, the point-to-curve vector makes * 90~degrees with the curve. We solve this with the Newton-Raphson * method. * - * (7) We first assume an arbitary value of factor `t`, which we then + * (7) We first assume an arbitrary value of factor `t`, which we then * improve. * * ``` @@ -2684,11 +2684,11 @@ * ``` * * (6) Our task is to find a value of `t` such that the above equation - * `Q(t)` becomes zero, this is, the point-to-curve vector makes + * `Q(t)` becomes zero, that is, the point-to-curve vector makes * 90~degree with curve. We solve this with the Newton-Raphson * method. * - * (7) We first assume an arbitary value of factor `t`, which we then + * (7) We first assume an arbitrary value of factor `t`, which we then * improve. * * ``` @@ -2718,8 +2718,9 @@ FT_Error error = FT_Err_Ok; - FT_26D6_Vec aA, bB, cC, dD; /* A, B, C in the above comment */ - FT_16D16_Vec nearest_point; /* point on curve nearest to `point` */ + FT_26D6_Vec aA, bB, cC, dD; /* A, B, C, D in the above comment */ + FT_16D16_Vec nearest_point = { 0, 0 }; + /* point on curve nearest to `point` */ FT_16D16_Vec direction; /* direction of curve at `nearest_point` */ FT_26D6_Vec p0, p1, p2, p3; /* control points of a cubic curve */ @@ -3761,9 +3762,13 @@ */ static FT_Error - sdf_raster_new( FT_Memory memory, - SDF_PRaster* araster ) + sdf_raster_new( void* memory_, /* FT_Memory */ + FT_Raster* araster_ ) /* SDF_PRaster* */ { + FT_Memory memory = (FT_Memory)memory_; + SDF_PRaster* araster = (SDF_PRaster*)araster_; + + FT_Error error; SDF_PRaster raster = NULL; diff --git a/src/3rdparty/freetype/src/sdf/ftsdfrend.c b/src/3rdparty/freetype/src/sdf/ftsdfrend.c index 9ac7d6f6..5610c119 100644 --- a/src/3rdparty/freetype/src/sdf/ftsdfrend.c +++ b/src/3rdparty/freetype/src/sdf/ftsdfrend.c @@ -197,10 +197,10 @@ static FT_Module_Interface - ft_sdf_requester( FT_Renderer render, + ft_sdf_requester( FT_Module module, const char* module_interface ) { - FT_UNUSED( render ); + FT_UNUSED( module ); return ft_service_list_lookup( sdf_services, module_interface ); } @@ -221,9 +221,9 @@ */ static FT_Error - ft_sdf_init( FT_Renderer render ) + ft_sdf_init( FT_Module module ) /* SDF_Renderer */ { - SDF_Renderer sdf_render = SDF_RENDERER( render ); + SDF_Renderer sdf_render = SDF_RENDERER( module ); sdf_render->spread = DEFAULT_SPREAD; @@ -236,9 +236,9 @@ static void - ft_sdf_done( FT_Renderer render ) + ft_sdf_done( FT_Module module ) { - FT_UNUSED( render ); + FT_UNUSED( module ); } @@ -300,7 +300,7 @@ /* nothing to render */ if ( !bitmap->rows || !bitmap->pitch ) - return FT_Err_Ok; + goto Exit; /* the padding will simply be equal to the `spread' */ x_pad = sdf_module->spread; @@ -508,6 +508,10 @@ goto Exit; } + /* nothing to render */ + if ( !bitmap->rows || !bitmap->pitch ) + goto Exit; + /* Do not generate SDF if the bitmap is not owned by the */ /* glyph: it might be that the source buffer is already freed. */ if ( !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) @@ -519,10 +523,6 @@ goto Exit; } - /* nothing to render */ - if ( !bitmap->rows || !bitmap->pitch ) - return FT_Err_Ok; - FT_Bitmap_New( &target ); /* padding will simply be equal to `spread` */ @@ -557,15 +557,14 @@ { /* the glyph is successfully converted to a SDF */ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) - { FT_FREE( bitmap->buffer ); - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; - } - slot->bitmap = target; - slot->bitmap_top += y_pad; - slot->bitmap_left -= x_pad; - slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + slot->bitmap = target; + slot->bitmap_top += y_pad; + slot->bitmap_left -= x_pad; + + if ( target.buffer ) + slot->internal->flags |= FT_GLYPH_OWN_BITMAP; } else if ( target.buffer ) FT_FREE( target.buffer ); diff --git a/src/3rdparty/freetype/src/sfnt/pngshim.c b/src/3rdparty/freetype/src/sfnt/pngshim.c index 423b07b0..33712162 100644 --- a/src/3rdparty/freetype/src/sfnt/pngshim.c +++ b/src/3rdparty/freetype/src/sfnt/pngshim.c @@ -406,10 +406,7 @@ switch ( color_type ) { - default: - /* Shouldn't happen, but ... */ - FALL_THROUGH; - + default: /* Shouldn't happen, but ... */ case PNG_COLOR_TYPE_RGB_ALPHA: png_set_read_user_transform_fn( png, premultiply_data ); break; @@ -457,7 +454,7 @@ #else /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ /* ANSI C doesn't like empty source files */ - typedef int _pngshim_dummy; + typedef int pngshim_dummy_; #endif /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ diff --git a/src/3rdparty/freetype/src/sfnt/sfdriver.c b/src/3rdparty/freetype/src/sfnt/sfdriver.c index 762883db..0925940b 100644 --- a/src/3rdparty/freetype/src/sfnt/sfdriver.c +++ b/src/3rdparty/freetype/src/sfnt/sfdriver.c @@ -79,41 +79,57 @@ * */ - static void* - get_sfnt_table( TT_Face face, + FT_CALLBACK_DEF( FT_Error ) + sfnt_load_table( FT_Face face, /* TT_Face */ + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ) + { + TT_Face ttface = (TT_Face)face; + + + return tt_face_load_any( ttface, tag, offset, buffer, length ); + } + + + FT_CALLBACK_DEF( void* ) + get_sfnt_table( FT_Face face, /* TT_Face */ FT_Sfnt_Tag tag ) { + TT_Face ttface = (TT_Face)face; + void* table; switch ( tag ) { case FT_SFNT_HEAD: - table = &face->header; + table = &ttface->header; break; case FT_SFNT_HHEA: - table = &face->horizontal; + table = &ttface->horizontal; break; case FT_SFNT_VHEA: - table = face->vertical_info ? &face->vertical : NULL; + table = ttface->vertical_info ? &ttface->vertical : NULL; break; case FT_SFNT_OS2: - table = ( face->os2.version == 0xFFFFU ) ? NULL : &face->os2; + table = ( ttface->os2.version == 0xFFFFU ) ? NULL : &ttface->os2; break; case FT_SFNT_POST: - table = &face->postscript; + table = &ttface->postscript; break; case FT_SFNT_MAXP: - table = &face->max_profile; + table = &ttface->max_profile; break; case FT_SFNT_PCLT: - table = face->pclt.Version ? &face->pclt : NULL; + table = ttface->pclt.Version ? &ttface->pclt : NULL; break; default: @@ -124,26 +140,29 @@ } - static FT_Error - sfnt_table_info( TT_Face face, + FT_CALLBACK_DEF( FT_Error ) + sfnt_table_info( FT_Face face, /* TT_Face */ FT_UInt idx, FT_ULong *tag, FT_ULong *offset, FT_ULong *length ) { + TT_Face ttface = (TT_Face)face; + + if ( !offset || !length ) return FT_THROW( Invalid_Argument ); if ( !tag ) - *length = face->num_tables; + *length = ttface->num_tables; else { - if ( idx >= face->num_tables ) + if ( idx >= ttface->num_tables ) return FT_THROW( Table_Missing ); - *tag = face->dir_tables[idx].Tag; - *offset = face->dir_tables[idx].Offset; - *length = face->dir_tables[idx].Length; + *tag = ttface->dir_tables[idx].Tag; + *offset = ttface->dir_tables[idx].Offset; + *length = ttface->dir_tables[idx].Length; } return FT_Err_Ok; @@ -153,9 +172,9 @@ FT_DEFINE_SERVICE_SFNT_TABLEREC( sfnt_service_sfnt_table, - (FT_SFNT_TableLoadFunc)tt_face_load_any, /* load_table */ - (FT_SFNT_TableGetFunc) get_sfnt_table, /* get_table */ - (FT_SFNT_TableInfoFunc)sfnt_table_info /* table_info */ + sfnt_load_table, /* FT_SFNT_TableLoadFunc load_table */ + get_sfnt_table, /* FT_SFNT_TableGetFunc get_table */ + sfnt_table_info /* FT_SFNT_TableInfoFunc table_info */ ) @@ -166,7 +185,7 @@ * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) sfnt_get_glyph_name( FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, @@ -184,7 +203,7 @@ } - static FT_UInt + FT_CALLBACK_DEF( FT_UInt ) sfnt_get_name_index( FT_Face face, const FT_String* glyph_name ) { @@ -221,8 +240,8 @@ FT_DEFINE_SERVICE_GLYPHDICTREC( sfnt_service_glyph_dict, - (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, /* get_name */ - (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index /* name_index */ + sfnt_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ + sfnt_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ ) #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ @@ -523,15 +542,14 @@ FT_TRACE0(( "get_win_string:" " Character 0x%X invalid in PS name string\n", ((unsigned)p[0])*256 + (unsigned)p[1] )); - break; + continue; } } - if ( !len ) - *r = '\0'; + *r = '\0'; FT_FRAME_EXIT(); - if ( !len ) + if ( r != result ) return result; get_win_string_error: @@ -580,15 +598,14 @@ FT_TRACE0(( "get_apple_string:" " Character `%c' (0x%X) invalid in PS name string\n", *p, *p )); - break; + continue; } } - if ( !len ) - *r = '\0'; + *r = '\0'; FT_FRAME_EXIT(); - if ( !len ) + if ( r != result ) return result; get_apple_string_error: @@ -602,7 +619,7 @@ } - static FT_Bool + FT_CALLBACK_DEF( FT_Bool ) sfnt_get_name_id( TT_Face face, FT_UShort id, FT_Int *win, @@ -819,9 +836,9 @@ if ( !found ) { - /* as a last resort we try the family name; note that this is */ - /* not in the Adobe TechNote, but GX fonts (which predate the */ - /* TechNote) benefit from this behaviour */ + /* according to the 'name' documentation in the OpenType */ + /* specification the font family name is to be used if the */ + /* typographic family name is missing, so let's do that */ found = sfnt_get_name_id( face, TT_NAME_ID_FONT_FAMILY, &win, @@ -853,6 +870,10 @@ { FT_TRACE0(( "sfnt_get_var_ps_name:" " No valid PS name prefix for font instances found\n" )); + /* XXX It probably makes sense to never let this fail */ + /* since an arbitrary prefix should work, too. */ + /* On the other hand, it is very unlikely that */ + /* we ever reach this code at all. */ return NULL; } @@ -1041,47 +1062,49 @@ #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - static const char* - sfnt_get_ps_name( TT_Face face ) + FT_CALLBACK_DEF( const char* ) + sfnt_get_ps_name( FT_Face face ) /* TT_Face */ { + TT_Face ttface = (TT_Face)face; + FT_Int found, win, apple; const char* result = NULL; - if ( face->postscript_name ) - return face->postscript_name; + if ( ttface->postscript_name ) + return ttface->postscript_name; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( face->blend && - ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || - FT_IS_VARIATION( FT_FACE( face ) ) ) ) + if ( ttface->blend && + ( FT_IS_NAMED_INSTANCE( face ) || + FT_IS_VARIATION( face ) ) ) { - face->postscript_name = sfnt_get_var_ps_name( face ); - return face->postscript_name; + ttface->postscript_name = sfnt_get_var_ps_name( ttface ); + return ttface->postscript_name; } #endif /* scan the name table to see whether we have a Postscript name here, */ /* either in Macintosh or Windows platform encodings */ - found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple ); + found = sfnt_get_name_id( ttface, TT_NAME_ID_PS_NAME, &win, &apple ); if ( !found ) return NULL; /* prefer Windows entries over Apple */ if ( win != -1 ) - result = get_win_string( face->root.memory, - face->name_table.stream, - face->name_table.names + win, + result = get_win_string( FT_FACE_MEMORY( face ), + ttface->name_table.stream, + ttface->name_table.names + win, sfnt_is_postscript, 1 ); if ( !result && apple != -1 ) - result = get_apple_string( face->root.memory, - face->name_table.stream, - face->name_table.names + apple, + result = get_apple_string( FT_FACE_MEMORY( face ), + ttface->name_table.stream, + ttface->name_table.names + apple, sfnt_is_postscript, 1 ); - face->postscript_name = result; + ttface->postscript_name = result; return result; } @@ -1090,7 +1113,7 @@ FT_DEFINE_SERVICE_PSFONTNAMEREC( sfnt_service_ps_name, - (FT_PsName_GetFunc)sfnt_get_ps_name /* get_ps_font_name */ + sfnt_get_ps_name /* FT_PsName_GetFunc get_ps_font_name */ ) @@ -1100,14 +1123,14 @@ FT_DEFINE_SERVICE_TTCMAPSREC( tt_service_get_cmap_info, - (TT_CMap_Info_GetFunc)tt_get_cmap_info /* get_cmap_info */ + tt_get_cmap_info /* TT_CMap_Info_GetFunc get_cmap_info */ ) #ifdef TT_CONFIG_OPTION_BDF static FT_Error - sfnt_get_charset_id( TT_Face face, + sfnt_get_charset_id( FT_Face face, const char* *acharset_encoding, const char* *acharset_registry ) { @@ -1145,8 +1168,8 @@ FT_DEFINE_SERVICE_BDFRec( sfnt_service_bdf, - (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, /* get_charset_id */ - (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop /* get_property */ + sfnt_get_charset_id, /* FT_BDF_GetCharsetIdFunc get_charset_id */ + tt_face_find_bdf_prop /* FT_BDF_GetPropertyFunc get_property */ ) @@ -1337,9 +1360,9 @@ (const void*)&sfnt_interface, /* module specific interface */ - (FT_Module_Constructor)NULL, /* module_init */ - (FT_Module_Destructor) NULL, /* module_done */ - (FT_Module_Requester) sfnt_get_interface /* get_interface */ + NULL, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + sfnt_get_interface /* FT_Module_Requester get_interface */ ) diff --git a/src/3rdparty/freetype/src/sfnt/sfobjs.c b/src/3rdparty/freetype/src/sfnt/sfobjs.c index e018934c..f5d66ef8 100644 --- a/src/3rdparty/freetype/src/sfnt/sfobjs.c +++ b/src/3rdparty/freetype/src/sfnt/sfobjs.c @@ -534,17 +534,23 @@ 0 ); } - if ( !face->var ) + if ( !face->tt_var ) { /* we want the metrics variations interface */ /* from the `truetype' module only */ FT_Module tt_module = FT_Get_Module( library, "truetype" ); - face->var = ft_module_get_service( tt_module, - FT_SERVICE_ID_METRICS_VARIATIONS, - 0 ); + face->tt_var = ft_module_get_service( tt_module, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); } + + if ( !face->face_var ) + face->face_var = ft_module_get_service( + &face->root.driver->root, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); #endif FT_TRACE2(( "SFNT driver\n" )); @@ -692,6 +698,9 @@ instance_offset += instance_size; } + /* named instance indices start with value 1 */ + face->var_default_named_instance = i + 1; + if ( i == num_instances ) { /* no default instance in named instance table; */ @@ -1054,6 +1063,16 @@ GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { + FT_Memory memory = face->root.memory; + + + if ( FT_STRDUP( face->non_var_style_name, face->root.style_name ) ) + goto Exit; + } +#endif + /* now set up root fields */ { FT_Face root = &face->root; @@ -1221,7 +1240,7 @@ if ( count > 0 ) { - FT_Memory memory = face->root.stream->memory; + FT_Memory memory = face->root.memory; FT_UShort em_size = face->header.Units_Per_EM; FT_Short avgwidth = face->os2.xAvgCharWidth; FT_Size_Metrics metrics; @@ -1500,6 +1519,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_FREE( face->var_postscript_prefix ); + FT_FREE( face->non_var_style_name ); #endif /* freeing glyph color palette data */ diff --git a/src/3rdparty/freetype/src/sfnt/sfwoff.c b/src/3rdparty/freetype/src/sfnt/sfwoff.c index 9559bf34..7c0ce220 100644 --- a/src/3rdparty/freetype/src/sfnt/sfwoff.c +++ b/src/3rdparty/freetype/src/sfnt/sfwoff.c @@ -426,7 +426,7 @@ #else /* !FT_CONFIG_OPTION_USE_ZLIB */ /* ANSI C doesn't like empty source files */ - typedef int _sfwoff_dummy; + typedef int sfwoff_dummy_; #endif /* !FT_CONFIG_OPTION_USE_ZLIB */ diff --git a/src/3rdparty/freetype/src/sfnt/sfwoff2.c b/src/3rdparty/freetype/src/sfnt/sfwoff2.c index 7a01977f..2be44a34 100644 --- a/src/3rdparty/freetype/src/sfnt/sfwoff2.c +++ b/src/3rdparty/freetype/src/sfnt/sfwoff2.c @@ -36,6 +36,8 @@ #undef FT_COMPONENT #define FT_COMPONENT sfwoff2 + /* An arbitrary, heuristic size limit (67MByte) for expanded WOFF2 data. */ +#define MAX_SFNT_SIZE ( 1 << 26 ) #define READ_255USHORT( var ) FT_SET_ERROR( Read255UShort( stream, &var ) ) @@ -2180,9 +2182,8 @@ else sfnt_size = woff2.totalSfntSize; - /* Value 1<<26 = 67108864 is heuristic. */ - if (sfnt_size >= (1 << 26)) - sfnt_size = 1 << 26; + if ( sfnt_size >= MAX_SFNT_SIZE ) + sfnt_size = MAX_SFNT_SIZE; #ifdef FT_DEBUG_LEVEL_TRACE if ( sfnt_size != woff2.totalSfntSize ) @@ -2257,10 +2258,15 @@ goto Exit; } - if ( woff2.uncompressed_size > sfnt_size ) + /* We must not blindly trust `uncompressed_size` since its */ + /* value might be corrupted. If it is too large, reject the */ + /* font. In other words, we don't accept a WOFF2 font that */ + /* expands to something larger than MAX_SFNT_SIZE. If ever */ + /* necessary, this limit can be easily adjusted. */ + if ( woff2.uncompressed_size > MAX_SFNT_SIZE ) { - FT_ERROR(( "woff2_open_font: SFNT table lengths are too large.\n" )); - error = FT_THROW( Invalid_Table ); + FT_ERROR(( "Uncompressed font too large.\n" )); + error = FT_THROW( Array_Too_Large ); goto Exit; } @@ -2378,7 +2384,7 @@ #else /* !FT_CONFIG_OPTION_USE_BROTLI */ /* ANSI C doesn't like empty source files */ - typedef int _sfwoff2_dummy; + typedef int sfwoff2_dummy_; #endif /* !FT_CONFIG_OPTION_USE_BROTLI */ diff --git a/src/3rdparty/freetype/src/sfnt/ttbdf.c b/src/3rdparty/freetype/src/sfnt/ttbdf.c index 118f475e..536fa746 100644 --- a/src/3rdparty/freetype/src/sfnt/ttbdf.c +++ b/src/3rdparty/freetype/src/sfnt/ttbdf.c @@ -136,13 +136,14 @@ FT_LOCAL_DEF( FT_Error ) - tt_face_find_bdf_prop( TT_Face face, + tt_face_find_bdf_prop( FT_Face face, /* TT_Face */ const char* property_name, BDF_PropertyRec *aprop ) { - TT_BDF bdf = &face->bdf; - FT_Size size = FT_FACE( face )->size; - FT_Error error = FT_Err_Ok; + TT_Face ttface = (TT_Face)face; + TT_BDF bdf = &ttface->bdf; + FT_Size size = FT_FACE_SIZE( face ); + FT_Error error = FT_Err_Ok; FT_Byte* p; FT_UInt count; FT_Byte* strike; @@ -153,7 +154,7 @@ if ( bdf->loaded == 0 ) { - error = tt_face_load_bdf_props( face, FT_FACE( face )->stream ); + error = tt_face_load_bdf_props( ttface, FT_FACE_STREAM( face ) ); if ( error ) goto Exit; } @@ -248,7 +249,7 @@ #else /* !TT_CONFIG_OPTION_BDF */ /* ANSI C doesn't like empty source files */ - typedef int _tt_bdf_dummy; + typedef int tt_bdf_dummy_; #endif /* !TT_CONFIG_OPTION_BDF */ diff --git a/src/3rdparty/freetype/src/sfnt/ttbdf.h b/src/3rdparty/freetype/src/sfnt/ttbdf.h index 595aeb76..0d7a0ace 100644 --- a/src/3rdparty/freetype/src/sfnt/ttbdf.h +++ b/src/3rdparty/freetype/src/sfnt/ttbdf.h @@ -34,7 +34,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - tt_face_find_bdf_prop( TT_Face face, + tt_face_find_bdf_prop( FT_Face face, const char* property_name, BDF_PropertyRec *aprop ); diff --git a/src/3rdparty/freetype/src/sfnt/ttcmap.c b/src/3rdparty/freetype/src/sfnt/ttcmap.c index 820cd08e..9ba25dcb 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcmap.c +++ b/src/3rdparty/freetype/src/sfnt/ttcmap.c @@ -59,10 +59,14 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap_init( TT_CMap cmap, - FT_Byte* table ) + tt_cmap_init( FT_CMap cmap, /* TT_CMap */ + void* table_ ) { - cmap->data = table; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = (FT_Byte*)table_; + + + ttcmap->data = table; return FT_Err_Ok; } @@ -128,21 +132,23 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap0_char_index( TT_CMap cmap, + tt_cmap0_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; return char_code < 256 ? table[6 + char_code] : 0; } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap0_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap0_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 charcode = *pchar_code; FT_UInt32 result = 0; FT_UInt gindex = 0; @@ -165,10 +171,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap0_get_info( TT_CMap cmap, + tt_cmap0_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 0; @@ -453,10 +460,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap2_char_index( TT_CMap cmap, + tt_cmap2_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* subheader; @@ -491,11 +499,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap2_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap2_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pcharcode ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt gindex = 0; FT_UInt32 result = 0; FT_UInt32 charcode = *pcharcode + 1; @@ -579,10 +588,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap2_get_info( TT_CMap cmap, + tt_cmap2_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 2; @@ -706,18 +716,20 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_init( TT_CMap4 cmap, - FT_Byte* table ) + tt_cmap4_init( FT_CMap cmap, /* TT_CMap4 */ + void* table_ ) { + TT_CMap4 ttcmap = (TT_CMap4)cmap; + FT_Byte* table = (FT_Byte*)table_; FT_Byte* p; - cmap->cmap.data = table; + ttcmap->cmap.data = table; - p = table + 6; - cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; - cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; - cmap->cur_gindex = 0; + p = table + 6; + ttcmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; + ttcmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; + ttcmap->cur_gindex = 0; return FT_Err_Ok; } @@ -755,7 +767,7 @@ cmap->cur_start == 0xFFFFU && cmap->cur_end == 0xFFFFU ) { - TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; @@ -788,15 +800,12 @@ static void tt_cmap4_next( TT_CMap4 cmap ) { - TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt charcode; - if ( cmap->cur_charcode >= 0xFFFFUL ) - goto Fail; - charcode = (FT_UInt)cmap->cur_charcode + 1; if ( charcode < cmap->cur_start ) @@ -882,7 +891,6 @@ charcode = cmap->cur_start; } - Fail: cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; cmap->cur_gindex = 0; } @@ -1097,32 +1105,26 @@ FT_UInt32* pcharcode, FT_Bool next ) { - TT_Face face = (TT_Face)cmap->cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt num_segs2, start, end, offset; FT_Int delta; FT_UInt i, num_segs; - FT_UInt32 charcode = *pcharcode; + FT_UInt32 charcode = *pcharcode + next; FT_UInt gindex = 0; FT_Byte* p; FT_Byte* q; p = cmap->data + 6; - num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); - - num_segs = num_segs2 >> 1; + num_segs = TT_PEEK_USHORT( p ) >> 1; if ( !num_segs ) return 0; - if ( next ) - charcode++; - - if ( charcode > 0xFFFFU ) - return 0; + num_segs2 = num_segs << 1; /* linear search */ p = cmap->data + 14; /* ends table */ @@ -1232,37 +1234,30 @@ FT_UInt32* pcharcode, FT_Bool next ) { - TT_Face face = (TT_Face)cmap->cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt num_segs2, start, end, offset; FT_Int delta; FT_UInt max, min, mid, num_segs; - FT_UInt charcode = (FT_UInt)*pcharcode; + FT_UInt charcode = (FT_UInt)*pcharcode + next; FT_UInt gindex = 0; FT_Byte* p; p = cmap->data + 6; - num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); + num_segs = TT_PEEK_USHORT( p ) >> 1; - if ( !num_segs2 ) + if ( !num_segs ) return 0; - num_segs = num_segs2 >> 1; - - /* make compiler happy */ - mid = num_segs; - end = 0xFFFFU; - - if ( next ) - charcode++; + num_segs2 = num_segs << 1; min = 0; max = num_segs; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 14 + mid * 2; @@ -1445,6 +1440,7 @@ break; } } + while ( min < max ); if ( next ) { @@ -1454,12 +1450,8 @@ /* if `charcode' is not in any segment, then `mid' is */ /* the segment nearest to `charcode' */ - if ( charcode > end ) - { - mid++; - if ( mid == num_segs ) - return 0; - } + if ( charcode > end && ++mid == num_segs ) + return 0; if ( tt_cmap4_set_range( cmap4, mid ) ) { @@ -1474,7 +1466,6 @@ cmap4->cur_gindex = gindex; else { - cmap4->cur_charcode = charcode; tt_cmap4_next( cmap4 ); gindex = cmap4->cur_gindex; } @@ -1489,31 +1480,35 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap4_char_index( TT_CMap cmap, + tt_cmap4_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { + TT_CMap ttcmap = (TT_CMap)cmap; + + if ( char_code >= 0x10000UL ) return 0; - if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) - return tt_cmap4_char_map_linear( cmap, &char_code, 0 ); + if ( ttcmap->flags & TT_CMAP_FLAG_UNSORTED ) + return tt_cmap4_char_map_linear( ttcmap, &char_code, 0 ); else - return tt_cmap4_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap4_char_map_binary( ttcmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap4_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap4_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { + TT_CMap ttcmap = (TT_CMap)cmap; FT_UInt gindex; if ( *pchar_code >= 0xFFFFU ) return 0; - if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) - gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 ); + if ( ttcmap->flags & TT_CMAP_FLAG_UNSORTED ) + gindex = tt_cmap4_char_map_linear( ttcmap, pchar_code, 1 ); else { TT_CMap4 cmap4 = (TT_CMap4)cmap; @@ -1528,7 +1523,7 @@ *pchar_code = cmap4->cur_charcode; } else - gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap4_char_map_binary( ttcmap, pchar_code, 1 ); } return gindex; @@ -1536,10 +1531,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_get_info( TT_CMap cmap, + tt_cmap4_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 4; @@ -1640,10 +1636,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap6_char_index( TT_CMap cmap, + tt_cmap6_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 6; FT_UInt start = TT_NEXT_USHORT( p ); @@ -1661,11 +1658,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap6_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap6_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 result = 0; FT_UInt32 char_code = *pchar_code + 1; FT_UInt gindex = 0; @@ -1706,10 +1704,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap6_get_info( TT_CMap cmap, + tt_cmap6_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 6; @@ -1900,10 +1899,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap8_char_index( TT_CMap cmap, + tt_cmap8_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 8204; FT_UInt32 num_groups = TT_NEXT_ULONG( p ); @@ -1932,15 +1932,16 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap8_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap8_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Face face = cmap->cmap.charmap.face; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); FT_UInt32 result = 0; FT_UInt32 char_code; FT_UInt gindex = 0; - FT_Byte* table = cmap->data; + FT_Byte* table = ttcmap->data; FT_Byte* p = table + 8204; FT_UInt32 num_groups = TT_NEXT_ULONG( p ); FT_UInt32 start, end, start_id; @@ -2000,10 +2001,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap8_get_info( TT_CMap cmap, + tt_cmap8_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 8; @@ -2104,10 +2106,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap10_char_index( TT_CMap cmap, + tt_cmap10_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 12; FT_UInt32 start = TT_NEXT_ULONG( p ); @@ -2130,11 +2133,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap10_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap10_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 char_code; FT_UInt gindex = 0; FT_Byte* p = table + 12; @@ -2172,10 +2176,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap10_get_info( TT_CMap cmap, + tt_cmap10_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 10; @@ -2253,15 +2258,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_init( TT_CMap12 cmap, - FT_Byte* table ) + tt_cmap12_init( FT_CMap cmap, /* TT_CMap12 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap12 ttcmap = (TT_CMap12)cmap; + FT_Byte* table = (FT_Byte*)table_; - table += 12; - cmap->num_groups = FT_PEEK_ULONG( table ); - cmap->valid = 0; + ttcmap->cmap.data = table; + + table += 12; + ttcmap->num_groups = FT_PEEK_ULONG( table ); + + ttcmap->valid = 0; return FT_Err_Ok; } @@ -2331,23 +2340,21 @@ /* cmap->cur_group should be set up properly by caller */ /* */ static void - tt_cmap12_next( TT_CMap12 cmap ) + tt_cmap12_next( FT_CMap cmap ) /* TT_CMap12 */ { - FT_Face face = cmap->cmap.cmap.charmap.face; - FT_Byte* p; - FT_ULong start, end, start_id, char_code; - FT_ULong n; - FT_UInt gindex; + TT_CMap12 ttcmap = (TT_CMap12)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Byte* p; + FT_ULong start, end, start_id, char_code; + FT_ULong n; + FT_UInt gindex; - if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) - goto Fail; + char_code = ttcmap->cur_charcode + 1; - char_code = cmap->cur_charcode + 1; - - for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) + for ( n = ttcmap->cur_group; n < ttcmap->num_groups; n++ ) { - p = cmap->cmap.data + 16 + 12 * n; + p = ttcmap->cmap.data + 16 + 12 * n; start = TT_NEXT_ULONG( p ); end = TT_NEXT_ULONG( p ); start_id = TT_PEEK_ULONG( p ); @@ -2379,16 +2386,16 @@ if ( gindex >= (FT_UInt)face->num_glyphs ) continue; - cmap->cur_charcode = char_code; - cmap->cur_gindex = gindex; - cmap->cur_group = n; + ttcmap->cur_charcode = char_code; + ttcmap->cur_gindex = gindex; + ttcmap->cur_group = n; return; } } Fail: - cmap->valid = 0; + ttcmap->valid = 0; } @@ -2400,7 +2407,7 @@ FT_UInt gindex = 0; FT_Byte* p = cmap->data + 12; FT_UInt32 num_groups = TT_PEEK_ULONG( p ); - FT_UInt32 char_code = *pchar_code; + FT_UInt32 char_code = *pchar_code + next; FT_UInt32 start, end, start_id; FT_UInt32 max, min, mid; @@ -2408,23 +2415,11 @@ if ( !num_groups ) return 0; - /* make compiler happy */ - mid = num_groups; - end = 0xFFFFFFFFUL; - - if ( next ) - { - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - min = 0; max = num_groups; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 16 + 12 * mid; @@ -2448,22 +2443,19 @@ break; } } + while ( min < max ); if ( next ) { - FT_Face face = cmap->cmap.charmap.face; + FT_Face face = FT_CMAP_FACE( cmap ); TT_CMap12 cmap12 = (TT_CMap12)cmap; /* if `char_code' is not in any group, then `mid' is */ /* the group nearest to `char_code' */ - if ( char_code > end ) - { - mid++; - if ( mid == num_groups ) - return 0; - } + if ( char_code > end && ++mid == num_groups ) + return 0; cmap12->valid = 1; cmap12->cur_charcode = char_code; @@ -2474,7 +2466,7 @@ if ( !gindex ) { - tt_cmap12_next( cmap12 ); + tt_cmap12_next( FT_CMAP( cmap12 ) ); if ( cmap12->valid ) gindex = cmap12->cur_gindex; @@ -2490,25 +2482,28 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap12_char_index( TT_CMap cmap, + tt_cmap12_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - return tt_cmap12_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap12_char_map_binary( (TT_CMap)cmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap12_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap12_char_next( FT_CMap cmap, /* TT_CMap12 */ FT_UInt32 *pchar_code ) { TT_CMap12 cmap12 = (TT_CMap12)cmap; FT_UInt gindex; + if ( *pchar_code >= 0xFFFFFFFFUL ) + return 0; + /* no need to search */ if ( cmap12->valid && cmap12->cur_charcode == *pchar_code ) { - tt_cmap12_next( cmap12 ); + tt_cmap12_next( FT_CMAP( cmap12 ) ); if ( cmap12->valid ) { gindex = cmap12->cur_gindex; @@ -2518,17 +2513,18 @@ gindex = 0; } else - gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap12_char_map_binary( (TT_CMap)cmap, pchar_code, 1 ); return gindex; } FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_get_info( TT_CMap cmap, + tt_cmap12_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 12; @@ -2606,15 +2602,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_init( TT_CMap13 cmap, - FT_Byte* table ) + tt_cmap13_init( FT_CMap cmap, /* TT_CMap13 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap13 ttcmap = (TT_CMap13)cmap; + FT_Byte* table = (FT_Byte*)table_; - table += 12; - cmap->num_groups = FT_PEEK_ULONG( table ); - cmap->valid = 0; + ttcmap->cmap.data = table; + + table += 12; + ttcmap->num_groups = FT_PEEK_ULONG( table ); + + ttcmap->valid = 0; return FT_Err_Ok; } @@ -2679,23 +2679,21 @@ /* cmap->cur_group should be set up properly by caller */ /* */ static void - tt_cmap13_next( TT_CMap13 cmap ) + tt_cmap13_next( FT_CMap cmap ) /* TT_CMap13 */ { - FT_Face face = cmap->cmap.cmap.charmap.face; - FT_Byte* p; - FT_ULong start, end, glyph_id, char_code; - FT_ULong n; - FT_UInt gindex; + TT_CMap13 ttcmap = (TT_CMap13)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Byte* p; + FT_ULong start, end, glyph_id, char_code; + FT_ULong n; + FT_UInt gindex; - if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) - goto Fail; + char_code = ttcmap->cur_charcode + 1; - char_code = cmap->cur_charcode + 1; - - for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) + for ( n = ttcmap->cur_group; n < ttcmap->num_groups; n++ ) { - p = cmap->cmap.data + 16 + 12 * n; + p = ttcmap->cmap.data + 16 + 12 * n; start = TT_NEXT_ULONG( p ); end = TT_NEXT_ULONG( p ); glyph_id = TT_PEEK_ULONG( p ); @@ -2709,17 +2707,16 @@ if ( gindex && gindex < (FT_UInt)face->num_glyphs ) { - cmap->cur_charcode = char_code; - cmap->cur_gindex = gindex; - cmap->cur_group = n; + ttcmap->cur_charcode = char_code; + ttcmap->cur_gindex = gindex; + ttcmap->cur_group = n; return; } } } - Fail: - cmap->valid = 0; + ttcmap->valid = 0; } @@ -2731,7 +2728,7 @@ FT_UInt gindex = 0; FT_Byte* p = cmap->data + 12; FT_UInt32 num_groups = TT_PEEK_ULONG( p ); - FT_UInt32 char_code = *pchar_code; + FT_UInt32 char_code = *pchar_code + next; FT_UInt32 start, end; FT_UInt32 max, min, mid; @@ -2739,23 +2736,11 @@ if ( !num_groups ) return 0; - /* make compiler happy */ - mid = num_groups; - end = 0xFFFFFFFFUL; - - if ( next ) - { - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - min = 0; max = num_groups; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 16 + 12 * mid; @@ -2774,6 +2759,7 @@ break; } } + while ( min < max ); if ( next ) { @@ -2784,12 +2770,8 @@ /* if `char_code' is not in any group, then `mid' is */ /* the group nearest to `char_code' */ - if ( char_code > end ) - { - mid++; - if ( mid == num_groups ) - return 0; - } + if ( char_code > end && ++mid == num_groups ) + return 0; cmap13->valid = 1; cmap13->cur_charcode = char_code; @@ -2800,7 +2782,7 @@ if ( !gindex ) { - tt_cmap13_next( cmap13 ); + tt_cmap13_next( FT_CMAP( cmap13 ) ); if ( cmap13->valid ) gindex = cmap13->cur_gindex; @@ -2816,25 +2798,28 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap13_char_index( TT_CMap cmap, + tt_cmap13_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - return tt_cmap13_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap13_char_map_binary( (TT_CMap)cmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap13_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap13_char_next( FT_CMap cmap, /* TT_CMap13 */ FT_UInt32 *pchar_code ) { TT_CMap13 cmap13 = (TT_CMap13)cmap; FT_UInt gindex; + if ( *pchar_code >= 0xFFFFFFFFUL ) + return 0; + /* no need to search */ if ( cmap13->valid && cmap13->cur_charcode == *pchar_code ) { - tt_cmap13_next( cmap13 ); + tt_cmap13_next( FT_CMAP( cmap13 ) ); if ( cmap13->valid ) { gindex = cmap13->cur_gindex; @@ -2844,17 +2829,18 @@ gindex = 0; } else - gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap13_char_map_binary( (TT_CMap)cmap, pchar_code, 1 ); return gindex; } FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_get_info( TT_CMap cmap, + tt_cmap13_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 13; @@ -2969,14 +2955,15 @@ FT_CALLBACK_DEF( void ) - tt_cmap14_done( TT_CMap14 cmap ) + tt_cmap14_done( FT_CMap cmap ) /* TT_CMap14 */ { - FT_Memory memory = cmap->memory; + TT_CMap14 ttcmap = (TT_CMap14)cmap; + FT_Memory memory = ttcmap->memory; - cmap->max_results = 0; - if ( memory && cmap->results ) - FT_FREE( cmap->results ); + ttcmap->max_results = 0; + if ( memory && ttcmap->results ) + FT_FREE( ttcmap->results ); } @@ -3004,15 +2991,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_init( TT_CMap14 cmap, - FT_Byte* table ) + tt_cmap14_init( FT_CMap cmap, /* TT_CMap14 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap14 ttcmap = (TT_CMap14)cmap; + FT_Byte* table = (FT_Byte*)table_; - table += 6; - cmap->num_selectors = FT_PEEK_ULONG( table ); - cmap->max_results = 0; - cmap->results = NULL; + + ttcmap->cmap.data = table; + + table += 6; + ttcmap->num_selectors = FT_PEEK_ULONG( table ); + ttcmap->max_results = 0; + ttcmap->results = NULL; return FT_Err_Ok; } @@ -3142,7 +3133,7 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap14_char_index( TT_CMap cmap, + tt_cmap14_char_index( FT_CMap cmap, FT_UInt32 char_code ) { FT_UNUSED( cmap ); @@ -3153,8 +3144,8 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap14_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap14_char_next( FT_CMap cmap, FT_UInt32 *pchar_code ) { FT_UNUSED( cmap ); @@ -3166,7 +3157,7 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_get_info( TT_CMap cmap, + tt_cmap14_get_info( FT_CharMap cmap, TT_CMapInfo *cmap_info ) { FT_UNUSED( cmap ); @@ -3280,12 +3271,16 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap14_char_var_index( TT_CMap cmap, - TT_CMap ucmap, + tt_cmap14_char_var_index( FT_CMap cmap, /* TT_CMap */ + FT_CMap ucmap, /* TT_CMap */ FT_UInt32 charcode, FT_UInt32 variantSelector ) { - FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); + TT_CMap ttcmap = (TT_CMap)cmap; + TT_CMap ttucmap = (TT_CMap)ucmap; + + FT_Byte* p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); FT_ULong defOff; FT_ULong nondefOff; @@ -3296,16 +3291,16 @@ defOff = TT_NEXT_ULONG( p ); nondefOff = TT_PEEK_ULONG( p ); - if ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) + if ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, charcode ) ) { /* This is the default variant of this charcode. GID not stored */ /* here; stored in the normal Unicode charmap instead. */ - return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode ); + return ttucmap->cmap.clazz->char_index( &ttucmap->cmap, charcode ); } if ( nondefOff != 0 ) - return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, + return tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, charcode ); return 0; @@ -3313,11 +3308,13 @@ FT_CALLBACK_DEF( FT_Int ) - tt_cmap14_char_var_isdefault( TT_CMap cmap, + tt_cmap14_char_var_isdefault( FT_CMap cmap, /* TT_CMap */ FT_UInt32 charcode, FT_UInt32 variantSelector ) { - FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); FT_ULong defOff; FT_ULong nondefOff; @@ -3328,13 +3325,13 @@ defOff = TT_NEXT_ULONG( p ); nondefOff = TT_NEXT_ULONG( p ); - if ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) + if ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, charcode ) ) return 1; - if ( nondefOff != 0 && - tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charcode ) != 0 ) + if ( nondefOff != 0 && + tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, + charcode ) != 0 ) return 0; return -1; @@ -3342,12 +3339,13 @@ FT_CALLBACK_DEF( FT_UInt32* ) - tt_cmap14_variants( TT_CMap cmap, + tt_cmap14_variants( FT_CMap cmap, /* TT_CMap14 */ FT_Memory memory ) { + TT_CMap ttcmap = (TT_CMap)cmap; TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 count = cmap14->num_selectors; - FT_Byte* p = cmap->data + 10; + FT_Byte* p = ttcmap->data + 10; FT_UInt32* result; FT_UInt32 i; @@ -3368,13 +3366,14 @@ FT_CALLBACK_DEF( FT_UInt32 * ) - tt_cmap14_char_variants( TT_CMap cmap, + tt_cmap14_char_variants( FT_CMap cmap, /* TT_CMap14 */ FT_Memory memory, FT_UInt32 charCode ) { - TT_CMap14 cmap14 = (TT_CMap14) cmap; + TT_CMap ttcmap = (TT_CMap)cmap; + TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 count = cmap14->num_selectors; - FT_Byte* p = cmap->data + 10; + FT_Byte* p = ttcmap->data + 10; FT_UInt32* q; @@ -3388,12 +3387,12 @@ FT_ULong nondefOff = TT_NEXT_ULONG( p ); - if ( ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, - charCode ) ) || - ( nondefOff != 0 && - tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charCode ) != 0 ) ) + if ( ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, + charCode ) ) || + ( nondefOff != 0 && + tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, + charCode ) != 0 ) ) { q[0] = varSel; q++; @@ -3489,15 +3488,16 @@ FT_CALLBACK_DEF( FT_UInt32 * ) - tt_cmap14_variant_chars( TT_CMap cmap, + tt_cmap14_variant_chars( FT_CMap cmap, /* TT_CMap */ FT_Memory memory, FT_UInt32 variantSelector ) { - FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6, - variantSelector ); - FT_Int i; - FT_ULong defOff; - FT_ULong nondefOff; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte *p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); + FT_Int i; + FT_ULong defOff; + FT_ULong nondefOff; if ( !p ) @@ -3510,16 +3510,16 @@ return NULL; if ( defOff == 0 ) - return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, + return tt_cmap14_get_nondef_chars( ttcmap, ttcmap->data + nondefOff, memory ); else if ( nondefOff == 0 ) - return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, + return tt_cmap14_get_def_chars( ttcmap, ttcmap->data + defOff, memory ); else { /* Both a default and a non-default glyph set? That's probably not */ /* good font design, but the spec allows for it... */ - TT_CMap14 cmap14 = (TT_CMap14) cmap; + TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 numRanges; FT_UInt32 numMappings; FT_UInt32 duni; @@ -3531,18 +3531,18 @@ FT_UInt32 *ret; - p = cmap->data + nondefOff; - dp = cmap->data + defOff; + p = ttcmap->data + nondefOff; + dp = ttcmap->data + defOff; numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); dcnt = tt_cmap14_def_char_count( dp ); numRanges = (FT_UInt32)TT_NEXT_ULONG( dp ); if ( numMappings == 0 ) - return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, + return tt_cmap14_get_def_chars( ttcmap, ttcmap->data + defOff, memory ); if ( dcnt == 0 ) - return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, + return tt_cmap14_get_nondef_chars( ttcmap, ttcmap->data + nondefOff, memory ); if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) ) @@ -3664,9 +3664,10 @@ #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES FT_CALLBACK_DEF( const char * ) - tt_get_glyph_name( TT_Face face, + tt_get_glyph_name( void* face_, /* TT_Face */ FT_UInt idx ) { + TT_Face face = (TT_Face)face_; FT_String* PSname = NULL; @@ -3677,12 +3678,13 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap_unicode_init( PS_Unicodes unicodes, - FT_Pointer pointer ) + tt_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ + FT_Pointer pointer ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; FT_UNUSED( pointer ); @@ -3693,17 +3695,18 @@ return psnames->unicodes_init( memory, unicodes, face->root.num_glyphs, - (PS_GetGlyphNameFunc)&tt_get_glyph_name, + &tt_get_glyph_name, (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } FT_CALLBACK_DEF( void ) - tt_cmap_unicode_done( PS_Unicodes unicodes ) + tt_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Unicodes unicodes = (PS_Unicodes)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( unicodes->maps ); @@ -3712,23 +3715,25 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) + tt_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 char_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_index( unicodes, char_code ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 *pchar_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_next( unicodes, pchar_code ); @@ -3883,7 +3888,7 @@ tt_get_cmap_info( FT_CharMap charmap, TT_CMapInfo *cmap_info ) { - FT_CMap cmap = (FT_CMap)charmap; + FT_CMap cmap = FT_CMAP( charmap ); TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; diff --git a/src/3rdparty/freetype/src/sfnt/ttcolr.c b/src/3rdparty/freetype/src/sfnt/ttcolr.c index 5d98dcab..281e7135 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcolr.c +++ b/src/3rdparty/freetype/src/sfnt/ttcolr.c @@ -229,7 +229,7 @@ base_glyphs_offset_v1 = FT_NEXT_ULONG( p ); - if ( base_glyphs_offset_v1 + 4 >= table_size ) + if ( base_glyphs_offset_v1 >= table_size - 4 ) goto InvalidTable; p1 = (FT_Byte*)( table + base_glyphs_offset_v1 ); @@ -249,7 +249,7 @@ if ( layer_offset_v1 ) { - if ( layer_offset_v1 + 4 >= table_size ) + if ( layer_offset_v1 >= table_size - 4 ) goto InvalidTable; p1 = (FT_Byte*)( table + layer_offset_v1 ); @@ -699,7 +699,7 @@ item_deltas ) ) return 0; - apaint->u.solid.color.alpha += item_deltas[0]; + apaint->u.solid.color.alpha += (FT_F2Dot14)item_deltas[0]; } #endif @@ -1646,7 +1646,7 @@ return 0; color_stop->stop_offset += F2DOT14_TO_FIXED( item_deltas[0] ); - color_stop->color.alpha += item_deltas[1]; + color_stop->color.alpha += (FT_F2Dot14)item_deltas[1]; } #else FT_UNUSED( var_index_base ); @@ -1914,7 +1914,7 @@ #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_colr_dummy; + typedef int tt_colr_dummy_; #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */ diff --git a/src/3rdparty/freetype/src/sfnt/ttcpal.c b/src/3rdparty/freetype/src/sfnt/ttcpal.c index 4279bc0b..46ae0859 100644 --- a/src/3rdparty/freetype/src/sfnt/ttcpal.c +++ b/src/3rdparty/freetype/src/sfnt/ttcpal.c @@ -303,7 +303,7 @@ #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_cpal_dummy; + typedef int tt_cpal_dummy_; #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */ diff --git a/src/3rdparty/freetype/src/sfnt/ttload.c b/src/3rdparty/freetype/src/sfnt/ttload.c index 14f625c8..7b44e9cd 100644 --- a/src/3rdparty/freetype/src/sfnt/ttload.c +++ b/src/3rdparty/freetype/src/sfnt/ttload.c @@ -504,6 +504,13 @@ FT_FRAME_EXIT(); + if ( !valid_entries ) + { + FT_TRACE2(( "tt_face_load_font_dir: no valid tables found\n" )); + error = FT_THROW( Unknown_File_Format ); + goto Exit; + } + FT_TRACE2(( "table directory loaded\n" )); FT_TRACE2(( "\n" )); diff --git a/src/3rdparty/freetype/src/sfnt/ttmtx.c b/src/3rdparty/freetype/src/sfnt/ttmtx.c index 5e53e6dd..38ee9ae7 100644 --- a/src/3rdparty/freetype/src/sfnt/ttmtx.c +++ b/src/3rdparty/freetype/src/sfnt/ttmtx.c @@ -239,7 +239,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_Service_MetricsVariations var = - (FT_Service_MetricsVariations)face->var; + (FT_Service_MetricsVariations)face->tt_var; #endif diff --git a/src/3rdparty/freetype/src/sfnt/ttpost.c b/src/3rdparty/freetype/src/sfnt/ttpost.c index 0e17c6f3..1dfad429 100644 --- a/src/3rdparty/freetype/src/sfnt/ttpost.c +++ b/src/3rdparty/freetype/src/sfnt/ttpost.c @@ -156,86 +156,66 @@ static FT_Error - load_format_20( TT_Face face, - FT_Stream stream, - FT_ULong post_len ) + load_format_20( TT_Post_Names names, + FT_Stream stream, + FT_UShort num_glyphs, + FT_ULong post_len ) { FT_Memory memory = stream->memory; FT_Error error; - FT_Int num_glyphs; - FT_UShort num_names; + FT_UShort n; + FT_UShort num_names = 0; FT_UShort* glyph_indices = NULL; - FT_Char** name_strings = NULL; - FT_Byte* strings = NULL; + FT_Byte** name_strings = NULL; + FT_Byte* q; - if ( FT_READ_USHORT( num_glyphs ) ) - goto Exit; - - /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ - /* than the value in the maxp table (cf. cyberbit.ttf). */ - - /* There already exist fonts which have more than 32768 glyph names */ - /* in this table, so the test for this threshold has been dropped. */ - - if ( num_glyphs > face->max_profile.numGlyphs || - (FT_ULong)num_glyphs * 2UL > post_len - 2 ) + if ( (FT_ULong)num_glyphs * 2 > post_len ) { error = FT_THROW( Invalid_File_Format ); goto Exit; } - /* load the indices */ + /* load the indices and note their maximum */ + if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || + FT_FRAME_ENTER( num_glyphs * 2 ) ) + goto Fail; + + q = (FT_Byte*)stream->cursor; + + for ( n = 0; n < num_glyphs; n++ ) { - FT_Int n; + FT_UShort idx = FT_NEXT_USHORT( q ); - if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || - FT_FRAME_ENTER( num_glyphs * 2L ) ) - goto Fail; + if ( idx > num_names ) + num_names = idx; - for ( n = 0; n < num_glyphs; n++ ) - glyph_indices[n] = FT_GET_USHORT(); - - FT_FRAME_EXIT(); + glyph_indices[n] = idx; } - /* compute number of names stored in table */ - { - FT_Int n; + FT_FRAME_EXIT(); - - num_names = 0; - - for ( n = 0; n < num_glyphs; n++ ) - { - FT_Int idx; - - - idx = glyph_indices[n]; - if ( idx >= 258 ) - { - idx -= 257; - if ( idx > num_names ) - num_names = (FT_UShort)idx; - } - } - } + /* compute number of names stored in the table */ + num_names = num_names > 257 ? num_names - 257 : 0; /* now load the name strings */ if ( num_names ) { - FT_UShort n; FT_ULong p; + FT_Byte* strings; - post_len -= (FT_ULong)num_glyphs * 2UL + 2; + post_len -= (FT_ULong)num_glyphs * 2; - if ( FT_QALLOC( strings, post_len + 1 ) || - FT_STREAM_READ( strings, post_len ) || - FT_QNEW_ARRAY( name_strings, num_names ) ) + if ( FT_QALLOC( name_strings, num_names * sizeof ( FT_Byte* ) + + post_len + 1 ) ) + goto Fail; + + strings = (FT_Byte*)( name_strings + num_names ); + if ( FT_STREAM_READ( strings, post_len ) ) goto Fail; /* convert from Pascal- to C-strings and set pointers */ @@ -251,7 +231,7 @@ } strings[p] = 0; - name_strings[n] = (FT_Char*)strings + p + 1; + name_strings[n] = strings + p + 1; p += len + 1; } strings[post_len] = 0; @@ -259,40 +239,24 @@ /* deal with missing or insufficient string data */ if ( n < num_names ) { - if ( post_len == 0 ) - { - /* fake empty string */ - if ( FT_QREALLOC( strings, 1, 2 ) ) - goto Fail; + FT_TRACE4(( "load_format_20: %hu PostScript names are truncated\n", + num_names - n )); - post_len = 1; - strings[post_len] = 0; - } - - FT_ERROR(( "load_format_20:" - " all entries in post table are already parsed," - " using NULL names for gid %d - %d\n", - n, num_names - 1 )); for ( ; n < num_names; n++ ) - name_strings[n] = (FT_Char*)strings + post_len; + name_strings[n] = strings + post_len; } } /* all right, set table fields and exit successfully */ - { - TT_Post_20 table = &face->postscript_names.names.format_20; + names->num_glyphs = num_glyphs; + names->num_names = num_names; + names->glyph_indices = glyph_indices; + names->glyph_names = name_strings; - - table->num_glyphs = (FT_UShort)num_glyphs; - table->num_names = (FT_UShort)num_names; - table->glyph_indices = glyph_indices; - table->glyph_names = name_strings; - } return FT_Err_Ok; Fail: FT_FREE( name_strings ); - FT_FREE( strings ); FT_FREE( glyph_indices ); Exit: @@ -301,66 +265,55 @@ static FT_Error - load_format_25( TT_Face face, - FT_Stream stream, - FT_ULong post_len ) + load_format_25( TT_Post_Names names, + FT_Stream stream, + FT_UShort num_glyphs, + FT_ULong post_len ) { FT_Memory memory = stream->memory; FT_Error error; - FT_Int num_glyphs; - FT_Char* offset_table = NULL; - - FT_UNUSED( post_len ); + FT_UShort n; + FT_UShort* glyph_indices = NULL; + FT_Byte* q; - if ( FT_READ_USHORT( num_glyphs ) ) - goto Exit; - - /* check the number of glyphs */ - if ( num_glyphs > face->max_profile.numGlyphs || - num_glyphs > 258 || - num_glyphs < 1 ) + /* check the number of glyphs, including the theoretical limit */ + if ( num_glyphs > post_len || + num_glyphs > 258 + 128 ) { error = FT_THROW( Invalid_File_Format ); goto Exit; } - if ( FT_QNEW_ARRAY( offset_table, num_glyphs ) || - FT_STREAM_READ( offset_table, num_glyphs ) ) + /* load the indices and check their Mac range */ + if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || + FT_FRAME_ENTER( num_glyphs ) ) goto Fail; - /* now check the offset table */ + q = (FT_Byte*)stream->cursor; + + for ( n = 0; n < num_glyphs; n++ ) { - FT_Int n; + FT_Int idx = n + FT_NEXT_CHAR( q ); - for ( n = 0; n < num_glyphs; n++ ) - { - FT_Long idx = (FT_Long)n + offset_table[n]; + if ( idx < 0 || idx > 257 ) + idx = 0; - - if ( idx < 0 || idx > num_glyphs ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - } + glyph_indices[n] = (FT_UShort)idx; } + FT_FRAME_EXIT(); + /* OK, set table fields and exit successfully */ - { - TT_Post_25 table = &face->postscript_names.names.format_25; - - - table->num_glyphs = (FT_UShort)num_glyphs; - table->offsets = offset_table; - } + names->num_glyphs = num_glyphs; + names->glyph_indices = glyph_indices; return FT_Err_Ok; Fail: - FT_FREE( offset_table ); + FT_FREE( glyph_indices ); Exit: return error; @@ -370,37 +323,37 @@ static FT_Error load_post_names( TT_Face face ) { - FT_Stream stream; - FT_Error error; - FT_Fixed format; + FT_Error error = FT_Err_Ok; + FT_Stream stream = face->root.stream; + FT_Fixed format = face->postscript.FormatType; FT_ULong post_len; + FT_UShort num_glyphs; - /* get a stream for the face's resource */ - stream = face->root.stream; - /* seek to the beginning of the PS names table */ error = face->goto_table( face, TTAG_post, stream, &post_len ); if ( error ) goto Exit; - format = face->postscript.FormatType; - - /* go to beginning of subtable */ - if ( FT_STREAM_SKIP( 32 ) ) + /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ + /* than the value in the maxp table (cf. cyberbit.ttf). */ + if ( post_len < 34 || + FT_STREAM_SKIP( 32 ) || + FT_READ_USHORT( num_glyphs ) || + num_glyphs > face->max_profile.numGlyphs || + num_glyphs == 0 ) goto Exit; - /* now read postscript table */ - if ( format == 0x00020000L && post_len >= 34 ) - error = load_format_20( face, stream, post_len - 32 ); - else if ( format == 0x00025000L && post_len >= 34 ) - error = load_format_25( face, stream, post_len - 32 ); - else - error = FT_THROW( Invalid_File_Format ); - - face->postscript_names.loaded = 1; + /* now read postscript names data */ + if ( format == 0x00020000L ) + error = load_format_20( &face->postscript_names, stream, + num_glyphs, post_len - 34 ); + else if ( format == 0x00025000L ) + error = load_format_25( &face->postscript_names, stream, + num_glyphs, post_len - 34 ); Exit: + face->postscript_names.loaded = 1; /* even if failed */ return error; } @@ -410,39 +363,20 @@ { FT_Memory memory = face->root.memory; TT_Post_Names names = &face->postscript_names; - FT_Fixed format; - if ( names->loaded ) + if ( names->num_glyphs ) { - format = face->postscript.FormatType; - - if ( format == 0x00020000L ) - { - TT_Post_20 table = &names->names.format_20; - - - FT_FREE( table->glyph_indices ); - table->num_glyphs = 0; - - if ( table->num_names ) - { - table->glyph_names[0]--; - FT_FREE( table->glyph_names[0] ); - - FT_FREE( table->glyph_names ); - table->num_names = 0; - } - } - else if ( format == 0x00025000L ) - { - TT_Post_25 table = &names->names.format_25; - - - FT_FREE( table->offsets ); - table->num_glyphs = 0; - } + FT_FREE( names->glyph_indices ); + names->num_glyphs = 0; } + + if ( names->num_names ) + { + FT_FREE( names->glyph_names ); + names->num_names = 0; + } + names->loaded = 0; } @@ -478,7 +412,6 @@ FT_String** PSname ) { FT_Error error; - TT_Post_Names names; FT_Fixed format; #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES @@ -498,8 +431,6 @@ return FT_THROW( Unimplemented_Feature ); #endif - names = &face->postscript_names; - /* `.notdef' by default */ *PSname = MAC_NAME( 0 ); @@ -510,9 +441,10 @@ if ( idx < 258 ) /* paranoid checking */ *PSname = MAC_NAME( idx ); } - else if ( format == 0x00020000L ) + else if ( format == 0x00020000L || + format == 0x00025000L ) { - TT_Post_20 table = &names->names.format_20; + TT_Post_Names names = &face->postscript_names; if ( !names->loaded ) @@ -522,43 +454,29 @@ goto End; } - if ( idx < (FT_UInt)table->num_glyphs ) + if ( idx < (FT_UInt)names->num_glyphs ) { - FT_UShort name_index = table->glyph_indices[idx]; + FT_UShort name_index = names->glyph_indices[idx]; if ( name_index < 258 ) *PSname = MAC_NAME( name_index ); - else - *PSname = (FT_String*)table->glyph_names[name_index - 258]; + else /* only for version 2.0 */ + *PSname = (FT_String*)names->glyph_names[name_index - 258]; } } - else if ( format == 0x00025000L ) - { - TT_Post_25 table = &names->names.format_25; - - - if ( !names->loaded ) - { - error = load_post_names( face ); - if ( error ) - goto End; - } - - if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */ - *PSname = MAC_NAME( (FT_Int)idx + table->offsets[idx] ); - } /* nothing to do for format == 0x00030000L */ End: + /* post format errors ignored */ return FT_Err_Ok; } #else /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ /* ANSI C doesn't like empty source files */ - typedef int _tt_post_dummy; + typedef int tt_post_dummy_; #endif /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ diff --git a/src/3rdparty/freetype/src/sfnt/ttsbit.c b/src/3rdparty/freetype/src/sfnt/ttsbit.c index 3c069551..03f90a62 100644 --- a/src/3rdparty/freetype/src/sfnt/ttsbit.c +++ b/src/3rdparty/freetype/src/sfnt/ttsbit.c @@ -1677,7 +1677,7 @@ #else /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_sbit_dummy; + typedef int tt_sbit_dummy_; #endif /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ diff --git a/src/3rdparty/freetype/src/sfnt/ttsvg.c b/src/3rdparty/freetype/src/sfnt/ttsvg.c index c1bbb66b..4461d483 100644 --- a/src/3rdparty/freetype/src/sfnt/ttsvg.c +++ b/src/3rdparty/freetype/src/sfnt/ttsvg.c @@ -405,7 +405,7 @@ #else /* !FT_CONFIG_OPTION_SVG */ /* ANSI C doesn't like empty source files */ - typedef int _tt_svg_dummy; + typedef int tt_svg_dummy_; #endif /* !FT_CONFIG_OPTION_SVG */ diff --git a/src/3rdparty/freetype/src/sfnt/woff2tags.c b/src/3rdparty/freetype/src/sfnt/woff2tags.c index 7a0a351f..eeedd990 100644 --- a/src/3rdparty/freetype/src/sfnt/woff2tags.c +++ b/src/3rdparty/freetype/src/sfnt/woff2tags.c @@ -111,7 +111,7 @@ #else /* !FT_CONFIG_OPTION_USE_BROTLI */ /* ANSI C doesn't like empty source files */ - typedef int _woff2tags_dummy; + typedef int woff2tags_dummy_; #endif /* !FT_CONFIG_OPTION_USE_BROTLI */ diff --git a/src/3rdparty/freetype/src/smooth/ftgrays.c b/src/3rdparty/freetype/src/smooth/ftgrays.c index d9f20eef..0918272f 100644 --- a/src/3rdparty/freetype/src/smooth/ftgrays.c +++ b/src/3rdparty/freetype/src/smooth/ftgrays.c @@ -1006,10 +1006,11 @@ typedef ptrdiff_t FT_PtrDist; * * For other cases, using binary splits is actually slightly faster. */ -#if defined( __SSE2__ ) || \ - defined( __x86_64__ ) || \ - defined( _M_AMD64 ) || \ - ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) +#if ( defined( __SSE2__ ) || \ + defined( __x86_64__ ) || \ + defined( _M_AMD64 ) || \ + ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) ) && \ + !defined( __VMS ) # define FT_SSE2 1 #else # define FT_SSE2 0 @@ -1427,8 +1428,10 @@ typedef ptrdiff_t FT_PtrDist; static int gray_move_to( const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + TPos x, y; @@ -1446,8 +1449,11 @@ typedef ptrdiff_t FT_PtrDist; static int gray_line_to( const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + + gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) ); return 0; } @@ -1456,8 +1462,11 @@ typedef ptrdiff_t FT_PtrDist; static int gray_conic_to( const FT_Vector* control, const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + + gray_render_conic( RAS_VAR_ control, to ); return 0; } @@ -1467,8 +1476,11 @@ typedef ptrdiff_t FT_PtrDist; gray_cubic_to( const FT_Vector* control1, const FT_Vector* control2, const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + + gray_render_cubic( RAS_VAR_ control1, control2, to ); return 0; } @@ -1666,6 +1678,8 @@ typedef ptrdiff_t FT_PtrDist; int n; /* index of contour in outline */ int first; /* index of first point in contour */ + int last; /* index of last point in contour */ + char tag; /* current point's state */ int shift; @@ -1680,18 +1694,17 @@ typedef ptrdiff_t FT_PtrDist; shift = func_interface->shift; delta = func_interface->delta; - first = 0; + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { - int last; /* index of last point in contour */ - - - FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); + FT_TRACE5(( "FT_Outline_Decompose: Contour %d\n", n )); + first = last + 1; last = outline->contours[n]; - if ( last < 0 ) + if ( last < first ) goto Invalid_Outline; + limit = outline->points + last; v_start = outline->points[first]; @@ -1874,11 +1887,9 @@ typedef ptrdiff_t FT_PtrDist; v_start.x / 64.0, v_start.y / 64.0 )); error = func_interface->line_to( &v_start, user ); - Close: + Close: if ( error ) goto Exit; - - first = last + 1; } FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); @@ -1923,7 +1934,7 @@ typedef ptrdiff_t FT_PtrDist; if ( continued ) FT_Trace_Enable(); - FT_TRACE7(( "band [%d..%d]: %ld cell%s remaining/\n", + FT_TRACE7(( "band [%d..%d]: %td cell%s remaining/\n", ras.min_ey, ras.max_ey, ras.cell_null - ras.cell_free, @@ -2156,9 +2167,12 @@ typedef ptrdiff_t FT_PtrDist; #else /* !STANDALONE_ */ static int - gray_raster_new( FT_Memory memory, - gray_PRaster* araster ) + gray_raster_new( void* memory_, + FT_Raster* araster_ ) { + FT_Memory memory = (FT_Memory)memory_; + gray_PRaster* araster = (gray_PRaster*)araster_; + FT_Error error; gray_PRaster raster = NULL; diff --git a/src/3rdparty/freetype/src/smooth/ftsmooth.c b/src/3rdparty/freetype/src/smooth/ftsmooth.c index cdbc78c3..9b0e8886 100644 --- a/src/3rdparty/freetype/src/smooth/ftsmooth.c +++ b/src/3rdparty/freetype/src/smooth/ftsmooth.c @@ -87,8 +87,10 @@ /* initialize renderer -- init its raster */ static FT_Error - ft_smooth_init( FT_Renderer render ) + ft_smooth_init( FT_Module module ) /* FT_Renderer */ { + FT_Renderer render = (FT_Renderer)module; + FT_Vector* sub = render->root.library->lcd_geometry; @@ -111,8 +113,10 @@ ft_smooth_lcd_spans( int y, int count, const FT_Span* spans, - TOrigin* target ) + void* target_ ) /* TOrigin* */ { + TOrigin* target = (TOrigin*)target_; + unsigned char* dst_line = target->origin - y * target->pitch; unsigned char* dst; unsigned short w; @@ -141,7 +145,7 @@ /* Set up direct rendering to record them on each third byte. */ params.source = outline; params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; - params.gray_spans = (FT_SpanFunc)ft_smooth_lcd_spans; + params.gray_spans = ft_smooth_lcd_spans; params.user = ⌖ params.clip_box.xMin = 0; @@ -256,8 +260,11 @@ /* initialize renderer -- init its raster */ static FT_Error - ft_smooth_init( FT_Renderer render ) + ft_smooth_init( FT_Module module ) /* FT_Renderer */ { + FT_Renderer render = (FT_Renderer)module; + + /* set up default LCD filtering */ FT_Library_SetLcdFilter( render->root.library, FT_LCD_FILTER_DEFAULT ); @@ -340,8 +347,11 @@ ft_smooth_overlap_spans( int y, int count, const FT_Span* spans, - TOrigin* target ) + void* target_ ) { + TOrigin* target = (TOrigin*)target_; + + unsigned char* dst = target->origin - ( y / SCALE ) * target->pitch; unsigned short x; unsigned int cover, sum; @@ -386,7 +396,7 @@ /* Set up direct rendering to average oversampled spans. */ params.source = outline; params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; - params.gray_spans = (FT_SpanFunc)ft_smooth_overlap_spans; + params.gray_spans = ft_smooth_overlap_spans; params.user = ⌖ params.clip_box.xMin = 0; diff --git a/src/3rdparty/freetype/src/svg/ftsvg.c b/src/3rdparty/freetype/src/svg/ftsvg.c index 7edb1a33..ba237f63 100644 --- a/src/3rdparty/freetype/src/svg/ftsvg.c +++ b/src/3rdparty/freetype/src/svg/ftsvg.c @@ -40,26 +40,31 @@ /* ft_svg_init */ static FT_Error - ft_svg_init( SVG_Renderer svg_module ) + ft_svg_init( FT_Module module ) { + SVG_Renderer render = (SVG_Renderer)module; + FT_Error error = FT_Err_Ok; - svg_module->loaded = FALSE; - svg_module->hooks_set = FALSE; + render->loaded = FALSE; + render->hooks_set = FALSE; return error; } static void - ft_svg_done( SVG_Renderer svg_module ) + ft_svg_done( FT_Module module ) { - if ( svg_module->loaded == TRUE && - svg_module->hooks_set == TRUE ) - svg_module->hooks.free_svg( &svg_module->state ); + SVG_Renderer render = (SVG_Renderer)module; - svg_module->loaded = FALSE; + + if ( render->loaded == TRUE && + render->hooks_set == TRUE ) + render->hooks.free_svg( &render->state ); + + render->loaded = FALSE; } @@ -148,7 +153,7 @@ static const SVG_Interface svg_interface = { - (Preset_Bitmap_Func)ft_svg_preset_slot + ft_svg_preset_slot /* Preset_Bitmap_Func preset_slot */ }; @@ -203,7 +208,7 @@ static FT_Error ft_svg_property_get( FT_Module module, const char* property_name, - const void* value ) + void* value ) { FT_Error error = FT_Err_Ok; SVG_Renderer renderer = (SVG_Renderer)module; @@ -226,8 +231,8 @@ FT_DEFINE_SERVICE_PROPERTIESREC( ft_svg_service_properties, - (FT_Properties_SetFunc)ft_svg_property_set, /* set_property */ - (FT_Properties_GetFunc)ft_svg_property_get /* get_property */ + ft_svg_property_set, /* FT_Properties_SetFunc set_property */ + ft_svg_property_get /* FT_Properties_GetFunc get_property */ ) @@ -333,17 +338,17 @@ (const void*)PUT_SVG_MODULE( &svg_interface ), /* module specific interface */ - (FT_Module_Constructor)PUT_SVG_MODULE( ft_svg_init ), /* module_init */ - (FT_Module_Destructor)PUT_SVG_MODULE( ft_svg_done ), /* module_done */ - PUT_SVG_MODULE( ft_svg_get_interface ), /* get_interface */ + PUT_SVG_MODULE( ft_svg_init ), /* FT_Module_Constructor module_init */ + PUT_SVG_MODULE( ft_svg_done ), /* FT_Module_Destructor module_done */ + PUT_SVG_MODULE( ft_svg_get_interface ), /* FT_Module_Requester get_interface */ SVG_GLYPH_FORMAT, - (FT_Renderer_RenderFunc) PUT_SVG_MODULE( ft_svg_render ), /* render_glyph */ - (FT_Renderer_TransformFunc)PUT_SVG_MODULE( ft_svg_transform ), /* transform_glyph */ - NULL, /* get_glyph_cbox */ - NULL, /* set_mode */ - NULL /* raster_class */ + PUT_SVG_MODULE( ft_svg_render ), /* FT_Renderer_RenderFunc render_glyph */ + PUT_SVG_MODULE( ft_svg_transform ), /* FT_Renderer_TransformFunc transform_glyph */ + NULL, /* FT_Renderer_GetCBoxFunc get_glyph_cbox */ + NULL, /* FT_Renderer_SetModeFunc set_mode */ + NULL /* FT_Raster_Funcs* raster_class */ ) diff --git a/src/3rdparty/freetype/src/tools/apinames.c b/src/3rdparty/freetype/src/tools/apinames.c index 8a8b0822..dfa258fd 100644 --- a/src/3rdparty/freetype/src/tools/apinames.c +++ b/src/3rdparty/freetype/src/tools/apinames.c @@ -18,11 +18,14 @@ #include #include +#include #include #include +#include "vms_shorten_symbol.c" + #define PROGRAM_NAME "apinames" -#define PROGRAM_VERSION "0.4" +#define PROGRAM_VERSION "0.5" #define LINEBUFF_SIZE 1024 @@ -41,9 +44,20 @@ typedef enum OutputFormat_ static void -panic( const char* message ) +panic( const char* fmt, + ... ) { - fprintf( stderr, "PANIC: %s\n", message ); + va_list ap; + + + fprintf( stderr, "PANIC: " ); + + va_start( ap, fmt ); + vfprintf( stderr, fmt, ap ); + va_end( ap ); + + fprintf( stderr, "\n" ); + exit(2); } @@ -202,12 +216,24 @@ names_dump( FILE* out, break; case OUTPUT_VMS_OPT: - fprintf( out, "GSMATCH=LEQUAL,2,0\n" - "CASE_SENSITIVE=YES\n" - "SYMBOL_VECTOR=(-\n" ); - for ( nn = 0; nn < num_names - 1; nn++ ) - fprintf( out, " %s=PROCEDURE,-\n", the_names[nn].name ); - fprintf( out, " %s=PROCEDURE)\n", the_names[num_names - 1].name ); + fprintf( out, "case_sensitive=YES\n" ); + + for ( nn = 0; nn < num_names; nn++ ) + { + char short_symbol[32]; + + + if ( vms_shorten_symbol( the_names[nn].name, short_symbol, 1 ) == -1 ) + panic( "could not shorten name '%s'", the_names[nn].name ); + fprintf( out, "symbol_vector = ( %s = PROCEDURE)\n", short_symbol ); + + /* Also emit a 64-bit symbol, as created by the `vms_auto64` tool. */ + /* It has the string '64__' appended to its name. */ + strcat( the_names[nn].name , "64__" ); + if ( vms_shorten_symbol( the_names[nn].name, short_symbol, 1 ) == -1 ) + panic( "could not shorten name '%s'", the_names[nn].name ); + fprintf( out, "symbol_vector = ( %s = PROCEDURE)\n", short_symbol ); + } break; diff --git a/src/3rdparty/freetype/src/tools/ftrandom/ftrandom.c b/src/3rdparty/freetype/src/tools/ftrandom/ftrandom.c index 4f912cd2..0ee765e5 100644 --- a/src/3rdparty/freetype/src/tools/ftrandom/ftrandom.c +++ b/src/3rdparty/freetype/src/tools/ftrandom/ftrandom.c @@ -520,7 +520,7 @@ char buffer[1024]; - sprintf( buffer, "%s/test%d", results_dir, test_num++ ); + snprintf( buffer, 1024, "%s/test%d", results_dir, test_num++ ); if ( copyfont ( &fontlist[i], buffer ) ) { diff --git a/src/3rdparty/freetype/src/tools/vms_shorten_symbol.c b/src/3rdparty/freetype/src/tools/vms_shorten_symbol.c new file mode 100644 index 00000000..81f2a718 --- /dev/null +++ b/src/3rdparty/freetype/src/tools/vms_shorten_symbol.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2010, 2017 Craig A. Berry + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* vms_shorten_symbol + * + * This program provides shortening of long symbols (> 31 characters) using the + * same mechanism as the OpenVMS C compiler. The basic procedure is to compute + * an AUTODIN II checksum of the entire symbol, encode the checksum in base32, + * and glue together a shortened symbol from the first 23 characters of the + * original symbol plus the encoded checksum appended. The output format is + * the same used in the name mangler database, stored by default in + * [.CXX_REPOSITORY]CXX$DEMANGLER_DB. + * + * To obtain the same result as CC/NAMES=SHORTENED, run like so: + * + * $ mcr []vms_shorten_symbol "Please_forgive_this_absurdly_long_symbol_name" + * PLEASE_FORGIVE_THIS_ABS1ARO4QU$Please_forgive_this_absurdly_long_symbol_name + * + * To obtain the same result as CC/NAMES=(SHORTENED,AS_IS), pass a non-zero + * value as the second argument, like so: + * + * $ mcr []vms_shorten_symbol "Please_forgive_this_absurdly_long_symbol_name" 1 + * Please_forgive_this_abs3rv8rnn$Please_forgive_this_absurdly_long_symbol_name + */ + +#include +#include +#include +#include + +#ifdef __VMS +#define UINT32 unsigned int +#else +#include +#define UINT32 uint32_t +#endif + +extern UINT32 crc32(const char *input_string); +extern int u32_to_base32(UINT32 input, char *output); +extern int vms_shorten_symbol(const char *symbol, char *shortened, char as_is_flag); + +/* + * This routine implements the AUTODIN II polynomial. + */ + +UINT32 +crc32(const char *input_string) +{ + +/* + * CRC code and data based partly on FreeBSD implementation, which + * notes: + * + * The crc32 functions and data was originally written by Spencer + * Garrett and was cleaned from the PostgreSQL source + * tree via the files contrib/ltree/crc32.[ch]. No license was + * included, therefore it is assumed that this code is public + * domain. Attribution still noted. + * + * (I think they mean "gleaned" not "cleaned".) + */ + + static const UINT32 autodin_ii_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + }; + + UINT32 crc = ~0U; + char *c; + for (c = (char *)input_string; *c; ++c) + crc = (crc >> 8) ^ autodin_ii_table[(crc ^ *c) & 0xff]; + return ~crc; +} + +/* + * This is the RFC2938 variant of base32, not RFC3548, Crockford's, or + * other newer variant. It produces an 8-byte encoded character string + * (plus trailing null) from a 32-bit integer input. + */ + +int +u32_to_base32(UINT32 input, char *output) +{ + static const char base32hex_table[32] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v' + }; + int i; + + /* + * Grab lowest 5 bits and look up conversion in table. Lather, rinse, + * repeat for a total of 7, 5-bit chunks to accommodate 32 bits of input. + */ + for (i = 0; i < 7; i++) { + output[6 - i] = base32hex_table[input & 0x1f]; + input >>= 5; /* position to look at next 5 */ + } + output[7] = '$'; /* It's DEC, so use '$' not '=' to pad. */ + output[8] = '\0'; + return 0; +} + +/* + * Take an input symbol name of arbitrary length and produce a symbol shortened + * to 31 characters. The shortened symbol consists of the first 23 characters + * of the original symbol plus the 8 characters of the encoded checksum. The + * third argument is a boolean indicating whether to emulate the compiler's + * /NAMES=AS_IS option. When false (the compiler's default), the shortened + * symbol will be upper cased. When the original symbol is 31 characters or + * fewer in length, no checksum will be appended and the original symbol is + * returned verbatim (though upper cased if the as_is_flag is false). + */ + +int +vms_shorten_symbol(const char *input_symbol, char *shortened, char as_is_flag) +{ + char b32str[9]; + UINT32 crc; + char *c, *symbol; + int symlen; + + symlen = strlen(input_symbol); + symbol = (char *)malloc(symlen + 1); + if (symbol == NULL) + return -1; + + strncpy(symbol, input_symbol, symlen); + symbol[symlen] = '\0'; + + if (!as_is_flag) { + for (c = symbol; *c; c++) + *c = toupper(*c); + } + + if (symlen <= 31) { + strncpy(shortened, symbol, symlen); + shortened[symlen] = '\0'; + free(symbol); + return 0; + } + + /* + * Compute the checksum on the whole symbol. + */ + + crc = crc32(symbol); + + /* The compiler does not use the inverted checksum, so we invert it + * back before encoding in base32. + */ + + if (u32_to_base32(~crc, (char *)&b32str) == -1) { + free(symbol); + return -1; + } + + if (!as_is_flag) { + for (c = (char *)&b32str; *c; c++) + *c = toupper(*c); + } + + sprintf(shortened, "%.23s%.8s", symbol, b32str); + shortened[31] = '\0'; + free(symbol); + return 0; +} + +#ifdef TEST_MAIN +int +main(int argc, char **argv) +{ + char short_symbol[32]; + char as_is_flag = 0; + + if (argc < 2) { + fprintf(stderr, "Usage: %s []\n", argv[0]); + exit(EXIT_FAILURE); + } + if (argc > 2) + as_is_flag = 1; + + if (vms_shorten_symbol(argv[1], (char *)&short_symbol, as_is_flag) == -1) { + fprintf(stderr, "Symbol shortening failed\n"); + exit(EXIT_FAILURE); + } + + printf("%s%s\n", (char *)&short_symbol, argv[1]); +} +#endif diff --git a/src/3rdparty/freetype/src/truetype/rules.mk b/src/3rdparty/freetype/src/truetype/rules.mk index 23f6f006..dde26de1 100644 --- a/src/3rdparty/freetype/src/truetype/rules.mk +++ b/src/3rdparty/freetype/src/truetype/rules.mk @@ -33,8 +33,7 @@ TT_DRV_SRC := $(TT_DIR)/ttdriver.c \ $(TT_DIR)/ttgxvar.c \ $(TT_DIR)/ttinterp.c \ $(TT_DIR)/ttobjs.c \ - $(TT_DIR)/ttpload.c \ - $(TT_DIR)/ttsubpix.c + $(TT_DIR)/ttpload.c # TrueType driver headers # diff --git a/src/3rdparty/freetype/src/truetype/truetype.c b/src/3rdparty/freetype/src/truetype/truetype.c index c5faa962..fcc0ea33 100644 --- a/src/3rdparty/freetype/src/truetype/truetype.c +++ b/src/3rdparty/freetype/src/truetype/truetype.c @@ -24,7 +24,6 @@ #include "ttinterp.c" #include "ttobjs.c" /* object manager */ #include "ttpload.c" /* tables loader */ -#include "ttsubpix.c" /* END */ diff --git a/src/3rdparty/freetype/src/truetype/ttdriver.c b/src/3rdparty/freetype/src/truetype/ttdriver.c index 4bea63ef..d1496fec 100644 --- a/src/3rdparty/freetype/src/truetype/ttdriver.c +++ b/src/3rdparty/freetype/src/truetype/ttdriver.c @@ -57,7 +57,7 @@ * PROPERTY SERVICE * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_property_set( FT_Module module, /* TT_Driver */ const char* property_name, const void* value, @@ -93,17 +93,22 @@ interpreter_version = *iv; } - if ( interpreter_version == TT_INTERPRETER_VERSION_35 -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - || interpreter_version == TT_INTERPRETER_VERSION_38 -#endif + switch ( interpreter_version ) + { + case TT_INTERPRETER_VERSION_35: + driver->interpreter_version = TT_INTERPRETER_VERSION_35; + break; + + case TT_INTERPRETER_VERSION_38: + case TT_INTERPRETER_VERSION_40: #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - || interpreter_version == TT_INTERPRETER_VERSION_40 + driver->interpreter_version = TT_INTERPRETER_VERSION_40; + break; #endif - ) - driver->interpreter_version = interpreter_version; - else + + default: error = FT_ERR( Unimplemented_Feature ); + } return error; } @@ -114,10 +119,10 @@ } - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_property_get( FT_Module module, /* TT_Driver */ const char* property_name, - const void* value ) + void* value ) { FT_Error error = FT_Err_Ok; TT_Driver driver = (TT_Driver)module; @@ -144,8 +149,8 @@ FT_DEFINE_SERVICE_PROPERTIESREC( tt_service_properties, - (FT_Properties_SetFunc)tt_property_set, /* set_property */ - (FT_Properties_GetFunc)tt_property_get /* get_property */ + tt_property_set, /* FT_Properties_SetFunc set_property */ + tt_property_get /* FT_Properties_GetFunc get_property */ ) @@ -198,35 +203,35 @@ * * They can be implemented by format-specific interfaces. */ - static FT_Error - tt_get_kerning( FT_Face ttface, /* TT_Face */ + FT_CALLBACK_DEF( FT_Error ) + tt_get_kerning( FT_Face face, /* TT_Face */ FT_UInt left_glyph, FT_UInt right_glyph, FT_Vector* kerning ) { - TT_Face face = (TT_Face)ttface; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + TT_Face ttface = (TT_Face)face; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; kerning->x = 0; kerning->y = 0; if ( sfnt ) - kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); + kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph ); return 0; } - static FT_Error - tt_get_advances( FT_Face ttface, + FT_CALLBACK_DEF( FT_Error ) + tt_get_advances( FT_Face face, /* TT_Face */ FT_UInt start, FT_UInt count, FT_Int32 flags, FT_Fixed *advances ) { FT_UInt nn; - TT_Face face = (TT_Face)ttface; + TT_Face ttface = (TT_Face)face; /* XXX: TODO: check for sbits */ @@ -235,8 +240,8 @@ { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without VVAR table */ - if ( ( FT_IS_NAMED_INSTANCE( ttface ) || FT_IS_VARIATION( ttface ) ) && - !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && + !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -247,7 +252,7 @@ /* since we don't need `tsb', we use zero for `yMax' parameter */ - TT_Get_VMetrics( face, start + nn, 0, &tsb, &ah ); + TT_Get_VMetrics( ttface, start + nn, 0, &tsb, &ah ); advances[nn] = ah; } } @@ -255,8 +260,8 @@ { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without HVAR table */ - if ( ( FT_IS_NAMED_INSTANCE( ttface ) || FT_IS_VARIATION( ttface ) ) && - !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && + !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -266,7 +271,7 @@ FT_UShort aw; - TT_Get_HMetrics( face, start + nn, &lsb, &aw ); + TT_Get_HMetrics( ttface, start + nn, &lsb, &aw ); advances[nn] = aw; } } @@ -290,7 +295,7 @@ #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_size_select( FT_Size size, FT_ULong strike_index ) { @@ -306,7 +311,7 @@ /* use the scaled metrics, even when tt_size_reset fails */ FT_Select_Metrics( size->face, strike_index ); - tt_size_reset( ttsize, 0 ); /* ignore return value */ + tt_size_reset( ttsize ); /* ignore return value */ } else { @@ -327,7 +332,7 @@ #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_size_request( FT_Size size, FT_Size_Request req ) { @@ -367,7 +372,7 @@ if ( FT_IS_SCALABLE( size->face ) ) { - error = tt_size_reset( ttsize, 0 ); + error = tt_size_reset( ttsize ); #ifdef TT_USE_BYTECODE_INTERPRETER /* for the `MPS' bytecode instruction we need the point size */ @@ -426,15 +431,15 @@ * @Return: * FreeType error code. 0 means success. */ - static FT_Error - tt_glyph_load( FT_GlyphSlot ttslot, /* TT_GlyphSlot */ - FT_Size ttsize, /* TT_Size */ + FT_CALLBACK_DEF( FT_Error ) + tt_glyph_load( FT_GlyphSlot slot, /* TT_GlyphSlot */ + FT_Size size, /* TT_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { - TT_GlyphSlot slot = (TT_GlyphSlot)ttslot; - TT_Size size = (TT_Size)ttsize; - FT_Face face = ttslot->face; + TT_GlyphSlot ttslot = (TT_GlyphSlot)slot; + TT_Size ttsize = (TT_Size)size; + FT_Face face = ttslot->face; FT_Error error; @@ -476,12 +481,12 @@ } /* use hinted metrics only if we load a glyph with hinting */ - size->metrics = ( load_flags & FT_LOAD_NO_HINTING ) - ? &ttsize->metrics - : &size->hinted_metrics; + ttsize->metrics = ( load_flags & FT_LOAD_NO_HINTING ) + ? &size->metrics + : &ttsize->hinted_metrics; /* now fill in the glyph slot with outline/bitmap/layered */ - error = TT_Load_Glyph( size, slot, glyph_index, load_flags ); + error = TT_Load_Glyph( ttsize, ttslot, glyph_index, load_flags ); /* force drop-out mode to 2 - irrelevant now */ /* slot->outline.dropout_mode = 2; */ @@ -507,49 +512,47 @@ FT_DEFINE_SERVICE_MULTIMASTERSREC( tt_service_gx_multi_masters, - (FT_Get_MM_Func) NULL, /* get_mm */ - (FT_Set_MM_Design_Func) NULL, /* set_mm_design */ - (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, /* set_mm_blend */ - (FT_Get_MM_Blend_Func) TT_Get_MM_Blend, /* get_mm_blend */ - (FT_Get_MM_Var_Func) TT_Get_MM_Var, /* get_mm_var */ - (FT_Set_Var_Design_Func)TT_Set_Var_Design, /* set_var_design */ - (FT_Get_Var_Design_Func)TT_Get_Var_Design, /* get_var_design */ - (FT_Set_Instance_Func) TT_Set_Named_Instance, /* set_instance */ - (FT_Set_MM_WeightVector_Func) - NULL, /* set_mm_weightvector */ - (FT_Get_MM_WeightVector_Func) - NULL, /* get_mm_weightvector */ - (FT_Var_Load_Delta_Set_Idx_Map_Func) - tt_var_load_delta_set_index_mapping, - /* load_delta_set_idx_map */ - (FT_Var_Load_Item_Var_Store_Func) - tt_var_load_item_variation_store, - /* load_item_variation_store */ - (FT_Var_Get_Item_Delta_Func) - tt_var_get_item_delta, /* get_item_delta */ - (FT_Var_Done_Item_Var_Store_Func) - tt_var_done_item_variation_store, - /* done_item_variation_store */ - (FT_Var_Done_Delta_Set_Idx_Map_Func) - tt_var_done_delta_set_index_map, - /* done_delta_set_index_map */ - (FT_Get_Var_Blend_Func) tt_get_var_blend, /* get_var_blend */ - (FT_Done_Blend_Func) tt_done_blend /* done_blend */ + NULL, /* FT_Get_MM_Func get_mm */ + NULL, /* FT_Set_MM_Design_Func set_mm_design */ + TT_Set_MM_Blend, /* FT_Set_MM_Blend_Func set_mm_blend */ + TT_Get_MM_Blend, /* FT_Get_MM_Blend_Func get_mm_blend */ + TT_Get_MM_Var, /* FT_Get_MM_Var_Func get_mm_var */ + TT_Set_Var_Design, /* FT_Set_Var_Design_Func set_var_design */ + TT_Get_Var_Design, /* FT_Get_Var_Design_Func get_var_design */ + TT_Set_Named_Instance, /* FT_Set_Named_Instance_Func set_named_instance */ + TT_Get_Default_Named_Instance, + /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ + NULL, /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ + NULL, /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ + + tt_construct_ps_name, /* FT_Construct_PS_Name_Func construct_ps_name */ + tt_var_load_delta_set_index_mapping, + /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ + tt_var_load_item_variation_store, + /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ + tt_var_get_item_delta, /* FT_Var_Get_Item_Delta_Func get_item_delta */ + tt_var_done_item_variation_store, + /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ + tt_var_done_delta_set_index_map, + /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ + tt_get_var_blend, /* FT_Get_Var_Blend_Func get_var_blend */ + tt_done_blend /* FT_Done_Blend_Func done_blend */ ) FT_DEFINE_SERVICE_METRICSVARIATIONSREC( tt_service_metrics_variations, - (FT_HAdvance_Adjust_Func)tt_hadvance_adjust, /* hadvance_adjust */ - (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ - (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ + tt_hadvance_adjust, /* FT_HAdvance_Adjust_Func hadvance_adjust */ + NULL, /* FT_LSB_Adjust_Func lsb_adjust */ + NULL, /* FT_RSB_Adjust_Func rsb_adjust */ - (FT_VAdvance_Adjust_Func)tt_vadvance_adjust, /* vadvance_adjust */ - (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ - (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ - (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ + tt_vadvance_adjust, /* FT_VAdvance_Adjust_Func vadvance_adjust */ + NULL, /* FT_TSB_Adjust_Func tsb_adjust */ + NULL, /* FT_BSB_Adjust_Func bsb_adjust */ + NULL, /* FT_VOrg_Adjust_Func vorg_adjust */ - (FT_Metrics_Adjust_Func) tt_apply_mvar /* metrics_adjust */ + tt_apply_mvar, /* FT_Metrics_Adjust_Func metrics_adjust */ + tt_size_reset_height /* FT_Size_Reset_Func size_reset */ ) #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/src/3rdparty/freetype/src/truetype/ttgload.c b/src/3rdparty/freetype/src/truetype/ttgload.c index d33bdad6..dc427e8a 100644 --- a/src/3rdparty/freetype/src/truetype/ttgload.c +++ b/src/3rdparty/freetype/src/truetype/ttgload.c @@ -35,7 +35,6 @@ #endif #include "tterrors.h" -#include "ttsubpix.h" /************************************************************************** @@ -152,9 +151,6 @@ FT_UInt glyph_index ) { TT_Face face = loader->face; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); -#endif FT_Error error; FT_Stream stream = loader->stream; @@ -183,20 +179,6 @@ loader->top_bearing = top_bearing; loader->vadvance = advance_height; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 && - loader->exec ) - { - loader->exec->sph_tweak_flags = 0; - - /* This may not be the right place for this, but it works... */ - /* Note that we have to unconditionally load the tweaks since */ - /* it is possible that glyphs individually switch ClearType's */ - /* backward compatibility mode on and off. */ - sph_set_tweaks( loader, glyph_index ); - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - #ifdef FT_CONFIG_OPTION_INCREMENTAL /* With the incremental interface, these values are set by */ /* a call to `tt_get_metrics_incremental'. */ @@ -362,17 +344,16 @@ FT_Byte* p = load->cursor; FT_Byte* limit = load->limit; FT_GlyphLoader gloader = load->gloader; + FT_Outline* outline = &gloader->current.outline; FT_Int n_contours = load->n_contours; - FT_Outline* outline; - FT_UShort n_ins; FT_Int n_points; + FT_UShort n_ins; FT_Byte *flag, *flag_limit; FT_Byte c, count; FT_Vector *vec, *vec_limit; FT_Pos x, y; - FT_Short *cont, *cont_limit, prev_cont; - FT_Int xy_size = 0; + FT_Short *cont, *cont_limit, last; /* check that we can add the contours to the glyph */ @@ -380,40 +361,26 @@ if ( error ) goto Fail; + /* check space for contours array + instructions count */ + if ( n_contours >= 0xFFF || p + 2 * n_contours + 2 > limit ) + goto Invalid_Outline; + /* reading the contours' endpoints & number of points */ - cont = gloader->current.outline.contours; + cont = outline->contours; cont_limit = cont + n_contours; - /* check space for contours array + instructions count */ - if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit ) - goto Invalid_Outline; - - prev_cont = FT_NEXT_SHORT( p ); - - if ( n_contours > 0 ) - cont[0] = prev_cont; - - if ( prev_cont < 0 ) - goto Invalid_Outline; - - for ( cont++; cont < cont_limit; cont++ ) + last = -1; + for ( ; cont < cont_limit; cont++ ) { - cont[0] = FT_NEXT_SHORT( p ); - if ( cont[0] <= prev_cont ) - { - /* unordered contours: this is invalid */ + *cont = FT_NEXT_SHORT( p ); + + if ( *cont <= last ) goto Invalid_Outline; - } - prev_cont = cont[0]; + + last = *cont; } - n_points = 0; - if ( n_contours > 0 ) - { - n_points = cont[-1] + 1; - if ( n_points < 0 ) - goto Invalid_Outline; - } + n_points = last + 1; FT_TRACE5(( " # of points: %d\n", n_points )); @@ -422,59 +389,48 @@ if ( error ) goto Fail; - /* reading the bytecode instructions */ - load->glyph->control_len = 0; - load->glyph->control_data = NULL; - - if ( p + 2 > limit ) - goto Invalid_Outline; - + /* space checked above */ n_ins = FT_NEXT_USHORT( p ); FT_TRACE5(( " Instructions size: %u\n", n_ins )); + /* check instructions size */ + if ( p + n_ins > limit ) + { + FT_TRACE1(( "TT_Load_Simple_Glyph: excessive instruction count\n" )); + error = FT_THROW( Too_Many_Hints ); + goto Fail; + } + #ifdef TT_USE_BYTECODE_INTERPRETER if ( IS_HINTED( load->load_flags ) ) { - FT_ULong tmp; + TT_ExecContext exec = load->exec; + FT_Memory memory = exec->memory; - /* check instructions size */ - if ( ( limit - p ) < n_ins ) - { - FT_TRACE1(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); - error = FT_THROW( Too_Many_Hints ); - goto Fail; - } + if ( exec->glyphSize ) + FT_FREE( exec->glyphIns ); + exec->glyphSize = 0; /* we don't trust `maxSizeOfInstructions' in the `maxp' table */ - /* and thus update the bytecode array size by ourselves */ - - tmp = load->exec->glyphSize; - error = Update_Max( load->exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&load->exec->glyphIns, - n_ins ); - - load->exec->glyphSize = (FT_UInt)tmp; - if ( error ) - return error; - - load->glyph->control_len = n_ins; - load->glyph->control_data = load->exec->glyphIns; - + /* and thus allocate the bytecode array size by ourselves */ if ( n_ins ) - FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins ); + { + if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) ) + return error; + + FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins ); + + exec->glyphSize = n_ins; + } } #endif /* TT_USE_BYTECODE_INTERPRETER */ p += n_ins; - outline = &gloader->current.outline; - /* reading the point tags */ flag = (FT_Byte*)outline->tags; flag_limit = flag + n_points; @@ -512,9 +468,6 @@ flag = (FT_Byte*)outline->tags; x = 0; - if ( p + xy_size > limit ) - goto Invalid_Outline; - for ( ; vec < vec_limit; vec++, flag++ ) { FT_Pos delta = 0; @@ -544,7 +497,7 @@ /* reading the Y coordinates */ - vec = gloader->current.outline.points; + vec = outline->points; vec_limit = vec + n_points; flag = (FT_Byte*)outline->tags; y = 0; @@ -827,8 +780,7 @@ TT_Hint_Glyph( TT_Loader loader, FT_Bool is_composite ) { -#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \ - defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL TT_Face face = loader->face; TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); #endif @@ -836,35 +788,34 @@ TT_GlyphZone zone = &loader->zone; #ifdef TT_USE_BYTECODE_INTERPRETER - FT_Long n_ins; + TT_ExecContext exec = loader->exec; + FT_Long n_ins = exec->glyphSize; #else FT_UNUSED( is_composite ); #endif #ifdef TT_USE_BYTECODE_INTERPRETER - n_ins = loader->glyph->control_len; - /* save original point positions in `org' array */ if ( n_ins > 0 ) FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points ); /* Reset graphics state. */ - loader->exec->GS = loader->size->GS; + exec->GS = loader->size->GS; /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */ /* completely refer to the (already) hinted subglyphs. */ if ( is_composite ) { - loader->exec->metrics.x_scale = 1 << 16; - loader->exec->metrics.y_scale = 1 << 16; + exec->metrics.x_scale = 1 << 16; + exec->metrics.y_scale = 1 << 16; FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points ); } else { - loader->exec->metrics.x_scale = loader->size->metrics->x_scale; - loader->exec->metrics.y_scale = loader->size->metrics->y_scale; + exec->metrics.x_scale = loader->size->metrics->x_scale; + exec->metrics.y_scale = loader->size->metrics->y_scale; } #endif @@ -884,53 +835,37 @@ { FT_Error error; - FT_GlyphLoader gloader = loader->gloader; - FT_Outline current_outline = gloader->current.outline; + TT_Set_CodeRange( exec, tt_coderange_glyph, exec->glyphIns, n_ins ); - TT_Set_CodeRange( loader->exec, tt_coderange_glyph, - loader->exec->glyphIns, n_ins ); + exec->is_composite = is_composite; + exec->pts = *zone; - loader->exec->is_composite = is_composite; - loader->exec->pts = *zone; - - error = TT_Run_Context( loader->exec ); - if ( error && loader->exec->pedantic_hinting ) + error = TT_Run_Context( exec ); + if ( error && exec->pedantic_hinting ) return error; /* store drop-out mode in bits 5-7; set bit 2 also as a marker */ - current_outline.tags[0] |= - ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; + loader->gloader->current.outline.tags[0] |= + ( exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; } #endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* Save possibly modified glyph phantom points unless in v40 backward */ /* compatibility mode, where no movement on the x axis means no reason */ /* to change bearings or advance widths. */ - if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - loader->exec->backward_compatibility ) ) - { -#endif - loader->pp1 = zone->cur[zone->n_points - 4]; - loader->pp2 = zone->cur[zone->n_points - 3]; - loader->pp3 = zone->cur[zone->n_points - 2]; - loader->pp4 = zone->cur[zone->n_points - 1]; + #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - } + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && + exec->backward_compatibility ) + return FT_Err_Ok; #endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN ) - FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 ); - - else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN ) - FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 ); - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ + loader->pp1 = zone->cur[zone->n_points - 4]; + loader->pp2 = zone->cur[zone->n_points - 3]; + loader->pp3 = zone->cur[zone->n_points - 2]; + loader->pp4 = zone->cur[zone->n_points - 1]; return FT_Err_Ok; } @@ -949,10 +884,10 @@ static FT_Error TT_Process_Simple_Glyph( TT_Loader loader ) { - FT_GlyphLoader gloader = loader->gloader; - FT_Error error = FT_Err_Ok; - FT_Outline* outline; - FT_Int n_points; + FT_Error error = FT_Err_Ok; + FT_GlyphLoader gloader = loader->gloader; + FT_Outline* outline = &gloader->current.outline; + FT_Int n_points = outline->n_points; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_Memory memory = loader->face->root.memory; @@ -960,11 +895,7 @@ #endif - outline = &gloader->current.outline; - n_points = outline->n_points; - /* set phantom points */ - outline->points[n_points ] = loader->pp1; outline->points[n_points + 1] = loader->pp2; outline->points[n_points + 2] = loader->pp3; @@ -976,7 +907,7 @@ if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) ) { - if ( FT_NEW_ARRAY( unrounded, n_points ) ) + if ( FT_QNEW_ARRAY( unrounded, n_points ) ) goto Exit; /* Deltas apply to the unscaled data. */ @@ -998,16 +929,6 @@ } { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - TT_Face face = loader->face; - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); - - FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics->x_ppem; - FT_String* style = face->root.style_name; - FT_UInt x_scale_factor = 1000; -#endif - FT_Vector* vec = outline->points; FT_Vector* limit = outline->points + n_points; @@ -1017,52 +938,6 @@ FT_Bool do_scale = FALSE; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - /* scale, but only if enabled and only if TT hinting is being used */ - if ( IS_HINTED( loader->load_flags ) ) - x_scale_factor = sph_test_tweak_x_scaling( face, - family, - ppem, - style, - loader->glyph_index ); - /* scale the glyph */ - if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 || - x_scale_factor != 1000 ) - { - x_scale = FT_MulDiv( loader->size->metrics->x_scale, - (FT_Long)x_scale_factor, 1000 ); - y_scale = loader->size->metrics->y_scale; - - /* compensate for any scaling by de/emboldening; */ - /* the amount was determined via experimentation */ - if ( x_scale_factor != 1000 && ppem > 11 ) - { -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_Vector* orig_points = outline->points; - - - if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) ) - outline->points = unrounded; -#endif - FT_Outline_EmboldenXY( outline, - FT_MulFix( 1280 * ppem, - 1000 - x_scale_factor ), - 0 ); -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) ) - outline->points = orig_points; -#endif - } - do_scale = TRUE; - } - } - else - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - { /* scale the glyph */ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) @@ -1331,12 +1206,12 @@ FT_UInt start_contour ) { FT_Error error; - FT_Outline* outline; + FT_Outline* outline = &loader->gloader->base.outline; + FT_Stream stream = loader->stream; + FT_UShort n_ins; FT_UInt i; - outline = &loader->gloader->base.outline; - /* make room for phantom points */ error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader, outline->n_points + 4, @@ -1352,11 +1227,14 @@ #ifdef TT_USE_BYTECODE_INTERPRETER { - FT_Stream stream = loader->stream; - FT_UShort n_ins, max_ins; - FT_ULong tmp; + TT_ExecContext exec = loader->exec; + FT_Memory memory = exec->memory; + if ( exec->glyphSize ) + FT_FREE( exec->glyphIns ); + exec->glyphSize = 0; + /* TT_Load_Composite_Glyph only gives us the offset of instructions */ /* so we read them here */ if ( FT_STREAM_SEEK( loader->ins_pos ) || @@ -1365,39 +1243,24 @@ FT_TRACE5(( " Instructions size = %hu\n", n_ins )); - /* check it */ - max_ins = loader->face->max_profile.maxSizeOfInstructions; - if ( n_ins > max_ins ) - { - /* don't trust `maxSizeOfInstructions'; */ - /* only do a rough safety check */ - if ( n_ins > loader->byte_len ) - { - FT_TRACE1(( "TT_Process_Composite_Glyph:" - " too many instructions (%hu) for glyph with length %u\n", - n_ins, loader->byte_len )); - return FT_THROW( Too_Many_Hints ); - } - - tmp = loader->exec->glyphSize; - error = Update_Max( loader->exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&loader->exec->glyphIns, - n_ins ); - - loader->exec->glyphSize = (FT_UShort)tmp; - if ( error ) - return error; - } - else if ( n_ins == 0 ) + if ( !n_ins ) return FT_Err_Ok; - if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) ) + /* don't trust `maxSizeOfInstructions'; */ + /* only do a rough safety check */ + if ( n_ins > loader->byte_len ) + { + FT_TRACE1(( "TT_Process_Composite_Glyph:" + " too many instructions (%hu) for glyph with length %u\n", + n_ins, loader->byte_len )); + return FT_THROW( Too_Many_Hints ); + } + + if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) || + FT_STREAM_READ( exec->glyphIns, n_ins ) ) return error; - loader->glyph->control_data = loader->exec->glyphIns; - loader->glyph->control_len = n_ins; + exec->glyphSize = n_ins; } #endif @@ -1501,45 +1364,31 @@ static void tt_loader_set_pp( TT_Loader loader ) { - FT_Bool subpixel_hinting = 0; - FT_Bool grayscale = 0; - FT_Bool use_aw_2 = 0; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face ); -#endif - - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting - : 0; - grayscale = loader->exec ? loader->exec->grayscale - : 0; - } -#endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) - { - subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting_lean - : 0; - grayscale = loader->exec ? loader->exec->grayscale_cleartype - : 0; - } -#endif - - use_aw_2 = FT_BOOL( subpixel_hinting && grayscale ); - loader->pp1.x = loader->bbox.xMin - loader->left_bearing; loader->pp1.y = 0; loader->pp2.x = loader->pp1.x + loader->advance; loader->pp2.y = 0; - loader->pp3.x = use_aw_2 ? loader->advance / 2 : 0; + loader->pp3.x = 0; loader->pp3.y = loader->bbox.yMax + loader->top_bearing; - loader->pp4.x = use_aw_2 ? loader->advance / 2 : 0; + loader->pp4.x = 0; loader->pp4.y = loader->pp3.y - loader->vadvance; + +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + { + TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face ); + + + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && + loader->exec && + loader->exec->subpixel_hinting_lean && + loader->exec->grayscale_cleartype ) + { + loader->pp3.x = loader->advance / 2; + loader->pp4.x = loader->advance / 2; + } + } +#endif } @@ -1662,8 +1511,14 @@ else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ + { + FT_ULong len; - offset = tt_face_get_location( face, glyph_index, &loader->byte_len ); + + offset = tt_face_get_location( FT_FACE( face ), glyph_index, &len ); + + loader->byte_len = (FT_UInt)len; + } if ( loader->byte_len > 0 ) { @@ -1889,10 +1744,7 @@ short i, limit; FT_SubGlyph subglyph; - FT_Outline outline; - FT_Vector* points = NULL; - char* tags = NULL; - short* contours = NULL; + FT_Outline outline = { 0, 0, NULL, NULL, NULL, 0 }; FT_Vector* unrounded = NULL; @@ -1900,18 +1752,14 @@ /* construct an outline structure for */ /* communication with `TT_Vary_Apply_Glyph_Deltas' */ - outline.n_contours = outline.n_points = limit; - - outline.points = NULL; - outline.tags = NULL; - outline.contours = NULL; - - if ( FT_NEW_ARRAY( points, limit + 4 ) || - FT_NEW_ARRAY( tags, limit + 4 ) || - FT_NEW_ARRAY( contours, limit + 4 ) || - FT_NEW_ARRAY( unrounded, limit + 4 ) ) + if ( FT_QNEW_ARRAY( outline.points, limit + 4 ) || + FT_QNEW_ARRAY( outline.tags, limit ) || + FT_QNEW_ARRAY( outline.contours, limit ) || + FT_QNEW_ARRAY( unrounded, limit + 4 ) ) goto Exit1; + outline.n_contours = outline.n_points = limit; + subglyph = gloader->current.subglyphs; for ( i = 0; i < limit; i++, subglyph++ ) @@ -1919,20 +1767,16 @@ /* applying deltas for anchor points doesn't make sense, */ /* but we don't have to specially check this since */ /* unused delta values are zero anyways */ - points[i].x = subglyph->arg1; - points[i].y = subglyph->arg2; - tags[i] = 1; - contours[i] = i; + outline.points[i].x = subglyph->arg1; + outline.points[i].y = subglyph->arg2; + outline.tags[i] = ON_CURVE_POINT; + outline.contours[i] = i; } - points[i++] = loader->pp1; - points[i++] = loader->pp2; - points[i++] = loader->pp3; - points[i ] = loader->pp4; - - outline.points = points; - outline.tags = tags; - outline.contours = contours; + outline.points[i++] = loader->pp1; + outline.points[i++] = loader->pp2; + outline.points[i++] = loader->pp3; + outline.points[i ] = loader->pp4; /* this call provides additional offsets */ /* for each component's translation */ @@ -1947,8 +1791,8 @@ { if ( subglyph->flags & ARGS_ARE_XY_VALUES ) { - subglyph->arg1 = (FT_Int16)points[i].x; - subglyph->arg2 = (FT_Int16)points[i].y; + subglyph->arg1 = (FT_Int16)outline.points[i].x; + subglyph->arg2 = (FT_Int16)outline.points[i].y; } } @@ -2332,8 +2176,7 @@ #ifdef TT_USE_BYTECODE_INTERPRETER FT_Error error; FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); -#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \ - defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face ); #endif #endif @@ -2353,20 +2196,6 @@ FT_Bool grayscale_cleartype; #endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - FT_Bool subpixel_hinting = FALSE; - -#if 0 - /* not used yet */ - FT_Bool compatible_widths; - FT_Bool symmetrical_smoothing; - FT_Bool bgr; - FT_Bool vertical_lcd; - FT_Bool subpixel_positioned; - FT_Bool gray_cleartype; -#endif -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - FT_Bool reexecute = FALSE; @@ -2386,6 +2215,9 @@ if ( !exec ) return FT_THROW( Could_Not_Find_Context ); + grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != + FT_RENDER_MODE_MONO ); + #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) { @@ -2402,6 +2234,7 @@ FT_BOOL( subpixel_hinting_lean && ( load_flags & FT_LOAD_TARGET_LCD_V ) ); + grayscale = FT_BOOL( grayscale && !subpixel_hinting_lean ); } else { @@ -2411,111 +2244,11 @@ } #endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) != - FT_RENDER_MODE_MONO ) && - SPH_OPTION_SET_SUBPIXEL ); - - if ( subpixel_hinting ) - grayscale = FALSE; - else if ( SPH_OPTION_SET_GRAYSCALE ) - { - grayscale = TRUE; - subpixel_hinting = FALSE; - } - else - grayscale = FALSE; - - if ( FT_IS_TRICKY( glyph->face ) ) - subpixel_hinting = FALSE; - - exec->ignore_x_mode = subpixel_hinting || grayscale; - exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) - exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - -#if 1 - exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS; - exec->symmetrical_smoothing = TRUE; - exec->bgr = FALSE; - exec->vertical_lcd = FALSE; - exec->subpixel_positioned = TRUE; - exec->gray_cleartype = FALSE; -#else /* 0 */ - exec->compatible_widths = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_COMPATIBLE_WIDTHS ); - exec->symmetrical_smoothing = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_SYMMETRICAL_SMOOTHING ); - exec->bgr = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_BGR ); - exec->vertical_lcd = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_VERTICAL_LCD ); - exec->subpixel_positioned = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_SUBPIXEL_POSITIONED ); - exec->gray_cleartype = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_GRAY_CLEARTYPE ); -#endif /* 0 */ - - } - else - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) - grayscale = FT_BOOL( !subpixel_hinting_lean && - FT_LOAD_TARGET_MODE( load_flags ) != - FT_RENDER_MODE_MONO ); - else -#endif - grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - FT_RENDER_MODE_MONO ); - error = TT_Load_Context( exec, face, size ); if ( error ) return error; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) { - /* a change from mono to subpixel rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( subpixel_hinting != exec->subpixel_hinting ) - { - FT_TRACE4(( "tt_loader_init: subpixel hinting change," - " re-executing `prep' table\n" )); - - exec->subpixel_hinting = subpixel_hinting; - reexecute = TRUE; - } - - /* a change from mono to grayscale rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( grayscale != exec->grayscale ) - { - FT_TRACE4(( "tt_loader_init: grayscale hinting change," - " re-executing `prep' table\n" )); - - exec->grayscale = grayscale; - reexecute = TRUE; - } - } - else - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - { - #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) { @@ -2573,14 +2306,6 @@ if ( exec->GS.instruct_control & 2 ) exec->GS = tt_default_graphics_state; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* check whether we have a font hinted for ClearType -- */ - /* note that this flag can also be modified in a glyph's bytecode */ - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 && - exec->GS.instruct_control & 4 ) - exec->ignore_x_mode = FALSE; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* * Toggle backward compatibility according to what font wants, except @@ -2616,13 +2341,6 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && exec->backward_compatibility ) && -#endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - !( driver->interpreter_version == TT_INTERPRETER_VERSION_38 && - !SPH_OPTION_BITMAP_WIDTHS && - FT_LOAD_TARGET_MODE( loader->load_flags ) != - FT_RENDER_MODE_MONO && - exec->compatible_widths ) && #endif !face->postscript.isFixedPitch ) { @@ -2857,7 +2575,9 @@ #ifdef FT_CONFIG_OPTION_SVG /* check for OT-SVG */ - if ( ( load_flags & FT_LOAD_COLOR ) && face->svg ) + if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && + ( load_flags & FT_LOAD_COLOR ) && + face->svg ) { SFNT_Service sfnt = (SFNT_Service)face->sfnt; @@ -2955,6 +2675,9 @@ if ( IS_HINTED( load_flags ) ) { + glyph->control_data = loader.exec->glyphIns; + glyph->control_len = loader.exec->glyphSize; + if ( loader.exec->GS.scan_control ) { /* convert scan conversion mode to FT_OUTLINE_XXX flags */ diff --git a/src/3rdparty/freetype/src/truetype/ttgxvar.c b/src/3rdparty/freetype/src/truetype/ttgxvar.c index 60a0095b..ad4f266b 100644 --- a/src/3rdparty/freetype/src/truetype/ttgxvar.c +++ b/src/3rdparty/freetype/src/truetype/ttgxvar.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -465,7 +466,7 @@ if ( store_offset ) { error = tt_var_load_item_variation_store( - face, + FT_FACE( face ), table_offset + store_offset, &table->itemStore ); if ( error ) @@ -475,7 +476,7 @@ if ( axisMap_offset ) { error = tt_var_load_delta_set_index_mapping( - face, + FT_FACE( face ), table_offset + axisMap_offset, &table->axisMap, &table->itemStore, @@ -492,10 +493,11 @@ FT_LOCAL_DEF( FT_Error ) - tt_var_load_item_variation_store( TT_Face face, + tt_var_load_item_variation_store( FT_Face face, /* TT_Face */ FT_ULong offset, GX_ItemVarStore itemStore ) { + TT_Face ttface = (TT_Face)face; FT_Stream stream = FT_FACE_STREAM( face ); FT_Memory memory = stream->memory; @@ -507,10 +509,10 @@ FT_UShort axis_count; FT_UInt region_count; - FT_UInt i, j, k; + FT_UInt i, j; FT_Bool long_words; - GX_Blend blend = face->blend; + GX_Blend blend = ttface->blend; FT_ULong* dataOffsetArray = NULL; @@ -619,9 +621,10 @@ { GX_ItemVarData varData = &itemStore->varData[i]; - FT_UInt item_count; - FT_UInt word_delta_count; - FT_UInt region_idx_count; + FT_UInt item_count; + FT_UShort word_delta_count; + FT_UInt region_idx_count; + FT_UInt per_region_size; if ( FT_STREAM_SEEK( offset + dataOffsetArray[i] ) ) @@ -658,6 +661,8 @@ if ( FT_NEW_ARRAY( varData->regionIndices, region_idx_count ) ) goto Exit; varData->regionIdxCount = region_idx_count; + varData->wordDeltaCount = word_delta_count; + varData->longWords = long_words; for ( j = 0; j < varData->regionIdxCount; j++ ) { @@ -673,37 +678,22 @@ } } - /* Parse delta set. */ - /* */ - /* On input, deltas are (word_delta_count + region_idx_count) bytes */ - /* each if `long_words` isn't set, and twice as much otherwise. */ - /* */ - /* On output, deltas are expanded to `region_idx_count` shorts each. */ - if ( FT_NEW_ARRAY( varData->deltaSet, item_count * region_idx_count ) ) - goto Exit; - varData->itemCount = item_count; + per_region_size = word_delta_count + region_idx_count; + if ( long_words ) + per_region_size *= 2; - for ( j = 0; j < item_count * region_idx_count; ) + if ( FT_NEW_ARRAY( varData->deltaSet, per_region_size * item_count ) ) + goto Exit; + if ( FT_Stream_Read( stream, + varData->deltaSet, + per_region_size * item_count ) ) { - if ( long_words ) - { - for ( k = 0; k < word_delta_count; k++, j++ ) - if ( FT_READ_LONG( varData->deltaSet[j] ) ) - goto Exit; - for ( ; k < region_idx_count; k++, j++ ) - if ( FT_READ_SHORT( varData->deltaSet[j] ) ) - goto Exit; - } - else - { - for ( k = 0; k < word_delta_count; k++, j++ ) - if ( FT_READ_SHORT( varData->deltaSet[j] ) ) - goto Exit; - for ( ; k < region_idx_count; k++, j++ ) - if ( FT_READ_CHAR( varData->deltaSet[j] ) ) - goto Exit; - } + FT_TRACE2(( "deltaSet read failed." )); + error = FT_THROW( Invalid_Table ); + goto Exit; } + + varData->itemCount = item_count; } Exit: @@ -714,7 +704,7 @@ FT_LOCAL_DEF( FT_Error ) - tt_var_load_delta_set_index_mapping( TT_Face face, + tt_var_load_delta_set_index_mapping( FT_Face face, /* TT_Face */ FT_ULong offset, GX_DeltaSetIdxMap map, GX_ItemVarStore itemStore, @@ -941,7 +931,7 @@ } error = tt_var_load_item_variation_store( - face, + FT_FACE( face ), table_offset + store_offset, &table->itemStore ); if ( error ) @@ -950,7 +940,7 @@ if ( widthMap_offset ) { error = tt_var_load_delta_set_index_mapping( - face, + FT_FACE( face ), table_offset + widthMap_offset, &table->widthMap, &table->itemStore, @@ -992,24 +982,30 @@ FT_LOCAL_DEF( FT_ItemVarDelta ) - tt_var_get_item_delta( TT_Face face, + tt_var_get_item_delta( FT_Face face, /* TT_Face */ GX_ItemVarStore itemStore, FT_UInt outerIndex, FT_UInt innerIndex ) { + TT_Face ttface = (TT_Face)face; FT_Stream stream = FT_FACE_STREAM( face ); FT_Memory memory = stream->memory; FT_Error error = FT_Err_Ok; GX_ItemVarData varData; - FT_ItemVarDelta* deltaSet; + FT_ItemVarDelta* deltaSet = NULL; + FT_ItemVarDelta deltaSetStack[16]; + + FT_Fixed* scalars = NULL; + FT_Fixed scalarsStack[16]; FT_UInt master, j; - FT_Fixed* scalars = NULL; - FT_ItemVarDelta returnValue; + FT_ItemVarDelta returnValue = 0; + FT_UInt per_region_size; + FT_Byte* bytes; - if ( !face->blend || !face->blend->normalizedcoords ) + if ( !ttface->blend || !ttface->blend->normalizedcoords ) return 0; /* OpenType 1.8.4+: No variation data for this item */ @@ -1023,15 +1019,48 @@ if ( outerIndex >= itemStore->dataCount ) return 0; /* Out of range. */ - varData = &itemStore->varData[outerIndex]; - deltaSet = FT_OFFSET( varData->deltaSet, - varData->regionIdxCount * innerIndex ); + varData = &itemStore->varData[outerIndex]; if ( innerIndex >= varData->itemCount ) return 0; /* Out of range. */ - if ( FT_QNEW_ARRAY( scalars, varData->regionIdxCount ) ) - return 0; + if ( varData->regionIdxCount < 16 ) + { + deltaSet = deltaSetStack; + scalars = scalarsStack; + } + else + { + if ( FT_QNEW_ARRAY( deltaSet, varData->regionIdxCount ) ) + goto Exit; + if ( FT_QNEW_ARRAY( scalars, varData->regionIdxCount ) ) + goto Exit; + } + + /* Parse delta set. */ + /* */ + /* Deltas are (word_delta_count + region_idx_count) bytes each */ + /* if `longWords` isn't set, and twice as much otherwise. */ + per_region_size = varData->wordDeltaCount + varData->regionIdxCount; + if ( varData->longWords ) + per_region_size *= 2; + + bytes = varData->deltaSet + per_region_size * innerIndex; + + if ( varData->longWords ) + { + for ( master = 0; master < varData->wordDeltaCount; master++ ) + deltaSet[master] = FT_NEXT_LONG( bytes ); + for ( ; master < varData->regionIdxCount; master++ ) + deltaSet[master] = FT_NEXT_SHORT( bytes ); + } + else + { + for ( master = 0; master < varData->wordDeltaCount; master++ ) + deltaSet[master] = FT_NEXT_SHORT( bytes ); + for ( ; master < varData->regionIdxCount; master++ ) + deltaSet[master] = FT_NEXT_CHAR( bytes ); + } /* outer loop steps through master designs to be blended */ for ( master = 0; master < varData->regionIdxCount; master++ ) @@ -1060,27 +1089,27 @@ else if ( axis->peakCoord == 0 ) continue; - else if ( face->blend->normalizedcoords[j] == axis->peakCoord ) + else if ( ttface->blend->normalizedcoords[j] == axis->peakCoord ) continue; /* ignore this region if coords are out of range */ - else if ( face->blend->normalizedcoords[j] <= axis->startCoord || - face->blend->normalizedcoords[j] >= axis->endCoord ) + else if ( ttface->blend->normalizedcoords[j] <= axis->startCoord || + ttface->blend->normalizedcoords[j] >= axis->endCoord ) { scalar = 0; break; } /* cumulative product of all the axis scalars */ - else if ( face->blend->normalizedcoords[j] < axis->peakCoord ) + else if ( ttface->blend->normalizedcoords[j] < axis->peakCoord ) scalar = FT_MulDiv( scalar, - face->blend->normalizedcoords[j] - axis->startCoord, + ttface->blend->normalizedcoords[j] - axis->startCoord, axis->peakCoord - axis->startCoord ); else scalar = FT_MulDiv( scalar, - axis->endCoord - face->blend->normalizedcoords[j], + axis->endCoord - ttface->blend->normalizedcoords[j], axis->endCoord - axis->peakCoord ); } /* per-axis loop */ @@ -1106,7 +1135,11 @@ */ returnValue = FT_MulAddFix( scalars, deltaSet, varData->regionIdxCount ); - FT_FREE( scalars ); + Exit: + if ( scalars != scalarsStack ) + FT_FREE( scalars ); + if ( deltaSet != deltaSetStack ) + FT_FREE( deltaSet ); return returnValue; } @@ -1206,7 +1239,7 @@ innerIndex = gindex; } - delta = tt_var_get_item_delta( face, + delta = tt_var_get_item_delta( FT_FACE( face ), &table->itemStore, outerIndex, innerIndex ); @@ -1229,20 +1262,20 @@ FT_LOCAL_DEF( FT_Error ) - tt_hadvance_adjust( TT_Face face, + tt_hadvance_adjust( FT_Face face, /* TT_Face */ FT_UInt gindex, FT_Int *avalue ) { - return tt_hvadvance_adjust( face, gindex, avalue, 0 ); + return tt_hvadvance_adjust( (TT_Face)face, gindex, avalue, 0 ); } FT_LOCAL_DEF( FT_Error ) - tt_vadvance_adjust( TT_Face face, + tt_vadvance_adjust( FT_Face face, /* TT_Face */ FT_UInt gindex, FT_Int *avalue ) { - return tt_hvadvance_adjust( face, gindex, avalue, 1 ); + return tt_hvadvance_adjust( (TT_Face)face, gindex, avalue, 1 ); } @@ -1389,7 +1422,7 @@ records_offset = FT_STREAM_POS(); error = tt_var_load_item_variation_store( - face, + FT_FACE( face ), table_offset + store_offset, &blend->mvar_table->itemStore ); if ( error ) @@ -1462,15 +1495,14 @@ static FT_Error - tt_size_reset_iterator( FT_ListNode node, + ft_size_reset_iterator( FT_ListNode node, void* user ) { - TT_Size size = (TT_Size)node->data; - - FT_UNUSED( user ); + FT_Size size = (FT_Size)node->data; + FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)user; - tt_size_reset( size, 1 ); + var->size_reset( size ); return FT_Err_Ok; } @@ -1489,16 +1521,19 @@ * The font face. */ FT_LOCAL_DEF( void ) - tt_apply_mvar( TT_Face face ) + tt_apply_mvar( FT_Face face ) /* TT_Face */ { - GX_Blend blend = face->blend; + TT_Face ttface = (TT_Face)face; + + GX_Blend blend = ttface->blend; GX_Value value, limit; + FT_Short mvar_hasc_delta = 0; FT_Short mvar_hdsc_delta = 0; FT_Short mvar_hlgp_delta = 0; - if ( !( face->variation_support & TT_FACE_FLAG_VAR_MVAR ) ) + if ( !( ttface->variation_support & TT_FACE_FLAG_VAR_MVAR ) ) return; value = blend->mvar_table->values; @@ -1506,7 +1541,7 @@ for ( ; value < limit; value++ ) { - FT_Short* p = ft_var_get_value_pointer( face, value->tag ); + FT_Short* p = ft_var_get_value_pointer( ttface, value->tag ); FT_Int delta; @@ -1543,7 +1578,8 @@ /* adjust all derived values */ { - FT_Face root = &face->root; + FT_Service_MetricsVariations var = + (FT_Service_MetricsVariations)ttface->face_var; /* * Apply the deltas of hasc, hdsc and hlgp to the FT_Face's ascender, @@ -1571,24 +1607,25 @@ * whether they were actually changed or the font had the OS/2 table's * fsSelection's bit 7 (USE_TYPO_METRICS) set. */ - FT_Short current_line_gap = root->height - root->ascender + - root->descender; + FT_Short current_line_gap = face->height - face->ascender + + face->descender; - root->ascender = root->ascender + mvar_hasc_delta; - root->descender = root->descender + mvar_hdsc_delta; - root->height = root->ascender - root->descender + + face->ascender = face->ascender + mvar_hasc_delta; + face->descender = face->descender + mvar_hdsc_delta; + face->height = face->ascender - face->descender + current_line_gap + mvar_hlgp_delta; - root->underline_position = face->postscript.underlinePosition - - face->postscript.underlineThickness / 2; - root->underline_thickness = face->postscript.underlineThickness; + face->underline_position = ttface->postscript.underlinePosition - + ttface->postscript.underlineThickness / 2; + face->underline_thickness = ttface->postscript.underlineThickness; - /* iterate over all FT_Size objects and call `tt_size_reset' */ - /* to propagate the metrics changes */ - FT_List_Iterate( &root->sizes_list, - tt_size_reset_iterator, - NULL ); + /* iterate over all FT_Size objects and call `var->size_reset' */ + /* to propagate the metrics changes */ + if ( var && var->size_reset ) + FT_List_Iterate( &face->sizes_list, + ft_size_reset_iterator, + (void*)var ); } } @@ -2099,7 +2136,7 @@ innerIndex = table->axisMap.innerIndex[idx]; } - delta = tt_var_get_item_delta( face, + delta = tt_var_get_item_delta( FT_FACE( face ), &table->itemStore, outerIndex, innerIndex ); @@ -2261,11 +2298,12 @@ * FreeType error code. 0 means success. */ FT_LOCAL_DEF( FT_Error ) - TT_Get_MM_Var( TT_Face face, + TT_Get_MM_Var( FT_Face face, /* TT_Face */ FT_MM_Var* *master ) { - FT_Stream stream = face->root.stream; - FT_Memory memory = face->root.memory; + TT_Face ttface = (TT_Face)face; + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_ULong table_len; FT_Error error = FT_Err_Ok; FT_ULong fvar_start = 0; @@ -2329,19 +2367,19 @@ /* the default instance, which might be missing in the table of named */ /* instances (in 'fvar'). This value is validated in `sfobjs.c` and */ /* may be reset to 0 if consistency checks fail. */ - num_instances = (FT_UInt)face->root.style_flags >> 16; + num_instances = (FT_UInt)face->style_flags >> 16; /* read the font data and set up the internal representation */ /* if not already done */ - need_init = !face->blend; + need_init = !ttface->blend; if ( need_init ) { FT_TRACE2(( "FVAR " )); - if ( FT_SET_ERROR( face->goto_table( face, TTAG_fvar, - stream, &table_len ) ) ) + if ( FT_SET_ERROR( ttface->goto_table( ttface, TTAG_fvar, + stream, &table_len ) ) ) { FT_TRACE1(( "is missing\n" )); goto Exit; @@ -2374,14 +2412,14 @@ fvar_head.axisCount, fvar_head.axisCount == 1 ? "is" : "es" )); - if ( FT_NEW( face->blend ) ) + if ( FT_NEW( ttface->blend ) ) goto Exit; - num_axes = fvar_head.axisCount; - face->blend->num_axis = num_axes; + num_axes = fvar_head.axisCount; + ttface->blend->num_axis = num_axes; } else - num_axes = face->blend->num_axis; + num_axes = ttface->blend->num_axis; /* prepare storage area for MM data; this cannot overflow */ /* 32-bit arithmetic because of the size limits used in the */ @@ -2410,16 +2448,16 @@ if ( need_init ) { - face->blend->mmvar_len = mmvar_size + - axis_flags_size + - axis_size + - namedstyle_size + - next_coords_size + - next_name_size; + ttface->blend->mmvar_len = mmvar_size + + axis_flags_size + + axis_size + + namedstyle_size + + next_coords_size + + next_name_size; - if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) + if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) ) goto Exit; - face->blend->mmvar = mmvar; + ttface->blend->mmvar = mmvar; /* set up pointers and offsets into the `mmvar' array; */ /* the data gets filled in later on */ @@ -2525,27 +2563,27 @@ /* named instance coordinates are stored as design coordinates; */ /* we have to convert them to normalized coordinates also */ - if ( FT_NEW_ARRAY( face->blend->normalized_stylecoords, + if ( FT_NEW_ARRAY( ttface->blend->normalized_stylecoords, num_axes * num_instances ) ) goto Exit; - if ( fvar_head.instanceCount && !face->blend->avar_loaded ) + if ( fvar_head.instanceCount && !ttface->blend->avar_loaded ) { FT_ULong offset = FT_STREAM_POS(); - ft_var_load_avar( face ); + ft_var_load_avar( ttface ); if ( FT_STREAM_SEEK( offset ) ) goto Exit; } - FT_TRACE5(( "%d instance%s\n", + FT_TRACE5(( "%d named instance%s\n", fvar_head.instanceCount, fvar_head.instanceCount == 1 ? "" : "s" )); ns = mmvar->namedstyle; - nsc = face->blend->normalized_stylecoords; + nsc = ttface->blend->normalized_stylecoords; for ( i = 0; i < fvar_head.instanceCount; i++, ns++ ) { /* PostScript names add 2 bytes to the instance record size */ @@ -2568,7 +2606,7 @@ #ifdef FT_DEBUG_LEVEL_TRACE { - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; FT_String* strname = NULL; FT_String* psname = NULL; @@ -2580,7 +2618,7 @@ if ( ns->strid != 0xFFFF ) { - (void)sfnt->get_name( face, + (void)sfnt->get_name( ttface, (FT_UShort)ns->strid, &strname ); if ( strname && !ft_strcmp( strname, ".notdef" ) ) @@ -2589,7 +2627,7 @@ if ( ns->psid != 0xFFFF ) { - (void)sfnt->get_name( face, + (void)sfnt->get_name( ttface, (FT_UShort)ns->psid, &psname ); if ( psname && !ft_strcmp( psname, ".notdef" ) ) @@ -2598,7 +2636,7 @@ (void)FT_STREAM_SEEK( pos ); - FT_TRACE5(( " instance %d (%s%s%s, %s%s%s)\n", + FT_TRACE5(( " named instance %d (%s%s%s, %s%s%s)\n", i, strname ? "name: `" : "", strname ? strname : "unnamed", @@ -2612,7 +2650,7 @@ } #endif /* FT_DEBUG_LEVEL_TRACE */ - ft_var_to_normalized( face, num_axes, ns->coords, nsc ); + ft_var_to_normalized( ttface, num_axes, ns->coords, nsc ); nsc += num_axes; FT_FRAME_EXIT(); @@ -2620,15 +2658,17 @@ if ( num_instances != fvar_head.instanceCount ) { - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; FT_Int found, dummy1, dummy2; FT_UInt strid = ~0U; - /* the default instance is missing in array the */ - /* of named instances; try to synthesize an entry */ - found = sfnt->get_name_id( face, + /* The default instance is missing in array the */ + /* of named instances; try to synthesize an entry. */ + /* If this fails, `default_named_instance` remains */ + /* at value zero, which doesn't do any harm. */ + found = sfnt->get_name_id( ttface, TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY, &dummy1, &dummy2 ); @@ -2636,7 +2676,7 @@ strid = TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY; else { - found = sfnt->get_name_id( face, + found = sfnt->get_name_id( ttface, TT_NAME_ID_FONT_SUBFAMILY, &dummy1, &dummy2 ); @@ -2646,7 +2686,7 @@ if ( found ) { - found = sfnt->get_name_id( face, + found = sfnt->get_name_id( ttface, TT_NAME_ID_PS_NAME, &dummy1, &dummy2 ); @@ -2655,6 +2695,9 @@ FT_TRACE5(( "TT_Get_MM_Var:" " Adding default instance to named instances\n" )); + /* named instance indices start with value 1 */ + ttface->var_default_named_instance = num_instances; + ns = &mmvar->namedstyle[fvar_head.instanceCount]; ns->strid = strid; @@ -2668,7 +2711,7 @@ } } - ft_var_load_mvar( face ); + ft_var_load_mvar( ttface ); } /* fill the output array if requested */ @@ -2678,9 +2721,9 @@ FT_UInt n; - if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) + if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) ) goto Exit; - FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len ); + FT_MEM_COPY( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ); axis_flags = (FT_UShort*)( (char*)mmvar + mmvar_size ); @@ -2756,7 +2799,7 @@ if ( !face->blend ) { - if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) + if ( FT_SET_ERROR( TT_Get_MM_Var( FT_FACE( face ), NULL ) ) ) goto Exit; } @@ -2841,26 +2884,29 @@ } } - if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + if ( !have_diff ) { - FT_UInt instance_index = (FT_UInt)face->root.face_index >> 16; + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + { + FT_UInt instance_index = (FT_UInt)face->root.face_index >> 16; - c = blend->normalizedcoords + i; - n = blend->normalized_stylecoords + - ( instance_index - 1 ) * mmvar->num_axis + - i; + c = blend->normalizedcoords + i; + n = blend->normalized_stylecoords + + ( instance_index - 1 ) * mmvar->num_axis + + i; - for ( j = i; j < mmvar->num_axis; j++, n++, c++ ) - if ( *c != *n ) - have_diff = 1; - } - else - { - c = blend->normalizedcoords + i; - for ( j = i; j < mmvar->num_axis; j++, c++ ) - if ( *c != 0 ) - have_diff = 1; + for ( j = i; j < mmvar->num_axis; j++, n++, c++ ) + if ( *c != *n ) + have_diff = 1; + } + else + { + c = blend->normalizedcoords + i; + for ( j = i; j < mmvar->num_axis; j++, c++ ) + if ( *c != 0 ) + have_diff = 1; + } } /* return value -1 indicates `no change' */ @@ -2924,9 +2970,6 @@ } } - /* enforce recomputation of the PostScript name; */ - FT_FREE( face->postscript_name ); - Exit: return error; } @@ -2958,26 +3001,15 @@ * An array of `num_coords', each between [-1,1]. * * @Return: - * FreeType error code. 0 means success. + * FreeType error code. 0 means success, -1 means success and unchanged + * axis values. */ FT_LOCAL_DEF( FT_Error ) - TT_Set_MM_Blend( TT_Face face, + TT_Set_MM_Blend( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - - - error = tt_set_mm_blend( face, num_coords, coords, 1 ); - if ( error ) - return error; - - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - - return FT_Err_Ok; + return tt_set_mm_blend( (TT_Face)face, num_coords, coords, 1 ); } @@ -3005,31 +3037,34 @@ * An array of `num_coords', each between [-1,1]. * * @Return: - * FreeType error code. 0 means success. + * FreeType error code. 0 means success, -1 means success and unchanged + * axis values. */ FT_LOCAL_DEF( FT_Error ) - TT_Get_MM_Blend( TT_Face face, + TT_Get_MM_Blend( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { + TT_Face ttface = (TT_Face)face; + FT_Error error = FT_Err_Ok; GX_Blend blend; FT_UInt i, nc; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) return error; } - blend = face->blend; + blend = ttface->blend; if ( !blend->coords ) { /* select default instance coordinates */ /* if no instance is selected yet */ - if ( FT_SET_ERROR( tt_set_mm_blend( face, 0, NULL, 1 ) ) ) + if ( FT_SET_ERROR( tt_set_mm_blend( ttface, 0, NULL, 1 ) ) ) return error; } @@ -3042,7 +3077,7 @@ nc = blend->num_axis; } - if ( face->doblend ) + if ( ttface->doblend ) { for ( i = 0; i < nc; i++ ) coords[i] = blend->normalizedcoords[i]; @@ -3089,15 +3124,16 @@ * FreeType error code. 0 means success. */ FT_LOCAL_DEF( FT_Error ) - TT_Set_Var_Design( TT_Face face, + TT_Set_Var_Design( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { + TT_Face ttface = (TT_Face)face; FT_Error error = FT_Err_Ok; GX_Blend blend; FT_MM_Var* mmvar; FT_UInt i; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); FT_Fixed* c; FT_Fixed* n; @@ -3106,13 +3142,13 @@ FT_Bool have_diff = 0; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) goto Exit; } - blend = face->blend; + blend = ttface->blend; mmvar = blend->mmvar; if ( num_coords > mmvar->num_axis ) @@ -3140,13 +3176,13 @@ } } - if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + if ( FT_IS_NAMED_INSTANCE( face ) ) { FT_UInt instance_index; FT_Var_Named_Style* named_style; - instance_index = (FT_UInt)face->root.face_index >> 16; + instance_index = (FT_UInt)face->face_index >> 16; named_style = mmvar->namedstyle + instance_index - 1; n = named_style->coords + num_coords; @@ -3183,22 +3219,17 @@ if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) goto Exit; - if ( !face->blend->avar_loaded ) - ft_var_load_avar( face ); + if ( !ttface->blend->avar_loaded ) + ft_var_load_avar( ttface ); FT_TRACE5(( "TT_Set_Var_Design:\n" )); FT_TRACE5(( " normalized design coordinates:\n" )); - ft_var_to_normalized( face, num_coords, blend->coords, normalized ); + ft_var_to_normalized( ttface, num_coords, blend->coords, normalized ); - error = tt_set_mm_blend( face, mmvar->num_axis, normalized, 0 ); + error = tt_set_mm_blend( ttface, mmvar->num_axis, normalized, 0 ); if ( error ) goto Exit; - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - Exit: FT_FREE( normalized ); return error; @@ -3231,28 +3262,29 @@ * FreeType error code. 0~means success. */ FT_LOCAL_DEF( FT_Error ) - TT_Get_Var_Design( TT_Face face, + TT_Get_Var_Design( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error = FT_Err_Ok; + TT_Face ttface = (TT_Face)face; + FT_Error error = FT_Err_Ok; GX_Blend blend; FT_UInt i, nc; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) return error; } - blend = face->blend; + blend = ttface->blend; if ( !blend->coords ) { /* select default instance coordinates */ /* if no instance is selected yet */ - if ( FT_SET_ERROR( tt_set_mm_blend( face, 0, NULL, 1 ) ) ) + if ( FT_SET_ERROR( tt_set_mm_blend( ttface, 0, NULL, 1 ) ) ) return error; } @@ -3265,7 +3297,7 @@ nc = blend->num_axis; } - if ( face->doblend ) + if ( ttface->doblend ) { for ( i = 0; i < nc; i++ ) coords[i] = blend->coords[i]; @@ -3301,29 +3333,33 @@ * Value 0 indicates to not use an instance. * * @Return: - * FreeType error code. 0~means success. + * FreeType error code. 0~means success, -1 means success and unchanged + * axis values. */ FT_LOCAL_DEF( FT_Error ) - TT_Set_Named_Instance( TT_Face face, + TT_Set_Named_Instance( FT_Face face, /* TT_Face */ FT_UInt instance_index ) { + TT_Face ttface = (TT_Face)face; FT_Error error; GX_Blend blend; FT_MM_Var* mmvar; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_UInt num_instances; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) goto Exit; } - blend = face->blend; + blend = ttface->blend; mmvar = blend->mmvar; - num_instances = (FT_UInt)face->root.style_flags >> 16; + num_instances = (FT_UInt)face->style_flags >> 16; /* `instance_index' starts with value 1, thus `>' */ if ( instance_index > num_instances ) @@ -3334,8 +3370,7 @@ if ( instance_index > 0 ) { - FT_Memory memory = face->root.memory; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; FT_Var_Named_Style* named_style; FT_String* style_name; @@ -3343,40 +3378,89 @@ named_style = mmvar->namedstyle + instance_index - 1; - error = sfnt->get_name( face, + error = sfnt->get_name( ttface, (FT_UShort)named_style->strid, &style_name ); if ( error ) goto Exit; /* set (or replace) style name */ - FT_FREE( face->root.style_name ); - face->root.style_name = style_name; + FT_FREE( face->style_name ); + face->style_name = style_name; /* finally, select the named instance */ error = TT_Set_Var_Design( face, mmvar->num_axis, named_style->coords ); - if ( error ) - { - /* internal error code -1 means `no change' */ - if ( error == -1 ) - error = FT_Err_Ok; - goto Exit; - } } else + { + /* restore non-VF style name */ + FT_FREE( face->style_name ); + if ( FT_STRDUP( face->style_name, ttface->non_var_style_name ) ) + goto Exit; error = TT_Set_Var_Design( face, 0, NULL ); - - face->root.face_index = ( instance_index << 16 ) | - ( face->root.face_index & 0xFFFFL ); - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; + } Exit: return error; } + /************************************************************************** + * + * @Function: + * TT_Get_Default_Named_Instance + * + * @Description: + * Get the default named instance. + * + * @Input: + * face :: + * A handle to the source face. + * + * @Output: + * instance_index :: + * The default named instance index. + * + * @Return: + * FreeType error code. 0~means success. + */ + FT_LOCAL_DEF( FT_Error ) + TT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ) + { + TT_Face ttface = (TT_Face)face; + FT_Error error = FT_Err_Ok; + + + if ( !ttface->blend ) + { + if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) + goto Exit; + } + + *instance_index = ttface->var_default_named_instance; + + Exit: + return error; + } + + + /* This function triggers (lazy) recomputation of the `postscript_name` */ + /* field in `TT_Face`. */ + + FT_LOCAL_DEF( void ) + tt_construct_ps_name( FT_Face face ) + { + TT_Face ttface = (TT_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); + + + FT_FREE( ttface->postscript_name ); + } + + /*************************************************************************/ /*************************************************************************/ /***** *****/ @@ -4409,22 +4493,25 @@ * the MM machinery in case it isn't loaded yet. */ FT_LOCAL_DEF( FT_Error ) - tt_get_var_blend( TT_Face face, + tt_get_var_blend( FT_Face face, /* TT_Face */ FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ) { - if ( face->blend ) + TT_Face ttface = (TT_Face)face; + + + if ( ttface->blend ) { if ( num_coords ) - *num_coords = face->blend->num_axis; + *num_coords = ttface->blend->num_axis; if ( coords ) - *coords = face->blend->coords; + *coords = ttface->blend->coords; if ( normalizedcoords ) - *normalizedcoords = face->blend->normalizedcoords; + *normalizedcoords = ttface->blend->normalizedcoords; if ( mm_var ) - *mm_var = face->blend->mmvar; + *mm_var = ttface->blend->mmvar; } else { @@ -4441,7 +4528,7 @@ FT_LOCAL_DEF( void ) - tt_var_done_item_variation_store( TT_Face face, + tt_var_done_item_variation_store( FT_Face face, GX_ItemVarStore itemStore ) { FT_Memory memory = FT_FACE_MEMORY( face ); @@ -4470,7 +4557,7 @@ FT_LOCAL_DEF( void ) - tt_var_done_delta_set_index_map( TT_Face face, + tt_var_done_delta_set_index_map( FT_Face face, GX_DeltaSetIdxMap deltaSetIdxMap ) { FT_Memory memory = FT_FACE_MEMORY( face ); @@ -4490,10 +4577,11 @@ * Free the blend internal data structure. */ FT_LOCAL_DEF( void ) - tt_done_blend( TT_Face face ) + tt_done_blend( FT_Face face ) { + TT_Face ttface = (TT_Face)face; FT_Memory memory = FT_FACE_MEMORY( face ); - GX_Blend blend = face->blend; + GX_Blend blend = ttface->blend; if ( blend ) @@ -4565,7 +4653,7 @@ #else /* !TT_CONFIG_OPTION_GX_VAR_SUPPORT */ /* ANSI C doesn't like empty source files */ - typedef int _tt_gxvar_dummy; + typedef int tt_gxvar_dummy_; #endif /* !TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/src/3rdparty/freetype/src/truetype/ttgxvar.h b/src/3rdparty/freetype/src/truetype/ttgxvar.h index 4fec980d..e3da6d17 100644 --- a/src/3rdparty/freetype/src/truetype/ttgxvar.h +++ b/src/3rdparty/freetype/src/truetype/ttgxvar.h @@ -347,33 +347,40 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - TT_Set_MM_Blend( TT_Face face, + TT_Set_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Get_MM_Blend( TT_Face face, + TT_Get_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Set_Var_Design( TT_Face face, + TT_Set_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Get_MM_Var( TT_Face face, + TT_Get_MM_Var( FT_Face face, FT_MM_Var* *master ); FT_LOCAL( FT_Error ) - TT_Get_Var_Design( TT_Face face, + TT_Get_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Set_Named_Instance( TT_Face face, + TT_Set_Named_Instance( FT_Face face, FT_UInt instance_index ); + FT_LOCAL( FT_Error ) + TT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ); + + FT_LOCAL( void ) + tt_construct_ps_name( FT_Face face ); + FT_LOCAL( FT_Error ) tt_face_vary_cvt( TT_Face face, FT_Stream stream ); @@ -385,55 +392,54 @@ FT_BEGIN_HEADER FT_Vector* unrounded ); FT_LOCAL( FT_Error ) - tt_hadvance_adjust( TT_Face face, + tt_hadvance_adjust( FT_Face face, FT_UInt gindex, FT_Int *adelta ); FT_LOCAL( FT_Error ) - tt_vadvance_adjust( TT_Face face, + tt_vadvance_adjust( FT_Face face, FT_UInt gindex, FT_Int *adelta ); FT_LOCAL( void ) - tt_apply_mvar( TT_Face face ); - + tt_apply_mvar( FT_Face face ); FT_LOCAL( FT_Error ) - tt_var_load_item_variation_store( TT_Face face, + tt_var_load_item_variation_store( FT_Face face, FT_ULong offset, GX_ItemVarStore itemStore ); FT_LOCAL( FT_Error ) - tt_var_load_delta_set_index_mapping( TT_Face face, + tt_var_load_delta_set_index_mapping( FT_Face face, FT_ULong offset, GX_DeltaSetIdxMap map, GX_ItemVarStore itemStore, FT_ULong table_len ); FT_LOCAL( FT_ItemVarDelta ) - tt_var_get_item_delta( TT_Face face, + tt_var_get_item_delta( FT_Face face, GX_ItemVarStore itemStore, FT_UInt outerIndex, FT_UInt innerIndex ); FT_LOCAL( void ) - tt_var_done_item_variation_store( TT_Face face, + tt_var_done_item_variation_store( FT_Face face, GX_ItemVarStore itemStore ); FT_LOCAL( void ) - tt_var_done_delta_set_index_map( TT_Face face, + tt_var_done_delta_set_index_map( FT_Face face, GX_DeltaSetIdxMap deltaSetIdxMap ); FT_LOCAL( FT_Error ) - tt_get_var_blend( TT_Face face, + tt_get_var_blend( FT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); FT_LOCAL( void ) - tt_done_blend( TT_Face face ); + tt_done_blend( FT_Face face ); #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/src/3rdparty/freetype/src/truetype/ttinterp.c b/src/3rdparty/freetype/src/truetype/ttinterp.c index 4fcfaa3e..79df4555 100644 --- a/src/3rdparty/freetype/src/truetype/ttinterp.c +++ b/src/3rdparty/freetype/src/truetype/ttinterp.c @@ -29,7 +29,6 @@ #include "ttinterp.h" #include "tterrors.h" -#include "ttsubpix.h" #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT #include "ttgxvar.h" #endif @@ -52,12 +51,6 @@ ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ TT_INTERPRETER_VERSION_35 ) -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY -#define SUBPIXEL_HINTING_INFINALITY \ - ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ - TT_INTERPRETER_VERSION_38 ) -#endif - #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL #define SUBPIXEL_HINTING_MINIMAL \ ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ @@ -275,57 +268,6 @@ } - /************************************************************************** - * - * @Function: - * Update_Max - * - * @Description: - * Checks the size of a buffer and reallocates it if necessary. - * - * @Input: - * memory :: - * A handle to the parent memory object. - * - * multiplier :: - * The size in bytes of each element in the buffer. - * - * new_max :: - * The new capacity (size) of the buffer. - * - * @InOut: - * size :: - * The address of the buffer's current size expressed - * in elements. - * - * buff :: - * The address of the buffer base pointer. - * - * @Return: - * FreeType error code. 0 means success. - */ - FT_LOCAL_DEF( FT_Error ) - Update_Max( FT_Memory memory, - FT_ULong* size, - FT_ULong multiplier, - void* _pbuff, - FT_ULong new_max ) - { - FT_Error error; - void** pbuff = (void**)_pbuff; - - - if ( *size < new_max ) - { - if ( FT_QREALLOC( *pbuff, *size * multiplier, new_max * multiplier ) ) - return error; - *size = new_max; - } - - return FT_Err_Ok; - } - - /************************************************************************** * * @Function: @@ -359,9 +301,9 @@ TT_Size size ) { FT_Int i; - FT_ULong tmp; TT_MaxProfile* maxp; FT_Error error; + FT_Memory memory = exec->memory; exec->face = face; @@ -406,25 +348,15 @@ /* XXX: We reserve a little more elements on the stack to deal safely */ /* with broken fonts like arialbs, courbs, timesbs, etc. */ - tmp = (FT_ULong)exec->stackSize; - error = Update_Max( exec->memory, - &tmp, - sizeof ( FT_F26Dot6 ), - (void*)&exec->stack, - maxp->maxStackElements + 32 ); - exec->stackSize = (FT_Long)tmp; - if ( error ) + if ( FT_QRENEW_ARRAY( exec->stack, + exec->stackSize, + maxp->maxStackElements + 32 ) ) return error; + exec->stackSize = maxp->maxStackElements + 32; - tmp = (FT_ULong)exec->glyphSize; - error = Update_Max( exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&exec->glyphIns, - maxp->maxSizeOfInstructions ); - exec->glyphSize = (FT_UInt)tmp; - if ( error ) - return error; + /* free previous glyph code range */ + FT_FREE( exec->glyphIns ); + exec->glyphSize = 0; exec->pts.n_points = 0; exec->pts.n_contours = 0; @@ -1530,14 +1462,16 @@ if ( exc->iniRange == tt_coderange_glyph && exc->cvt != exc->glyfCvt ) { - exc->error = Update_Max( exc->memory, - &exc->glyfCvtSize, - sizeof ( FT_Long ), - (void*)&exc->glyfCvt, - exc->cvtSize ); - if ( exc->error ) + FT_Memory memory = exc->memory; + FT_Error error; + + + FT_MEM_QRENEW_ARRAY( exc->glyfCvt, exc->glyfCvtSize, exc->cvtSize ); + exc->error = error; + if ( error ) return; + exc->glyfCvtSize = exc->cvtSize; FT_ARRAY_COPY( exc->glyfCvt, exc->cvt, exc->glyfCvtSize ); exc->cvt = exc->glyfCvt; } @@ -1744,17 +1678,6 @@ if ( v != 0 ) { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - ( !exc->ignore_x_mode || - ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) ) - zone->cur[point].x = ADD_LONG( zone->cur[point].x, - FT_MulDiv( distance, - v, - exc->F_dot_P ) ); - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* Exception to the post-IUP curfew: Allow the x component of */ /* diagonal moves, but only post-IUP. DejaVu tries to adjust */ @@ -1860,12 +1783,6 @@ FT_UShort point, FT_F26Dot6 distance ) { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode ) - zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility ) zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); @@ -3069,28 +2986,7 @@ args[0] = 0; } else - { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* subpixel hinting - avoid Typeman Dstroke and */ - /* IStroke and Vacuform rounds */ - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - ( ( I == 24 && - ( exc->face->sph_found_func_flags & - ( SPH_FDEF_SPACING_1 | - SPH_FDEF_SPACING_2 ) ) ) || - ( I == 22 && - ( exc->sph_in_func_flags & - SPH_FDEF_TYPEMAN_STROKES ) ) || - ( I == 8 && - ( exc->face->sph_found_func_flags & - SPH_FDEF_VACUFORM_ROUND_1 ) && - exc->iup_called ) ) ) - args[0] = 0; - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - args[0] = exc->storage[I]; - } + args[0] = exc->storage[I]; } @@ -3117,18 +3013,18 @@ if ( exc->iniRange == tt_coderange_glyph && exc->storage != exc->glyfStorage ) { - FT_ULong tmp = (FT_ULong)exc->glyfStoreSize; + FT_Memory memory = exc->memory; + FT_Error error; - exc->error = Update_Max( exc->memory, - &tmp, - sizeof ( FT_Long ), - (void*)&exc->glyfStorage, - exc->storeSize ); - exc->glyfStoreSize = (FT_UShort)tmp; - if ( exc->error ) + FT_MEM_QRENEW_ARRAY( exc->glyfStorage, + exc->glyfStoreSize, + exc->storeSize ); + exc->error = error; + if ( error ) return; + exc->glyfStoreSize = exc->storeSize; FT_ARRAY_COPY( exc->glyfStorage, exc->storage, exc->glyfStoreSize ); exc->storage = exc->glyfStorage; } @@ -3604,106 +3500,6 @@ TT_DefRecord* rec; TT_DefRecord* limit; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* arguments to opcodes are skipped by `SKIP_Code' */ - FT_Byte opcode_pattern[9][12] = { - /* #0 inline delta function 1 */ - { - 0x4B, /* PPEM */ - 0x53, /* GTEQ */ - 0x23, /* SWAP */ - 0x4B, /* PPEM */ - 0x51, /* LTEQ */ - 0x5A, /* AND */ - 0x58, /* IF */ - 0x38, /* SHPIX */ - 0x1B, /* ELSE */ - 0x21, /* POP */ - 0x21, /* POP */ - 0x59 /* EIF */ - }, - /* #1 inline delta function 2 */ - { - 0x4B, /* PPEM */ - 0x54, /* EQ */ - 0x58, /* IF */ - 0x38, /* SHPIX */ - 0x1B, /* ELSE */ - 0x21, /* POP */ - 0x21, /* POP */ - 0x59 /* EIF */ - }, - /* #2 diagonal stroke function */ - { - 0x20, /* DUP */ - 0x20, /* DUP */ - 0xB0, /* PUSHB_1 */ - /* 1 */ - 0x60, /* ADD */ - 0x46, /* GC_cur */ - 0xB0, /* PUSHB_1 */ - /* 64 */ - 0x23, /* SWAP */ - 0x42 /* WS */ - }, - /* #3 VacuFormRound function */ - { - 0x45, /* RCVT */ - 0x23, /* SWAP */ - 0x46, /* GC_cur */ - 0x60, /* ADD */ - 0x20, /* DUP */ - 0xB0 /* PUSHB_1 */ - /* 38 */ - }, - /* #4 TTFautohint bytecode (old) */ - { - 0x20, /* DUP */ - 0x64, /* ABS */ - 0xB0, /* PUSHB_1 */ - /* 32 */ - 0x60, /* ADD */ - 0x66, /* FLOOR */ - 0x23, /* SWAP */ - 0xB0 /* PUSHB_1 */ - }, - /* #5 spacing function 1 */ - { - 0x01, /* SVTCA_x */ - 0xB0, /* PUSHB_1 */ - /* 24 */ - 0x43, /* RS */ - 0x58 /* IF */ - }, - /* #6 spacing function 2 */ - { - 0x01, /* SVTCA_x */ - 0x18, /* RTG */ - 0xB0, /* PUSHB_1 */ - /* 24 */ - 0x43, /* RS */ - 0x58 /* IF */ - }, - /* #7 TypeMan Talk DiagEndCtrl function */ - { - 0x01, /* SVTCA_x */ - 0x20, /* DUP */ - 0xB0, /* PUSHB_1 */ - /* 3 */ - 0x25, /* CINDEX */ - }, - /* #8 TypeMan Talk Align */ - { - 0x06, /* SPVTL */ - 0x7D, /* RDTG */ - }, - }; - FT_UShort opcode_patterns = 9; - FT_UShort opcode_pointer[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - FT_UShort opcode_size[9] = { 12, 8, 8, 6, 7, 4, 5, 4, 2 }; - FT_UShort i; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - /* FDEF is only allowed in `prep' or `fpgm' */ if ( exc->iniRange == tt_coderange_glyph ) @@ -3748,136 +3544,15 @@ rec->opc = (FT_UInt16)n; rec->start = exc->IP + 1; rec->active = TRUE; - rec->inline_delta = FALSE; - rec->sph_fdef_flags = 0x0000; if ( n > exc->maxFunc ) exc->maxFunc = (FT_UInt16)n; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* We don't know for sure these are typeman functions, */ - /* however they are only active when RS 22 is called */ - if ( n >= 64 && n <= 66 ) - rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_STROKES; -#endif - /* Now skip the whole function definition. */ /* We don't allow nested IDEFS & FDEFs. */ while ( SkipCode( exc ) == SUCCESS ) { - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( SUBPIXEL_HINTING_INFINALITY ) - { - for ( i = 0; i < opcode_patterns; i++ ) - { - if ( opcode_pointer[i] < opcode_size[i] && - exc->opcode == opcode_pattern[i][opcode_pointer[i]] ) - { - opcode_pointer[i] += 1; - - if ( opcode_pointer[i] == opcode_size[i] ) - { - FT_TRACE6(( "sph: Function %d, opcode ptrn: %ld, %s %s\n", - i, n, - exc->face->root.family_name, - exc->face->root.style_name )); - - switch ( i ) - { - case 0: - rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1; - exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1; - break; - - case 1: - rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_2; - exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2; - break; - - case 2: - switch ( n ) - { - /* needs to be implemented still */ - case 58: - rec->sph_fdef_flags |= SPH_FDEF_DIAGONAL_STROKE; - exc->face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE; - } - break; - - case 3: - switch ( n ) - { - case 0: - rec->sph_fdef_flags |= SPH_FDEF_VACUFORM_ROUND_1; - exc->face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1; - } - break; - - case 4: - /* probably not necessary to detect anymore */ - rec->sph_fdef_flags |= SPH_FDEF_TTFAUTOHINT_1; - exc->face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1; - break; - - case 5: - switch ( n ) - { - case 0: - case 1: - case 2: - case 4: - case 7: - case 8: - rec->sph_fdef_flags |= SPH_FDEF_SPACING_1; - exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_1; - } - break; - - case 6: - switch ( n ) - { - case 0: - case 1: - case 2: - case 4: - case 7: - case 8: - rec->sph_fdef_flags |= SPH_FDEF_SPACING_2; - exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_2; - } - break; - - case 7: - rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; - exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; - break; - - case 8: -#if 0 - rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; - exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; -#endif - break; - } - opcode_pointer[i] = 0; - } - } - - else - opcode_pointer[i] = 0; - } - - /* Set sph_compatibility_mode only when deltas are detected */ - exc->face->sph_compatibility_mode = - ( ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) | - ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ); - } - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - switch ( exc->opcode ) { case 0x89: /* IDEF */ @@ -3905,10 +3580,6 @@ TT_CallRec* pRec; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - exc->sph_in_func_flags = 0x0000; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - if ( exc->callTop <= 0 ) /* We encountered an ENDF without a call */ { exc->error = FT_THROW( ENDF_In_Exec_Stream ); @@ -3996,17 +3667,6 @@ if ( !def->active ) goto Fail; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - ( ( exc->iup_called && - ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) || - ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) ) - goto Fail; - else - exc->sph_in_func_flags = def->sph_fdef_flags; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - /* check the call stack */ if ( exc->callTop >= exc->callSize ) { @@ -4084,15 +3744,6 @@ if ( !def->active ) goto Fail; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) - goto Fail; - else - exc->sph_in_func_flags = def->sph_fdef_flags; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - /* check stack */ if ( exc->callTop >= exc->callSize ) { @@ -4998,14 +4649,6 @@ } } -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */ - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - ( D < 0 ? NEG_LONG( D ) : D ) == 64 ) - D += 1; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - args[0] = D; } @@ -5267,13 +4910,6 @@ /* except to change the subpixel flags temporarily */ else if ( exc->iniRange == tt_coderange_glyph && K == 3 ) { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* INSTCTRL modifying flag 3 also has an effect */ - /* outside of the CVT program */ - if ( SUBPIXEL_HINTING_INFINALITY ) - exc->ignore_x_mode = !FT_BOOL( L == 4 ); -#endif - #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* Native ClearType fonts sign a waiver that turns off all backward */ /* compatibility hacks and lets them program points to the grid like */ @@ -5605,12 +5241,6 @@ } } else -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* doesn't follow Cleartype spec but produces better result */ - if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode ) - Move_Zp2_Point( exc, point, 0, dy, TRUE ); - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ Move_Zp2_Point( exc, point, dx, dy, TRUE ); exc->GS.loop--; @@ -5771,76 +5401,6 @@ } } else -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode ) - { - FT_Int B1, B2; - - - /* If not using ignore_x_mode rendering, allow ZP2 move. */ - /* If inline deltas aren't allowed, skip ZP2 move. */ - /* If using ignore_x_mode rendering, allow ZP2 point move if: */ - /* - freedom vector is y and sph_compatibility_mode is off */ - /* - the glyph is composite and the move is in the Y direction */ - /* - the glyph is specifically set to allow SHPIX moves */ - /* - the move is on a previously Y-touched point */ - - /* save point for later comparison */ - B1 = exc->zp2.cur[point].y; - - if ( exc->face->sph_compatibility_mode ) - { - if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) - dy = FT_PIX_ROUND( B1 + dy ) - B1; - - /* skip post-iup deltas */ - if ( exc->iup_called && - ( ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) || - ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) ) - goto Skip; - - if ( !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) && - ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || - ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) || - ( exc->sph_tweak_flags & SPH_TWEAK_DO_SHPIX ) ) ) - Move_Zp2_Point( exc, point, 0, dy, TRUE ); - - /* save new point */ - if ( exc->GS.freeVector.y != 0 ) - { - B2 = exc->zp2.cur[point].y; - - /* reverse any disallowed moves */ - if ( ( B1 & 63 ) == 0 && - ( B2 & 63 ) != 0 && - B1 != B2 ) - Move_Zp2_Point( exc, point, 0, NEG_LONG( dy ), TRUE ); - } - } - else if ( exc->GS.freeVector.y != 0 ) - { - Move_Zp2_Point( exc, point, dx, dy, TRUE ); - - /* save new point */ - B2 = exc->zp2.cur[point].y; - - /* reverse any disallowed moves */ - if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) && - ( B1 & 63 ) != 0 && - ( B2 & 63 ) != 0 && - B1 != B2 ) - Move_Zp2_Point( exc, - point, - NEG_LONG( dx ), - NEG_LONG( dy ), - TRUE ); - } - else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL ) - Move_Zp2_Point( exc, point, dx, dy, TRUE ); - } - else -#endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( SUBPIXEL_HINTING_MINIMAL && exc->backward_compatibility ) @@ -5860,9 +5420,6 @@ #endif Move_Zp2_Point( exc, point, dx, dy, TRUE ); -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - Skip: -#endif exc->GS.loop--; } @@ -5907,28 +5464,6 @@ distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 ); -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* subpixel hinting - make MSIRP respect CVT cut-in; */ - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - { - FT_F26Dot6 control_value_cutin = exc->GS.control_value_cutin; - FT_F26Dot6 delta; - - - if ( !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - control_value_cutin = 0; - - delta = SUB_LONG( distance, args[1] ); - if ( delta < 0 ) - delta = NEG_LONG( delta ); - - if ( delta >= control_value_cutin ) - distance = args[1]; - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - exc->func_move( exc, &exc->zp1, point, @@ -5969,14 +5504,7 @@ if ( ( exc->opcode & 1 ) != 0 ) { cur_dist = FAST_PROJECT( &exc->zp0.cur[point] ); -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - distance = SUB_LONG( Round_None( exc, cur_dist, 3 ), cur_dist ); - else -#endif - distance = SUB_LONG( exc->func_round( exc, cur_dist, 3 ), cur_dist ); + distance = SUB_LONG( exc->func_round( exc, cur_dist, 3 ), cur_dist ); } else distance = 0; @@ -6039,27 +5567,12 @@ if ( exc->GS.gep0 == 0 ) /* If in twilight zone */ { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */ - /* Determined via experimentation and may be incorrect... */ - if ( !( SUBPIXEL_HINTING_INFINALITY && - ( exc->ignore_x_mode && - exc->face->sph_compatibility_mode ) ) ) -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - exc->zp0.org[point].x = TT_MulFix14( distance, + exc->zp0.org[point].x = TT_MulFix14( distance, exc->GS.freeVector.x ); exc->zp0.org[point].y = TT_MulFix14( distance, exc->GS.freeVector.y ); exc->zp0.cur[point] = exc->zp0.org[point]; } -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) && - distance > 0 && - exc->GS.freeVector.y != 0 ) - distance = 0; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ org_dist = FAST_PROJECT( &exc->zp0.cur[point] ); @@ -6069,15 +5582,6 @@ FT_F26Dot6 delta; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - exc->GS.freeVector.y == 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - control_value_cutin = 0; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - delta = SUB_LONG( distance, org_dist ); if ( delta < 0 ) delta = NEG_LONG( delta ); @@ -6085,14 +5589,7 @@ if ( delta > control_value_cutin ) distance = org_dist; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - distance = Round_None( exc, distance, 3 ); - else -#endif - distance = exc->func_round( exc, distance, 3 ); + distance = exc->func_round( exc, distance, 3 ); } exc->func_move( exc, &exc->zp0, point, SUB_LONG( distance, org_dist ) ); @@ -6185,14 +5682,7 @@ if ( ( exc->opcode & 4 ) != 0 ) { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - distance = Round_None( exc, org_dist, exc->opcode & 3 ); - else -#endif - distance = exc->func_round( exc, org_dist, exc->opcode & 3 ); + distance = exc->func_round( exc, org_dist, exc->opcode & 3 ); } else distance = Round_None( exc, org_dist, exc->opcode & 3 ); @@ -6204,14 +5694,6 @@ FT_F26Dot6 minimum_distance = exc->GS.minimum_distance; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - minimum_distance = 0; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - if ( org_dist >= 0 ) { if ( distance < minimum_distance ) @@ -6354,41 +5836,7 @@ distance = exc->func_round( exc, cvt_dist, exc->opcode & 3 ); } else - { - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* do cvt cut-in always in MIRP for sph */ - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.gep0 == exc->GS.gep1 ) - { - FT_F26Dot6 control_value_cutin = exc->GS.control_value_cutin; - - - if ( exc->GS.freeVector.x != 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - control_value_cutin = 0; - - if ( exc->GS.freeVector.y != 0 && - ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) ) - { - if ( cur_dist < -64 ) - cvt_dist -= 16; - else if ( cur_dist > 64 && cur_dist < 84 ) - cvt_dist += 32; - } - - delta = SUB_LONG( cvt_dist, org_dist ); - if ( delta < 0 ) - delta = NEG_LONG( delta ); - - if ( delta > control_value_cutin ) - cvt_dist = org_dist; - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - distance = Round_None( exc, cvt_dist, exc->opcode & 3 ); - } /* minimum distance test */ @@ -6397,14 +5845,6 @@ FT_F26Dot6 minimum_distance = exc->GS.minimum_distance; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - minimum_distance = 0; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - if ( org_dist >= 0 ) { if ( distance < minimum_distance ) @@ -6417,51 +5857,10 @@ } } -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.y != 0 ) - { - FT_Int B1, B2; - - - B1 = exc->zp1.cur[point].y; - - /* Round moves if necessary */ - if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) - distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist; - - if ( ( exc->opcode & 16 ) == 0 && - ( exc->opcode & 8 ) == 0 && - ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) ) - distance += 64; - - exc->func_move( exc, - &exc->zp1, - point, - SUB_LONG( distance, cur_dist ) ); - - B2 = exc->zp1.cur[point].y; - - /* Reverse move if necessary */ - if ( ( exc->face->sph_compatibility_mode && - ( B1 & 63 ) == 0 && - ( B2 & 63 ) != 0 ) || - ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) && - ( B1 & 63 ) != 0 && - ( B2 & 63 ) != 0 ) ) - exc->func_move( exc, - &exc->zp1, - point, - SUB_LONG( cur_dist, distance ) ); - } - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - exc->func_move( exc, - &exc->zp1, - point, - SUB_LONG( distance, cur_dist ) ); + exc->func_move( exc, + &exc->zp1, + point, + SUB_LONG( distance, cur_dist ) ); Fail: exc->GS.rp1 = exc->GS.rp0; @@ -6486,17 +5885,6 @@ FT_F26Dot6 distance; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->iup_called && - ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) ) - { - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - if ( exc->top < exc->GS.loop || BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) { @@ -7055,16 +6443,6 @@ contour = 0; point = 0; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode ) - { - exc->iup_called = TRUE; - if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP ) - return; - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - do { end_point = exc->pts.contours[contour] - exc->pts.first_point; @@ -7137,14 +6515,6 @@ FT_Long B; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->iup_called && - ( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) ) - goto Fail; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - P = (FT_ULong)exc->func_cur_ppem( exc ); nump = (FT_ULong)args[0]; /* some points theoretically may occur more than once, thus UShort isn't enough */ @@ -7197,87 +6567,21 @@ B++; B *= 1L << ( 6 - exc->GS.delta_shift ); -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( SUBPIXEL_HINTING_INFINALITY ) - { - /* - * Allow delta move if - * - * - not using ignore_x_mode rendering, - * - glyph is specifically set to allow it, or - * - glyph is composite and freedom vector is not in subpixel - * direction. - */ - if ( !exc->ignore_x_mode || - ( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) || - ( exc->is_composite && exc->GS.freeVector.y != 0 ) ) - exc->func_move( exc, &exc->zp0, A, B ); - - /* Otherwise, apply subpixel hinting and compatibility mode */ - /* rules, always skipping deltas in subpixel direction. */ - else if ( exc->ignore_x_mode && exc->GS.freeVector.y != 0 ) - { - FT_UShort B1, B2; - - - /* save the y value of the point now; compare after move */ - B1 = (FT_UShort)exc->zp0.cur[A].y; - - /* Standard subpixel hinting: Allow y move for y-touched */ - /* points. This messes up DejaVu ... */ - if ( !exc->face->sph_compatibility_mode && - ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) - exc->func_move( exc, &exc->zp0, A, B ); - - /* compatibility mode */ - else if ( exc->face->sph_compatibility_mode && - !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) ) - { - if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) - B = FT_PIX_ROUND( B1 + B ) - B1; - - /* Allow delta move if using sph_compatibility_mode, */ - /* IUP has not been called, and point is touched on Y. */ - if ( !exc->iup_called && - ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) - exc->func_move( exc, &exc->zp0, A, B ); - } - - B2 = (FT_UShort)exc->zp0.cur[A].y; - - /* Reverse this move if it results in a disallowed move */ - if ( exc->GS.freeVector.y != 0 && - ( ( exc->face->sph_compatibility_mode && - ( B1 & 63 ) == 0 && - ( B2 & 63 ) != 0 ) || - ( ( exc->sph_tweak_flags & - SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) && - ( B1 & 63 ) != 0 && - ( B2 & 63 ) != 0 ) ) ) - exc->func_move( exc, &exc->zp0, A, NEG_LONG( B ) ); - } - } - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backward compatibility */ - /* mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility ) - { - if ( !( exc->iupx_called && exc->iupy_called ) && - ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || - ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) ) - exc->func_move( exc, &exc->zp0, A, B ); - } - else -#endif + /* See `ttinterp.h' for details on backward compatibility */ + /* mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) + { + if ( !( exc->iupx_called && exc->iupy_called ) && + ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || + ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) ) exc->func_move( exc, &exc->zp0, A, B ); } + else +#endif + exc->func_move( exc, &exc->zp0, A, B ); } } else @@ -7380,14 +6684,6 @@ * GETINFO[]: GET INFOrmation * Opcode range: 0x88 * Stack: uint32 --> uint32 - * - * XXX: UNDOCUMENTED: Selector bits higher than 9 are currently (May - * 2015) not documented in the OpenType specification. - * - * Selector bit 11 is incorrectly described as bit 8, while the - * real meaning of bit 8 (vertical LCD subpixels) stays - * undocumented. The same mistake can be found in Greg Hitchcock's - * whitepaper. */ static void Ins_GETINFO( TT_ExecContext exc, @@ -7399,31 +6695,8 @@ K = 0; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /********************************* - * RASTERIZER VERSION - * Selector Bit: 0 - * Return Bit(s): 0-7 - */ - if ( SUBPIXEL_HINTING_INFINALITY && - ( args[0] & 1 ) != 0 && - exc->subpixel_hinting ) - { - if ( exc->ignore_x_mode ) - { - /* if in ClearType backward compatibility mode, */ - /* we sometimes change the TrueType version dynamically */ - K = exc->rasterizer_version; - FT_TRACE6(( "Setting rasterizer version %d\n", - exc->rasterizer_version )); - } - else - K = TT_INTERPRETER_VERSION_38; - } - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - if ( ( args[0] & 1 ) != 0 ) - K = driver->interpreter_version; + if ( ( args[0] & 1 ) != 0 ) + K = driver->interpreter_version; /********************************* * GLYPH ROTATED @@ -7446,8 +6719,6 @@ * VARIATION GLYPH * Selector Bit: 3 * Return Bit(s): 10 - * - * XXX: UNDOCUMENTED! */ if ( (args[0] & 8 ) != 0 && exc->face->blend ) K |= 1 << 10; @@ -7522,89 +6793,6 @@ } #endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( SUBPIXEL_HINTING_INFINALITY && - exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 ) - { - - if ( exc->rasterizer_version >= 37 ) - { - /********************************* - * HINTING FOR SUBPIXEL - * Selector Bit: 6 - * Return Bit(s): 13 - */ - if ( ( args[0] & 64 ) != 0 && exc->subpixel_hinting ) - K |= 1 << 13; - - /********************************* - * COMPATIBLE WIDTHS ENABLED - * Selector Bit: 7 - * Return Bit(s): 14 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 128 ) != 0 && exc->compatible_widths ) - K |= 1 << 14; - - /********************************* - * VERTICAL LCD SUBPIXELS? - * Selector Bit: 8 - * Return Bit(s): 15 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd ) - K |= 1 << 15; - - /********************************* - * HINTING FOR BGR? - * Selector Bit: 9 - * Return Bit(s): 16 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 512 ) != 0 && exc->bgr ) - K |= 1 << 16; - - if ( exc->rasterizer_version >= 38 ) - { - /********************************* - * SUBPIXEL POSITIONED? - * Selector Bit: 10 - * Return Bit(s): 17 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 1024 ) != 0 && exc->subpixel_positioned ) - K |= 1 << 17; - - /********************************* - * SYMMETRICAL SMOOTHING - * Selector Bit: 11 - * Return Bit(s): 18 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 2048 ) != 0 && exc->symmetrical_smoothing ) - K |= 1 << 18; - - /********************************* - * GRAY CLEARTYPE - * Selector Bit: 12 - * Return Bit(s): 19 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 4096 ) != 0 && exc->gray_cleartype ) - K |= 1 << 19; - } - } - } - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - args[0] = K; } @@ -7739,25 +6927,14 @@ /* documentation is in ttinterp.h */ FT_EXPORT_DEF( FT_Error ) - TT_RunIns( TT_ExecContext exc ) + TT_RunIns( void* exec ) { + TT_ExecContext exc = (TT_ExecContext)exec; + FT_ULong ins_counter = 0; /* executed instructions counter */ FT_ULong num_twilight_points; FT_UShort i; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - FT_Byte opcode_pattern[1][2] = { - /* #8 TypeMan Talk Align */ - { - 0x06, /* SPVTL */ - 0x7D, /* RDTG */ - }, - }; - FT_UShort opcode_patterns = 1; - FT_UShort opcode_pointer[1] = { 0 }; - FT_UShort opcode_size[1] = { 1 }; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - /* We restrict the number of twilight points to a reasonable, */ /* heuristic value to avoid slow execution of malformed bytecode. */ @@ -7835,9 +7012,6 @@ Compute_Round( exc, (FT_Byte)exc->GS.round_state ); /* These flags cancel execution of some opcodes after IUP is called */ -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - exc->iup_called = FALSE; -#endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL exc->iupx_called = FALSE; exc->iupy_called = FALSE; @@ -7906,7 +7080,7 @@ /* a variable number of arguments */ /* it is the job of the application to `activate' GX handling, */ - /* this is, calling any of the GX API functions on the current */ + /* that is, calling any of the GX API functions on the current */ /* font to select a variation instance */ if ( exc->face->blend ) exc->new_top = exc->args + exc->face->blend->num_axis; @@ -7927,39 +7101,6 @@ exc->step_ins = TRUE; exc->error = FT_Err_Ok; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( SUBPIXEL_HINTING_INFINALITY ) - { - for ( i = 0; i < opcode_patterns; i++ ) - { - if ( opcode_pointer[i] < opcode_size[i] && - exc->opcode == opcode_pattern[i][opcode_pointer[i]] ) - { - opcode_pointer[i] += 1; - - if ( opcode_pointer[i] == opcode_size[i] ) - { - FT_TRACE6(( "sph: opcode ptrn: %d, %s %s\n", - i, - exc->face->root.family_name, - exc->face->root.style_name )); - - switch ( i ) - { - case 0: - break; - } - opcode_pointer[i] = 0; - } - } - else - opcode_pointer[i] = 0; - } - } - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - { FT_Long* args = exc->stack + exc->args; FT_Byte opcode = exc->opcode; @@ -8466,7 +7607,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT case 0x91: /* it is the job of the application to `activate' GX handling, */ - /* this is, calling any of the GX API functions on the current */ + /* that is, calling any of the GX API functions on the current */ /* font to select a variation instance */ if ( exc->face->blend ) Ins_GETVARIATION( exc, args ); @@ -8604,7 +7745,7 @@ #else /* !TT_USE_BYTECODE_INTERPRETER */ /* ANSI C doesn't like empty source files */ - typedef int _tt_interp_dummy; + typedef int tt_interp_dummy_; #endif /* !TT_USE_BYTECODE_INTERPRETER */ diff --git a/src/3rdparty/freetype/src/truetype/ttinterp.h b/src/3rdparty/freetype/src/truetype/ttinterp.h index c54c053b..e98e258f 100644 --- a/src/3rdparty/freetype/src/truetype/ttinterp.h +++ b/src/3rdparty/freetype/src/truetype/ttinterp.h @@ -98,48 +98,6 @@ FT_BEGIN_HEADER } TT_CallRec, *TT_CallStack; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - /************************************************************************** - * - * These structures define rules used to tweak subpixel hinting for - * various fonts. "", 0, "", NULL value indicates to match any value. - */ - -#define SPH_MAX_NAME_SIZE 32 -#define SPH_MAX_CLASS_MEMBERS 100 - - typedef struct SPH_TweakRule_ - { - const char family[SPH_MAX_NAME_SIZE]; - const FT_UInt ppem; - const char style[SPH_MAX_NAME_SIZE]; - const FT_ULong glyph; - - } SPH_TweakRule; - - - typedef struct SPH_ScaleRule_ - { - const char family[SPH_MAX_NAME_SIZE]; - const FT_UInt ppem; - const char style[SPH_MAX_NAME_SIZE]; - const FT_ULong glyph; - const FT_ULong scale; - - } SPH_ScaleRule; - - - typedef struct SPH_Font_Class_ - { - const char name[SPH_MAX_NAME_SIZE]; - const char member[SPH_MAX_CLASS_MEMBERS][SPH_MAX_NAME_SIZE]; - - } SPH_Font_Class; - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - /************************************************************************** * * The main structure for the interpreter which collects all necessary @@ -399,38 +357,6 @@ FT_BEGIN_HEADER FT_Bool grayscale_cleartype; #endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */ -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - TT_Round_Func func_round_sphn; /* subpixel rounding function */ - - FT_Bool subpixel_hinting; /* Using subpixel hinting? */ - FT_Bool ignore_x_mode; /* Standard rendering mode for */ - /* subpixel hinting. On if gray */ - /* or subpixel hinting is on. */ - - /* The following 6 aren't fully implemented but here for MS rasterizer */ - /* compatibility. */ - FT_Bool compatible_widths; /* compatible widths? */ - FT_Bool symmetrical_smoothing; /* symmetrical_smoothing? */ - FT_Bool bgr; /* bgr instead of rgb? */ - FT_Bool vertical_lcd; /* long side of LCD subpixel */ - /* rectangles is horizontal */ - FT_Bool subpixel_positioned; /* subpixel positioned */ - /* (DirectWrite ClearType)? */ - FT_Bool gray_cleartype; /* ClearType hinting but */ - /* grayscale rendering */ - - FT_Int rasterizer_version; /* MS rasterizer version */ - - FT_Bool iup_called; /* IUP called for glyph? */ - - FT_ULong sph_tweak_flags; /* flags to control */ - /* hint tweaks */ - - FT_ULong sph_in_func_flags; /* flags to indicate if in */ - /* special functions */ - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - /* We maintain two counters (in addition to the instruction counter) */ /* that act as loop detectors for LOOPCALL and jump opcodes with */ /* negative arguments. */ @@ -460,14 +386,6 @@ FT_BEGIN_HEADER FT_LOCAL( void ) TT_Clear_CodeRange( TT_ExecContext exec, FT_Int range ); - - - FT_LOCAL( FT_Error ) - Update_Max( FT_Memory memory, - FT_ULong* size, - FT_ULong multiplier, - void* _pbuff, - FT_ULong new_max ); #endif /* TT_USE_BYTECODE_INTERPRETER */ @@ -536,7 +454,7 @@ FT_BEGIN_HEADER * invoked by the TrueType debugger. */ FT_EXPORT( FT_Error ) - TT_RunIns( TT_ExecContext exec ); + TT_RunIns( void* exec ); FT_END_HEADER diff --git a/src/3rdparty/freetype/src/truetype/ttobjs.c b/src/3rdparty/freetype/src/truetype/ttobjs.c index 4a8873fd..5b56af71 100644 --- a/src/3rdparty/freetype/src/truetype/ttobjs.c +++ b/src/3rdparty/freetype/src/truetype/ttobjs.c @@ -312,7 +312,8 @@ #define TRICK_SFNT_IDS_NUM_FACES 31 static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES] - [TRICK_SFNT_IDS_PER_FACE] = { + [TRICK_SFNT_IDS_PER_FACE] = + { #define TRICK_SFNT_ID_cvt 0 #define TRICK_SFNT_ID_fpgm 1 @@ -581,7 +582,7 @@ FT_Bool result = FALSE; TT_Face face = (TT_Face)ttface; - FT_UInt asize; + FT_ULong asize; FT_ULong i; FT_ULong glyph_index = 0; FT_UInt count = 0; @@ -589,7 +590,7 @@ for( i = 0; i < face->num_locations; i++ ) { - tt_face_get_location( face, i, &asize ); + tt_face_get_location( ttface, i, &asize ); if ( asize > 0 ) { count += 1; @@ -777,7 +778,6 @@ } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - { FT_UInt instance_index = (FT_UInt)face_index >> 16; @@ -785,14 +785,11 @@ if ( FT_HAS_MULTIPLE_MASTERS( ttface ) && instance_index > 0 ) { - error = TT_Set_Named_Instance( face, instance_index ); + error = FT_Set_Named_Instance( ttface, instance_index ); if ( error ) goto Exit; - - tt_apply_mvar( face ); } } - #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ /* initialize standard glyph loading routines */ @@ -858,7 +855,7 @@ face->cvt_program_size = 0; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - tt_done_blend( face ); + tt_done_blend( ttface ); face->blend = NULL; #endif } @@ -1338,39 +1335,29 @@ /************************************************************************** * * @Function: - * tt_size_reset + * tt_size_reset_height * * @Description: - * Reset a TrueType size when resolutions and character dimensions - * have been changed. + * Recompute a TrueType size's ascender, descender, and height + * when resolutions and character dimensions have been changed. + * Used for variation fonts as an iterator function. * * @Input: - * size :: - * A handle to the target size object. - * - * only_height :: - * Only recompute ascender, descender, and height; - * this flag is used for variation fonts where - * `tt_size_reset' is used as an iterator function. + * ft_size :: + * A handle to the target TT_Size object. This function will be called + * through a `FT_Size_Reset_Func` pointer which takes `FT_Size`. This + * function must take `FT_Size` as a result. The passed `FT_Size` is + * expected to point to a `TT_Size`. */ FT_LOCAL_DEF( FT_Error ) - tt_size_reset( TT_Size size, - FT_Bool only_height ) + tt_size_reset_height( FT_Size ft_size ) { - TT_Face face; - FT_Size_Metrics* size_metrics; - - - face = (TT_Face)size->root.face; - - /* nothing to do for CFF2 */ - if ( face->is_cff2 ) - return FT_Err_Ok; + TT_Size size = (TT_Size)ft_size; + TT_Face face = (TT_Face)size->root.face; + FT_Size_Metrics* size_metrics = &size->hinted_metrics; size->ttmetrics.valid = FALSE; - size_metrics = &size->hinted_metrics; - /* copy the result from base layer */ *size_metrics = size->root.metrics; @@ -1397,12 +1384,34 @@ size->ttmetrics.valid = TRUE; - if ( only_height ) - { - /* we must not recompute the scaling values here since */ - /* `tt_size_reset' was already called (with only_height = 0) */ - return FT_Err_Ok; - } + return FT_Err_Ok; + } + + + /************************************************************************** + * + * @Function: + * tt_size_reset + * + * @Description: + * Reset a TrueType size when resolutions and character dimensions + * have been changed. + * + * @Input: + * size :: + * A handle to the target size object. + */ + FT_LOCAL_DEF( FT_Error ) + tt_size_reset( TT_Size size ) + { + FT_Error error; + TT_Face face = (TT_Face)size->root.face; + FT_Size_Metrics* size_metrics = &size->hinted_metrics; + + + error = tt_size_reset_height( (FT_Size)size ); + if ( error ) + return error; if ( face->header.Flags & 8 ) { @@ -1472,9 +1481,6 @@ TT_Driver driver = (TT_Driver)ttdriver; driver->interpreter_version = TT_INTERPRETER_VERSION_35; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - driver->interpreter_version = TT_INTERPRETER_VERSION_38; -#endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL driver->interpreter_version = TT_INTERPRETER_VERSION_40; #endif diff --git a/src/3rdparty/freetype/src/truetype/ttobjs.h b/src/3rdparty/freetype/src/truetype/ttobjs.h index bc6fbe7f..40eb37b4 100644 --- a/src/3rdparty/freetype/src/truetype/ttobjs.h +++ b/src/3rdparty/freetype/src/truetype/ttobjs.h @@ -162,8 +162,6 @@ FT_BEGIN_HEADER FT_Long end; /* where does it end? */ FT_UInt opc; /* function #, or instruction code */ FT_Bool active; /* is it active? */ - FT_Bool inline_delta; /* is function that defines inline delta? */ - FT_ULong sph_fdef_flags; /* flags to identify special functions */ } TT_DefRecord, *TT_DefArray; @@ -391,8 +389,10 @@ FT_BEGIN_HEADER #endif /* TT_USE_BYTECODE_INTERPRETER */ FT_LOCAL( FT_Error ) - tt_size_reset( TT_Size size, - FT_Bool only_height ); + tt_size_reset_height( FT_Size size ); + + FT_LOCAL( FT_Error ) + tt_size_reset( TT_Size size ); /************************************************************************** diff --git a/src/3rdparty/freetype/src/truetype/ttpload.c b/src/3rdparty/freetype/src/truetype/ttpload.c index e08bf309..54a64c7b 100644 --- a/src/3rdparty/freetype/src/truetype/ttpload.c +++ b/src/3rdparty/freetype/src/truetype/ttpload.c @@ -180,10 +180,11 @@ FT_LOCAL_DEF( FT_ULong ) - tt_face_get_location( TT_Face face, - FT_UInt gindex, - FT_UInt *asize ) + tt_face_get_location( FT_Face face, /* TT_Face */ + FT_UInt gindex, + FT_ULong *asize ) { + TT_Face ttface = (TT_Face)face; FT_ULong pos1, pos2; FT_Byte* p; FT_Byte* p_limit; @@ -191,12 +192,12 @@ pos1 = pos2 = 0; - if ( gindex < face->num_locations ) + if ( gindex < ttface->num_locations ) { - if ( face->header.Index_To_Loc_Format != 0 ) + if ( ttface->header.Index_To_Loc_Format != 0 ) { - p = face->glyph_locations + gindex * 4; - p_limit = face->glyph_locations + face->num_locations * 4; + p = ttface->glyph_locations + gindex * 4; + p_limit = ttface->glyph_locations + ttface->num_locations * 4; pos1 = FT_NEXT_ULONG( p ); pos2 = pos1; @@ -206,8 +207,8 @@ } else { - p = face->glyph_locations + gindex * 2; - p_limit = face->glyph_locations + face->num_locations * 2; + p = ttface->glyph_locations + gindex * 2; + p_limit = ttface->glyph_locations + ttface->num_locations * 2; pos1 = FT_NEXT_USHORT( p ); pos2 = pos1; @@ -221,30 +222,30 @@ } /* Check broken location data. */ - if ( pos1 > face->glyf_len ) + if ( pos1 > ttface->glyf_len ) { FT_TRACE1(( "tt_face_get_location:" " too large offset (0x%08lx) found for glyph index %d,\n", pos1, gindex )); FT_TRACE1(( " " " exceeding the end of `glyf' table (0x%08lx)\n", - face->glyf_len )); + ttface->glyf_len )); *asize = 0; return 0; } - if ( pos2 > face->glyf_len ) + if ( pos2 > ttface->glyf_len ) { /* We try to sanitize the last `loca' entry. */ - if ( gindex == face->num_locations - 2 ) + if ( gindex == ttface->num_locations - 2 ) { FT_TRACE1(( "tt_face_get_location:" " too large size (%ld bytes) found for glyph index %d,\n", pos2 - pos1, gindex )); FT_TRACE1(( " " " truncating at the end of `glyf' table to %ld bytes\n", - face->glyf_len - pos1 )); - pos2 = face->glyf_len; + ttface->glyf_len - pos1 )); + pos2 = ttface->glyf_len; } else { @@ -253,7 +254,7 @@ pos2, gindex + 1 )); FT_TRACE1(( " " " exceeding the end of `glyf' table (0x%08lx)\n", - face->glyf_len )); + ttface->glyf_len )); *asize = 0; return 0; } @@ -268,9 +269,9 @@ /* We get (intentionally) a wrong, non-zero result in case the */ /* `glyf' table is missing. */ if ( pos2 >= pos1 ) - *asize = (FT_UInt)( pos2 - pos1 ); + *asize = (FT_ULong)( pos2 - pos1 ); else - *asize = (FT_UInt)( face->glyf_len - pos1 ); + *asize = (FT_ULong)( ttface->glyf_len - pos1 ); return pos1; } diff --git a/src/3rdparty/freetype/src/truetype/ttpload.h b/src/3rdparty/freetype/src/truetype/ttpload.h index 939e02fe..ed229fa4 100644 --- a/src/3rdparty/freetype/src/truetype/ttpload.h +++ b/src/3rdparty/freetype/src/truetype/ttpload.h @@ -31,9 +31,9 @@ FT_BEGIN_HEADER FT_Stream stream ); FT_LOCAL( FT_ULong ) - tt_face_get_location( TT_Face face, - FT_UInt gindex, - FT_UInt *asize ); + tt_face_get_location( FT_Face face, + FT_UInt gindex, + FT_ULong *asize ); FT_LOCAL( void ) tt_face_done_loca( TT_Face face ); diff --git a/src/3rdparty/freetype/src/truetype/ttsubpix.c b/src/3rdparty/freetype/src/truetype/ttsubpix.c deleted file mode 100644 index d811beef..00000000 --- a/src/3rdparty/freetype/src/truetype/ttsubpix.c +++ /dev/null @@ -1,1013 +0,0 @@ -/**************************************************************************** - * - * ttsubpix.c - * - * TrueType Subpixel Hinting. - * - * Copyright (C) 2010-2023 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "ttsubpix.h" - - -#if defined( TT_USE_BYTECODE_INTERPRETER ) && \ - defined( TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY ) - - /************************************************************************** - * - * These rules affect how the TT Interpreter does hinting, with the - * goal of doing subpixel hinting by (in general) ignoring x moves. - * Some of these rules are fixes that go above and beyond the - * stated techniques in the MS whitepaper on Cleartype, due to - * artifacts in many glyphs. So, these rules make some glyphs render - * better than they do in the MS rasterizer. - * - * "" string or 0 int/char indicates to apply to all glyphs. - * "-" used as dummy placeholders, but any non-matching string works. - * - * Some of this could arguably be implemented in fontconfig, however: - * - * - Fontconfig can't set things on a glyph-by-glyph basis. - * - The tweaks that happen here are very low-level, from an average - * user's point of view and are best implemented in the hinter. - * - * The goal is to make the subpixel hinting techniques as generalized - * as possible across all fonts to prevent the need for extra rules such - * as these. - * - * The rule structure is designed so that entirely new rules can easily - * be added when a new compatibility feature is discovered. - * - * The rule structures could also use some enhancement to handle ranges. - * - * ****************** WORK IN PROGRESS ******************* - */ - - /* These are `classes' of fonts that can be grouped together and used in */ - /* rules below. A blank entry "" is required at the end of these! */ -#define FAMILY_CLASS_RULES_SIZE 7 - - static const SPH_Font_Class FAMILY_CLASS_Rules - [FAMILY_CLASS_RULES_SIZE] = - { - { "MS Legacy Fonts", - { "Aharoni", - "Andale Mono", - "Andalus", - "Angsana New", - "AngsanaUPC", - "Arabic Transparent", - "Arial Black", - "Arial Narrow", - "Arial Unicode MS", - "Arial", - "Batang", - "Browallia New", - "BrowalliaUPC", - "Comic Sans MS", - "Cordia New", - "CordiaUPC", - "Courier New", - "DFKai-SB", - "David Transparent", - "David", - "DilleniaUPC", - "Estrangelo Edessa", - "EucrosiaUPC", - "FangSong_GB2312", - "Fixed Miriam Transparent", - "FrankRuehl", - "Franklin Gothic Medium", - "FreesiaUPC", - "Garamond", - "Gautami", - "Georgia", - "Gulim", - "Impact", - "IrisUPC", - "JasmineUPC", - "KaiTi_GB2312", - "KodchiangUPC", - "Latha", - "Levenim MT", - "LilyUPC", - "Lucida Console", - "Lucida Sans Unicode", - "MS Gothic", - "MS Mincho", - "MV Boli", - "Mangal", - "Marlett", - "Microsoft Sans Serif", - "Mingliu", - "Miriam Fixed", - "Miriam Transparent", - "Miriam", - "Narkisim", - "Palatino Linotype", - "Raavi", - "Rod Transparent", - "Rod", - "Shruti", - "SimHei", - "Simplified Arabic Fixed", - "Simplified Arabic", - "Simsun", - "Sylfaen", - "Symbol", - "Tahoma", - "Times New Roman", - "Traditional Arabic", - "Trebuchet MS", - "Tunga", - "Verdana", - "Webdings", - "Wingdings", - "", - }, - }, - { "Core MS Legacy Fonts", - { "Arial Black", - "Arial Narrow", - "Arial Unicode MS", - "Arial", - "Comic Sans MS", - "Courier New", - "Garamond", - "Georgia", - "Impact", - "Lucida Console", - "Lucida Sans Unicode", - "Microsoft Sans Serif", - "Palatino Linotype", - "Tahoma", - "Times New Roman", - "Trebuchet MS", - "Verdana", - "", - }, - }, - { "Apple Legacy Fonts", - { "Geneva", - "Times", - "Monaco", - "Century", - "Chalkboard", - "Lobster", - "Century Gothic", - "Optima", - "Lucida Grande", - "Gill Sans", - "Baskerville", - "Helvetica", - "Helvetica Neue", - "", - }, - }, - { "Legacy Sans Fonts", - { "Andale Mono", - "Arial Unicode MS", - "Arial", - "Century Gothic", - "Comic Sans MS", - "Franklin Gothic Medium", - "Geneva", - "Lucida Console", - "Lucida Grande", - "Lucida Sans Unicode", - "Lucida Sans Typewriter", - "Microsoft Sans Serif", - "Monaco", - "Tahoma", - "Trebuchet MS", - "Verdana", - "", - }, - }, - - { "Misc Legacy Fonts", - { "Dark Courier", "", }, }, - { "Verdana Clones", - { "DejaVu Sans", - "Bitstream Vera Sans", "", }, }, - { "Verdana and Clones", - { "DejaVu Sans", - "Bitstream Vera Sans", - "Verdana", "", }, }, - }; - - - /* Define this to force natural (i.e. not bitmap-compatible) widths. */ - /* The default leans strongly towards natural widths except for a few */ - /* legacy fonts where a selective combination produces nicer results. */ -/* #define FORCE_NATURAL_WIDTHS */ - - - /* Define `classes' of styles that can be grouped together and used in */ - /* rules below. A blank entry "" is required at the end of these! */ -#define STYLE_CLASS_RULES_SIZE 5 - - static const SPH_Font_Class STYLE_CLASS_Rules - [STYLE_CLASS_RULES_SIZE] = - { - { "Regular Class", - { "Regular", - "Book", - "Medium", - "Roman", - "Normal", - "", - }, - }, - { "Regular/Italic Class", - { "Regular", - "Book", - "Medium", - "Italic", - "Oblique", - "Roman", - "Normal", - "", - }, - }, - { "Bold/BoldItalic Class", - { "Bold", - "Bold Italic", - "Black", - "", - }, - }, - { "Bold/Italic/BoldItalic Class", - { "Bold", - "Bold Italic", - "Black", - "Italic", - "Oblique", - "", - }, - }, - { "Regular/Bold Class", - { "Regular", - "Book", - "Medium", - "Normal", - "Roman", - "Bold", - "Black", - "", - }, - }, - }; - - - /* Force special legacy fixes for fonts. */ -#define COMPATIBILITY_MODE_RULES_SIZE 1 - - static const SPH_TweakRule COMPATIBILITY_MODE_Rules - [COMPATIBILITY_MODE_RULES_SIZE] = - { - { "Verdana Clones", 0, "", 0 }, - }; - - - /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting. */ -#define PIXEL_HINTING_RULES_SIZE 2 - - static const SPH_TweakRule PIXEL_HINTING_Rules - [PIXEL_HINTING_RULES_SIZE] = - { - /* these characters are almost always safe */ - { "Courier New", 12, "Italic", 'z' }, - { "Courier New", 11, "Italic", 'z' }, - }; - - - /* Subpixel hinting ignores SHPIX rules on X. Force SHPIX for these. */ -#define DO_SHPIX_RULES_SIZE 1 - - static const SPH_TweakRule DO_SHPIX_Rules - [DO_SHPIX_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Skip Y moves that start with a point that is not on a Y pixel */ - /* boundary and don't move that point to a Y pixel boundary. */ -#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 4 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules - [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] = - { - /* fix vwxyz thinness */ - { "Consolas", 0, "", 0 }, - /* Fix thin middle stems */ - { "Core MS Legacy Fonts", 0, "Regular", 0 }, - /* Cyrillic small letter I */ - { "Legacy Sans Fonts", 0, "", 0 }, - /* Fix artifacts with some Regular & Bold */ - { "Verdana Clones", 0, "", 0 }, - }; - - -#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions - [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - /* Fixes < and > */ - { "Courier New", 0, "Regular", 0 }, - }; - - - /* Skip Y moves that start with a point that is not on a Y pixel */ - /* boundary and don't move that point to a Y pixel boundary. */ -#define SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE 2 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules - [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] = - { - /* Maintain thickness of diagonal in 'N' */ - { "Times New Roman", 0, "Regular/Bold Class", 'N' }, - { "Georgia", 0, "Regular/Bold Class", 'N' }, - }; - - - /* Skip Y moves that move a point off a Y pixel boundary. */ -#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE 1 - - static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules - [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - -#define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions - [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Round moves that don't move a point to a Y pixel boundary. */ -#define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE 2 - - static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules - [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] = - { - /* Droid font instructions don't snap Y to pixels */ - { "Droid Sans", 0, "Regular/Italic Class", 0 }, - { "Droid Sans Mono", 0, "", 0 }, - }; - - -#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions - [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Allow a Direct_Move along X freedom vector if matched. */ -#define ALLOW_X_DMOVE_RULES_SIZE 1 - - static const SPH_TweakRule ALLOW_X_DMOVE_Rules - [ALLOW_X_DMOVE_RULES_SIZE] = - { - /* Fixes vanishing diagonal in 4 */ - { "Verdana", 0, "Regular", '4' }, - }; - - - /* Return MS rasterizer version 35 if matched. */ -#define RASTERIZER_35_RULES_SIZE 8 - - static const SPH_TweakRule RASTERIZER_35_Rules - [RASTERIZER_35_RULES_SIZE] = - { - /* This seems to be the only way to make these look good */ - { "Times New Roman", 0, "Regular", 'i' }, - { "Times New Roman", 0, "Regular", 'j' }, - { "Times New Roman", 0, "Regular", 'm' }, - { "Times New Roman", 0, "Regular", 'r' }, - { "Times New Roman", 0, "Regular", 'a' }, - { "Times New Roman", 0, "Regular", 'n' }, - { "Times New Roman", 0, "Regular", 'p' }, - { "Times", 0, "", 0 }, - }; - - - /* Don't round to the subpixel grid. Round to pixel grid. */ -#define NORMAL_ROUND_RULES_SIZE 1 - - static const SPH_TweakRule NORMAL_ROUND_Rules - [NORMAL_ROUND_RULES_SIZE] = - { - /* Fix serif thickness for certain ppems */ - /* Can probably be generalized somehow */ - { "Courier New", 0, "", 0 }, - }; - - - /* Skip IUP instructions if matched. */ -#define SKIP_IUP_RULES_SIZE 1 - - static const SPH_TweakRule SKIP_IUP_Rules - [SKIP_IUP_RULES_SIZE] = - { - { "Arial", 13, "Regular", 'a' }, - }; - - - /* Skip MIAP Twilight hack if matched. */ -#define MIAP_HACK_RULES_SIZE 1 - - static const SPH_TweakRule MIAP_HACK_Rules - [MIAP_HACK_RULES_SIZE] = - { - { "Geneva", 12, "", 0 }, - }; - - - /* Skip DELTAP instructions if matched. */ -#define ALWAYS_SKIP_DELTAP_RULES_SIZE 23 - - static const SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules - [ALWAYS_SKIP_DELTAP_RULES_SIZE] = - { - { "Georgia", 0, "Regular", 'k' }, - /* fix various problems with e in different versions */ - { "Trebuchet MS", 14, "Regular", 'e' }, - { "Trebuchet MS", 13, "Regular", 'e' }, - { "Trebuchet MS", 15, "Regular", 'e' }, - { "Trebuchet MS", 0, "Italic", 'v' }, - { "Trebuchet MS", 0, "Italic", 'w' }, - { "Trebuchet MS", 0, "Regular", 'Y' }, - { "Arial", 11, "Regular", 's' }, - /* prevent problems with '3' and others */ - { "Verdana", 10, "Regular", 0 }, - { "Verdana", 9, "Regular", 0 }, - /* Cyrillic small letter short I */ - { "Legacy Sans Fonts", 0, "", 0x438 }, - { "Legacy Sans Fonts", 0, "", 0x439 }, - { "Arial", 10, "Regular", '6' }, - { "Arial", 0, "Bold/BoldItalic Class", 'a' }, - /* Make horizontal stems consistent with the rest */ - { "Arial", 24, "Bold", 'a' }, - { "Arial", 25, "Bold", 'a' }, - { "Arial", 24, "Bold", 's' }, - { "Arial", 25, "Bold", 's' }, - { "Arial", 34, "Bold", 's' }, - { "Arial", 35, "Bold", 's' }, - { "Arial", 36, "Bold", 's' }, - { "Arial", 25, "Regular", 's' }, - { "Arial", 26, "Regular", 's' }, - }; - - - /* Always do DELTAP instructions if matched. */ -#define ALWAYS_DO_DELTAP_RULES_SIZE 1 - - static const SPH_TweakRule ALWAYS_DO_DELTAP_Rules - [ALWAYS_DO_DELTAP_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Don't allow ALIGNRP after IUP. */ -#define NO_ALIGNRP_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_ALIGNRP_AFTER_IUP_Rules - [NO_ALIGNRP_AFTER_IUP_RULES_SIZE] = - { - /* Prevent creation of dents in outline */ - { "-", 0, "", 0 }, - }; - - - /* Don't allow DELTAP after IUP. */ -#define NO_DELTAP_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_DELTAP_AFTER_IUP_Rules - [NO_DELTAP_AFTER_IUP_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Don't allow CALL after IUP. */ -#define NO_CALL_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_CALL_AFTER_IUP_Rules - [NO_CALL_AFTER_IUP_RULES_SIZE] = - { - /* Prevent creation of dents in outline */ - { "-", 0, "", 0 }, - }; - - - /* De-embolden these glyphs slightly. */ -#define DEEMBOLDEN_RULES_SIZE 9 - - static const SPH_TweakRule DEEMBOLDEN_Rules - [DEEMBOLDEN_RULES_SIZE] = - { - { "Courier New", 0, "Bold", 'A' }, - { "Courier New", 0, "Bold", 'W' }, - { "Courier New", 0, "Bold", 'w' }, - { "Courier New", 0, "Bold", 'M' }, - { "Courier New", 0, "Bold", 'X' }, - { "Courier New", 0, "Bold", 'K' }, - { "Courier New", 0, "Bold", 'x' }, - { "Courier New", 0, "Bold", 'z' }, - { "Courier New", 0, "Bold", 'v' }, - }; - - - /* Embolden these glyphs slightly. */ -#define EMBOLDEN_RULES_SIZE 2 - - static const SPH_TweakRule EMBOLDEN_Rules - [EMBOLDEN_RULES_SIZE] = - { - { "Courier New", 0, "Regular", 0 }, - { "Courier New", 0, "Italic", 0 }, - }; - - - /* This is a CVT hack that makes thick horizontal stems on 2, 5, 7 */ - /* similar to Windows XP. */ -#define TIMES_NEW_ROMAN_HACK_RULES_SIZE 12 - - static const SPH_TweakRule TIMES_NEW_ROMAN_HACK_Rules - [TIMES_NEW_ROMAN_HACK_RULES_SIZE] = - { - { "Times New Roman", 16, "Italic", '2' }, - { "Times New Roman", 16, "Italic", '5' }, - { "Times New Roman", 16, "Italic", '7' }, - { "Times New Roman", 16, "Regular", '2' }, - { "Times New Roman", 16, "Regular", '5' }, - { "Times New Roman", 16, "Regular", '7' }, - { "Times New Roman", 17, "Italic", '2' }, - { "Times New Roman", 17, "Italic", '5' }, - { "Times New Roman", 17, "Italic", '7' }, - { "Times New Roman", 17, "Regular", '2' }, - { "Times New Roman", 17, "Regular", '5' }, - { "Times New Roman", 17, "Regular", '7' }, - }; - - - /* This fudges distance on 2 to get rid of the vanishing stem issue. */ - /* A real solution to this is certainly welcome. */ -#define COURIER_NEW_2_HACK_RULES_SIZE 15 - - static const SPH_TweakRule COURIER_NEW_2_HACK_Rules - [COURIER_NEW_2_HACK_RULES_SIZE] = - { - { "Courier New", 10, "Regular", '2' }, - { "Courier New", 11, "Regular", '2' }, - { "Courier New", 12, "Regular", '2' }, - { "Courier New", 13, "Regular", '2' }, - { "Courier New", 14, "Regular", '2' }, - { "Courier New", 15, "Regular", '2' }, - { "Courier New", 16, "Regular", '2' }, - { "Courier New", 17, "Regular", '2' }, - { "Courier New", 18, "Regular", '2' }, - { "Courier New", 19, "Regular", '2' }, - { "Courier New", 20, "Regular", '2' }, - { "Courier New", 21, "Regular", '2' }, - { "Courier New", 22, "Regular", '2' }, - { "Courier New", 23, "Regular", '2' }, - { "Courier New", 24, "Regular", '2' }, - }; - - -#ifndef FORCE_NATURAL_WIDTHS - - /* Use compatible widths with these glyphs. Compatible widths is always */ - /* on when doing B/W TrueType instructing, but is used selectively here, */ - /* typically on glyphs with 3 or more vertical stems. */ -#define COMPATIBLE_WIDTHS_RULES_SIZE 38 - - static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules - [COMPATIBLE_WIDTHS_RULES_SIZE] = - { - { "Arial Unicode MS", 12, "Regular Class", 'm' }, - { "Arial Unicode MS", 14, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 10, "Regular Class", 0x448 }, - { "Arial", 11, "Regular Class", 'm' }, - { "Arial", 12, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 12, "Regular Class", 0x448 }, - { "Arial", 13, "Regular Class", 0x448 }, - { "Arial", 14, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 14, "Regular Class", 0x448 }, - { "Arial", 15, "Regular Class", 0x448 }, - { "Arial", 17, "Regular Class", 'm' }, - { "DejaVu Sans", 15, "Regular Class", 0 }, - { "Microsoft Sans Serif", 11, "Regular Class", 0 }, - { "Microsoft Sans Serif", 12, "Regular Class", 0 }, - { "Segoe UI", 11, "Regular Class", 0 }, - { "Monaco", 0, "Regular Class", 0 }, - { "Segoe UI", 12, "Regular Class", 'm' }, - { "Segoe UI", 14, "Regular Class", 'm' }, - { "Tahoma", 11, "Regular Class", 0 }, - { "Times New Roman", 16, "Regular Class", 'c' }, - { "Times New Roman", 16, "Regular Class", 'm' }, - { "Times New Roman", 16, "Regular Class", 'o' }, - { "Times New Roman", 16, "Regular Class", 'w' }, - { "Trebuchet MS", 11, "Regular Class", 0 }, - { "Trebuchet MS", 12, "Regular Class", 0 }, - { "Trebuchet MS", 14, "Regular Class", 0 }, - { "Trebuchet MS", 15, "Regular Class", 0 }, - { "Ubuntu", 12, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Verdana", 10, "Regular Class", 0x448 }, - { "Verdana", 11, "Regular Class", 0x448 }, - { "Verdana and Clones", 12, "Regular Class", 'i' }, - { "Verdana and Clones", 12, "Regular Class", 'j' }, - { "Verdana and Clones", 12, "Regular Class", 'l' }, - { "Verdana and Clones", 12, "Regular Class", 'm' }, - { "Verdana and Clones", 13, "Regular Class", 'i' }, - { "Verdana and Clones", 13, "Regular Class", 'j' }, - { "Verdana and Clones", 13, "Regular Class", 'l' }, - { "Verdana and Clones", 14, "Regular Class", 'm' }, - }; - - - /* Scaling slightly in the x-direction prior to hinting results in */ - /* more visually pleasing glyphs in certain cases. */ - /* This sometimes needs to be coordinated with compatible width rules. */ - /* A value of 1000 corresponds to a scaled value of 1.0. */ - -#define X_SCALING_RULES_SIZE 50 - - static const SPH_ScaleRule X_SCALING_Rules[X_SCALING_RULES_SIZE] = - { - { "DejaVu Sans", 12, "Regular Class", 'm', 950 }, - { "Verdana and Clones", 12, "Regular Class", 'a', 1100 }, - { "Verdana and Clones", 13, "Regular Class", 'a', 1050 }, - { "Arial", 11, "Regular Class", 'm', 975 }, - { "Arial", 12, "Regular Class", 'm', 1050 }, - /* Cyrillic small letter el */ - { "Arial", 13, "Regular Class", 0x43B, 950 }, - { "Arial", 13, "Regular Class", 'o', 950 }, - { "Arial", 13, "Regular Class", 'e', 950 }, - { "Arial", 14, "Regular Class", 'm', 950 }, - /* Cyrillic small letter el */ - { "Arial", 15, "Regular Class", 0x43B, 925 }, - { "Bitstream Vera Sans", 10, "Regular/Italic Class", 0, 1100 }, - { "Bitstream Vera Sans", 12, "Regular/Italic Class", 0, 1050 }, - { "Bitstream Vera Sans", 16, "Regular Class", 0, 1050 }, - { "Bitstream Vera Sans", 9, "Regular/Italic Class", 0, 1050 }, - { "DejaVu Sans", 12, "Regular Class", 'l', 975 }, - { "DejaVu Sans", 12, "Regular Class", 'i', 975 }, - { "DejaVu Sans", 12, "Regular Class", 'j', 975 }, - { "DejaVu Sans", 13, "Regular Class", 'l', 950 }, - { "DejaVu Sans", 13, "Regular Class", 'i', 950 }, - { "DejaVu Sans", 13, "Regular Class", 'j', 950 }, - { "DejaVu Sans", 10, "Regular/Italic Class", 0, 1100 }, - { "DejaVu Sans", 12, "Regular/Italic Class", 0, 1050 }, - { "Georgia", 10, "", 0, 1050 }, - { "Georgia", 11, "", 0, 1100 }, - { "Georgia", 12, "", 0, 1025 }, - { "Georgia", 13, "", 0, 1050 }, - { "Georgia", 16, "", 0, 1050 }, - { "Georgia", 17, "", 0, 1030 }, - { "Liberation Sans", 12, "Regular Class", 'm', 1100 }, - { "Lucida Grande", 11, "Regular Class", 'm', 1100 }, - { "Microsoft Sans Serif", 11, "Regular Class", 'm', 950 }, - { "Microsoft Sans Serif", 12, "Regular Class", 'm', 1050 }, - { "Segoe UI", 12, "Regular Class", 'H', 1050 }, - { "Segoe UI", 12, "Regular Class", 'm', 1050 }, - { "Segoe UI", 14, "Regular Class", 'm', 1050 }, - { "Tahoma", 11, "Regular Class", 'i', 975 }, - { "Tahoma", 11, "Regular Class", 'l', 975 }, - { "Tahoma", 11, "Regular Class", 'j', 900 }, - { "Tahoma", 11, "Regular Class", 'm', 918 }, - { "Verdana", 10, "Regular/Italic Class", 0, 1100 }, - { "Verdana", 12, "Regular Class", 'm', 975 }, - { "Verdana", 12, "Regular/Italic Class", 0, 1050 }, - { "Verdana", 13, "Regular/Italic Class", 'i', 950 }, - { "Verdana", 13, "Regular/Italic Class", 'j', 950 }, - { "Verdana", 13, "Regular/Italic Class", 'l', 950 }, - { "Verdana", 16, "Regular Class", 0, 1050 }, - { "Verdana", 9, "Regular/Italic Class", 0, 1050 }, - { "Times New Roman", 16, "Regular Class", 'm', 918 }, - { "Trebuchet MS", 11, "Regular Class", 'm', 800 }, - { "Trebuchet MS", 12, "Regular Class", 'm', 800 }, - }; - -#else - -#define COMPATIBLE_WIDTHS_RULES_SIZE 1 - - static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules - [COMPATIBLE_WIDTHS_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - -#define X_SCALING_RULES_SIZE 1 - - static const SPH_ScaleRule X_SCALING_Rules - [X_SCALING_RULES_SIZE] = - { - { "-", 0, "", 0, 1000 }, - }; - -#endif /* FORCE_NATURAL_WIDTHS */ - - - static FT_Bool - is_member_of_family_class( const FT_String* detected_font_name, - const FT_String* rule_font_name ) - { - FT_UInt i, j; - - - /* Does font name match rule family? */ - if ( ft_strcmp( detected_font_name, rule_font_name ) == 0 ) - return TRUE; - - /* Is font name a wildcard ""? */ - if ( ft_strcmp( rule_font_name, "" ) == 0 ) - return TRUE; - - /* Is font name contained in a class list? */ - for ( i = 0; i < FAMILY_CLASS_RULES_SIZE; i++ ) - { - if ( ft_strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 ) - { - for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) - { - if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 ) - continue; - if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], - detected_font_name ) == 0 ) - return TRUE; - } - } - } - - return FALSE; - } - - - static FT_Bool - is_member_of_style_class( const FT_String* detected_font_style, - const FT_String* rule_font_style ) - { - FT_UInt i, j; - - - /* Does font style match rule style? */ - if ( ft_strcmp( detected_font_style, rule_font_style ) == 0 ) - return TRUE; - - /* Is font style a wildcard ""? */ - if ( ft_strcmp( rule_font_style, "" ) == 0 ) - return TRUE; - - /* Is font style contained in a class list? */ - for ( i = 0; i < STYLE_CLASS_RULES_SIZE; i++ ) - { - if ( ft_strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 ) - { - for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) - { - if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 ) - continue; - if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], - detected_font_style ) == 0 ) - return TRUE; - } - } - } - - return FALSE; - } - - - FT_LOCAL_DEF( FT_Bool ) - sph_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_TweakRule* rule, - FT_UInt num_rules ) - { - FT_UInt i; - - - /* rule checks may be able to be optimized further */ - for ( i = 0; i < num_rules; i++ ) - { - if ( family && - ( is_member_of_family_class ( family, rule[i].family ) ) ) - if ( rule[i].ppem == 0 || - rule[i].ppem == ppem ) - if ( style && - is_member_of_style_class ( style, rule[i].style ) ) - if ( rule[i].glyph == 0 || - FT_Get_Char_Index( (FT_Face)face, - rule[i].glyph ) == glyph_index ) - return TRUE; - } - - return FALSE; - } - - - static FT_UInt - scale_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_ScaleRule* rule, - FT_UInt num_rules ) - { - FT_UInt i; - - - /* rule checks may be able to be optimized further */ - for ( i = 0; i < num_rules; i++ ) - { - if ( family && - ( is_member_of_family_class ( family, rule[i].family ) ) ) - if ( rule[i].ppem == 0 || - rule[i].ppem == ppem ) - if ( style && - is_member_of_style_class( style, rule[i].style ) ) - if ( rule[i].glyph == 0 || - FT_Get_Char_Index( (FT_Face)face, - rule[i].glyph ) == glyph_index ) - return rule[i].scale; - } - - return 1000; - } - - - FT_LOCAL_DEF( FT_UInt ) - sph_test_tweak_x_scaling( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index ) - { - return scale_test_tweak( face, family, ppem, style, glyph_index, - X_SCALING_Rules, X_SCALING_RULES_SIZE ); - } - - -#define TWEAK_RULES( x ) \ - if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ - x##_Rules, x##_RULES_SIZE ) ) \ - loader->exec->sph_tweak_flags |= SPH_TWEAK_##x - -#define TWEAK_RULES_EXCEPTIONS( x ) \ - if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ - x##_Rules_Exceptions, x##_RULES_EXCEPTIONS_SIZE ) ) \ - loader->exec->sph_tweak_flags &= ~SPH_TWEAK_##x - - - FT_LOCAL_DEF( void ) - sph_set_tweaks( TT_Loader loader, - FT_UInt glyph_index ) - { - TT_Face face = loader->face; - FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics->x_ppem; - FT_String* style = face->root.style_name; - - - /* don't apply rules if style isn't set */ - if ( !face->root.style_name ) - return; - -#ifdef SPH_DEBUG_MORE_VERBOSE - printf( "%s,%d,%s,%c=%d ", - family, ppem, style, glyph_index, glyph_index ); -#endif - - TWEAK_RULES( PIXEL_HINTING ); - - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_PIXEL_HINTING ) - { - loader->exec->ignore_x_mode = FALSE; - return; - } - - TWEAK_RULES( ALLOW_X_DMOVE ); - TWEAK_RULES( ALWAYS_DO_DELTAP ); - TWEAK_RULES( ALWAYS_SKIP_DELTAP ); - TWEAK_RULES( DEEMBOLDEN ); - TWEAK_RULES( DO_SHPIX ); - TWEAK_RULES( EMBOLDEN ); - TWEAK_RULES( MIAP_HACK ); - TWEAK_RULES( NORMAL_ROUND ); - TWEAK_RULES( NO_ALIGNRP_AFTER_IUP ); - TWEAK_RULES( NO_CALL_AFTER_IUP ); - TWEAK_RULES( NO_DELTAP_AFTER_IUP ); - TWEAK_RULES( RASTERIZER_35 ); - TWEAK_RULES( SKIP_IUP ); - - TWEAK_RULES( SKIP_OFFPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( SKIP_OFFPIXEL_Y_MOVES ); - - TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES_DELTAP ); - - TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( SKIP_NONPIXEL_Y_MOVES ); - - TWEAK_RULES( ROUND_NONPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( ROUND_NONPIXEL_Y_MOVES ); - - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) - { - if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 ) - { - loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - loader->exec->size->cvt_ready = -1; - - tt_size_ready_bytecode( - loader->exec->size, - FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); - } - else - loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - } - else - { - if ( loader->exec->rasterizer_version != - SPH_OPTION_SET_RASTERIZER_VERSION ) - { - loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - loader->exec->size->cvt_ready = -1; - - tt_size_ready_bytecode( - loader->exec->size, - FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); - } - else - loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - } - - if ( IS_HINTED( loader->load_flags ) ) - { - TWEAK_RULES( TIMES_NEW_ROMAN_HACK ); - TWEAK_RULES( COURIER_NEW_2_HACK ); - } - - if ( sph_test_tweak( face, family, ppem, style, glyph_index, - COMPATIBILITY_MODE_Rules, COMPATIBILITY_MODE_RULES_SIZE ) ) - loader->exec->face->sph_compatibility_mode = TRUE; - - - if ( IS_HINTED( loader->load_flags ) ) - { - if ( sph_test_tweak( face, family, ppem, style, glyph_index, - COMPATIBLE_WIDTHS_Rules, COMPATIBLE_WIDTHS_RULES_SIZE ) ) - loader->exec->compatible_widths |= TRUE; - } - } - -#else /* !(TT_USE_BYTECODE_INTERPRETER && */ - /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ - - /* ANSI C doesn't like empty source files */ - typedef int _tt_subpix_dummy; - -#endif /* !(TT_USE_BYTECODE_INTERPRETER && */ - /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ - - -/* END */ diff --git a/src/3rdparty/freetype/src/truetype/ttsubpix.h b/src/3rdparty/freetype/src/truetype/ttsubpix.h deleted file mode 100644 index 62af4c27..00000000 --- a/src/3rdparty/freetype/src/truetype/ttsubpix.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** - * - * ttsubpix.h - * - * TrueType Subpixel Hinting. - * - * Copyright (C) 2010-2023 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - - -#ifndef TTSUBPIX_H_ -#define TTSUBPIX_H_ - -#include "ttobjs.h" -#include "ttinterp.h" - - -FT_BEGIN_HEADER - - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - /************************************************************************** - * - * ID flags to identify special functions at FDEF and runtime. - * - */ -#define SPH_FDEF_INLINE_DELTA_1 0x0000001 -#define SPH_FDEF_INLINE_DELTA_2 0x0000002 -#define SPH_FDEF_DIAGONAL_STROKE 0x0000004 -#define SPH_FDEF_VACUFORM_ROUND_1 0x0000008 -#define SPH_FDEF_TTFAUTOHINT_1 0x0000010 -#define SPH_FDEF_SPACING_1 0x0000020 -#define SPH_FDEF_SPACING_2 0x0000040 -#define SPH_FDEF_TYPEMAN_STROKES 0x0000080 -#define SPH_FDEF_TYPEMAN_DIAGENDCTRL 0x0000100 - - - /************************************************************************** - * - * Tweak flags that are set for each glyph by the below rules. - * - */ -#define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001UL -#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002UL -#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004UL -#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000008UL -#define SPH_TWEAK_DEEMBOLDEN 0x0000010UL -#define SPH_TWEAK_DO_SHPIX 0x0000020UL -#define SPH_TWEAK_EMBOLDEN 0x0000040UL -#define SPH_TWEAK_MIAP_HACK 0x0000080UL -#define SPH_TWEAK_NORMAL_ROUND 0x0000100UL -#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0000200UL -#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0000400UL -#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0000800UL -#define SPH_TWEAK_PIXEL_HINTING 0x0001000UL -#define SPH_TWEAK_RASTERIZER_35 0x0002000UL -#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0004000UL -#define SPH_TWEAK_SKIP_IUP 0x0008000UL -#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0010000UL -#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0020000UL -#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0040000UL -#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP 0x0080000UL - - - FT_LOCAL( FT_Bool ) - sph_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_TweakRule* rule, - FT_UInt num_rules ); - - FT_LOCAL( FT_UInt ) - sph_test_tweak_x_scaling( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index ); - - FT_LOCAL( void ) - sph_set_tweaks( TT_Loader loader, - FT_UInt glyph_index ); - - - /* These macros are defined absent a method for setting them */ -#define SPH_OPTION_BITMAP_WIDTHS FALSE -#define SPH_OPTION_SET_SUBPIXEL TRUE -#define SPH_OPTION_SET_GRAYSCALE FALSE -#define SPH_OPTION_SET_COMPATIBLE_WIDTHS FALSE -#define SPH_OPTION_SET_RASTERIZER_VERSION 38 - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - -FT_END_HEADER - -#endif /* TTSUBPIX_H_ */ - - -/* END */ diff --git a/src/3rdparty/freetype/src/type1/t1afm.c b/src/3rdparty/freetype/src/type1/t1afm.c index 787aa92c..d9b9398b 100644 --- a/src/3rdparty/freetype/src/type1/t1afm.c +++ b/src/3rdparty/freetype/src/type1/t1afm.c @@ -299,7 +299,7 @@ /* ascender and descender are optional and could both be zero */ /* check if values are meaningful before overriding defaults */ if ( fi->Ascender > fi->Descender ) - { + { /* no `U' suffix here to 0x8000! */ t1_face->ascender = (FT_Short)( ( fi->Ascender + 0x8000 ) >> 16 ); t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 ); @@ -405,7 +405,7 @@ #else /* T1_CONFIG_OPTION_NO_AFM */ /* ANSI C doesn't like empty source files */ - typedef int _t1_afm_dummy; + typedef int t1_afm_dummy_; #endif /* T1_CONFIG_OPTION_NO_AFM */ diff --git a/src/3rdparty/freetype/src/type1/t1driver.c b/src/3rdparty/freetype/src/type1/t1driver.c index ded3b264..a4cdf372 100644 --- a/src/3rdparty/freetype/src/type1/t1driver.c +++ b/src/3rdparty/freetype/src/type1/t1driver.c @@ -56,28 +56,32 @@ * */ - static FT_Error - t1_get_glyph_name( T1_Face face, + FT_CALLBACK_DEF( FT_Error ) + t1_get_glyph_name( FT_Face face, /* T1_Face */ FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ) { - FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max ); + T1_Face t1face = (T1_Face)face; + + + FT_STRCPYN( buffer, t1face->type1.glyph_names[glyph_index], buffer_max ); return FT_Err_Ok; } - static FT_UInt - t1_get_name_index( T1_Face face, + FT_CALLBACK_DEF( FT_UInt ) + t1_get_name_index( FT_Face face, /* T1_Face */ const FT_String* glyph_name ) { - FT_Int i; + T1_Face t1face = (T1_Face)face; + FT_Int i; - for ( i = 0; i < face->type1.num_glyphs; i++ ) + for ( i = 0; i < t1face->type1.num_glyphs; i++ ) { - FT_String* gname = face->type1.glyph_names[i]; + FT_String* gname = t1face->type1.glyph_names[i]; if ( !ft_strcmp( glyph_name, gname ) ) @@ -90,8 +94,8 @@ static const FT_Service_GlyphDictRec t1_service_glyph_dict = { - (FT_GlyphDict_GetNameFunc) t1_get_glyph_name, /* get_name */ - (FT_GlyphDict_NameIndexFunc)t1_get_name_index /* name_index */ + t1_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ + t1_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ }; @@ -101,9 +105,12 @@ */ static const char* - t1_get_ps_name( T1_Face face ) + t1_get_ps_name( FT_Face face ) /* T1_Face */ { - return (const char*) face->type1.font_name; + T1_Face t1face = (T1_Face)face; + + + return (const char*) t1face->type1.font_name; } @@ -121,30 +128,28 @@ #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT static const FT_Service_MultiMastersRec t1_service_multi_masters = { - (FT_Get_MM_Func) T1_Get_Multi_Master, /* get_mm */ - (FT_Set_MM_Design_Func) T1_Set_MM_Design, /* set_mm_design */ - (FT_Set_MM_Blend_Func) T1_Set_MM_Blend, /* set_mm_blend */ - (FT_Get_MM_Blend_Func) T1_Get_MM_Blend, /* get_mm_blend */ - (FT_Get_MM_Var_Func) T1_Get_MM_Var, /* get_mm_var */ - (FT_Set_Var_Design_Func)T1_Set_Var_Design, /* set_var_design */ - (FT_Get_Var_Design_Func)T1_Get_Var_Design, /* get_var_design */ - (FT_Set_Instance_Func) T1_Reset_MM_Blend, /* set_instance */ - (FT_Set_MM_WeightVector_Func) - T1_Set_MM_WeightVector, /* set_mm_weightvector */ - (FT_Get_MM_WeightVector_Func) - T1_Get_MM_WeightVector, /* get_mm_weightvector */ - (FT_Var_Load_Delta_Set_Idx_Map_Func) - NULL, /* load_delta_set_idx_map */ - (FT_Var_Load_Item_Var_Store_Func) - NULL, /* load_item_variation_store */ - (FT_Var_Get_Item_Delta_Func) - NULL, /* get_item_delta */ - (FT_Var_Done_Item_Var_Store_Func) - NULL, /* done_item_variation_store */ - (FT_Var_Done_Delta_Set_Idx_Map_Func) - NULL, /* done_delta_set_index_map */ - (FT_Get_Var_Blend_Func) NULL, /* get_var_blend */ - (FT_Done_Blend_Func) T1_Done_Blend /* done_blend */ + T1_Get_Multi_Master, /* FT_Get_MM_Func get_mm */ + T1_Set_MM_Design, /* FT_Set_MM_Design_Func set_mm_design */ + T1_Set_MM_Blend, /* FT_Set_MM_Blend_Func set_mm_blend */ + T1_Get_MM_Blend, /* FT_Get_MM_Blend_Func get_mm_blend */ + T1_Get_MM_Var, /* FT_Get_MM_Var_Func get_mm_var */ + T1_Set_Var_Design, /* FT_Set_Var_Design_Func set_var_design */ + T1_Get_Var_Design, /* FT_Get_Var_Design_Func get_var_design */ + T1_Reset_MM_Blend, /* FT_Set_Named_Instance_Func set_named_instance */ + NULL, /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ + T1_Set_MM_WeightVector, + /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ + T1_Get_MM_WeightVector, + /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ + + NULL, /* FT_Construct_PS_Name_Func construct_ps_name */ + NULL, /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ + NULL, /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ + NULL, /* FT_Var_Get_Item_Delta_Func get_item_delta */ + NULL, /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ + NULL, /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ + NULL, /* FT_Get_Var_Blend_Func get_var_blend */ + T1_Done_Blend /* FT_Done_Blend_Func done_blend */ }; #endif @@ -632,11 +637,11 @@ static const FT_Service_PsInfoRec t1_service_ps_info = { - (PS_GetFontInfoFunc) t1_ps_get_font_info, /* ps_get_font_info */ - (PS_GetFontExtraFunc) t1_ps_get_font_extra, /* ps_get_font_extra */ - (PS_HasGlyphNamesFunc) t1_ps_has_glyph_names, /* ps_has_glyph_names */ - (PS_GetFontPrivateFunc)t1_ps_get_font_private, /* ps_get_font_private */ - (PS_GetFontValueFunc) t1_ps_get_font_value, /* ps_get_font_value */ + t1_ps_get_font_info, /* PS_GetFontInfoFunc ps_get_font_info */ + t1_ps_get_font_extra, /* PS_GetFontExtraFunc ps_get_font_extra */ + t1_ps_has_glyph_names, /* PS_HasGlyphNamesFunc ps_has_glyph_names */ + t1_ps_get_font_private, /* PS_GetFontPrivateFunc ps_get_font_private */ + t1_ps_get_font_value, /* PS_GetFontValueFunc ps_get_font_value */ }; @@ -656,9 +661,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( t1_service_properties, - (FT_Properties_SetFunc)ps_property_set, /* set_property */ - (FT_Properties_GetFunc)ps_property_get ) /* get_property */ - + ps_property_set, /* FT_Properties_SetFunc set_property */ + ps_property_get /* FT_Properties_GetFunc get_property */ + ) /* * SERVICE LIST diff --git a/src/3rdparty/freetype/src/type1/t1load.c b/src/3rdparty/freetype/src/type1/t1load.c index 5a1afd8d..be7cd0fd 100644 --- a/src/3rdparty/freetype/src/type1/t1load.c +++ b/src/3rdparty/freetype/src/type1/t1load.c @@ -73,7 +73,8 @@ #ifdef FT_CONFIG_OPTION_INCREMENTAL -#define IS_INCREMENTAL FT_BOOL( face->root.internal->incremental_interface ) +#define IS_INCREMENTAL \ + FT_BOOL( FT_FACE( face )->internal->incremental_interface ) #else #define IS_INCREMENTAL 0 #endif @@ -174,10 +175,11 @@ FT_LOCAL_DEF( FT_Error ) - T1_Get_Multi_Master( T1_Face face, + T1_Get_Multi_Master( FT_Face face, /* T1_Face */ FT_Multi_Master* master ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_UInt n; FT_Error error; @@ -225,11 +227,12 @@ for ( j = 1; j < axismap->num_points; j++ ) { if ( ncv <= axismap->blend_points[j] ) - return INT_TO_FIXED( axismap->design_points[j - 1] ) + - ( axismap->design_points[j] - axismap->design_points[j - 1] ) * - FT_DivFix( ncv - axismap->blend_points[j - 1], - axismap->blend_points[j] - - axismap->blend_points[j - 1] ); + return INT_TO_FIXED( axismap->design_points[j - 1] + + FT_MulDiv( ncv - axismap->blend_points[j - 1], + axismap->design_points[j] - + axismap->design_points[j - 1], + axismap->blend_points[j] - + axismap->blend_points[j - 1] ) ); } return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] ); @@ -284,16 +287,17 @@ * arguments needed by the GX var distortable fonts. */ FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_Var( T1_Face face, + T1_Get_MM_Var( FT_Face face, /* T1_Face */ FT_MM_Var* *master ) { - FT_Memory memory = face->root.memory; - FT_MM_Var *mmvar = NULL; + T1_Face t1face = (T1_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_MM_Var *mmvar = NULL; FT_Multi_Master mmaster; FT_Error error; FT_UInt i; FT_Fixed axiscoords[T1_MAX_MM_AXIS]; - PS_Blend blend = face->blend; + PS_Blend blend = t1face->blend; FT_UShort* axis_flags; FT_Offset mmvar_size; @@ -319,9 +323,9 @@ sizeof ( FT_UShort ) ); axis_size = mmaster.num_axis * sizeof ( FT_Var_Axis ); - if ( FT_ALLOC( mmvar, mmvar_size + - axis_flags_size + - axis_size ) ) + if ( FT_QALLOC( mmvar, mmvar_size + + axis_flags_size + + axis_size ) ) goto Exit; mmvar->num_axis = mmaster.num_axis; @@ -332,8 +336,7 @@ /* to make `FT_Get_Var_Axis_Flags' work: the function expects that the */ /* values directly follow the data of `FT_MM_Var' */ axis_flags = (FT_UShort*)( (char*)mmvar + mmvar_size ); - for ( i = 0; i < mmaster.num_axis; i++ ) - axis_flags[i] = 0; + FT_ARRAY_ZERO( axis_flags, mmaster.num_axis ); mmvar->axis = (FT_Var_Axis*)( (char*)axis_flags + axis_flags_size ); mmvar->namedstyle = NULL; @@ -438,32 +441,21 @@ FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_Blend( T1_Face face, + T1_Set_MM_Blend( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - - - error = t1_set_mm_blend( face, num_coords, coords ); - if ( error ) - return error; - - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - - return FT_Err_Ok; + return t1_set_mm_blend( (T1_Face)face, num_coords, coords ); } FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_Blend( T1_Face face, + T1_Get_MM_Blend( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_Fixed axiscoords[4]; FT_UInt i, nc; @@ -494,11 +486,12 @@ FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_WeightVector( T1_Face face, + T1_Set_MM_WeightVector( FT_Face face, /* T1_Face */ FT_UInt len, FT_Fixed* weightvector ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_UInt i, n; @@ -522,11 +515,6 @@ for ( ; i < blend->num_designs; i++ ) blend->weight_vector[i] = (FT_Fixed)0; - - if ( len ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; } return FT_Err_Ok; @@ -534,11 +522,12 @@ FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_WeightVector( T1_Face face, + T1_Get_MM_WeightVector( FT_Face face, /* T1_Face */ FT_UInt* len, FT_Fixed* weightvector ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_UInt i; @@ -563,12 +552,13 @@ FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_Design( T1_Face face, + T1_Set_MM_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Long* coords ) { + T1_Face t1face = (T1_Face)face; FT_Error error; - PS_Blend blend = face->blend; + PS_Blend blend = t1face->blend; FT_UInt n; FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; @@ -634,15 +624,10 @@ final_blends[n] = the_blend; } - error = t1_set_mm_blend( face, blend->num_axis, final_blends ); + error = t1_set_mm_blend( t1face, blend->num_axis, final_blends ); if ( error ) return error; - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - return FT_Err_Ok; } @@ -650,7 +635,7 @@ /* MM fonts don't have named instances, so only the design is reset */ FT_LOCAL_DEF( FT_Error ) - T1_Reset_MM_Blend( T1_Face face, + T1_Reset_MM_Blend( FT_Face face, FT_UInt instance_index ) { FT_UNUSED( instance_index ); @@ -665,7 +650,7 @@ * arguments needed by the GX var distortable fonts. */ FT_LOCAL_DEF( FT_Error ) - T1_Set_Var_Design( T1_Face face, + T1_Set_Var_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { @@ -684,11 +669,12 @@ FT_LOCAL_DEF( FT_Error ) - T1_Get_Var_Design( T1_Face face, + T1_Get_Var_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_Fixed axiscoords[4]; FT_UInt i, nc; @@ -720,10 +706,11 @@ FT_LOCAL_DEF( void ) - T1_Done_Blend( T1_Face face ) + T1_Done_Blend( FT_Face face ) /* T1_Face */ { - FT_Memory memory = face->root.memory; - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Blend blend = t1face->blend; if ( blend ) @@ -768,20 +755,22 @@ dmap->num_points = 0; } - FT_FREE( face->blend ); + FT_FREE( t1face->blend ); } } static void - parse_blend_axis_types( T1_Face face, - T1_Loader loader ) + parse_blend_axis_types( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; FT_Int n, num_axis; - FT_Error error = FT_Err_Ok; + FT_Error error = FT_Err_Ok; PS_Blend blend; - FT_Memory memory; + FT_Memory memory = FT_FACE_MEMORY( face ); /* take an array of objects */ @@ -801,14 +790,13 @@ } /* allocate blend if necessary */ - error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); + error = t1_allocate_blend( t1face, 0, (FT_UInt)num_axis ); if ( error ) goto Exit; FT_TRACE4(( " [" )); - blend = face->blend; - memory = face->root.memory; + blend = t1face->blend; /* each token is an immediate containing the name of the axis */ for ( n = 0; n < num_axis; n++ ) @@ -856,14 +844,16 @@ static void - parse_blend_design_positions( T1_Face face, - T1_Loader loader ) + parse_blend_design_positions( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; FT_Int num_designs; FT_Int num_axis = 0; /* make compiler happy */ T1_Parser parser = &loader->parser; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); FT_Error error = FT_Err_Ok; FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; @@ -921,7 +911,7 @@ } num_axis = n_axis; - error = t1_allocate_blend( face, + error = t1_allocate_blend( t1face, (FT_UInt)num_designs, (FT_UInt)num_axis ); if ( error ) @@ -962,7 +952,7 @@ loader->parser.root.limit = old_limit; /* a valid BlendDesignPosition has been parsed */ - blend = face->blend; + blend = t1face->blend; if ( blend->design_pos[0] ) FT_FREE( blend->design_pos[0] ); @@ -980,9 +970,11 @@ static void - parse_blend_design_map( T1_Face face, - T1_Loader loader ) + parse_blend_design_map( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; FT_Error error = FT_Err_Ok; T1_Parser parser = &loader->parser; PS_Blend blend; @@ -990,7 +982,7 @@ FT_Int n, num_axis; FT_Byte* old_cursor; FT_Byte* old_limit; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); T1_ToTokenArray( parser, axis_tokens, @@ -1011,10 +1003,10 @@ old_cursor = parser->root.cursor; old_limit = parser->root.limit; - error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); + error = t1_allocate_blend( t1face, 0, (FT_UInt)num_axis ); if ( error ) goto Exit; - blend = face->blend; + blend = t1face->blend; FT_TRACE4(( " [" )); @@ -1089,15 +1081,17 @@ static void - parse_weight_vector( T1_Face face, - T1_Loader loader ) + parse_weight_vector( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; FT_Int num_designs; FT_Error error = FT_Err_Ok; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); T1_Parser parser = &loader->parser; - PS_Blend blend = face->blend; + PS_Blend blend = t1face->blend; T1_Token token; FT_Int n; FT_Byte* old_cursor; @@ -1122,10 +1116,10 @@ if ( !blend || !blend->num_designs ) { - error = t1_allocate_blend( face, (FT_UInt)num_designs, 0 ); + error = t1_allocate_blend( t1face, (FT_UInt)num_designs, 0 ); if ( error ) goto Exit; - blend = face->blend; + blend = t1face->blend; } else if ( blend->num_designs != (FT_UInt)num_designs ) { @@ -1173,11 +1167,15 @@ /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */ /* we're only interested in the number of array elements */ static void - parse_buildchar( T1_Face face, - T1_Loader loader ) + parse_buildchar( FT_Face face, /* T1_Face */ + void* loader_ ) { - face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, - 0, NULL, 0 ); + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; + + + t1face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, + 0, NULL, 0 ); #ifdef FT_DEBUG_LEVEL_TRACE { @@ -1185,7 +1183,7 @@ FT_TRACE4(( " [" )); - for ( i = 0; i < face->len_buildchar; i++ ) + for ( i = 0; i < t1face->len_buildchar; i++ ) FT_TRACE4(( " 0" )); FT_TRACE4(( "]\n" )); @@ -1335,9 +1333,10 @@ static void - parse_private( T1_Face face, - T1_Loader loader ) + parse_private( FT_Face face, + void* loader_ ) { + T1_Loader loader = (T1_Loader)loader_; FT_UNUSED( face ); loader->keywords_encountered |= T1_PRIVATE; @@ -1401,13 +1400,14 @@ /* and `/CharStrings' dictionaries. */ static void - t1_parse_font_matrix( T1_Face face, - T1_Loader loader ) + t1_parse_font_matrix( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; - FT_Matrix* matrix = &face->type1.font_matrix; - FT_Vector* offset = &face->type1.font_offset; - FT_Face root = (FT_Face)&face->root; + FT_Matrix* matrix = &t1face->type1.font_matrix; + FT_Vector* offset = &t1face->type1.font_offset; FT_Fixed temp[6]; FT_Fixed temp_scale; FT_Int result; @@ -1443,7 +1443,7 @@ if ( temp_scale != 0x10000L ) { /* set units per EM based on FontMatrix values */ - root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); + face->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); temp[0] = FT_DivFix( temp[0], temp_scale ); temp[1] = FT_DivFix( temp[1], temp_scale ); @@ -1471,14 +1471,16 @@ static void - parse_encoding( T1_Face face, - T1_Loader loader ) + parse_encoding( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; FT_Byte* cur; FT_Byte* limit = parser->root.limit; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t1face->psaux; T1_Skip_Spaces( parser ); @@ -1494,7 +1496,7 @@ /* and we must load it now */ if ( ft_isdigit( *cur ) || *cur == '[' ) { - T1_Encoding encode = &face->type1.encoding; + T1_Encoding encode = &t1face->type1.encoding; FT_Int count, array_size, n; PS_Table char_table = &loader->encoding_table; FT_Memory memory = parser->root.memory; @@ -1676,7 +1678,7 @@ FT_TRACE4(( "]\n" )); #endif - face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; + t1face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; parser->root.cursor = cur; } @@ -1687,21 +1689,21 @@ if ( cur + 17 < limit && ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) { - face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; + t1face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; FT_TRACE4(( " StandardEncoding\n" )); } else if ( cur + 15 < limit && ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) { - face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; + t1face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; FT_TRACE4(( " ExpertEncoding\n" )); } else if ( cur + 18 < limit && ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) { - face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; + t1face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; FT_TRACE4(( " ISOLatin1Encoding\n" )); } @@ -1715,9 +1717,11 @@ static void - parse_subrs( T1_Face face, - T1_Loader loader ) + parse_subrs( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; PS_Table table = &loader->subrs; FT_Memory memory = parser->root.memory; @@ -1725,7 +1729,7 @@ FT_Int num_subrs; FT_UInt count; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t1face->psaux; T1_Skip_Spaces( parser ); @@ -1769,7 +1773,7 @@ */ FT_TRACE0(( "parse_subrs: adjusting number of subroutines" - " (from %d to %ld)\n", + " (from %d to %zu)\n", num_subrs, ( parser->root.limit - parser->root.cursor ) >> 3 )); num_subrs = ( parser->root.limit - parser->root.cursor ) >> 3; @@ -1857,7 +1861,7 @@ /* */ /* thanks to Tom Kacvinsky for pointing this out */ /* */ - if ( face->type1.private_dict.lenIV >= 0 ) + if ( t1face->type1.private_dict.lenIV >= 0 ) { FT_Byte* temp = NULL; @@ -1865,7 +1869,7 @@ /* some fonts define empty subr records -- this is not totally */ /* compliant to the specification (which says they should at */ /* least contain a `return'), but we support them anyway */ - if ( size < (FT_ULong)face->type1.private_dict.lenIV ) + if ( size < (FT_ULong)t1face->type1.private_dict.lenIV ) { error = FT_THROW( Invalid_File_Format ); goto Fail; @@ -1876,9 +1880,11 @@ goto Fail; FT_MEM_COPY( temp, base, size ); psaux->t1_decrypt( temp, size, 4330 ); - size -= (FT_ULong)face->type1.private_dict.lenIV; - error = T1_Add_Table( table, (FT_Int)idx, - temp + face->type1.private_dict.lenIV, size ); + size -= (FT_ULong)t1face->type1.private_dict.lenIV; + error = T1_Add_Table( table, + (FT_Int)idx, + temp + t1face->type1.private_dict.lenIV, + size ); FT_FREE( temp ); } else @@ -1910,9 +1916,11 @@ static void - parse_charstrings( T1_Face face, - T1_Loader loader ) + parse_charstrings( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; PS_Table code_table = &loader->charstrings; PS_Table name_table = &loader->glyph_names; @@ -1920,7 +1928,7 @@ FT_Memory memory = parser->root.memory; FT_Error error; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t1face->psaux; FT_Byte* cur = parser->root.cursor; FT_Byte* limit = parser->root.limit; @@ -1940,7 +1948,7 @@ if ( num_glyphs > ( limit - cur ) >> 3 ) { FT_TRACE0(( "parse_charstrings: adjusting number of glyphs" - " (from %d to %ld)\n", + " (from %d to %zu)\n", num_glyphs, ( limit - cur ) >> 3 )); num_glyphs = ( limit - cur ) >> 3; } @@ -2069,13 +2077,13 @@ notdef_found = 1; } - if ( face->type1.private_dict.lenIV >= 0 && + if ( t1face->type1.private_dict.lenIV >= 0 && n < num_glyphs + TABLE_EXTEND ) { FT_Byte* temp = NULL; - if ( size <= (FT_ULong)face->type1.private_dict.lenIV ) + if ( size <= (FT_ULong)t1face->type1.private_dict.lenIV ) { error = FT_THROW( Invalid_File_Format ); goto Fail; @@ -2086,9 +2094,11 @@ goto Fail; FT_MEM_COPY( temp, base, size ); psaux->t1_decrypt( temp, size, 4330 ); - size -= (FT_ULong)face->type1.private_dict.lenIV; - error = T1_Add_Table( code_table, n, - temp + face->type1.private_dict.lenIV, size ); + size -= (FT_ULong)t1face->type1.private_dict.lenIV; + error = T1_Add_Table( code_table, + n, + temp + t1face->type1.private_dict.lenIV, + size ); FT_FREE( temp ); } else @@ -2570,7 +2580,7 @@ { FT_ERROR(( "T1_Open_Face:" " number-of-designs != 2 ^^ number-of-axes\n" )); - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); } if ( face->blend && @@ -2590,15 +2600,15 @@ /* font as a normal PS font */ if ( face->blend && ( !face->blend->num_designs || !face->blend->num_axis ) ) - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); /* the font may have no valid WeightVector */ if ( face->blend && !face->blend->weight_vector ) - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); /* the font may have no valid BlendDesignPositions */ if ( face->blend && !face->blend->design_pos[0] ) - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); /* the font may have no valid BlendDesignMap */ if ( face->blend ) @@ -2609,7 +2619,7 @@ for ( i = 0; i < face->blend->num_axis; i++ ) if ( !face->blend->design_map[i].num_points ) { - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); break; } } diff --git a/src/3rdparty/freetype/src/type1/t1load.h b/src/3rdparty/freetype/src/type1/t1load.h index f8511ccc..d8c9d2d8 100644 --- a/src/3rdparty/freetype/src/type1/t1load.h +++ b/src/3rdparty/freetype/src/type1/t1load.h @@ -66,52 +66,52 @@ FT_BEGIN_HEADER #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT FT_LOCAL( FT_Error ) - T1_Get_Multi_Master( T1_Face face, + T1_Get_Multi_Master( FT_Face face, FT_Multi_Master* master ); FT_LOCAL( FT_Error ) - T1_Get_MM_Var( T1_Face face, + T1_Get_MM_Var( FT_Face face, FT_MM_Var* *master ); FT_LOCAL( FT_Error ) - T1_Set_MM_Blend( T1_Face face, + T1_Set_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - T1_Get_MM_Blend( T1_Face face, + T1_Get_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - T1_Set_MM_Design( T1_Face face, + T1_Set_MM_Design( FT_Face face, FT_UInt num_coords, FT_Long* coords ); FT_LOCAL( FT_Error ) - T1_Reset_MM_Blend( T1_Face face, + T1_Reset_MM_Blend( FT_Face face, FT_UInt instance_index ); FT_LOCAL( FT_Error ) - T1_Get_Var_Design( T1_Face face, + T1_Get_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - T1_Set_Var_Design( T1_Face face, + T1_Set_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( void ) - T1_Done_Blend( T1_Face face ); + T1_Done_Blend( FT_Face face ); FT_LOCAL( FT_Error ) - T1_Set_MM_WeightVector( T1_Face face, + T1_Set_MM_WeightVector( FT_Face face, FT_UInt len, FT_Fixed* weightvector ); FT_LOCAL( FT_Error ) - T1_Get_MM_WeightVector( T1_Face face, + T1_Get_MM_WeightVector( FT_Face face, FT_UInt* len, FT_Fixed* weightvector ); diff --git a/src/3rdparty/freetype/src/type1/t1objs.c b/src/3rdparty/freetype/src/type1/t1objs.c index 1bb2f15f..69e4fd50 100644 --- a/src/3rdparty/freetype/src/type1/t1objs.c +++ b/src/3rdparty/freetype/src/type1/t1objs.c @@ -167,8 +167,7 @@ FT_Module module; - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( slot->library, "pshinter" ); if ( module ) { T1_Hints_Funcs funcs; @@ -227,7 +226,7 @@ face->len_buildchar = 0; } - T1_Done_Blend( face ); + T1_Done_Blend( t1face ); face->blend = NULL; #endif @@ -290,7 +289,8 @@ * * @Input: * stream :: - * input stream where to load font data. + * Dummy argument for compatibility with the `FT_Face_InitFunc` API. + * Ignored. The stream should be passed through `face->root.stream`. * * face_index :: * The index of the font face in the resource. diff --git a/src/3rdparty/freetype/src/type42/t42drivr.c b/src/3rdparty/freetype/src/type42/t42drivr.c index ce1528e5..ee5fd44a 100644 --- a/src/3rdparty/freetype/src/type42/t42drivr.c +++ b/src/3rdparty/freetype/src/type42/t42drivr.c @@ -56,33 +56,41 @@ * */ - static FT_Error - t42_get_glyph_name( T42_Face face, + FT_CALLBACK_DEF( FT_Error ) + t42_get_glyph_name( FT_Face face, /* T42_Face */ FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ) { - FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max ); + T42_Face t42face = (T42_Face)face; + + + FT_STRCPYN( buffer, + t42face->type1.glyph_names[glyph_index], + buffer_max ); return FT_Err_Ok; } - static FT_UInt - t42_get_name_index( T42_Face face, + FT_CALLBACK_DEF( FT_UInt ) + t42_get_name_index( FT_Face face, /* T42_Face */ const FT_String* glyph_name ) { - FT_Int i; + T42_Face t42face = (T42_Face)face; + FT_Int i; - for ( i = 0; i < face->type1.num_glyphs; i++ ) + for ( i = 0; i < t42face->type1.num_glyphs; i++ ) { - FT_String* gname = face->type1.glyph_names[i]; + FT_String* gname = t42face->type1.glyph_names[i]; if ( glyph_name[0] == gname[0] && !ft_strcmp( glyph_name, gname ) ) - return (FT_UInt)ft_strtol( (const char *)face->type1.charstrings[i], - NULL, 10 ); + return (FT_UInt)ft_strtol( + (const char *)t42face->type1.charstrings[i], + NULL, + 10 ); } return 0; @@ -102,10 +110,13 @@ * */ - static const char* - t42_get_ps_font_name( T42_Face face ) + FT_CALLBACK_DEF( const char* ) + t42_get_ps_font_name( FT_Face face ) /* T42_Face */ { - return (const char*)face->type1.font_name; + T42_Face t42face = (T42_Face)face; + + + return (const char*)t42face->type1.font_name; } @@ -121,7 +132,7 @@ * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) t42_ps_get_font_info( FT_Face face, PS_FontInfoRec* afont_info ) { @@ -131,7 +142,7 @@ } - static FT_Error + FT_CALLBACK_DEF( FT_Error ) t42_ps_get_font_extra( FT_Face face, PS_FontExtraRec* afont_extra ) { @@ -141,7 +152,7 @@ } - static FT_Int + FT_CALLBACK_DEF( FT_Int ) t42_ps_has_glyph_names( FT_Face face ) { FT_UNUSED( face ); diff --git a/src/3rdparty/freetype/src/type42/t42parse.c b/src/3rdparty/freetype/src/type42/t42parse.c index 6d765c8c..f96a43b1 100644 --- a/src/3rdparty/freetype/src/type42/t42parse.c +++ b/src/3rdparty/freetype/src/type42/t42parse.c @@ -34,19 +34,19 @@ static void - t42_parse_font_matrix( T42_Face face, - T42_Loader loader ); + t42_parse_font_matrix( FT_Face face, + void* loader_ ); static void - t42_parse_encoding( T42_Face face, - T42_Loader loader ); + t42_parse_encoding( FT_Face face, + void* loader_ ); static void - t42_parse_charstrings( T42_Face face, - T42_Loader loader ); + t42_parse_charstrings( FT_Face face, + void* loader_ ); static void - t42_parse_sfnts( T42_Face face, - T42_Loader loader ); + t42_parse_sfnts( FT_Face face, + void* loader_ ); /* as Type42 fonts have no Private dict, */ @@ -241,12 +241,14 @@ static void - t42_parse_font_matrix( T42_Face face, - T42_Loader loader ) + t42_parse_font_matrix( FT_Face face, /* T42_Face */ + void* loader_ ) { - T42_Parser parser = &loader->parser; - FT_Matrix* matrix = &face->type1.font_matrix; - FT_Vector* offset = &face->type1.font_offset; + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; + T42_Parser parser = &loader->parser; + FT_Matrix* matrix = &t42face->type1.font_matrix; + FT_Vector* offset = &t42face->type1.font_offset; FT_Fixed temp[6]; FT_Fixed temp_scale; FT_Int result; @@ -299,14 +301,16 @@ static void - t42_parse_encoding( T42_Face face, - T42_Loader loader ) + t42_parse_encoding( FT_Face face, + void* loader_ ) { - T42_Parser parser = &loader->parser; + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; + T42_Parser parser = &loader->parser; FT_Byte* cur; - FT_Byte* limit = parser->root.limit; + FT_Byte* limit = parser->root.limit; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t42face->psaux; T1_Skip_Spaces( parser ); @@ -322,7 +326,7 @@ /* and we must load it now */ if ( ft_isdigit( *cur ) || *cur == '[' ) { - T1_Encoding encode = &face->type1.encoding; + T1_Encoding encode = &t42face->type1.encoding; FT_Int count, n; PS_Table char_table = &loader->encoding_table; FT_Memory memory = parser->root.memory; @@ -493,8 +497,8 @@ T1_Skip_Spaces( parser ); } - face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; - parser->root.cursor = cur; + t42face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; + parser->root.cursor = cur; } /* Otherwise, we should have either `StandardEncoding', */ @@ -503,15 +507,15 @@ { if ( cur + 17 < limit && ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; + t42face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; else if ( cur + 15 < limit && ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; + t42face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; else if ( cur + 18 < limit && ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; + t42face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; else parser->root.error = FT_ERR( Ignore ); @@ -529,9 +533,11 @@ static void - t42_parse_sfnts( T42_Face face, - T42_Loader loader ) + t42_parse_sfnts( FT_Face face, + void* loader_ ) { + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; T42_Parser parser = &loader->parser; FT_Memory memory = parser->root.memory; FT_Byte* cur; @@ -548,8 +554,8 @@ T42_Load_Status status; /** There should only be one sfnts array, but free any previous. */ - FT_FREE( face->ttf_data ); - face->ttf_size = 0; + FT_FREE( t42face->ttf_data ); + t42face->ttf_size = 0; /* The format is */ /* */ @@ -580,7 +586,7 @@ old_string_size = 0; ttf_count = 0; ttf_reserved = 12; - if ( FT_QALLOC( face->ttf_data, ttf_reserved ) ) + if ( FT_QALLOC( t42face->ttf_data, ttf_reserved ) ) goto Fail; FT_TRACE2(( "\n" )); @@ -596,7 +602,7 @@ if ( *cur == ']' ) { parser->root.cursor++; - face->ttf_size = ttf_count; + t42face->ttf_size = ttf_count; goto Exit; } @@ -707,7 +713,7 @@ /* load offset table, 12 bytes */ if ( ttf_count < 12 ) { - face->ttf_data[ttf_count++] = string_buf[n]; + t42face->ttf_data[ttf_count++] = string_buf[n]; continue; } else @@ -715,7 +721,7 @@ FT_Long ttf_reserved_prev = ttf_reserved; - num_tables = 16 * face->ttf_data[4] + face->ttf_data[5]; + num_tables = 16 * t42face->ttf_data[4] + t42face->ttf_data[5]; status = BEFORE_TABLE_DIR; ttf_reserved = 12 + 16 * num_tables; @@ -729,7 +735,7 @@ goto Fail; } - if ( FT_QREALLOC( face->ttf_data, ttf_reserved_prev, + if ( FT_QREALLOC( t42face->ttf_data, ttf_reserved_prev, ttf_reserved ) ) goto Fail; } @@ -739,7 +745,7 @@ /* the offset table is read; read the table directory */ if ( ttf_count < ttf_reserved ) { - face->ttf_data[ttf_count++] = string_buf[n]; + t42face->ttf_data[ttf_count++] = string_buf[n]; continue; } else @@ -755,7 +761,7 @@ for ( i = 0; i < num_tables; i++ ) { - FT_Byte* p = face->ttf_data + 12 + 16 * i + 12; + FT_Byte* p = t42face->ttf_data + 12 + 16 * i + 12; len = FT_PEEK_ULONG( p ); @@ -781,7 +787,7 @@ FT_TRACE2(( " allocating %ld bytes\n", ttf_reserved )); FT_TRACE2(( "\n" )); - if ( FT_QREALLOC( face->ttf_data, ttf_reserved_prev, + if ( FT_QREALLOC( t42face->ttf_data, ttf_reserved_prev, ttf_reserved ) ) goto Fail; } @@ -795,7 +801,7 @@ error = FT_THROW( Invalid_File_Format ); goto Fail; } - face->ttf_data[ttf_count++] = string_buf[n]; + t42face->ttf_data[ttf_count++] = string_buf[n]; } } @@ -811,8 +817,8 @@ Exit: if ( parser->root.error ) { - FT_FREE( face->ttf_data ); - face->ttf_size = 0; + FT_FREE( t42face->ttf_data ); + t42face->ttf_size = 0; } if ( allocated ) FT_FREE( string_buf ); @@ -820,9 +826,11 @@ static void - t42_parse_charstrings( T42_Face face, - T42_Loader loader ) + t42_parse_charstrings( FT_Face face, /* T42_Face */ + void* loader_ ) { + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; T42_Parser parser = &loader->parser; PS_Table code_table = &loader->charstrings; PS_Table name_table = &loader->glyph_names; @@ -830,7 +838,7 @@ FT_Memory memory = parser->root.memory; FT_Error error; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t42face->psaux; FT_Byte* cur; FT_Byte* limit = parser->root.limit; @@ -864,7 +872,7 @@ if ( loader->num_glyphs > ( limit - parser->root.cursor ) >> 2 ) { FT_TRACE0(( "t42_parse_charstrings: adjusting number of glyphs" - " (from %d to %ld)\n", + " (from %d to %zu)\n", loader->num_glyphs, ( limit - parser->root.cursor ) >> 2 )); loader->num_glyphs = ( limit - parser->root.cursor ) >> 2; diff --git a/src/3rdparty/freetype/src/winfonts/winfnt.c b/src/3rdparty/freetype/src/winfonts/winfnt.c index fa73ae4a..1160e4ef 100644 --- a/src/3rdparty/freetype/src/winfonts/winfnt.c +++ b/src/3rdparty/freetype/src/winfonts/winfnt.c @@ -624,31 +624,34 @@ static FT_Error - fnt_cmap_init( FNT_CMap cmap, + fnt_cmap_init( FT_CMap cmap, /* FNT_CMap */ FT_Pointer pointer ) { - FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap ); - FNT_Font font = face->font; + FNT_CMap fntcmap = (FNT_CMap)cmap; + FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap ); + FNT_Font font = face->font; FT_UNUSED( pointer ); - cmap->first = (FT_UInt32) font->header.first_char; - cmap->count = (FT_UInt32)( font->header.last_char - cmap->first + 1 ); + fntcmap->first = (FT_UInt32)font->header.first_char; + fntcmap->count = (FT_UInt32)( font->header.last_char - + fntcmap->first + 1 ); return 0; } static FT_UInt - fnt_cmap_char_index( FNT_CMap cmap, + fnt_cmap_char_index( FT_CMap cmap, /* FNT_CMap */ FT_UInt32 char_code ) { - FT_UInt gindex = 0; + FNT_CMap fntcmap = (FNT_CMap)cmap; + FT_UInt gindex = 0; - char_code -= cmap->first; - if ( char_code < cmap->count ) + char_code -= fntcmap->first; + if ( char_code < fntcmap->count ) /* we artificially increase the glyph index; */ /* FNT_Load_Glyph reverts to the right one */ gindex = (FT_UInt)( char_code + 1 ); @@ -656,26 +659,27 @@ } - static FT_UInt32 - fnt_cmap_char_next( FNT_CMap cmap, + static FT_UInt + fnt_cmap_char_next( FT_CMap cmap, /* FNT_CMap */ FT_UInt32 *pchar_code ) { - FT_UInt gindex = 0; - FT_UInt32 result = 0; + FNT_CMap fntcmap = (FNT_CMap)cmap; + FT_UInt gindex = 0; + FT_UInt32 result = 0; FT_UInt32 char_code = *pchar_code + 1; - if ( char_code <= cmap->first ) + if ( char_code <= fntcmap->first ) { - result = cmap->first; + result = fntcmap->first; gindex = 1; } else { - char_code -= cmap->first; - if ( char_code < cmap->count ) + char_code -= fntcmap->first; + if ( char_code < fntcmap->count ) { - result = cmap->first + char_code; + result = fntcmap->first + char_code; gindex = (FT_UInt)( char_code + 1 ); } } diff --git a/src/3rdparty/harfbuzz-ng/CMakeLists.txt b/src/3rdparty/harfbuzz-ng/CMakeLists.txt index c761bda3..96e21941 100644 --- a/src/3rdparty/harfbuzz-ng/CMakeLists.txt +++ b/src/3rdparty/harfbuzz-ng/CMakeLists.txt @@ -58,6 +58,7 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz src/hb-subset-input.cc src/hb-subset-instancer-solver.cc src/hb-subset-plan.cc + src/hb-subset-plan-member-list.hh src/hb-subset-repacker.cc src/hb-subset-repacker.h src/hb-unicode.cc src/hb-unicode.h src/hb-unicode.hh src/hb-utf.hh diff --git a/src/3rdparty/harfbuzz-ng/NEWS b/src/3rdparty/harfbuzz-ng/NEWS index e53a244f..35e9eefd 100644 --- a/src/3rdparty/harfbuzz-ng/NEWS +++ b/src/3rdparty/harfbuzz-ng/NEWS @@ -1,3 +1,114 @@ +Overview of changes leading to 8.2.0 +Friday, September 8, 2023 +==================================== +- Various build and fuzzing fixes +- Improvements to COLRv1 painting. + +- New API: ++hb_paint_color_glyph_func_t ++hb_paint_funcs_set_color_glyph_func ++hb_paint_color_glyph + + +Overview of changes leading to 8.1.1 +Wednesday, August 2, 2023 +==================================== +- Fix shaping of contextual rules at the end of string, introduced in 8.1.0 +- Fix stack-overflow in repacker with malicious fonts. +- 30% speed up loading Noto Duployan font. + + +Overview of changes leading to 8.1.0 +Tuesday, August 1, 2023 +==================================== +- Fix long-standing build issue with the AIX compiler and older Apple clang. + +- Revert optimization that could cause timeout during subsetting with malicious fonts. + +- More optimization work: + - 45% speed up in shaping Noto Duployan font. + - 10% speed up in subsetting Noto Duployan font. + - Another 8% speed up in shaping Gulzar. + - 5% speed up in loading Roboto. + +- New API: ++hb_ot_layout_collect_features_map() + + +Overview of changes leading to 8.0.1 +Wednesday, July 12, 2023 +==================================== +- Build fix on 32-bit ARM. + +- More speed optimizations: + - 60% speed up in retain-gid (used for IFT) subsetting of SourceHanSans-VF. + - 16% speed up in retain-gid (used for IFT) subsetting of NotoSansCJKkr. + - 38% speed up in subsetting (beyond-64k) mega-merged Noto. + + +Overview of changes leading to 8.0.0 +Sunday, July 9, 2023 +==================================== +- New, experimental, WebAssembly (WASM) shaper, that provides greater + flexibility over OpenType/AAT/Graphite shaping, using WebAssembly embedded + inside the font file. Currently WASM shaper is disabled by default and needs + to be enabled at build time. For details, see: + + https://github.com/harfbuzz/harfbuzz/blob/main/docs/wasm-shaper.md + + For example fonts making use of the WASM shaper, see: + + https://github.com/harfbuzz/harfbuzz-wasm-examples + +- Improvements to Experimental features introduced in earlier releases: + - Support for subsetting beyond-64k and VarComposites fonts. + - Support for instancing variable fonts with cubic “glyf” table. + +- Many big speed optimizations: + - Up to 89% speedup loading variable fonts for shaping. + - Up to 88% speedup in small subsets of large (eg. CJK) fonts (both TTF and + OTF), essential for Incremental Font Transfer (IFT). + - Over 50% speedup in loading Roboto font for shaping. + - Up to 40% speed up in loading (sanitizing) complex fonts. + - 30% speed up in shaping Gulzar font. + - Over 25% speedup in glyph loading Roboto font. + - 10% speed up loading glyph shapes in VarComposite Hangul font. + - hb-hashmap optimizations & hashing improvements. + +- New macro HB_ALWAYS_INLINE. HarfBuzz now inlines functions more aggressively, + which results in some speedup at the expense of bigger code size. To disable + this feature define the macro to just inline. + +- New API: ++HB_CODEPOINT_INVALID ++hb_ot_layout_get_baseline2() ++hb_ot_layout_get_baseline_with_fallback2() ++hb_ot_layout_get_font_extents() ++hb_ot_layout_get_font_extents2() ++hb_subset_input_set_axis_range() + + +Overview of changes leading to 7.3.0 +Tuesday, May 9, 2023 +==================================== +- Speedup applying glyph variation in VarComposites fonts (over 40% speedup). + (Behdad Esfahbod) +- Speedup instancing some fonts (over 20% speedup in instancing RobotoFlex). + (Behdad Esfahbod) +- Speedup shaping some fonts (over 30% speedup in shaping Roboto). + (Behdad Esfahbod) +- Support subsetting VarComposites and beyond-64k fonts. (Behdad Esfahbod) +- New configuration macro HB_MINIMIZE_MEMORY_USAGE to favor optimizing memory + usage over speed. (Behdad Esfahbod) +- Supporting setting the mapping between old and new glyph indices during + subsetting. (Garret Rieger) +- Various fixes and improvements. + (Behdad Esfahbod, Denis Rochette, Garret Rieger, Han Seung Min, Qunxin Liu) + +- New API: ++hb_subset_input_old_to_new_glyph_mapping() + + Overview of changes leading to 7.2.0 Thursday, April 27, 2023 ==================================== diff --git a/src/3rdparty/harfbuzz-ng/README.md b/src/3rdparty/harfbuzz-ng/README.md index 4202961e..099d4b77 100644 --- a/src/3rdparty/harfbuzz-ng/README.md +++ b/src/3rdparty/harfbuzz-ng/README.md @@ -5,13 +5,16 @@ [![Codacy Badge](https://app.codacy.com/project/badge/Grade/89c872f5ce1c42af802602bfcd15d90a)](https://www.codacy.com/gh/harfbuzz/harfbuzz/dashboard?utm_source=github.com&utm_medium=referral&utm_content=harfbuzz/harfbuzz&utm_campaign=Badge_Grade) [![Codecov Code Coverage](https://codecov.io/gh/harfbuzz/harfbuzz/branch/main/graph/badge.svg)](https://codecov.io/gh/harfbuzz/harfbuzz) [![Packaging status](https://repology.org/badge/tiny-repos/harfbuzz.svg)](https://repology.org/project/harfbuzz/versions) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/harfbuzz/harfbuzz/badge)](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz) + # HarfBuzz HarfBuzz is a text shaping engine. It primarily supports [OpenType][1], but also [Apple Advanced Typography][2]. HarfBuzz is used in Android, Chrome, -ChromeOS, Firefox, GNOME, GTK+, KDE, LibreOffice, OpenJDK, PlayStation, Qt, -XeTeX, and other places. +ChromeOS, Firefox, GNOME, GTK+, KDE, Qt, LibreOffice, OpenJDK, XeTeX, +PlayStation, Microsoft Edge, Photoshop, Illustrator, InDesign, +and other places. For bug reports, mailing list, and other information please visit: @@ -26,8 +29,8 @@ For user manual as well as API documentation, check: https://harfbuzz.github.io ## Download For tarball releases of HarfBuzz, look [here][3]. At the same place you -will also find Win32/Win64 binary bundles that include libharfbuzz DLL, -hb-view.exe, hb-shape.exe, and all dependencies. +will also find Win32/Win64 binary bundles that include `libharfbuzz` DLL, +`hb-view.exe`, `hb-shape.exe`, and all dependencies. The canonical source tree is available on [github][4]. diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json index b1ca7db3..7533dab1 100644 --- a/src/3rdparty/harfbuzz-ng/qt_attribution.json +++ b/src/3rdparty/harfbuzz-ng/qt_attribution.json @@ -7,8 +7,8 @@ "Description": "HarfBuzz is an OpenType text shaping engine.", "Homepage": "http://harfbuzz.org", - "Version": "7.2.0", - "DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/7.2.0", + "Version": "8.2.0", + "DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/8.2.0", "License": "MIT License", "LicenseId": "MIT", diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh index b1250523..457039bf 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/CBDT/CBDT.hh @@ -397,7 +397,6 @@ struct IndexSubtableRecord TRACE_SERIALIZE (this); auto *subtable = c->serializer->start_embed (); - if (unlikely (!subtable)) return_trace (false); if (unlikely (!c->serializer->extend_min (subtable))) return_trace (false); auto *old_subtable = get_subtable (base); @@ -545,7 +544,8 @@ struct IndexSubtableArray const IndexSubtableRecord*>> *lookup /* OUT */) const { bool start_glyph_is_set = false; - for (hb_codepoint_t new_gid = 0; new_gid < c->plan->num_output_glyphs (); new_gid++) + unsigned num_glyphs = c->plan->num_output_glyphs (); + for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++) { hb_codepoint_t old_gid; if (unlikely (!c->plan->old_gid_for_new_gid (new_gid, &old_gid))) continue; @@ -576,9 +576,6 @@ struct IndexSubtableArray { TRACE_SUBSET (this); - auto *dst = c->serializer->start_embed (); - if (unlikely (!dst)) return_trace (false); - hb_vector_t> lookup; build_lookup (c, bitmap_size_context, &lookup); if (unlikely (!c->serializer->propagate_error (lookup))) @@ -993,12 +990,10 @@ CBLC::subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - auto *cblc_prime = c->serializer->start_embed (); - // Use a vector as a secondary buffer as the tables need to be built in parallel. hb_vector_t cbdt_prime; - if (unlikely (!cblc_prime)) return_trace (false); + auto *cblc_prime = c->serializer->start_embed (); if (unlikely (!c->serializer->extend_min (cblc_prime))) return_trace (false); cblc_prime->version = version; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh index 191812f4..60b094ec 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh @@ -53,6 +53,7 @@ struct Paint; struct hb_paint_context_t : hb_dispatch_context_t { + const char *get_name () { return "PAINT"; } template return_t dispatch (const T &obj) { obj.paint_glyph (this); return hb_empty_t (); } static return_t default_return_value () { return hb_empty_t (); } @@ -68,6 +69,8 @@ public: unsigned int palette_index; hb_color_t foreground; VarStoreInstancer &instancer; + hb_map_t current_glyphs; + hb_map_t current_layers; int depth_left = HB_MAX_NESTING_LEVEL; int edge_count = HB_COLRV1_MAX_EDGE_COUNT; @@ -261,6 +264,7 @@ struct Variable void paint_glyph (hb_paint_context_t *c) const { + TRACE_PAINT (this); value.paint_glyph (c, varIdxBase); } @@ -281,7 +285,7 @@ struct Variable public: VarIdx varIdxBase; public: - DEFINE_SIZE_STATIC (4 + T::static_size); + DEFINE_SIZE_MIN (VarIdx::static_size + T::min_size); }; template @@ -315,6 +319,7 @@ struct NoVariable void paint_glyph (hb_paint_context_t *c) const { + TRACE_PAINT (this); value.paint_glyph (c, varIdxBase); } @@ -332,7 +337,7 @@ struct NoVariable T value; public: - DEFINE_SIZE_STATIC (T::static_size); + DEFINE_SIZE_MIN (T::min_size); }; // Color structures @@ -409,7 +414,6 @@ struct ColorLine { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (this); - if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); @@ -559,6 +563,7 @@ struct Affine2x3 void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); c->funcs->push_transform (c->data, xx.to_float (c->instancer (varIdxBase, 0)), yx.to_float (c->instancer (varIdxBase, 1)), @@ -640,6 +645,7 @@ struct PaintSolid void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); hb_bool_t is_foreground; hb_color_t color; @@ -694,6 +700,7 @@ struct PaintLinearGradient void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); hb_color_line_t cl = { (void *) &(this+colorLine), (this+colorLine).static_get_color_stops, c, @@ -760,6 +767,7 @@ struct PaintRadialGradient void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); hb_color_line_t cl = { (void *) &(this+colorLine), (this+colorLine).static_get_color_stops, c, @@ -824,6 +832,7 @@ struct PaintSweepGradient void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); hb_color_line_t cl = { (void *) &(this+colorLine), (this+colorLine).static_get_color_stops, c, @@ -875,6 +884,7 @@ struct PaintGlyph void paint_glyph (hb_paint_context_t *c) const { + TRACE_PAINT (this); c->funcs->push_inverse_root_transform (c->data, c->font); c->funcs->push_clip_glyph (c->data, gid, c->font); c->funcs->push_root_transform (c->data, c->font); @@ -947,6 +957,7 @@ struct PaintTransform void paint_glyph (hb_paint_context_t *c) const { + TRACE_PAINT (this); (this+transform).paint_glyph (c); c->recurse (this+src); c->funcs->pop_transform (c->data); @@ -991,6 +1002,7 @@ struct PaintTranslate void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); float ddx = dx + c->instancer (varIdxBase, 0); float ddy = dy + c->instancer (varIdxBase, 1); @@ -1039,6 +1051,7 @@ struct PaintScale void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); float sx = scaleX.to_float (c->instancer (varIdxBase, 0)); float sy = scaleY.to_float (c->instancer (varIdxBase, 1)); @@ -1089,6 +1102,7 @@ struct PaintScaleAroundCenter void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); float sx = scaleX.to_float (c->instancer (varIdxBase, 0)); float sy = scaleY.to_float (c->instancer (varIdxBase, 1)); float tCenterX = centerX + c->instancer (varIdxBase, 2); @@ -1142,6 +1156,7 @@ struct PaintScaleUniform void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); float s = scale.to_float (c->instancer (varIdxBase, 0)); bool p1 = c->funcs->push_scale (c->data, s, s); @@ -1189,6 +1204,7 @@ struct PaintScaleUniformAroundCenter void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); float s = scale.to_float (c->instancer (varIdxBase, 0)); float tCenterX = centerX + c->instancer (varIdxBase, 1); float tCenterY = centerY + c->instancer (varIdxBase, 2); @@ -1240,6 +1256,7 @@ struct PaintRotate void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); float a = angle.to_float (c->instancer (varIdxBase, 0)); bool p1 = c->funcs->push_rotate (c->data, a); @@ -1287,6 +1304,7 @@ struct PaintRotateAroundCenter void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); float a = angle.to_float (c->instancer (varIdxBase, 0)); float tCenterX = centerX + c->instancer (varIdxBase, 1); float tCenterY = centerY + c->instancer (varIdxBase, 2); @@ -1341,6 +1359,7 @@ struct PaintSkew void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); float sx = xSkewAngle.to_float(c->instancer (varIdxBase, 0)); float sy = ySkewAngle.to_float(c->instancer (varIdxBase, 1)); @@ -1391,6 +1410,7 @@ struct PaintSkewAroundCenter void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const { + TRACE_PAINT (this); float sx = xSkewAngle.to_float(c->instancer (varIdxBase, 0)); float sy = ySkewAngle.to_float(c->instancer (varIdxBase, 1)); float tCenterX = centerX + c->instancer (varIdxBase, 2); @@ -1426,20 +1446,24 @@ struct PaintComposite auto *out = c->serializer->embed (this); if (unlikely (!out)) return_trace (false); - if (!out->src.serialize_subset (c, src, this, instancer)) return_trace (false); - return_trace (out->backdrop.serialize_subset (c, backdrop, this, instancer)); + bool ret = false; + ret |= out->src.serialize_subset (c, src, this, instancer); + ret |= out->backdrop.serialize_subset (c, backdrop, this, instancer); + return_trace (ret); } bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + c->check_ops (this->min_size) && // PainComposite can get exponential src.sanitize (c, this) && backdrop.sanitize (c, this)); } void paint_glyph (hb_paint_context_t *c) const { + TRACE_PAINT (this); c->recurse (this+backdrop); c->funcs->push_group (c->data); c->recurse (this+src); @@ -1514,10 +1538,10 @@ struct ClipBoxFormat2 : Variable value.get_clip_box(clip_box, instancer); if (instancer) { - clip_box.xMin += _hb_roundf (instancer (varIdxBase, 0)); - clip_box.yMin += _hb_roundf (instancer (varIdxBase, 1)); - clip_box.xMax += _hb_roundf (instancer (varIdxBase, 2)); - clip_box.yMax += _hb_roundf (instancer (varIdxBase, 3)); + clip_box.xMin += roundf (instancer (varIdxBase, 0)); + clip_box.yMin += roundf (instancer (varIdxBase, 1)); + clip_box.xMax += roundf (instancer (varIdxBase, 2)); + clip_box.yMax += roundf (instancer (varIdxBase, 3)); } } }; @@ -1898,15 +1922,16 @@ struct LayerList : Array32OfOffset32To auto *out = c->serializer->start_embed (this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + bool ret = false; for (const auto& _ : + hb_enumerate (*this) | hb_filter (c->plan->colrv1_layers, hb_first)) { auto *o = out->serialize_append (c->serializer); - if (unlikely (!o) || !o->serialize_subset (c, _.second, this, instancer)) - return_trace (false); + if (unlikely (!o)) return_trace (false); + ret |= o->serialize_subset (c, _.second, this, instancer); } - return_trace (true); + return_trace (ret); } bool sanitize (hb_sanitize_context_t *c) const @@ -2167,7 +2192,7 @@ struct COLR if (version == 0 && (!base_it || !layer_it)) return_trace (false); - COLR *colr_prime = c->serializer->start_embed (); + auto *colr_prime = c->serializer->start_embed (); if (unlikely (!c->serializer->extend_min (colr_prime))) return_trace (false); if (version == 0) @@ -2284,6 +2309,7 @@ struct COLR &(this+varIdxMap), hb_array (font->coords, font->num_coords)); hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer); + c.current_glyphs.add (glyph); if (version == 1) { @@ -2399,18 +2425,42 @@ hb_paint_context_t::recurse (const Paint &paint) void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const { + TRACE_PAINT (this); const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList (); for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++) { + if (unlikely (c->current_layers.has (i))) + continue; + + c->current_layers.add (i); + const Paint &paint = paint_offset_lists.get_paint (i); c->funcs->push_group (c->data); c->recurse (paint); c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER); + + c->current_layers.del (i); } } void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const { + TRACE_PAINT (this); + + if (unlikely (c->current_glyphs.has (gid))) + return; + + c->current_glyphs.add (gid); + + c->funcs->push_inverse_root_transform (c->data, c->font); + if (c->funcs->color_glyph (c->data, gid, c->font)) + { + c->funcs->pop_transform (c->data); + c->current_glyphs.del (gid); + return; + } + c->funcs->pop_transform (c->data); + const COLR *colr_table = c->get_colr_table (); const Paint *paint = colr_table->get_base_glyph_paint (gid); @@ -2429,6 +2479,8 @@ void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const if (has_clip_box) c->funcs->pop_clip (c->data); + + c->current_glyphs.del (gid); } } /* namespace OT */ diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh index 46ad3fd5..ce8693cf 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/sbix/sbix.hh @@ -48,7 +48,6 @@ struct SBIXGlyph { TRACE_SERIALIZE (this); SBIXGlyph* new_glyph = c->start_embed (); - if (unlikely (!new_glyph)) return_trace (nullptr); if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr); new_glyph->xOffset = xOffset; @@ -143,7 +142,6 @@ struct SBIXStrike unsigned int num_output_glyphs = c->plan->num_output_glyphs (); auto* out = c->serializer->start_embed (); - if (unlikely (!out)) return_trace (false); auto snap = c->serializer->snapshot (); if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false); out->ppem = ppem; @@ -388,7 +386,6 @@ struct sbix TRACE_SERIALIZE (this); auto *out = c->serializer->start_embed> (); - if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); hb_vector_t*> new_strikes; @@ -423,8 +420,6 @@ struct sbix { TRACE_SUBSET (this); - sbix *sbix_prime = c->serializer->start_embed (); - if (unlikely (!sbix_prime)) return_trace (false); if (unlikely (!c->serializer->embed (this->version))) return_trace (false); if (unlikely (!c->serializer->embed (this->flags))) return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh index d35654e2..25056c9b 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh @@ -57,6 +57,9 @@ struct Coverage public: DEFINE_SIZE_UNION (2, format); +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -113,22 +116,33 @@ struct Coverage TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (this))) return_trace (false); - unsigned count = 0; + unsigned count = hb_len (glyphs); unsigned num_ranges = 0; hb_codepoint_t last = (hb_codepoint_t) -2; + hb_codepoint_t max = 0; + bool unsorted = false; for (auto g: glyphs) { + if (last != (hb_codepoint_t) -2 && g < last) + unsorted = true; if (last + 1 != g) - num_ranges++; + num_ranges++; last = g; - count++; + if (g > max) max = g; } - u.format = count <= num_ranges * 3 ? 1 : 2; + u.format = !unsorted && count <= num_ranges * 3 ? 1 : 2; #ifndef HB_NO_BEYOND_64K - if (count && last > 0xFFFFu) + if (max > 0xFFFFu) u.format += 2; + if (unlikely (max > 0xFFFFFFu)) +#else + if (unlikely (max > 0xFFFFu)) #endif + { + c->check_success (false, HB_SERIALIZE_ERROR_INT_OVERFLOW); + return_trace (false); + } switch (u.format) { @@ -148,8 +162,8 @@ struct Coverage auto it = + iter () | hb_take (c->plan->source->get_num_glyphs ()) - | hb_filter (c->plan->glyph_map_gsub) | hb_map_retains_sorting (c->plan->glyph_map_gsub) + | hb_filter ([] (hb_codepoint_t glyph) { return glyph != HB_MAP_VALUE_INVALID; }) ; // Cache the iterator result as it will be iterated multiple times diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh index 5d68e3d1..3f598d40 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat1.hh @@ -79,7 +79,7 @@ struct CoverageFormat1_3 { if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len) / 2) { - for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + for (auto g : *glyphs) if (get_coverage (g) != NOT_COVERED) return true; return false; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh index d7fcc352..9c875423 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/CoverageFormat2.hh @@ -95,19 +95,26 @@ struct CoverageFormat2_4 unsigned count = 0; unsigned range = (unsigned) -1; last = (hb_codepoint_t) -2; + unsigned unsorted = false; for (auto g: glyphs) { if (last + 1 != g) { + if (unlikely (last != (hb_codepoint_t) -2 && last + 1 > g)) + unsorted = true; + range++; - rangeRecord[range].first = g; - rangeRecord[range].value = count; + rangeRecord.arrayZ[range].first = g; + rangeRecord.arrayZ[range].value = count; } - rangeRecord[range].last = g; + rangeRecord.arrayZ[range].last = g; last = g; count++; } + if (unlikely (unsorted)) + rangeRecord.as_array ().qsort (RangeRecord::cmp_range); + return_trace (true); } @@ -115,7 +122,7 @@ struct CoverageFormat2_4 { if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len) / 2) { - for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);) + for (auto g : *glyphs) if (get_coverage (g) != NOT_COVERED) return true; return false; @@ -185,8 +192,8 @@ struct CoverageFormat2_4 if (__more__ ()) { unsigned int old = coverage; - j = c->rangeRecord[i].first; - coverage = c->rangeRecord[i].value; + j = c->rangeRecord.arrayZ[i].first; + coverage = c->rangeRecord.arrayZ[i].value; if (unlikely (coverage != old + 1)) { /* Broken table. Skip. Important to avoid DoS. diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh index a62629fa..85aacace 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/RangeRecord.hh @@ -51,6 +51,18 @@ struct RangeRecord int cmp (hb_codepoint_t g) const { return g < first ? -1 : g <= last ? 0 : +1; } + HB_INTERNAL static int cmp_range (const void *pa, const void *pb) { + const RangeRecord *a = (const RangeRecord *) pa; + const RangeRecord *b = (const RangeRecord *) pb; + if (a->first < b->first) return -1; + if (a->first > b->first) return +1; + if (a->last < b->last) return -1; + if (a->last > b->last) return +1; + if (a->value < b->value) return -1; + if (a->value > b->value) return +1; + return 0; + } + unsigned get_population () const { if (unlikely (last < first)) return 0; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh index 0551fcf8..4f85d3ce 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh @@ -32,6 +32,7 @@ #include "../../../hb-ot-layout-common.hh" #include "../../../hb-font.hh" +#include "../../../hb-cache.hh" namespace OT { @@ -48,8 +49,6 @@ struct AttachPoint : Array16Of { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); - return_trace (out->serialize (c->serializer, + iter ())); } }; @@ -201,7 +200,6 @@ struct CaretValueFormat3 { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); if (!c->serializer->embed (caretValueFormat)) return_trace (false); if (!c->serializer->embed (coordinate)) return_trace (false); @@ -441,6 +439,16 @@ struct MarkGlyphSetsFormat1 bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } + template + void collect_coverage (hb_vector_t &sets) const + { + for (const auto &offset : coverage) + { + const auto &cov = this+offset; + cov.collect_coverage (sets.push ()); + } + } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); @@ -494,6 +502,15 @@ struct MarkGlyphSets } } + template + void collect_coverage (hb_vector_t &sets) const + { + switch (u.format) { + case 1: u.format1.collect_coverage (sets); return; + default:return; + } + } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); @@ -858,10 +875,47 @@ struct GDEF hb_blob_destroy (table.get_blob ()); table = hb_blob_get_empty (); } + +#ifndef HB_NO_GDEF_CACHE + table->get_mark_glyph_sets ().collect_coverage (mark_glyph_set_digests); +#endif } ~accelerator_t () { table.destroy (); } + unsigned int get_glyph_props (hb_codepoint_t glyph) const + { + unsigned v; + +#ifndef HB_NO_GDEF_CACHE + if (glyph_props_cache.get (glyph, &v)) + return v; +#endif + + v = table->get_glyph_props (glyph); + +#ifndef HB_NO_GDEF_CACHE + if (likely (table.get_blob ())) // Don't try setting if we are the null instance! + glyph_props_cache.set (glyph, v); +#endif + + return v; + + } + + bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const + { + return +#ifndef HB_NO_GDEF_CACHE + mark_glyph_set_digests[set_index].may_have (glyph_id) && +#endif + table->mark_set_covers (set_index, glyph_id); + } + hb_blob_ptr_t table; +#ifndef HB_NO_GDEF_CACHE + hb_vector_t mark_glyph_set_digests; + mutable hb_cache_t<21, 3, 8> glyph_props_cache; +#endif }; void collect_variation_indices (hb_collect_variation_indices_context_t *c) const diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh index e7e3c5c6..8684f60c 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorFormat3.hh @@ -25,7 +25,9 @@ struct AnchorFormat3 bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); + if (unlikely (!c->check_struct (this))) return_trace (false); + + return_trace (xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); } void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, @@ -35,9 +37,9 @@ struct AnchorFormat3 *x = font->em_fscale_x (xCoordinate); *y = font->em_fscale_y (yCoordinate); - if (font->x_ppem || font->num_coords) + if ((font->x_ppem || font->num_coords) && xDeviceTable.sanitize (&c->sanitizer, this)) *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache); - if (font->y_ppem || font->num_coords) + if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this)) *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache); } @@ -45,7 +47,6 @@ struct AnchorFormat3 { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->embed (format))) return_trace (false); if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false); if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh index c442efa1..37ba7916 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh @@ -21,18 +21,25 @@ struct AnchorMatrix if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false); unsigned int count = rows * cols; if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false); + + if (c->lazy_some_gpos) + return_trace (true); + for (unsigned int i = 0; i < count; i++) if (!matrixZ[i].sanitize (c, this)) return_trace (false); return_trace (true); } - const Anchor& get_anchor (unsigned int row, unsigned int col, - unsigned int cols, bool *found) const + const Anchor& get_anchor (hb_ot_apply_context_t *c, + unsigned int row, unsigned int col, + unsigned int cols, bool *found) const { *found = false; if (unlikely (row >= rows || col >= cols)) return Null (Anchor); - *found = !matrixZ[row * cols + col].is_null (); - return this+matrixZ[row * cols + col]; + auto &offset = matrixZ[row * cols + col]; + if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor); + *found = !offset.is_null (); + return this+offset; } template serializer->extend_min (out))) return_trace (false); out->rows = num_rows; + bool ret = false; for (const unsigned i : index_iter) { auto *offset = c->serializer->embed (matrixZ[i]); if (!offset) return_trace (false); - offset->serialize_subset (c, matrixZ[i], this); + ret |= offset->serialize_subset (c, matrixZ[i], this); } - return_trace (true); + return_trace (ret); } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh index ff255e09..7c42c3f7 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/CursivePosFormat1.hh @@ -24,16 +24,17 @@ struct EntryExitRecord (src_base+exitAnchor).collect_variation_indices (c); } - EntryExitRecord* subset (hb_subset_context_t *c, - const void *src_base) const + bool subset (hb_subset_context_t *c, + const void *src_base) const { TRACE_SERIALIZE (this); auto *out = c->serializer->embed (this); - if (unlikely (!out)) return_trace (nullptr); + if (unlikely (!out)) return_trace (false); - out->entryAnchor.serialize_subset (c, entryAnchor, src_base); - out->exitAnchor.serialize_subset (c, exitAnchor, src_base); - return_trace (out); + bool ret = false; + ret |= out->entryAnchor.serialize_subset (c, entryAnchor, src_base); + ret |= out->exitAnchor.serialize_subset (c, exitAnchor, src_base); + return_trace (ret); } protected: @@ -91,7 +92,13 @@ struct CursivePosFormat1 bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this)); + if (unlikely (!coverage.sanitize (c, this))) + return_trace (false); + + if (c->lazy_some_gpos) + return_trace (entryExitRecord.sanitize_shallow (c)); + else + return_trace (entryExitRecord.sanitize (c, this)); } bool intersects (const hb_set_t *glyphs) const @@ -119,19 +126,21 @@ struct CursivePosFormat1 hb_buffer_t *buffer = c->buffer; const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)]; - if (!this_record.entryAnchor) return_trace (false); + if (!this_record.entryAnchor || + unlikely (!this_record.entryAnchor.sanitize (&c->sanitizer, this))) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx); unsigned unsafe_from; - if (!skippy_iter.prev (&unsafe_from)) + if (unlikely (!skippy_iter.prev (&unsafe_from))) { buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); return_trace (false); } const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)]; - if (!prev_record.exitAnchor) + if (!prev_record.exitAnchor || + unlikely (!prev_record.exitAnchor.sanitize (&c->sanitizer, this))) { buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); return_trace (false); @@ -200,8 +209,8 @@ struct CursivePosFormat1 * Arabic. */ unsigned int child = i; unsigned int parent = j; - hb_position_t x_offset = entry_x - exit_x; - hb_position_t y_offset = entry_y - exit_y; + hb_position_t x_offset = roundf (entry_x - exit_x); + hb_position_t y_offset = roundf (entry_y - exit_y); if (!(c->lookup_props & LookupFlag::RightToLeft)) { unsigned int k = child; @@ -278,7 +287,6 @@ struct CursivePosFormat1 const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); - if (unlikely (!out)) return_trace (false); auto it = + hb_zip (this+coverage, entryExitRecord) diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh index 9493ec98..f4af98b2 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/GPOS.hh @@ -156,7 +156,7 @@ GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) { for (unsigned i = 0; i < len; i++) if (unlikely (pos[i].y_offset)) - pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset); + pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset); } } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh index a2d807cc..59cca40a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh @@ -27,6 +27,7 @@ struct LigatureArray : List16OfOffset16To auto *out = c->serializer->start_embed (this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + bool ret = false; for (const auto _ : + hb_zip (coverage, *this) | hb_filter (glyphset, hb_first)) { @@ -38,13 +39,13 @@ struct LigatureArray : List16OfOffset16To + hb_range (src.rows * class_count) | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); }) ; - matrix->serialize_subset (c, - _.second, - this, - src.rows, - indexes); + ret |= matrix->serialize_subset (c, + _.second, + this, + src.rows, + indexes); } - return_trace (this->len); + return_trace (ret); } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh index ff43ffb8..0887cc15 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkArray.hh @@ -28,7 +28,7 @@ struct MarkArray : Array16Of /* Array of MarkRecords--in Cove const Anchor& mark_anchor = this + record.markAnchor; bool found; - const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found); + const Anchor& glyph_anchor = anchors.get_anchor (c, glyph_index, mark_class, class_count, &found); /* If this subtable doesn't have an anchor for this base and this class, * return false such that the subsequent subtables have a chance at it. */ if (unlikely (!found)) return_trace (false); @@ -82,10 +82,10 @@ struct MarkArray : Array16Of /* Array of MarkRecords--in Cove | hb_map (hb_second) ; + bool ret = false; unsigned new_length = 0; for (const auto& mark_record : mark_iter) { - if (unlikely (!mark_record.subset (c, this, klass_mapping))) - return_trace (false); + ret |= mark_record.subset (c, this, klass_mapping); new_length++; } @@ -93,7 +93,7 @@ struct MarkArray : Array16Of /* Array of MarkRecords--in Cove HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return_trace (false); - return_trace (true); + return_trace (ret); } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh index eb471204..1b8f3c80 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh @@ -197,9 +197,10 @@ struct MarkBasePosFormat1_2 if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ())) return_trace (false); - out->markArray.serialize_subset (c, markArray, this, - (this+markCoverage).iter (), - &klass_mapping); + if (unlikely (!out->markArray.serialize_subset (c, markArray, this, + (this+markCoverage).iter (), + &klass_mapping))) + return_trace (false); unsigned basecount = (this+baseArray).rows; auto base_iter = @@ -228,11 +229,9 @@ struct MarkBasePosFormat1_2 ; } - out->baseArray.serialize_subset (c, baseArray, this, - base_iter.len (), - base_indexes.iter ()); - - return_trace (true); + return_trace (out->baseArray.serialize_subset (c, baseArray, this, + base_iter.len (), + base_indexes.iter ())); } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh index 92e83a0e..af8b4723 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh @@ -195,9 +195,10 @@ struct MarkLigPosFormat1_2 if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage)) return_trace (false); - out->markArray.serialize_subset (c, markArray, this, - (this+markCoverage).iter (), - &klass_mapping); + if (unlikely (!out->markArray.serialize_subset (c, markArray, this, + (this+markCoverage).iter (), + &klass_mapping))) + return_trace (false); auto new_ligature_coverage = + hb_iter (this + ligatureCoverage) @@ -208,10 +209,9 @@ struct MarkLigPosFormat1_2 if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage)) return_trace (false); - out->ligatureArray.serialize_subset (c, ligatureArray, this, - hb_iter (this+ligatureCoverage), classCount, &klass_mapping); - - return_trace (true); + return_trace (out->ligatureArray.serialize_subset (c, ligatureArray, this, + hb_iter (this+ligatureCoverage), + classCount, &klass_mapping)); } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh index fbcebb80..70cf0716 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh @@ -100,16 +100,16 @@ struct MarkMarkPosFormat1_2 /* now we search backwards for a suitable mark glyph until a non-mark glyph */ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx); skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags); unsigned unsafe_from; - if (!skippy_iter.prev (&unsafe_from)) + if (unlikely (!skippy_iter.prev (&unsafe_from))) { buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); return_trace (false); } - if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) + if (likely (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))) { buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); return_trace (false); @@ -183,9 +183,10 @@ struct MarkMarkPosFormat1_2 if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) return_trace (false); - out->mark1Array.serialize_subset (c, mark1Array, this, - (this+mark1Coverage).iter (), - &klass_mapping); + if (unlikely (!out->mark1Array.serialize_subset (c, mark1Array, this, + (this+mark1Coverage).iter (), + &klass_mapping))) + return_trace (false); unsigned mark2count = (this+mark2Array).rows; auto mark2_iter = @@ -214,9 +215,10 @@ struct MarkMarkPosFormat1_2 ; } - out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ()); + return_trace (out->mark2Array.serialize_subset (c, mark2Array, this, + mark2_iter.len (), + mark2_indexes.iter ())); - return_trace (true); } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkRecord.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkRecord.hh index a7d489d2..3d11c777 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkRecord.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkRecord.hh @@ -24,17 +24,16 @@ struct MarkRecord return_trace (c->check_struct (this) && markAnchor.sanitize (c, base)); } - MarkRecord *subset (hb_subset_context_t *c, - const void *src_base, - const hb_map_t *klass_mapping) const + bool subset (hb_subset_context_t *c, + const void *src_base, + const hb_map_t *klass_mapping) const { TRACE_SUBSET (this); auto *out = c->serializer->embed (this); - if (unlikely (!out)) return_trace (nullptr); + if (unlikely (!out)) return_trace (false); out->klass = klass_mapping->get (klass); - out->markAnchor.serialize_subset (c, markAnchor, src_base); - return_trace (out); + return_trace (out->markAnchor.serialize_subset (c, markAnchor, src_base)); } void collect_variation_indices (hb_collect_variation_indices_context_t *c, diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh index 4dada1c8..e4a2006f 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh @@ -110,9 +110,9 @@ struct PairPosFormat1_3 if (likely (index == NOT_COVERED)) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx); unsigned unsafe_to; - if (!skippy_iter.next (&unsafe_to)) + if (unlikely (!skippy_iter.next (&unsafe_to))) { buffer->unsafe_to_concat (buffer->idx, unsafe_to); return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh index de15a29e..4adb1ef6 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -50,13 +50,13 @@ struct PairPosFormat2_4 unsigned int len1 = valueFormat1.get_len (); unsigned int len2 = valueFormat2.get_len (); unsigned int stride = HBUINT16::static_size * (len1 + len2); - unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size (); unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count; return_trace (c->check_range ((const void *) values, count, - record_size) && - valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && - valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)); + stride) && + (c->lazy_some_gpos || + (valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && + valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)))); } bool intersects (const hb_set_t *glyphs) const @@ -131,40 +131,46 @@ struct PairPosFormat2_4 if (likely (index == NOT_COVERED)) return_trace (false); hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; - skippy_iter.reset (buffer->idx, 1); + skippy_iter.reset_fast (buffer->idx); unsigned unsafe_to; - if (!skippy_iter.next (&unsafe_to)) + if (unlikely (!skippy_iter.next (&unsafe_to))) { buffer->unsafe_to_concat (buffer->idx, unsafe_to); return_trace (false); } + unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); + if (!klass2) + { + buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); + return_trace (false); + } + + unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint); + if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) + { + buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); + return_trace (false); + } + unsigned int len1 = valueFormat1.get_len (); unsigned int len2 = valueFormat2.get_len (); unsigned int record_len = len1 + len2; - unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint); - unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); - if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) - { - buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1); - return_trace (false); - } - const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; bool applied_first = false, applied_second = false; /* Isolate simple kerning and apply it half to each side. - * Results in better cursor positinoing / underline drawing. + * Results in better cursor positioning / underline drawing. * * Disabled, because causes issues... :-( * https://github.com/harfbuzz/harfbuzz/issues/3408 * https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978 */ #ifndef HB_SPLIT_KERN - if (0) + if (false) #endif { if (!len2) @@ -224,8 +230,8 @@ struct PairPosFormat2_4 c->buffer->idx, skippy_iter.idx); } - applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos()); - applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); + applied_first = len1 && valueFormat1.apply_value (c, this, v, buffer->cur_pos()); + applied_second = len2 && valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); if (applied_first || applied_second) if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) @@ -293,11 +299,13 @@ struct PairPosFormat2_4 out->valueFormat2 = out->valueFormat2.drop_device_table_flags (); } + unsigned total_len = len1 + len2; + hb_vector_t class2_idxs (+ hb_range ((unsigned) class2Count) | hb_filter (klass2_map)); for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map)) { - for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) + for (unsigned class2_idx : class2_idxs) { - unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); + unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * total_len; valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], &c->plan->layout_variation_idx_delta_map); valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], &c->plan->layout_variation_idx_delta_map); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh index 147b8e00..db301bb8 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairSet.hh @@ -52,8 +52,9 @@ struct PairSet unsigned int count = len; const PairValueRecord *record = &firstPairValueRecord; - return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) && - closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)); + return_trace (c->lazy_some_gpos || + (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) && + closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride))); } bool intersects (const hb_set_t *glyphs, @@ -120,8 +121,8 @@ struct PairSet c->buffer->idx, pos); } - bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); - bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); + bool applied_first = len1 && valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); + bool applied_second = len2 && valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); if (applied_first || applied_second) if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh index 32224777..72bf0e99 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairValueRecord.hh @@ -22,7 +22,7 @@ struct PairValueRecord ValueRecord values; /* Positioning data for the first glyph * followed by for second glyph */ public: - DEFINE_SIZE_ARRAY (Types::size, values); + DEFINE_SIZE_ARRAY (Types::HBGlyphID::static_size, values); int cmp (hb_codepoint_t k) const { return secondGlyph.cmp (k); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh index 623e4e66..dff1f731 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat1.hh @@ -90,6 +90,7 @@ struct SinglePosFormat1 bool position_single (hb_font_t *font, + hb_blob_t *table_blob, hb_direction_t direction, hb_codepoint_t gid, hb_glyph_position_t &pos) const @@ -100,7 +101,7 @@ struct SinglePosFormat1 /* This is ugly... */ hb_buffer_t buffer; buffer.props.direction = direction; - OT::hb_ot_apply_context_t c (1, font, &buffer); + OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob); valueFormat.apply_value (&c, this, values, pos); return true; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh index e8f2d7c2..168ad3bb 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/SinglePosFormat2.hh @@ -94,6 +94,7 @@ struct SinglePosFormat2 bool position_single (hb_font_t *font, + hb_blob_t *table_blob, hb_direction_t direction, hb_codepoint_t gid, hb_glyph_position_t &pos) const @@ -105,7 +106,7 @@ struct SinglePosFormat2 /* This is ugly... */ hb_buffer_t buffer; buffer.props.direction = direction; - OT::hb_ot_apply_context_t c (1, font, &buffer); + OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob); valueFormat.apply_value (&c, this, &values[index * valueFormat.get_len ()], diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh index 1aa451ab..461a13d4 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/ValueFormat.hh @@ -118,21 +118,25 @@ struct ValueFormat : HBUINT16 auto *cache = c->var_store_cache; /* pixel -> fractional pixel */ - if (format & xPlaDevice) { - if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store, cache); + if (format & xPlaDevice) + { + if (use_x_device) glyph_pos.x_offset += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache); values++; } - if (format & yPlaDevice) { - if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store, cache); + if (format & yPlaDevice) + { + if (use_y_device) glyph_pos.y_offset += get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache); values++; } - if (format & xAdvDevice) { - if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store, cache); + if (format & xAdvDevice) + { + if (horizontal && use_x_device) glyph_pos.x_advance += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache); values++; } - if (format & yAdvDevice) { + if (format & yAdvDevice) + { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store, cache); + if (!horizontal && use_y_device) glyph_pos.y_advance -= get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache); values++; } return ret; @@ -174,6 +178,9 @@ struct ValueFormat : HBUINT16 if (format & xAdvance) x_adv = copy_value (c, new_format, xAdvance, *values++); if (format & yAdvance) y_adv = copy_value (c, new_format, yAdvance, *values++); + if (!has_device ()) + return; + if (format & xPlaDevice) { add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map); @@ -233,14 +240,12 @@ struct ValueFormat : HBUINT16 if (format & ValueFormat::xAdvDevice) { - (base + get_device (&(values[i]))).collect_variation_indices (c); i++; } if (format & ValueFormat::yAdvDevice) { - (base + get_device (&(values[i]))).collect_variation_indices (c); i++; } @@ -277,10 +282,22 @@ struct ValueFormat : HBUINT16 { return *static_cast *> (value); } - static inline const Offset16To& get_device (const Value* value, bool *worked=nullptr) + static inline const Offset16To& get_device (const Value* value) + { + return *static_cast *> (value); + } + static inline const Device& get_device (const Value* value, + bool *worked, + const void *base, + hb_sanitize_context_t &c) { if (worked) *worked |= bool (*value); - return *static_cast *> (value); + auto &offset = *static_cast *> (value); + + if (unlikely (!offset.sanitize (&c, base))) + return Null(Device); + + return base + offset; } void add_delta_to_value (HBINT16 *value, @@ -340,25 +357,26 @@ struct ValueFormat : HBUINT16 bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const { TRACE_SANITIZE (this); - return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values))); + + if (unlikely (!c->check_range (values, get_size ()))) return_trace (false); + + if (c->lazy_some_gpos) + return_trace (true); + + return_trace (!has_device () || sanitize_value_devices (c, base, values)); } bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const { TRACE_SANITIZE (this); - unsigned int len = get_len (); + unsigned size = get_size (); - if (!c->check_range (values, count, get_size ())) return_trace (false); + if (!c->check_range (values, count, size)) return_trace (false); - if (!has_device ()) return_trace (true); + if (c->lazy_some_gpos) + return_trace (true); - for (unsigned int i = 0; i < count; i++) { - if (!sanitize_value_devices (c, base, values)) - return_trace (false); - values += len; - } - - return_trace (true); + return_trace (sanitize_values_stride_unsafe (c, base, values, count, size)); } /* Just sanitize referenced Device tables. Doesn't check the values themselves. */ diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh index 968bba04..b849494d 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Common.hh @@ -8,8 +8,6 @@ namespace OT { namespace Layout { namespace GSUB_impl { -typedef hb_pair_t hb_codepoint_pair_t; - template static void SingleSubst_serialize (hb_serialize_context_t *c, Iterator it); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh index 38057cb6..402ed12a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Ligature.hh @@ -10,10 +10,10 @@ namespace GSUB_impl { template struct Ligature { - protected: + public: typename Types::HBGlyphID ligGlyph; /* GlyphID of ligature to substitute */ - HeadlessArrayOf + HeadlessArray16Of component; /* Array of component GlyphIDs--start * with the second component--ordered * in writing direction */ diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh index 9db25cf5..08665438 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSet.hh @@ -75,12 +75,69 @@ struct LigatureSet bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); + unsigned int num_ligs = ligature.len; + +#ifndef HB_NO_OT_RULESETS_FAST_PATH + if (HB_OPTIMIZE_SIZE_VAL || num_ligs <= 4) +#endif + { + slow: + for (unsigned int i = 0; i < num_ligs; i++) + { + const auto &lig = this+ligature.arrayZ[i]; + if (lig.apply (c)) return_trace (true); + } + return_trace (false); + } + + /* This version is optimized for speed by matching the first component + * of the ligature here, instead of calling into the ligation code. + * + * This is replicated in ChainRuleSet and RuleSet. */ + + hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; + skippy_iter.reset (c->buffer->idx); + skippy_iter.set_match_func (match_always, nullptr); + skippy_iter.set_glyph_data ((HBUINT16 *) nullptr); + unsigned unsafe_to; + hb_codepoint_t first = (unsigned) -1; + bool matched = skippy_iter.next (&unsafe_to); + if (likely (matched)) + { + first = c->buffer->info[skippy_iter.idx].codepoint; + unsafe_to = skippy_iter.idx + 1; + + if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])) + { + /* Can't use the fast path if eg. the next char is a default-ignorable + * or other skippable. */ + goto slow; + } + } + else + goto slow; + + bool unsafe_to_concat = false; + for (unsigned int i = 0; i < num_ligs; i++) { - const auto &lig = this+ligature[i]; - if (lig.apply (c)) return_trace (true); + const auto &lig = this+ligature.arrayZ[i]; + if (unlikely (lig.component.lenP1 <= 1) || + lig.component.arrayZ[0] == first) + { + if (lig.apply (c)) + { + if (unsafe_to_concat) + c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to); + return_trace (true); + } + } + else if (likely (lig.component.lenP1 > 1)) + unsafe_to_concat = true; } + if (likely (unsafe_to_concat)) + c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to); return_trace (false); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh index 2c2e1aa4..916fa281 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh @@ -191,7 +191,6 @@ struct ReverseChainSingleSubstFormat1 TRACE_SERIALIZE (this); auto *out = c->serializer->start_embed (this); - if (unlikely (!c->serializer->check_success (out))) return_trace (false); if (unlikely (!c->serializer->embed (this->format))) return_trace (false); if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh index ae3292f3..a26cf8c6 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/Sequence.hh @@ -53,7 +53,7 @@ struct Sequence if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ()) { c->buffer->message (c->font, - "replaced glyph at %u (multiple subtitution)", + "replaced glyph at %u (multiple substitution)", c->buffer->idx - 1u); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh index 4529927b..181c9e52 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/SingleSubst.hh @@ -57,7 +57,7 @@ struct SingleSubst #ifndef HB_NO_BEYOND_64K if (+ glyphs - | hb_map_retains_sorting (hb_first) + | hb_map_retains_sorting (hb_second) | hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; })) { format += 2; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh index 94e00d3a..60858a5a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/CompositeGlyph.hh @@ -87,19 +87,54 @@ struct CompositeGlyphRecord } } - void transform_points (contour_point_vector_t &points, + static void transform (const float (&matrix)[4], + hb_array_t points) + { + if (matrix[0] != 1.f || matrix[1] != 0.f || + matrix[2] != 0.f || matrix[3] != 1.f) + for (auto &point : points) + point.transform (matrix); + } + + static void translate (const contour_point_t &trans, + hb_array_t points) + { + if (HB_OPTIMIZE_SIZE_VAL) + { + if (trans.x != 0.f || trans.y != 0.f) + for (auto &point : points) + point.translate (trans); + } + else + { + if (trans.x != 0.f && trans.y != 0.f) + for (auto &point : points) + point.translate (trans); + else + { + if (trans.x != 0.f) + for (auto &point : points) + point.x += trans.x; + else if (trans.y != 0.f) + for (auto &point : points) + point.y += trans.y; + } + } + } + + void transform_points (hb_array_t points, const float (&matrix)[4], const contour_point_t &trans) const { if (scaled_offsets ()) { - points.translate (trans); - points.transform (matrix); + translate (trans, points); + transform (matrix, points); } else { - points.transform (matrix); - points.translate (trans); + transform (matrix, points); + translate (trans, points); } } @@ -108,8 +143,8 @@ struct CompositeGlyphRecord float matrix[4]; contour_point_t trans; get_transformation (matrix, trans); - if (unlikely (!points.resize (points.length + 1))) return false; - points[points.length - 1] = trans; + if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points + points.push (trans); return true; } @@ -358,7 +393,7 @@ struct CompositeGlyph { /* last 4 points in points_with_deltas are phantom points and should not be included */ if (i >= points_with_deltas.length - 4) { - free (o); + hb_free (o); return false; } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh index 9e15a6e6..5ea61194 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh @@ -103,6 +103,63 @@ struct Glyph } } + bool get_all_points_without_var (const hb_face_t *face, + contour_point_vector_t &points /* OUT */) const + { + switch (type) { + case SIMPLE: + if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points))) + return false; + break; + case COMPOSITE: + { + for (auto &item : get_composite_iterator ()) + if (unlikely (!item.get_points (points))) return false; + break; + } +#ifndef HB_NO_VAR_COMPOSITES + case VAR_COMPOSITE: + { + for (auto &item : get_var_composite_iterator ()) + if (unlikely (!item.get_points (points))) return false; + break; + } +#endif + case EMPTY: + break; + } + + /* Init phantom points */ + if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false; + hb_array_t phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT); + { + int lsb = 0; + int h_delta = face->table.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ? + (int) header->xMin - lsb : 0; + HB_UNUSED int tsb = 0; + int v_orig = (int) header->yMax + +#ifndef HB_NO_VERTICAL + ((void) face->table.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb) +#else + 0 +#endif + ; + unsigned h_adv = face->table.hmtx->get_advance_without_var_unscaled (gid); + unsigned v_adv = +#ifndef HB_NO_VERTICAL + face->table.vmtx->get_advance_without_var_unscaled (gid) +#else + - face->get_upem () +#endif + ; + phantoms[PHANTOM_LEFT].x = h_delta; + phantoms[PHANTOM_RIGHT].x = (int) h_adv + h_delta; + phantoms[PHANTOM_TOP].y = v_orig; + phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv; + } + return true; + } + void update_mtx (const hb_subset_plan_t *plan, int xMin, int xMax, int yMin, int yMax, @@ -114,8 +171,8 @@ struct Glyph if (type != EMPTY) { - plan->bounds_width_map.set (new_gid, xMax - xMin); - plan->bounds_height_map.set (new_gid, yMax - yMin); + plan->bounds_width_vec[new_gid] = xMax - xMin; + plan->bounds_height_vec[new_gid] = yMax - yMin; } unsigned len = all_points.length; @@ -124,10 +181,12 @@ struct Glyph float topSideY = all_points[len - 2].y; float bottomSideY = all_points[len - 1].y; + uint32_t hash = hb_hash (new_gid); + signed hori_aw = roundf (rightSideX - leftSideX); if (hori_aw < 0) hori_aw = 0; int lsb = roundf (xMin - leftSideX); - plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb)); + plan->hmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) hori_aw, lsb)); //flag value should be computed using non-empty glyphs if (type != EMPTY && lsb != xMin) plan->head_maxp_info.allXMinIsLsb = false; @@ -135,7 +194,7 @@ struct Glyph signed vert_aw = roundf (topSideY - bottomSideY); if (vert_aw < 0) vert_aw = 0; int tsb = roundf (topSideY - yMax); - plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb)); + plan->vmtx_map.set_with_hash (new_gid, hash, hb_pair ((unsigned) vert_aw, tsb)); } bool compile_header_bytes (const hb_subset_plan_t *plan, @@ -155,24 +214,28 @@ struct Glyph { xMin = xMax = all_points[0].x; yMin = yMax = all_points[0].y; + + unsigned count = all_points.length - 4; + for (unsigned i = 1; i < count; i++) + { + float x = all_points[i].x; + float y = all_points[i].y; + xMin = hb_min (xMin, x); + xMax = hb_max (xMax, x); + yMin = hb_min (yMin, y); + yMax = hb_max (yMax, y); + } } - for (unsigned i = 1; i < all_points.length - 4; i++) - { - float x = all_points[i].x; - float y = all_points[i].y; - xMin = hb_min (xMin, x); - xMax = hb_max (xMax, x); - yMin = hb_min (yMin, y); - yMax = hb_max (yMax, y); - } - update_mtx (plan, roundf (xMin), roundf (xMax), roundf (yMin), roundf (yMax), all_points); - - int rounded_xMin = roundf (xMin); - int rounded_xMax = roundf (xMax); - int rounded_yMin = roundf (yMin); - int rounded_yMax = roundf (yMax); + // These are destined for storage in a 16 bit field to clamp the values to + // fit into a 16 bit signed integer. + int rounded_xMin = hb_clamp (roundf (xMin), -32768.0f, 32767.0f); + int rounded_xMax = hb_clamp (roundf (xMax), -32768.0f, 32767.0f); + int rounded_yMin = hb_clamp (roundf (yMin), -32768.0f, 32767.0f); + int rounded_yMax = hb_clamp (roundf (yMax), -32768.0f, 32767.0f); + + update_mtx (plan, rounded_xMin, rounded_xMax, rounded_yMin, rounded_yMax, all_points); if (type != EMPTY) { @@ -287,6 +350,7 @@ struct Glyph bool use_my_metrics = true, bool phantom_only = false, hb_array_t coords = hb_array_t (), + hb_map_t *current_glyphs = nullptr, unsigned int depth = 0, unsigned *edge_count = nullptr) const { @@ -295,7 +359,11 @@ struct Glyph if (!edge_count) edge_count = &stack_edge_count; if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false; (*edge_count)++; - + + hb_map_t current_glyphs_stack; + if (current_glyphs == nullptr) + current_glyphs = ¤t_glyphs_stack; + if (head_maxp_info) { head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth); @@ -305,9 +373,8 @@ struct Glyph coords = hb_array (font->coords, font->num_coords); contour_point_vector_t stack_points; - bool inplace = type == SIMPLE && all_points.length == 0; - /* Load into all_points if it's empty, as an optimization. */ - contour_point_vector_t &points = inplace ? all_points : stack_points; + contour_point_vector_t &points = type == SIMPLE ? all_points : stack_points; + unsigned old_length = points.length; switch (type) { case SIMPLE: @@ -315,7 +382,7 @@ struct Glyph head_maxp_info->maxContours = hb_max (head_maxp_info->maxContours, (unsigned) header->numberOfContours); if (depth > 0 && composite_contours) *composite_contours += (unsigned) header->numberOfContours; - if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only))) + if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (all_points, phantom_only))) return false; break; case COMPOSITE: @@ -329,6 +396,7 @@ struct Glyph { for (auto &item : get_var_composite_iterator ()) if (unlikely (!item.get_points (points))) return false; + break; } #endif case EMPTY: @@ -365,9 +433,11 @@ struct Glyph } #ifndef HB_NO_VAR - glyf_accelerator.gvar->apply_deltas_to_points (gid, - coords, - points.as_array ()); + if (coords) + glyf_accelerator.gvar->apply_deltas_to_points (gid, + coords, + points.as_array ().sub_array (old_length), + phantom_only && type == SIMPLE); #endif // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it @@ -375,27 +445,33 @@ struct Glyph if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE) { if (unlikely (!points_with_deltas->resize (points.length))) return false; - points_with_deltas->copy_vector (points); + *points_with_deltas = points; } switch (type) { case SIMPLE: if (depth == 0 && head_maxp_info) - head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, points.length - 4); - if (!inplace) - all_points.extend (points.as_array ()); + head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, all_points.length - old_length - 4); break; case COMPOSITE: { - contour_point_vector_t comp_points; unsigned int comp_index = 0; for (auto &item : get_composite_iterator ()) { - comp_points.reset (); - if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ()) + hb_codepoint_t item_gid = item.get_gid (); + + if (unlikely (current_glyphs->has (item_gid))) + continue; + + current_glyphs->add (item_gid); + + unsigned old_count = all_points.length; + + if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) && + !glyf_accelerator.glyph_for_gid (item_gid) .get_points (font, glyf_accelerator, - comp_points, + all_points, points_with_deltas, head_maxp_info, composite_contours, @@ -403,23 +479,32 @@ struct Glyph use_my_metrics, phantom_only, coords, + current_glyphs, depth + 1, edge_count))) + { + current_glyphs->del (item_gid); return false; + } + + auto comp_points = all_points.as_array ().sub_array (old_count); /* Copy phantom points from component if USE_MY_METRICS flag set */ if (use_my_metrics && item.is_use_my_metrics ()) for (unsigned int i = 0; i < PHANTOM_COUNT; i++) phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; - float matrix[4]; - contour_point_t default_trans; - item.get_transformation (matrix, default_trans); + if (comp_points) // Empty in case of phantom_only + { + float matrix[4]; + contour_point_t default_trans; + item.get_transformation (matrix, default_trans); - /* Apply component transformation & translation (with deltas applied) */ - item.transform_points (comp_points, matrix, points[comp_index]); + /* Apply component transformation & translation (with deltas applied) */ + item.transform_points (comp_points, matrix, points[comp_index]); + } - if (item.is_anchored ()) + if (item.is_anchored () && !phantom_only) { unsigned int p1, p2; item.get_anchor_points (p1, p2); @@ -429,16 +514,20 @@ struct Glyph delta.init (all_points[p1].x - comp_points[p2].x, all_points[p1].y - comp_points[p2].y); - comp_points.translate (delta); + item.translate (delta, comp_points); } } - all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT)); + all_points.resize (all_points.length - PHANTOM_COUNT); if (all_points.length > HB_GLYF_MAX_POINTS) + { + current_glyphs->del (item_gid); return false; + } comp_index++; + current_glyphs->del (item_gid); } if (head_maxp_info && depth == 0) @@ -453,26 +542,37 @@ struct Glyph #ifndef HB_NO_VAR_COMPOSITES case VAR_COMPOSITE: { - contour_point_vector_t comp_points; hb_array_t points_left = points.as_array (); for (auto &item : get_var_composite_iterator ()) { + hb_codepoint_t item_gid = item.get_gid (); + + if (unlikely (current_glyphs->has (item_gid))) + continue; + + current_glyphs->add (item_gid); + unsigned item_num_points = item.get_num_points (); hb_array_t record_points = points_left.sub_array (0, item_num_points); - - comp_points.reset (); + assert (record_points.length == item_num_points); auto component_coords = coords; - if (item.is_reset_unspecified_axes ()) + /* Copying coords is expensive; so we have put an arbitrary + * limit on the max number of coords for now. */ + if (item.is_reset_unspecified_axes () || + coords.length > HB_GLYF_VAR_COMPOSITE_MAX_AXES) component_coords = hb_array (); coord_setter_t coord_setter (component_coords); item.set_variations (coord_setter, record_points); - if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ()) + unsigned old_count = all_points.length; + + if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) && + !glyf_accelerator.glyph_for_gid (item_gid) .get_points (font, glyf_accelerator, - comp_points, + all_points, points_with_deltas, head_maxp_info, nullptr, @@ -480,24 +580,36 @@ struct Glyph use_my_metrics, phantom_only, coord_setter.get_coords (), + current_glyphs, depth + 1, edge_count))) + { + current_glyphs->del (item_gid); return false; + } + + auto comp_points = all_points.as_array ().sub_array (old_count); /* Apply component transformation */ - item.transform_points (record_points, comp_points); + if (comp_points) // Empty in case of phantom_only + item.transform_points (record_points, comp_points); /* Copy phantom points from component if USE_MY_METRICS flag set */ if (use_my_metrics && item.is_use_my_metrics ()) for (unsigned int i = 0; i < PHANTOM_COUNT; i++) phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; - all_points.extend (comp_points.as_array ().sub_array (0, comp_points.length - PHANTOM_COUNT)); + all_points.resize (all_points.length - PHANTOM_COUNT); if (all_points.length > HB_GLYF_MAX_POINTS) + { + current_glyphs->del (item_gid); return false; + } points_left += item_num_points; + + current_glyphs->del (item_gid); } all_points.extend (phantoms); } break; @@ -512,9 +624,10 @@ struct Glyph /* Undocumented rasterizer behavior: * Shift points horizontally by the updated left side bearing */ - contour_point_t delta; - delta.init (-phantoms[PHANTOM_LEFT].x, 0.f); - if (delta.x) all_points.translate (delta); + int v = -phantoms[PHANTOM_LEFT].x; + if (v) + for (auto &point : all_points) + point.x += v; } return !all_points.in_error (); @@ -545,10 +658,11 @@ struct Glyph int num_contours = header->numberOfContours; if (unlikely (num_contours == 0)) type = EMPTY; else if (num_contours > 0) type = SIMPLE; + else if (num_contours == -1) type = COMPOSITE; #ifndef HB_NO_VAR_COMPOSITES else if (num_contours == -2) type = VAR_COMPOSITE; #endif - else type = COMPOSITE; /* negative numbers */ + else type = EMPTY; // Spec deviation; Spec says COMPOSITE, but not seen in the wild. } protected: diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh index b6679b2d..1d42cc29 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SimpleGlyph.hh @@ -124,7 +124,7 @@ struct SimpleGlyph } static bool read_flags (const HBUINT8 *&p /* IN/OUT */, - contour_point_vector_t &points_ /* IN/OUT */, + hb_array_t points_ /* IN/OUT */, const HBUINT8 *end) { unsigned count = points_.length; @@ -146,7 +146,7 @@ struct SimpleGlyph } static bool read_points (const HBUINT8 *&p /* IN/OUT */, - contour_point_vector_t &points_ /* IN/OUT */, + hb_array_t points_ /* IN/OUT */, const HBUINT8 *end, float contour_point_t::*m, const simple_glyph_flag_t short_flag, @@ -154,10 +154,9 @@ struct SimpleGlyph { int v = 0; - unsigned count = points_.length; - for (unsigned i = 0; i < count; i++) + for (auto &point : points_) { - unsigned flag = points_[i].flag; + unsigned flag = point.flag; if (flag & short_flag) { if (unlikely (p + 1 > end)) return false; @@ -175,23 +174,27 @@ struct SimpleGlyph p += HBINT16::static_size; } } - points_.arrayZ[i].*m = v; + point.*m = v; } return true; } - bool get_contour_points (contour_point_vector_t &points_ /* OUT */, + bool get_contour_points (contour_point_vector_t &points /* OUT */, bool phantom_only = false) const { const HBUINT16 *endPtsOfContours = &StructAfter (header); int num_contours = header.numberOfContours; - assert (num_contours); + assert (num_contours > 0); /* One extra item at the end, for the instruction-count below. */ if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false; unsigned int num_points = endPtsOfContours[num_contours - 1] + 1; - points_.alloc (num_points + 4, true); // Allocate for phantom points, to avoid a possible copy - if (!points_.resize (num_points)) return false; + unsigned old_length = points.length; + points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy + if (unlikely (!points.resize (points.length + num_points, false))) return false; + auto points_ = points.as_array ().sub_array (old_length); + if (!phantom_only) + hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points); if (phantom_only) return true; for (int i = 0; i < num_contours; i++) @@ -214,7 +217,7 @@ struct SimpleGlyph } static void encode_coord (int value, - uint8_t &flag, + unsigned &flag, const simple_glyph_flag_t short_flag, const simple_glyph_flag_t same_flag, hb_vector_t &coords /* OUT */) @@ -239,9 +242,9 @@ struct SimpleGlyph } } - static void encode_flag (uint8_t &flag, - uint8_t &repeat, - uint8_t lastflag, + static void encode_flag (unsigned flag, + unsigned &repeat, + unsigned lastflag, hb_vector_t &flags /* OUT */) { if (flag == lastflag && repeat != 255) @@ -262,7 +265,7 @@ struct SimpleGlyph else { repeat = 0; - flags.push (flag); + flags.arrayZ[flags.length++] = flag; } } @@ -282,13 +285,13 @@ struct SimpleGlyph if (unlikely (!x_coords.alloc (2*num_points, true))) return false; if (unlikely (!y_coords.alloc (2*num_points, true))) return false; - uint8_t lastflag = 255, repeat = 0; + unsigned lastflag = 255, repeat = 0; int prev_x = 0, prev_y = 0; for (unsigned i = 0; i < num_points; i++) { - uint8_t flag = all_points.arrayZ[i].flag; - flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE; + unsigned flag = all_points.arrayZ[i].flag; + flag &= FLAG_ON_CURVE | FLAG_OVERLAP_SIMPLE | FLAG_CUBIC; int cur_x = roundf (all_points.arrayZ[i].x); int cur_y = roundf (all_points.arrayZ[i].y); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh index 26dc374e..8099d3c1 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/SubsetGlyph.hh @@ -22,7 +22,7 @@ struct SubsetGlyph bool serialize (hb_serialize_context_t *c, bool use_short_loca, - const hb_subset_plan_t *plan) + const hb_subset_plan_t *plan) const { TRACE_SERIALIZE (this); @@ -40,7 +40,7 @@ struct SubsetGlyph pad = 0; while (pad_length > 0) { - c->embed (pad); + (void) c->embed (pad); pad_length--; } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh index 309ec473..50cbece3 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/VarCompositeGlyph.hh @@ -36,24 +36,21 @@ struct VarCompositeGlyphRecord unsigned int get_size () const { + unsigned fl = flags; unsigned int size = min_size; - unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 4 : 3; + unsigned axis_width = (fl & AXIS_INDICES_ARE_SHORT) ? 4 : 3; size += numAxes * axis_width; - // gid - size += 2; - if (flags & GID_IS_24BIT) size += 1; + if (fl & GID_IS_24BIT) size += 1; - if (flags & HAVE_TRANSLATE_X) size += 2; - if (flags & HAVE_TRANSLATE_Y) size += 2; - if (flags & HAVE_ROTATION) size += 2; - if (flags & HAVE_SCALE_X) size += 2; - if (flags & HAVE_SCALE_Y) size += 2; - if (flags & HAVE_SKEW_X) size += 2; - if (flags & HAVE_SKEW_Y) size += 2; - if (flags & HAVE_TCENTER_X) size += 2; - if (flags & HAVE_TCENTER_Y) size += 2; + // 2 bytes each for the following flags + fl = fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y | + HAVE_ROTATION | + HAVE_SCALE_X | HAVE_SCALE_Y | + HAVE_SKEW_X | HAVE_SKEW_Y | + HAVE_TCENTER_X | HAVE_TCENTER_Y); + size += hb_popcount (fl) * 2; return size; } @@ -66,17 +63,17 @@ struct VarCompositeGlyphRecord hb_codepoint_t get_gid () const { if (flags & GID_IS_24BIT) - return StructAfter (numAxes); + return * (const HBGlyphID24 *) &pad; else - return StructAfter (numAxes); + return * (const HBGlyphID16 *) &pad; } void set_gid (hb_codepoint_t gid) { if (flags & GID_IS_24BIT) - StructAfter (numAxes) = gid; + * (HBGlyphID24 *) &pad = gid; else - StructAfter (numAxes) = gid; + * (HBGlyphID16 *) &pad = gid; } unsigned get_numAxes () const @@ -86,26 +83,44 @@ struct VarCompositeGlyphRecord unsigned get_num_points () const { + unsigned fl = flags; unsigned num = 0; - if (flags & AXES_HAVE_VARIATION) num += numAxes; - if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) num++; - if (flags & HAVE_ROTATION) num++; - if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) num++; - if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) num++; - if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) num++; + if (fl & AXES_HAVE_VARIATION) num += numAxes; + + /* Hopefully faster code, relying on the value of the flags. */ + fl = (((fl & (HAVE_TRANSLATE_Y | HAVE_SCALE_Y | HAVE_SKEW_Y | HAVE_TCENTER_Y)) >> 1) | fl) & + (HAVE_TRANSLATE_X | HAVE_ROTATION | HAVE_SCALE_X | HAVE_SKEW_X | HAVE_TCENTER_X); + num += hb_popcount (fl); + return num; + + /* Slower but more readable code. */ + if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) num++; + if (fl & HAVE_ROTATION) num++; + if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y)) num++; + if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y)) num++; + if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) num++; return num; } - void transform_points (hb_array_t record_points, - contour_point_vector_t &points) const + void transform_points (hb_array_t record_points, + hb_array_t points) const { float matrix[4]; contour_point_t trans; - get_transformation_from_points (record_points, matrix, trans); + get_transformation_from_points (record_points.arrayZ, matrix, trans); - points.transform (matrix); - points.translate (trans); + auto arrayZ = points.arrayZ; + unsigned count = points.length; + + if (matrix[0] != 1.f || matrix[1] != 0.f || + matrix[2] != 0.f || matrix[3] != 1.f) + for (unsigned i = 0; i < count; i++) + arrayZ[i].transform (matrix); + + if (trans.x != 0.f || trans.y != 0.f) + for (unsigned i = 0; i < count; i++) + arrayZ[i].translate (trans); } static inline void transform (float (&matrix)[4], contour_point_t &trans, @@ -136,26 +151,41 @@ struct VarCompositeGlyphRecord static void translate (float (&matrix)[4], contour_point_t &trans, float translateX, float translateY) { - // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L213 - float other[6] = {1.f, 0.f, 0.f, 1.f, translateX, translateY}; - transform (matrix, trans, other); + if (!translateX && !translateY) + return; + + trans.x += matrix[0] * translateX + matrix[2] * translateY; + trans.y += matrix[1] * translateX + matrix[3] * translateY; } static void scale (float (&matrix)[4], contour_point_t &trans, float scaleX, float scaleY) { - // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L224 - float other[6] = {scaleX, 0.f, 0.f, scaleY, 0.f, 0.f}; - transform (matrix, trans, other); + if (scaleX == 1.f && scaleY == 1.f) + return; + + matrix[0] *= scaleX; + matrix[1] *= scaleX; + matrix[2] *= scaleY; + matrix[3] *= scaleY; } static void rotate (float (&matrix)[4], contour_point_t &trans, float rotation) { + if (!rotation) + return; + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240 rotation = rotation * HB_PI; - float c = cosf (rotation); - float s = sinf (rotation); + float c; + float s; +#ifdef HAVE_SINCOSF + sincosf (rotation, &s, &c); +#else + c = cosf (rotation); + s = sinf (rotation); +#endif float other[6] = {c, s, -s, c, 0.f, 0.f}; transform (matrix, trans, other); } @@ -163,101 +193,100 @@ struct VarCompositeGlyphRecord static void skew (float (&matrix)[4], contour_point_t &trans, float skewX, float skewY) { + if (!skewX && !skewY) + return; + // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255 skewX = skewX * HB_PI; skewY = skewY * HB_PI; - float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f}; + float other[6] = {1.f, + skewY ? tanf (skewY) : 0.f, + skewX ? tanf (skewX) : 0.f, + 1.f, + 0.f, 0.f}; transform (matrix, trans, other); } bool get_points (contour_point_vector_t &points) const { - float translateX = 0.f; - float translateY = 0.f; - float rotation = 0.f; - float scaleX = 1.f * (1 << 10); - float scaleY = 1.f * (1 << 10); - float skewX = 0.f; - float skewY = 0.f; - float tCenterX = 0.f; - float tCenterY = 0.f; - unsigned num_points = get_num_points (); - if (unlikely (!points.resize (points.length + num_points))) return false; + points.alloc (points.length + num_points + 4); // For phantom points + if (unlikely (!points.resize (points.length + num_points, false))) return false; + contour_point_t *rec_points = points.arrayZ + (points.length - num_points); + hb_memset (rec_points, 0, num_points * sizeof (rec_points[0])); - unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1; - unsigned axes_size = numAxes * axis_width; + unsigned fl = flags; + + unsigned num_axes = numAxes; + unsigned axis_width = (fl & AXIS_INDICES_ARE_SHORT) ? 2 : 1; + unsigned axes_size = num_axes * axis_width; const F2DOT14 *q = (const F2DOT14 *) (axes_size + - (flags & GID_IS_24BIT ? 3 : 2) + - &StructAfter (numAxes)); + (fl & GID_IS_24BIT ? 3 : 2) + + (const HBUINT8 *) &pad); - hb_array_t rec_points = points.as_array ().sub_array (points.length - num_points); - - unsigned count = numAxes; - if (flags & AXES_HAVE_VARIATION) + unsigned count = num_axes; + if (fl & AXES_HAVE_VARIATION) { for (unsigned i = 0; i < count; i++) - rec_points[i].x = q++->to_int (); - rec_points += count; + rec_points++->x = q++->to_int (); } else q += count; const HBUINT16 *p = (const HBUINT16 *) q; - if (flags & HAVE_TRANSLATE_X) translateX = * (const FWORD *) p++; - if (flags & HAVE_TRANSLATE_Y) translateY = * (const FWORD *) p++; - if (flags & HAVE_ROTATION) rotation = ((const F4DOT12 *) p++)->to_int (); - if (flags & HAVE_SCALE_X) scaleX = ((const F6DOT10 *) p++)->to_int (); - if (flags & HAVE_SCALE_Y) scaleY = ((const F6DOT10 *) p++)->to_int (); - if (flags & HAVE_SKEW_X) skewX = ((const F4DOT12 *) p++)->to_int (); - if (flags & HAVE_SKEW_Y) skewY = ((const F4DOT12 *) p++)->to_int (); - if (flags & HAVE_TCENTER_X) tCenterX = * (const FWORD *) p++; - if (flags & HAVE_TCENTER_Y) tCenterY = * (const FWORD *) p++; - - if ((flags & UNIFORM_SCALE) && !(flags & HAVE_SCALE_Y)) - scaleY = scaleX; - - if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) + if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) { - rec_points[0].x = translateX; - rec_points[0].y = translateY; + int translateX = (fl & HAVE_TRANSLATE_X) ? * (const FWORD *) p++ : 0; + int translateY = (fl & HAVE_TRANSLATE_Y) ? * (const FWORD *) p++ : 0; + rec_points->x = translateX; + rec_points->y = translateY; rec_points++; } - if (flags & HAVE_ROTATION) + if (fl & HAVE_ROTATION) { - rec_points[0].x = rotation; + int rotation = (fl & HAVE_ROTATION) ? ((const F4DOT12 *) p++)->to_int () : 0; + rec_points->x = rotation; rec_points++; } - if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) + if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y)) { - rec_points[0].x = scaleX; - rec_points[0].y = scaleY; + int scaleX = (fl & HAVE_SCALE_X) ? ((const F6DOT10 *) p++)->to_int () : 1 << 10; + int scaleY = (fl & HAVE_SCALE_Y) ? ((const F6DOT10 *) p++)->to_int () : 1 << 10; + if ((fl & UNIFORM_SCALE) && !(fl & HAVE_SCALE_Y)) + scaleY = scaleX; + rec_points->x = scaleX; + rec_points->y = scaleY; rec_points++; } - if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) + if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y)) { - rec_points[0].x = skewX; - rec_points[0].y = skewY; + int skewX = (fl & HAVE_SKEW_X) ? ((const F4DOT12 *) p++)->to_int () : 0; + int skewY = (fl & HAVE_SKEW_Y) ? ((const F4DOT12 *) p++)->to_int () : 0; + rec_points->x = skewX; + rec_points->y = skewY; rec_points++; } - if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) + if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) { - rec_points[0].x = tCenterX; - rec_points[0].y = tCenterY; + int tCenterX = (fl & HAVE_TCENTER_X) ? * (const FWORD *) p++ : 0; + int tCenterY = (fl & HAVE_TCENTER_Y) ? * (const FWORD *) p++ : 0; + rec_points->x = tCenterX; + rec_points->y = tCenterY; rec_points++; } - assert (!rec_points); return true; } - void get_transformation_from_points (hb_array_t rec_points, + void get_transformation_from_points (const contour_point_t *rec_points, float (&matrix)[4], contour_point_t &trans) const { - if (flags & AXES_HAVE_VARIATION) + unsigned fl = flags; + + if (fl & AXES_HAVE_VARIATION) rec_points += numAxes; matrix[0] = matrix[3] = 1.f; @@ -274,36 +303,35 @@ struct VarCompositeGlyphRecord float tCenterX = 0.f; float tCenterY = 0.f; - if (flags & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) + if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y)) { - translateX = rec_points[0].x; - translateY = rec_points[0].y; + translateX = rec_points->x; + translateY = rec_points->y; rec_points++; } - if (flags & HAVE_ROTATION) + if (fl & HAVE_ROTATION) { - rotation = rec_points[0].x / (1 << 12); + rotation = rec_points->x / (1 << 12); rec_points++; } - if (flags & (HAVE_SCALE_X | HAVE_SCALE_Y)) + if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y)) { - scaleX = rec_points[0].x / (1 << 10); - scaleY = rec_points[0].y / (1 << 10); + scaleX = rec_points->x / (1 << 10); + scaleY = rec_points->y / (1 << 10); rec_points++; } - if (flags & (HAVE_SKEW_X | HAVE_SKEW_Y)) + if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y)) { - skewX = rec_points[0].x / (1 << 12); - skewY = rec_points[0].y / (1 << 12); + skewX = rec_points->x / (1 << 12); + skewY = rec_points->y / (1 << 12); rec_points++; } - if (flags & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) + if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y)) { - tCenterX = rec_points[0].x; - tCenterY = rec_points[0].y; + tCenterX = rec_points->x; + tCenterY = rec_points->y; rec_points++; } - assert (!rec_points); translate (matrix, trans, translateX + tCenterX, translateY + tCenterY); rotate (matrix, trans, rotation); @@ -317,18 +345,19 @@ struct VarCompositeGlyphRecord { bool have_variations = flags & AXES_HAVE_VARIATION; unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1; + unsigned num_axes = numAxes; const HBUINT8 *p = (const HBUINT8 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2)); const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2)); - const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes))); + const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + num_axes) : (HBUINT8 *) (q + num_axes))); - unsigned count = numAxes; + unsigned count = num_axes; for (unsigned i = 0; i < count; i++) { unsigned axis_index = axis_width == 1 ? (unsigned) *p++ : (unsigned) *q++; - signed v = have_variations ? rec_points[i].x : a++->to_int (); + signed v = have_variations ? rec_points.arrayZ[i].x : a++->to_int (); v = hb_clamp (v, -(1<<14), (1<<14)); setter[axis_index] = v; @@ -338,8 +367,9 @@ struct VarCompositeGlyphRecord protected: HBUINT16 flags; HBUINT8 numAxes; + HBUINT16 pad; public: - DEFINE_SIZE_MIN (3); + DEFINE_SIZE_MIN (5); }; using var_composite_iter_t = composite_iter_tmpl; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh index df64ed5a..cf059293 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/coord-setter.hh @@ -16,6 +16,8 @@ struct coord_setter_t int& operator [] (unsigned idx) { + if (unlikely (idx >= HB_GLYF_VAR_COMPOSITE_MAX_AXES)) + return Crap(int); if (coords.length < idx + 1) coords.resize (idx + 1); return coords[idx]; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh index 30106b2b..d0a5a132 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf-helpers.hh @@ -12,24 +12,44 @@ namespace OT { namespace glyf_impl { -template +template static void -_write_loca (IteratorIn&& it, bool short_offsets, IteratorOut&& dest) +_write_loca (IteratorIn&& it, + const hb_sorted_vector_t new_to_old_gid_list, + bool short_offsets, + TypeOut *dest, + unsigned num_offsets) { unsigned right_shift = short_offsets ? 1 : 0; - unsigned int offset = 0; - dest << 0; - + it - | hb_map ([=, &offset] (unsigned int padded_size) - { - offset += padded_size; - DEBUG_MSG (SUBSET, nullptr, "loca entry offset %u", offset); - return offset >> right_shift; - }) - | hb_sink (dest) - ; + unsigned offset = 0; + TypeOut value; + value = 0; + *dest++ = value; + hb_codepoint_t last = 0; + for (auto _ : new_to_old_gid_list) + { + hb_codepoint_t gid = _.first; + for (; last < gid; last++) + { + DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u", offset); + *dest++ = value; + } + + unsigned padded_size = *it++; + offset += padded_size; + DEBUG_MSG (SUBSET, nullptr, "loca entry gid %u offset %u padded-size %u", gid, offset, padded_size); + value = offset >> right_shift; + *dest++ = value; + + last++; // Skip over gid + } + unsigned num_glyphs = num_offsets - 1; + for (; last < num_glyphs; last++) + { + DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u", offset); + *dest++ = value; + } } static bool @@ -67,11 +87,14 @@ _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca) template static bool -_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca) +_add_loca_and_head (hb_subset_context_t *c, + Iterator padded_offsets, + bool use_short_loca) { - unsigned num_offsets = padded_offsets.len () + 1; + unsigned num_offsets = c->plan->num_output_glyphs () + 1; unsigned entry_size = use_short_loca ? 2 : 4; - char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets); + + char *loca_prime_data = (char *) hb_malloc (entry_size * num_offsets); if (unlikely (!loca_prime_data)) return false; @@ -79,9 +102,9 @@ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_s entry_size, num_offsets, entry_size * num_offsets); if (use_short_loca) - _write_loca (padded_offsets, true, hb_array ((HBUINT16 *) loca_prime_data, num_offsets)); + _write_loca (padded_offsets, c->plan->new_to_old_gid_list, true, (HBUINT16 *) loca_prime_data, num_offsets); else - _write_loca (padded_offsets, false, hb_array ((HBUINT32 *) loca_prime_data, num_offsets)); + _write_loca (padded_offsets, c->plan->new_to_old_gid_list, false, (HBUINT32 *) loca_prime_data, num_offsets); hb_blob_t *loca_blob = hb_blob_create (loca_prime_data, entry_size * num_offsets, @@ -89,8 +112,8 @@ _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_s loca_prime_data, hb_free); - bool result = plan->add_table (HB_OT_TAG_loca, loca_blob) - && _add_head_and_set_loca_version (plan, use_short_loca); + bool result = c->plan->add_table (HB_OT_TAG_loca, loca_blob) + && _add_head_and_set_loca_version (c->plan, use_short_loca); hb_blob_destroy (loca_blob); return result; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh index dd08dda6..6300cf4b 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh @@ -85,75 +85,72 @@ struct glyf return_trace (false); } - glyf *glyf_prime = c->serializer->start_embed (); - if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false); - hb_font_t *font = nullptr; if (c->plan->normalized_coords) { font = _create_font_for_instancing (c->plan); - if (unlikely (!font)) return false; + if (unlikely (!font)) + return_trace (false); } hb_vector_t padded_offsets; - unsigned num_glyphs = c->plan->num_output_glyphs (); - if (unlikely (!padded_offsets.resize (num_glyphs))) - { - hb_font_destroy (font); - return false; - } + if (unlikely (!padded_offsets.alloc (c->plan->new_to_old_gid_list.length, true))) + return_trace (false); hb_vector_t glyphs; if (!_populate_subset_glyphs (c->plan, font, glyphs)) { hb_font_destroy (font); - return false; + return_trace (false); } if (font) hb_font_destroy (font); unsigned max_offset = 0; - for (unsigned i = 0; i < num_glyphs; i++) + for (auto &g : glyphs) { - padded_offsets[i] = glyphs[i].padded_size (); - max_offset += padded_offsets[i]; + unsigned size = g.padded_size (); + padded_offsets.push (size); + max_offset += size; } bool use_short_loca = false; if (likely (!c->plan->force_long_loca)) use_short_loca = max_offset < 0x1FFFF; - if (!use_short_loca) { - for (unsigned i = 0; i < num_glyphs; i++) - padded_offsets[i] = glyphs[i].length (); + if (!use_short_loca) + { + padded_offsets.resize (0); + for (auto &g : glyphs) + padded_offsets.push (g.length ()); } - bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan); + auto *glyf_prime = c->serializer->start_embed (); + bool result = glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan); if (c->plan->normalized_coords && !c->plan->pinned_at_default) _free_compiled_subset_glyphs (glyphs); - if (!result) return false; + if (unlikely (!c->serializer->check_success (glyf_impl::_add_loca_and_head (c, + padded_offsets.iter (), + use_short_loca)))) + return_trace (false); - if (unlikely (c->serializer->in_error ())) return_trace (false); - - return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan, - padded_offsets.iter (), - use_short_loca))); + return result; } bool _populate_subset_glyphs (const hb_subset_plan_t *plan, hb_font_t *font, - hb_vector_t &glyphs /* OUT */) const; + hb_vector_t& glyphs /* OUT */) const; hb_font_t * _create_font_for_instancing (const hb_subset_plan_t *plan) const; void _free_compiled_subset_glyphs (hb_vector_t &glyphs) const { - for (unsigned i = 0; i < glyphs.length; i++) - glyphs[i].free_compiled_bytes (); + for (auto &g : glyphs) + g.free_compiled_bytes (); } protected: @@ -222,13 +219,14 @@ struct glyf_accelerator_t if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only))) return false; + unsigned count = all_points.length; + assert (count >= glyf_impl::PHANTOM_COUNT); + count -= glyf_impl::PHANTOM_COUNT; + if (consumer.is_consuming_contour_points ()) { - unsigned count = all_points.length; - assert (count >= glyf_impl::PHANTOM_COUNT); - count -= glyf_impl::PHANTOM_COUNT; - for (unsigned point_index = 0; point_index < count; point_index++) - consumer.consume_point (all_points[point_index]); + for (auto &point : all_points.as_array ().sub_array (0, count)) + consumer.consume_point (point); consumer.points_end (); } @@ -236,7 +234,7 @@ struct glyf_accelerator_t contour_point_t *phantoms = consumer.get_phantoms_sink (); if (phantoms) for (unsigned i = 0; i < glyf_impl::PHANTOM_COUNT; ++i) - phantoms[i] = all_points[all_points.length - glyf_impl::PHANTOM_COUNT + i]; + phantoms[i] = all_points.arrayZ[count + i]; return true; } @@ -299,6 +297,7 @@ struct glyf_accelerator_t if (extents) bounds = contour_bounds_t (); } + HB_ALWAYS_INLINE void consume_point (const contour_point_t &point) { bounds.add (point); } void points_end () { bounds.get_extents (font, extents, scaled); } @@ -431,16 +430,17 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan, hb_vector_t& glyphs /* OUT */) const { OT::glyf_accelerator_t glyf (plan->source); - unsigned num_glyphs = plan->num_output_glyphs (); - if (!glyphs.resize (num_glyphs)) return false; + if (!glyphs.alloc (plan->new_to_old_gid_list.length, true)) return false; - for (auto p : plan->glyph_map->iter ()) + for (const auto &pair : plan->new_to_old_gid_list) { - unsigned new_gid = p.second; - glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid]; - subset_glyph.old_gid = p.first; + hb_codepoint_t new_gid = pair.first; + hb_codepoint_t old_gid = pair.second; + glyf_impl::SubsetGlyph *p = glyphs.push (); + glyf_impl::SubsetGlyph& subset_glyph = *p; + subset_glyph.old_gid = old_gid; - if (unlikely (new_gid == 0 && + if (unlikely (old_gid == 0 && new_gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) && !plan->normalized_coords) subset_glyph.source_glyph = glyf_impl::Glyph (); @@ -487,7 +487,7 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const { hb_variation_t var; var.tag = _.first; - var.value = _.second; + var.value = _.second.middle; vars.push (var); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh index 8916241f..f5505245 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/path-builder.hh @@ -21,19 +21,15 @@ struct path_builder_t operator bool () const { return has_data; } bool has_data = false; - float x = 0.; - float y = 0.; + float x; + float y; - optional_point_t lerp (optional_point_t p, float t) - { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); } + optional_point_t mid (optional_point_t p) + { return optional_point_t ((x + p.x) * 0.5f, (y + p.y) * 0.5f); } } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2; - path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) - { - font = font_; - draw_session = &draw_session_; - first_oncurve = first_offcurve = first_offcurve2 = last_offcurve = last_offcurve2 = optional_point_t (); - } + path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) : + font (font_), draw_session (&draw_session_) {} /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287 See also: @@ -41,6 +37,7 @@ struct path_builder_t * https://stackoverflow.com/a/20772557 * * Cubic support added. */ + HB_ALWAYS_INLINE void consume_point (const contour_point_t &point) { bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE; @@ -50,7 +47,7 @@ struct path_builder_t bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC); #endif optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y)); - if (!first_oncurve) + if (unlikely (!first_oncurve)) { if (is_on_curve) { @@ -66,7 +63,7 @@ struct path_builder_t } else if (first_offcurve) { - optional_point_t mid = first_offcurve.lerp (p, .5f); + optional_point_t mid = first_offcurve.mid (p); first_oncurve = mid; last_offcurve = p; draw_session->move_to (mid.x, mid.y); @@ -102,7 +99,7 @@ struct path_builder_t } else { - optional_point_t mid = last_offcurve.lerp (p, .5f); + optional_point_t mid = last_offcurve.mid (p); if (is_cubic) { @@ -127,13 +124,13 @@ struct path_builder_t } } - if (point.is_end_point) + if (unlikely (point.is_end_point)) { if (first_offcurve && last_offcurve) { - optional_point_t mid = last_offcurve.lerp (first_offcurve2 ? - first_offcurve2 : - first_offcurve, .5f); + optional_point_t mid = last_offcurve.mid (first_offcurve2 ? + first_offcurve2 : + first_offcurve); if (last_offcurve2) draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, last_offcurve.x, last_offcurve.y, diff --git a/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh b/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh index c1839f3b..c8de1013 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/name/name.hh @@ -359,7 +359,7 @@ struct name record.nameID = ids.name_id; record.length = 0; // handled in NameRecord copy() record.offset = 0; - memcpy (name_records, &record, NameRecord::static_size); + hb_memcpy (name_records, &record, NameRecord::static_size); name_records++; } #endif @@ -384,10 +384,7 @@ struct name bool subset (hb_subset_context_t *c) const { - TRACE_SUBSET (this); - - name *name_prime = c->serializer->start_embed (); - if (unlikely (!name_prime)) return_trace (false); + auto *name_prime = c->serializer->start_embed (); #ifdef HB_EXPERIMENTAL_API const hb_hashmap_t *name_table_overrides = @@ -436,7 +433,7 @@ struct name if (!name_table_overrides->is_empty ()) { if (unlikely (!insert_name_records.alloc (name_table_overrides->get_population (), true))) - return_trace (false); + return false; for (const auto& record_ids : name_table_overrides->keys ()) { if (name_table_overrides->get (record_ids).length == 0) @@ -448,13 +445,13 @@ struct name } #endif - return (name_prime->serialize (c->serializer, it, - std::addressof (this + stringOffset) + return name_prime->serialize (c->serializer, it, + std::addressof (this + stringOffset) #ifdef HB_EXPERIMENTAL_API - , insert_name_records - , name_table_overrides + , insert_name_records + , name_table_overrides #endif - )); + ); } bool sanitize_records (hb_sanitize_context_t *c) const diff --git a/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh index c2e24a70..c1432883 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/classdef-graph.hh @@ -72,7 +72,7 @@ struct ClassDef : public OT::ClassDef class_def_link->width = SmallTypes::size; class_def_link->objidx = class_def_prime_id; class_def_link->position = link_position; - class_def_prime_vertex.parents.push (parent_id); + class_def_prime_vertex.add_parent (parent_id); return true; } @@ -94,7 +94,13 @@ struct ClassDef : public OT::ClassDef } hb_bytes_t class_def_copy = serializer.copy_bytes (); - c.add_buffer ((char *) class_def_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer. + if (!class_def_copy.arrayZ) return false; + // Give ownership to the context, it will cleanup the buffer. + if (!c.add_buffer ((char *) class_def_copy.arrayZ)) + { + hb_free ((char *) class_def_copy.arrayZ); + return false; + } auto& obj = c.graph.vertices_[dest_obj].obj; obj.head = (char *) class_def_copy.arrayZ; diff --git a/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh index 49d09363..4f44e076 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/coverage-graph.hh @@ -96,7 +96,7 @@ struct Coverage : public OT::Layout::Common::Coverage coverage_link->width = SmallTypes::size; coverage_link->objidx = coverage_prime_id; coverage_link->position = link_position; - coverage_prime_vertex.parents.push (parent_id); + coverage_prime_vertex.add_parent (parent_id); return (Coverage*) coverage_prime_vertex.obj.head; } @@ -118,7 +118,13 @@ struct Coverage : public OT::Layout::Common::Coverage } hb_bytes_t coverage_copy = serializer.copy_bytes (); - c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer. + if (!coverage_copy.arrayZ) return false; + // Give ownership to the context, it will cleanup the buffer. + if (!c.add_buffer ((char *) coverage_copy.arrayZ)) + { + hb_free ((char *) coverage_copy.arrayZ); + return false; + } auto& obj = c.graph.vertices_[dest_obj].obj; obj.head = (char *) coverage_copy.arrayZ; diff --git a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh index 38ca5db0..2b742eff 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh @@ -43,12 +43,28 @@ struct graph_t { hb_serialize_context_t::object_t obj; int64_t distance = 0 ; - int64_t space = 0 ; - hb_vector_t parents; + unsigned space = 0 ; unsigned start = 0; unsigned end = 0; unsigned priority = 0; + private: + unsigned incoming_edges_ = 0; + unsigned single_parent = (unsigned) -1; + hb_hashmap_t parents; + public: + auto parents_iter () const HB_AUTO_RETURN + ( + hb_concat ( + hb_iter (&single_parent, single_parent != (unsigned) -1), + parents.keys_ref () + ) + ) + + bool in_error () const + { + return parents.in_error (); + } bool link_positions_valid (unsigned num_objects, bool removed_nil) { @@ -143,7 +159,9 @@ struct graph_t hb_swap (a.obj, b.obj); hb_swap (a.distance, b.distance); hb_swap (a.space, b.space); + hb_swap (a.single_parent, b.single_parent); hb_swap (a.parents, b.parents); + hb_swap (a.incoming_edges_, b.incoming_edges_); hb_swap (a.start, b.start); hb_swap (a.end, b.end); hb_swap (a.priority, b.priority); @@ -154,6 +172,7 @@ struct graph_t { hb_hashmap_t result; + result.alloc (obj.real_links.length); for (const auto& l : obj.real_links) { result.set (l.position, l.objidx); } @@ -163,27 +182,83 @@ struct graph_t bool is_shared () const { - return parents.length > 1; + return parents.get_population () > 1; } unsigned incoming_edges () const { - return parents.length; + if (HB_DEBUG_SUBSET_REPACK) + { + assert (incoming_edges_ == (single_parent != (unsigned) -1) + + (parents.values_ref () | hb_reduce (hb_add, 0))); + } + return incoming_edges_; + } + + void reset_parents () + { + incoming_edges_ = 0; + single_parent = (unsigned) -1; + parents.reset (); + } + + void add_parent (unsigned parent_index) + { + assert (parent_index != (unsigned) -1); + if (incoming_edges_ == 0) + { + single_parent = parent_index; + incoming_edges_ = 1; + return; + } + else if (single_parent != (unsigned) -1) + { + assert (incoming_edges_ == 1); + if (!parents.set (single_parent, 1)) + return; + single_parent = (unsigned) -1; + } + + unsigned *v; + if (parents.has (parent_index, &v)) + { + (*v)++; + incoming_edges_++; + } + else if (parents.set (parent_index, 1)) + incoming_edges_++; } void remove_parent (unsigned parent_index) { - for (unsigned i = 0; i < parents.length; i++) + if (parent_index == single_parent) { - if (parents[i] != parent_index) continue; - parents.remove_unordered (i); - break; + single_parent = (unsigned) -1; + incoming_edges_--; + return; + } + + unsigned *v; + if (parents.has (parent_index, &v)) + { + incoming_edges_--; + if (*v > 1) + (*v)--; + else + parents.del (parent_index); + + if (incoming_edges_ == 1) + { + single_parent = *parents.keys (); + parents.reset (); + } } } void remove_real_link (unsigned child_index, const void* offset) { - for (unsigned i = 0; i < obj.real_links.length; i++) + unsigned count = obj.real_links.length; + for (unsigned i = 0; i < count; i++) { auto& link = obj.real_links.arrayZ[i]; if (link.objidx != child_index) @@ -197,18 +272,53 @@ struct graph_t } } - void remap_parents (const hb_vector_t& id_map) + bool remap_parents (const hb_vector_t& id_map) { - for (unsigned i = 0; i < parents.length; i++) - parents[i] = id_map[parents[i]]; + if (single_parent != (unsigned) -1) + { + assert (single_parent < id_map.length); + single_parent = id_map[single_parent]; + return true; + } + + hb_hashmap_t new_parents; + new_parents.alloc (parents.get_population ()); + for (auto _ : parents) + { + assert (_.first < id_map.length); + assert (!new_parents.has (id_map[_.first])); + new_parents.set (id_map[_.first], _.second); + } + + if (parents.in_error() || new_parents.in_error ()) + return false; + + parents = std::move (new_parents); + return true; } void remap_parent (unsigned old_index, unsigned new_index) { - for (unsigned i = 0; i < parents.length; i++) + if (single_parent != (unsigned) -1) { - if (parents[i] == old_index) - parents[i] = new_index; + if (single_parent == old_index) + single_parent = new_index; + return; + } + + const unsigned *pv; + if (parents.has (old_index, &pv)) + { + unsigned v = *pv; + if (!parents.set (new_index, v)) + incoming_edges_ -= v; + parents.del (old_index); + + if (incoming_edges_ == 1) + { + single_parent = *parents.keys (); + parents.reset (); + } } } @@ -328,11 +438,12 @@ struct graph_t bool removed_nil = false; vertices_.alloc (objects.length); vertices_scratch_.alloc (objects.length); - for (unsigned i = 0; i < objects.length; i++) + unsigned count = objects.length; + for (unsigned i = 0; i < count; i++) { // If this graph came from a serialization buffer object 0 is the // nil object. We don't need it for our purposes here so drop it. - if (i == 0 && !objects[i]) + if (i == 0 && !objects.arrayZ[i]) { removed_nil = true; continue; @@ -340,9 +451,9 @@ struct graph_t vertex_t* v = vertices_.push (); if (check_success (!vertices_.in_error ())) - v->obj = *objects[i]; + v->obj = *objects.arrayZ[i]; - check_success (v->link_positions_valid (objects.length, removed_nil)); + check_success (v->link_positions_valid (count, removed_nil)); if (!removed_nil) continue; // Fix indices to account for removed nil object. @@ -354,7 +465,6 @@ struct graph_t ~graph_t () { - vertices_.fini (); for (char* b : buffers) hb_free (b); } @@ -364,6 +474,18 @@ struct graph_t return root ().equals (other.root (), *this, other, 0); } + void print () const { + for (int i = vertices_.length - 1; i >= 0; i--) + { + const auto& v = vertices_[i]; + printf("%d: %lu [", i, v.table_size()); + for (const auto &l : v.obj.real_links) { + printf("%u, ", l.objidx); + } + printf("]\n"); + } + } + // Sorts links of all objects in a consistent manner and zeroes all offsets. void normalize () { @@ -396,9 +518,10 @@ struct graph_t return vertices_[i].obj; } - void add_buffer (char* buffer) + bool add_buffer (char* buffer) { buffers.push (buffer); + return !buffers.in_error (); } /* @@ -414,7 +537,7 @@ struct graph_t link->width = 2; link->objidx = child_id; link->position = (char*) offset - (char*) v.obj.head; - vertices_[child_id].parents.push (parent_id); + vertices_[child_id].add_parent (parent_id); } /* @@ -460,7 +583,7 @@ struct graph_t { unsigned next_id = queue.pop_minimum().second; - hb_swap (sorted_graph[new_id], vertices_[next_id]); + sorted_graph[new_id] = std::move (vertices_[next_id]); const vertex_t& next = sorted_graph[new_id]; if (unlikely (!check_success(new_id >= 0))) { @@ -488,8 +611,8 @@ struct graph_t check_success (!queue.in_error ()); check_success (!sorted_graph.in_error ()); - remap_all_obj_indices (id_map, &sorted_graph); - hb_swap (vertices_, sorted_graph); + check_success (remap_all_obj_indices (id_map, &sorted_graph)); + vertices_ = std::move (sorted_graph); if (!check_success (new_id == -1)) print_orphaned_nodes (); @@ -579,8 +702,8 @@ struct graph_t const auto& node = object (node_idx); if (offset < node.head || offset >= node.tail) return -1; - unsigned length = node.real_links.length; - for (unsigned i = 0; i < length; i++) + unsigned count = node.real_links.length; + for (unsigned i = 0; i < count; i++) { // Use direct access for increased performance, this is a hot method. const auto& link = node.real_links.arrayZ[i]; @@ -600,7 +723,7 @@ struct graph_t { unsigned child_idx = index_for_offset (node_idx, offset); auto& child = vertices_[child_idx]; - for (unsigned p : child.parents) + for (unsigned p : child.parents_iter ()) { if (p != node_idx) { return duplicate (node_idx, child_idx); @@ -683,12 +806,15 @@ struct graph_t subgraph.set (root_idx, wide_parents (root_idx, parents)); find_subgraph (root_idx, subgraph); } + if (subgraph.in_error ()) + return false; unsigned original_root_idx = root_idx (); hb_map_t index_map; bool made_changes = false; for (auto entry : subgraph.iter ()) { + assert (entry.first < vertices_.length); const auto& node = vertices_[entry.first]; unsigned subgraph_incoming_edges = entry.second; @@ -727,8 +853,7 @@ struct graph_t remap_obj_indices (index_map, parents.iter (), true); // Update roots set with new indices as needed. - uint32_t next = HB_SET_VALUE_INVALID; - while (roots.next (&next)) + for (auto next : roots) { const uint32_t *v; if (index_map.has (next, &v)) @@ -745,10 +870,10 @@ struct graph_t { for (const auto& link : vertices_[node_idx].obj.all_links ()) { - const uint32_t *v; + hb_codepoint_t *v; if (subgraph.has (link.objidx, &v)) { - subgraph.set (link.objidx, *v + 1); + (*v)++; continue; } subgraph.set (link.objidx, 1); @@ -820,7 +945,7 @@ struct graph_t new_link->position = (const char*) new_offset - (const char*) new_v.obj.head; auto& child = vertices_[child_id]; - child.parents.push (new_parent_idx); + child.add_parent (new_parent_idx); old_v.remove_real_link (child_id, old_offset); child.remove_parent (old_parent_idx); @@ -864,18 +989,18 @@ struct graph_t clone->obj.tail = child.obj.tail; clone->distance = child.distance; clone->space = child.space; - clone->parents.reset (); + clone->reset_parents (); unsigned clone_idx = vertices_.length - 2; for (const auto& l : child.obj.real_links) { clone->obj.real_links.push (l); - vertices_[l.objidx].parents.push (clone_idx); + vertices_[l.objidx].add_parent (clone_idx); } for (const auto& l : child.obj.virtual_links) { clone->obj.virtual_links.push (l); - vertices_[l.objidx].parents.push (clone_idx); + vertices_[l.objidx].add_parent (clone_idx); } check_success (!clone->obj.real_links.in_error ()); @@ -1004,13 +1129,13 @@ struct graph_t { update_parents(); - if (root().parents) + if (root().incoming_edges ()) // Root cannot have parents. return false; for (unsigned i = 0; i < root_idx (); i++) { - if (!vertices_[i].parents) + if (!vertices_[i].incoming_edges ()) return false; } return true; @@ -1074,14 +1199,14 @@ struct graph_t parents_invalid = true; update_parents(); - if (root().parents) { + if (root().incoming_edges ()) { DEBUG_MSG (SUBSET_REPACK, nullptr, "Root node has incoming edges."); } for (unsigned i = 0; i < root_idx (); i++) { const auto& v = vertices_[i]; - if (!v.parents) + if (!v.incoming_edges ()) DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i); } } @@ -1113,6 +1238,8 @@ struct graph_t unsigned space_for (unsigned index, unsigned* root = nullptr) const { + loop: + assert (index < vertices_.length); const auto& node = vertices_[index]; if (node.space) { @@ -1121,22 +1248,24 @@ struct graph_t return node.space; } - if (!node.parents) + if (!node.incoming_edges ()) { if (root) *root = index; return 0; } - return space_for (node.parents[0], root); + index = *node.parents_iter (); + goto loop; } void err_other_error () { this->successful = false; } size_t total_size_in_bytes () const { size_t total_size = 0; - for (unsigned i = 0; i < vertices_.length; i++) { - size_t size = vertices_[i].obj.tail - vertices_[i].obj.head; + unsigned count = vertices_.length; + for (unsigned i = 0; i < count; i++) { + size_t size = vertices_.arrayZ[i].obj.tail - vertices_.arrayZ[i].obj.head; total_size += size; } return total_size; @@ -1151,12 +1280,8 @@ struct graph_t unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const { unsigned count = 0; - hb_set_t visited; - for (unsigned p : vertices_[node_idx].parents) + for (unsigned p : vertices_[node_idx].parents_iter ()) { - if (visited.has (p)) continue; - visited.add (p); - // Only real links can be wide for (const auto& l : vertices_[p].obj.real_links) { @@ -1183,21 +1308,21 @@ struct graph_t { if (!parents_invalid) return; - for (unsigned i = 0; i < vertices_.length; i++) - vertices_[i].parents.reset (); + unsigned count = vertices_.length; - for (unsigned p = 0; p < vertices_.length; p++) + for (unsigned i = 0; i < count; i++) + vertices_.arrayZ[i].reset_parents (); + + for (unsigned p = 0; p < count; p++) { - for (auto& l : vertices_[p].obj.all_links ()) - { - vertices_[l.objidx].parents.push (p); - } + for (auto& l : vertices_.arrayZ[p].obj.all_links ()) + vertices_[l.objidx].add_parent (p); } - for (unsigned i = 0; i < vertices_.length; i++) + for (unsigned i = 0; i < count; i++) // parents arrays must be accurate or downstream operations like cycle detection // and sorting won't work correctly. - check_success (!vertices_[i].parents.in_error ()); + check_success (!vertices_.arrayZ[i].in_error ()); parents_invalid = false; } @@ -1239,13 +1364,10 @@ struct graph_t // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf // for practical performance this is faster then using a more advanced queue // (such as a fibonacci queue) with a fast decrease priority. - for (unsigned i = 0; i < vertices_.length; i++) - { - if (i == vertices_.length - 1) - vertices_[i].distance = 0; - else - vertices_[i].distance = hb_int_max (int64_t); - } + unsigned count = vertices_.length; + for (unsigned i = 0; i < count; i++) + vertices_.arrayZ[i].distance = hb_int_max (int64_t); + vertices_.tail ().distance = 0; hb_priority_queue_t queue; queue.insert (0, vertices_.length - 1); @@ -1265,15 +1387,15 @@ struct graph_t { if (visited[link.objidx]) continue; - const auto& child = vertices_[link.objidx].obj; + const auto& child = vertices_.arrayZ[link.objidx].obj; unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide int64_t child_weight = (child.tail - child.head) + - ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1); + ((int64_t) 1 << (link_width * 8)) * (vertices_.arrayZ[link.objidx].space + 1); int64_t child_distance = next_distance + child_weight; - if (child_distance < vertices_[link.objidx].distance) + if (child_distance < vertices_.arrayZ[link.objidx].distance) { - vertices_[link.objidx].distance = child_distance; + vertices_.arrayZ[link.objidx].distance = child_distance; queue.insert (child_distance, link.objidx); } } @@ -1301,7 +1423,7 @@ struct graph_t unsigned old_idx = link.objidx; link.objidx = new_idx; vertices_[old_idx].remove_parent (parent_idx); - vertices_[new_idx].parents.push (parent_idx); + vertices_[new_idx].add_parent (parent_idx); } /* @@ -1329,17 +1451,20 @@ struct graph_t /* * Updates all objidx's in all links using the provided mapping. */ - void remap_all_obj_indices (const hb_vector_t& id_map, + bool remap_all_obj_indices (const hb_vector_t& id_map, hb_vector_t* sorted_graph) const { - for (unsigned i = 0; i < sorted_graph->length; i++) + unsigned count = sorted_graph->length; + for (unsigned i = 0; i < count; i++) { - (*sorted_graph)[i].remap_parents (id_map); - for (auto& link : (*sorted_graph)[i].obj.all_links_writer ()) + if (!(*sorted_graph)[i].remap_parents (id_map)) + return false; + for (auto& link : sorted_graph->arrayZ[i].obj.all_links_writer ()) { link.objidx = id_map[link.objidx]; } } + return true; } /* @@ -1370,7 +1495,7 @@ struct graph_t for (const auto& l : v.obj.all_links ()) find_connected_nodes (l.objidx, targets, visited, connected); - for (unsigned p : v.parents) + for (unsigned p : v.parents_iter ()) find_connected_nodes (p, targets, visited, connected); } diff --git a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc index b2044426..d66eb49c 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc +++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.cc @@ -52,7 +52,11 @@ unsigned gsubgpos_graph_context_t::create_node (unsigned size) if (!buffer) return -1; - add_buffer (buffer); + if (!add_buffer (buffer)) { + // Allocation did not get stored for freeing later. + hb_free (buffer); + return -1; + } return graph.new_node (buffer, buffer + size); } diff --git a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh index 9fe9662e..b25d538f 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-context.hh @@ -40,16 +40,16 @@ struct gsubgpos_graph_context_t graph_t& graph; unsigned lookup_list_index; hb_hashmap_t lookups; - + hb_hashmap_t subtable_to_extension; HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_, graph_t& graph_); HB_INTERNAL unsigned create_node (unsigned size); - void add_buffer (char* buffer) + bool add_buffer (char* buffer) { - graph.add_buffer (buffer); + return graph.add_buffer (buffer); } private: diff --git a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh index c1706384..12fcbdc4 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/gsubgpos-graph.hh @@ -166,7 +166,7 @@ struct Lookup : public OT::Lookup } if (all_new_subtables) { - add_sub_tables (c, this_index, type, all_new_subtables); + return add_sub_tables (c, this_index, type, all_new_subtables); } return true; @@ -184,7 +184,7 @@ struct Lookup : public OT::Lookup return sub_table->split_subtables (c, parent_idx, objidx); } - void add_sub_tables (gsubgpos_graph_context_t& c, + bool add_sub_tables (gsubgpos_graph_context_t& c, unsigned this_index, unsigned type, hb_vector_t>>& subtable_ids) @@ -200,7 +200,12 @@ struct Lookup : public OT::Lookup size_t new_size = v.table_size () + new_subtable_count * OT::Offset16::static_size; char* buffer = (char*) hb_calloc (1, new_size); - c.add_buffer (buffer); + if (!buffer) return false; + if (!c.add_buffer (buffer)) + { + hb_free (buffer); + return false; + } hb_memcpy (buffer, v.obj.head, v.table_size()); v.obj.head = buffer; @@ -220,7 +225,7 @@ struct Lookup : public OT::Lookup if (is_ext) { unsigned ext_id = create_extension_subtable (c, subtable_id, type); - c.graph.vertices_[subtable_id].parents.push (ext_id); + c.graph.vertices_[subtable_id].add_parent (ext_id); subtable_id = ext_id; } @@ -229,7 +234,7 @@ struct Lookup : public OT::Lookup link->objidx = subtable_id; link->position = (char*) &new_lookup->subTable[offset_index++] - (char*) new_lookup; - c.graph.vertices_[subtable_id].parents.push (this_index); + c.graph.vertices_[subtable_id].add_parent (this_index); } } @@ -239,6 +244,7 @@ struct Lookup : public OT::Lookup // The head location of the lookup has changed, invalidating the lookups map entry // in the context. Update the map. c.lookups.set (this_index, new_lookup); + return true; } void fix_existing_subtable_links (gsubgpos_graph_context_t& c, @@ -293,24 +299,35 @@ struct Lookup : public OT::Lookup unsigned subtable_index) { unsigned type = lookupType; + unsigned ext_index = -1; + unsigned* existing_ext_index = nullptr; + if (c.subtable_to_extension.has(subtable_index, &existing_ext_index)) { + ext_index = *existing_ext_index; + } else { + ext_index = create_extension_subtable(c, subtable_index, type); + c.subtable_to_extension.set(subtable_index, ext_index); + } - unsigned ext_index = create_extension_subtable(c, subtable_index, type); if (ext_index == (unsigned) -1) return false; + auto& subtable_vertex = c.graph.vertices_[subtable_index]; auto& lookup_vertex = c.graph.vertices_[lookup_index]; for (auto& l : lookup_vertex.obj.real_links.writer ()) { - if (l.objidx == subtable_index) + if (l.objidx == subtable_index) { // Change lookup to point at the extension. l.objidx = ext_index; + if (existing_ext_index) + subtable_vertex.remove_parent(lookup_index); + } } // Make extension point at the subtable. auto& ext_vertex = c.graph.vertices_[ext_index]; - auto& subtable_vertex = c.graph.vertices_[subtable_index]; - ext_vertex.parents.push (lookup_index); - subtable_vertex.remap_parent (lookup_index, ext_index); + ext_vertex.add_parent (lookup_index); + if (!existing_ext_index) + subtable_vertex.remap_parent (lookup_index, ext_index); return true; } diff --git a/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh index 84ef5f71..e10e1cf3 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/markbasepos-graph.hh @@ -318,8 +318,11 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2 class_to_info; - unsigned class_count= classCount; - class_to_info.resize (class_count); + unsigned class_count = classCount; + if (!class_count) return class_to_info; + + if (!class_to_info.resize (class_count)) + return hb_vector_t(); auto mark_array = c.graph.as_table (this_index, &markArray); if (!mark_array) return hb_vector_t (); @@ -327,6 +330,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2= class_count) continue; class_to_info[klass].marks.add (mark); } @@ -335,6 +339,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2= class_count) continue; class_to_info[klass].child_indices.push (link.objidx); } diff --git a/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh index 1c13eb24..ad158cc9 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/pairpos-graph.hh @@ -215,7 +215,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4iter () | hb_map_retains_sorting ([&] (hb_codepoint_t gid) { - return hb_pair_t (gid, class_def_1->get_class (gid)); + return hb_codepoint_pair_t (gid, class_def_1->get_class (gid)); }) ; class_def_size_estimator_t estimator (gid_and_class); @@ -386,14 +386,14 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4iter () | hb_map_retains_sorting ([&] (hb_codepoint_t gid) { - return hb_pair_t (gid, class_def_1_table->get_class (gid)); + return hb_codepoint_pair_t (gid, class_def_1_table->get_class (gid)); }) | hb_filter ([&] (hb_codepoint_t klass) { return klass >= start && klass < end; }, hb_second) - | hb_map_retains_sorting ([&] (hb_pair_t gid_and_class) { + | hb_map_retains_sorting ([&] (hb_codepoint_pair_t gid_and_class) { // Classes must be from 0...N so subtract start - return hb_pair_t (gid_and_class.first, gid_and_class.second - start); + return hb_codepoint_pair_t (gid_and_class.first, gid_and_class.second - start); }) ; @@ -419,7 +419,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4width = SmallTypes::size; class_def_link->objidx = class_def_2_id; class_def_link->position = 10; - graph.vertices_[class_def_2_id].parents.push (pair_pos_prime_id); + graph.vertices_[class_def_2_id].add_parent (pair_pos_prime_id); graph.duplicate (pair_pos_prime_id, class_def_2_id); return pair_pos_prime_id; @@ -519,7 +519,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4iter () | hb_map_retains_sorting ([&] (hb_codepoint_t gid) { - return hb_pair_t (gid, class_def_1.table->get_class (gid)); + return hb_codepoint_pair_t (gid, class_def_1.table->get_class (gid)); }) | hb_filter ([&] (hb_codepoint_t klass) { return klass < count; diff --git a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh index 040fd1de..06e4bf44 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/serialize.hh @@ -116,10 +116,10 @@ will_overflow (graph_t& graph, for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--) { // Don't need to check virtual links for overflow - for (const auto& link : vertices[parent_idx].obj.real_links) + for (const auto& link : vertices.arrayZ[parent_idx].obj.real_links) { int64_t offset = compute_offset (graph, parent_idx, link); - if (is_valid_offset (offset, link)) + if (likely (is_valid_offset (offset, link))) continue; if (!overflows) return true; @@ -226,6 +226,9 @@ inline hb_blob_t* serialize (const graph_t& graph) { hb_vector_t buffer; size_t size = graph.total_size_in_bytes (); + + if (!size) return hb_blob_get_empty (); + if (!buffer.alloc (size)) { DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer."); return nullptr; diff --git a/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc b/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc index 55854ff5..266be5e2 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc +++ b/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc @@ -27,7 +27,7 @@ #include "gsubgpos-context.hh" #include "classdef-graph.hh" -typedef hb_pair_t gid_and_class_t; +typedef hb_codepoint_pair_t gid_and_class_t; typedef hb_vector_t gid_and_class_list_t; diff --git a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc index d7e8a93f..26e2bc14 100644 --- a/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc +++ b/src/3rdparty/harfbuzz-ng/src/harfbuzz.cc @@ -58,3 +58,5 @@ #include "hb-ucd.cc" #include "hb-unicode.cc" #include "hb-uniscribe.cc" +#include "hb-wasm-api.cc" +#include "hb-wasm-shape.cc" diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh index 2ba9355b..c72c0865 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout-trak-table.hh @@ -111,13 +111,13 @@ struct TrackData break; } } - if (!trackTableEntry) return 0.; + if (!trackTableEntry) return 0; /* * Choose size. */ unsigned int sizes = nSizes; - if (!sizes) return 0.; + if (!sizes) return 0; if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes); hb_array_t size_table ((base+sizeTable).arrayZ, sizes); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc index c9147ff7..5e4cea22 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-aat-layout.cc @@ -55,7 +55,13 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p buffer (buffer_), sanitizer (), ankr_table (&Null (AAT::ankr)), - gdef_table (face->table.GDEF->table), + gdef_table ( +#ifndef HB_NO_OT_LAYOUT + face->table.GDEF->table +#else + &Null (GDEF) +#endif + ), lookup_index (0) { sanitizer.init (blob); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh index 13587eac..ea970571 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh @@ -87,6 +87,19 @@ static inline constexpr uint16_t hb_uint16_swap (uint16_t v) static inline constexpr uint32_t hb_uint32_swap (uint32_t v) { return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } +#ifndef HB_FAST_INT_ACCESS +#if defined(__OPTIMIZE__) && \ + defined(__BYTE_ORDER) && \ + (__BYTE_ORDER == __BIG_ENDIAN || \ + (__BYTE_ORDER == __LITTLE_ENDIAN && \ + hb_has_builtin(__builtin_bswap16) && \ + hb_has_builtin(__builtin_bswap32))) +#define HB_FAST_INT_ACCESS 1 +#else +#define HB_FAST_INT_ACCESS 0 +#endif +#endif + template struct BEInt; template @@ -101,21 +114,25 @@ struct BEInt template struct BEInt { + struct __attribute__((packed)) packed_uint16_t { uint16_t v; }; + public: BEInt () = default; - constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF), - uint8_t ((V ) & 0xFF)} {} - struct __attribute__((packed)) packed_uint16_t { uint16_t v; }; - constexpr operator Type () const - { -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - defined(__BYTE_ORDER) && \ - (__BYTE_ORDER == __BIG_ENDIAN || \ - (__BYTE_ORDER == __LITTLE_ENDIAN && \ - hb_has_builtin(__builtin_bswap16))) - /* Spoon-feed the compiler a big-endian integer with alignment 1. - * https://github.com/harfbuzz/harfbuzz/pull/1398 */ + BEInt (Type V) +#if HB_FAST_INT_ACCESS +#if __BYTE_ORDER == __LITTLE_ENDIAN + { ((packed_uint16_t *) v)->v = __builtin_bswap16 (V); } +#else /* __BYTE_ORDER == __BIG_ENDIAN */ + { ((packed_uint16_t *) v)->v = V; } +#endif +#else + : v {uint8_t ((V >> 8) & 0xFF), + uint8_t ((V ) & 0xFF)} {} +#endif + + constexpr operator Type () const { +#if HB_FAST_INT_ACCESS #if __BYTE_ORDER == __LITTLE_ENDIAN return __builtin_bswap16 (((packed_uint16_t *) v)->v); #else /* __BYTE_ORDER == __BIG_ENDIAN */ @@ -146,22 +163,27 @@ struct BEInt template struct BEInt { + struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; + public: BEInt () = default; - constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF), - uint8_t ((V >> 16) & 0xFF), - uint8_t ((V >> 8) & 0xFF), - uint8_t ((V ) & 0xFF)} {} - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; + BEInt (Type V) +#if HB_FAST_INT_ACCESS +#if __BYTE_ORDER == __LITTLE_ENDIAN + { ((packed_uint32_t *) v)->v = __builtin_bswap32 (V); } +#else /* __BYTE_ORDER == __BIG_ENDIAN */ + { ((packed_uint32_t *) v)->v = V; } +#endif +#else + : v {uint8_t ((V >> 24) & 0xFF), + uint8_t ((V >> 16) & 0xFF), + uint8_t ((V >> 8) & 0xFF), + uint8_t ((V ) & 0xFF)} {} +#endif + constexpr operator Type () const { -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - defined(__BYTE_ORDER) && \ - (__BYTE_ORDER == __BIG_ENDIAN || \ - (__BYTE_ORDER == __LITTLE_ENDIAN && \ - hb_has_builtin(__builtin_bswap32))) - /* Spoon-feed the compiler a big-endian integer with alignment 1. - * https://github.com/harfbuzz/harfbuzz/pull/1398 */ +#if HB_FAST_INT_ACCESS #if __BYTE_ORDER == __LITTLE_ENDIAN return __builtin_bswap32 (((packed_uint32_t *) v)->v); #else /* __BYTE_ORDER == __BIG_ENDIAN */ @@ -231,12 +253,123 @@ struct } HB_FUNCOBJ (hb_bool); + +/* The MIT License + + Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com) + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + + +// Compression function for Merkle-Damgard construction. +// This function is generated using the framework provided. +#define mix(h) ( \ + (void) ((h) ^= (h) >> 23), \ + (void) ((h) *= 0x2127599bf4325c37ULL), \ + (h) ^= (h) >> 47) + +static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed) +{ + struct __attribute__((packed)) packed_uint64_t { uint64_t v; }; + const uint64_t m = 0x880355f21e6d1965ULL; + const packed_uint64_t *pos = (const packed_uint64_t *)buf; + const packed_uint64_t *end = pos + (len / 8); + const unsigned char *pos2; + uint64_t h = seed ^ (len * m); + uint64_t v; + +#ifndef HB_OPTIMIZE_SIZE + if (((uintptr_t) pos & 7) == 0) + { + while (pos != end) + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" + v = * (const uint64_t *) (pos++); +#pragma GCC diagnostic pop + h ^= mix(v); + h *= m; + } + } + else +#endif + { + while (pos != end) + { + v = pos++->v; + h ^= mix(v); + h *= m; + } + } + + pos2 = (const unsigned char*)pos; + v = 0; + + switch (len & 7) { + case 7: v ^= (uint64_t)pos2[6] << 48; HB_FALLTHROUGH; + case 6: v ^= (uint64_t)pos2[5] << 40; HB_FALLTHROUGH; + case 5: v ^= (uint64_t)pos2[4] << 32; HB_FALLTHROUGH; + case 4: v ^= (uint64_t)pos2[3] << 24; HB_FALLTHROUGH; + case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH; + case 2: v ^= (uint64_t)pos2[1] << 8; HB_FALLTHROUGH; + case 1: v ^= (uint64_t)pos2[0]; + h ^= mix(v); + h *= m; + } + + return mix(h); +} + +static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed) +{ + // the following trick converts the 64-bit hashcode to Fermat + // residue, which shall retain information from both the higher + // and lower parts of hashcode. + uint64_t h = fasthash64(buf, len, seed); + return h - (h >> 32); +} + struct { private: template constexpr auto - impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) + impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) + + // Horrible: std:hash() of integers seems to be identity in gcc / clang?! + // https://github.com/harfbuzz/harfbuzz/pull/4228 + // + // For performance characteristics see: + // https://github.com/harfbuzz/harfbuzz/pull/4228#issuecomment-1565079537 + template ::value && sizeof (T) <= sizeof (uint32_t))> constexpr auto + impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) v * 2654435761u /* Knuh's multiplicative hash */) + template ::value && sizeof (T) > sizeof (uint32_t))> constexpr auto + impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) (v ^ (v >> 32)) * 2654435761u /* Knuth's multiplicative hash */) + + template ::value)> constexpr auto + impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, fasthash32 (std::addressof (v), sizeof (T), 0xf437ffe6)) template constexpr auto impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash>{} (hb_deref (v))) @@ -551,6 +684,8 @@ struct hb_pair_t template static inline hb_pair_t hb_pair (T1&& a, T2&& b) { return hb_pair_t (a, b); } +typedef hb_pair_t hb_codepoint_pair_t; + struct { template constexpr typename Pair::first_t @@ -626,8 +761,10 @@ hb_popcount (T v) if (sizeof (T) == 8) { - unsigned int shift = 32; - return hb_popcount ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift)); + uint64_t y = (uint64_t) v; + y -= ((y >> 1) & 0x5555555555555555ull); + y = (y & 0x3333333333333333ull) + (y >> 2 & 0x3333333333333333ull); + return ((y + (y >> 4)) & 0xf0f0f0f0f0f0f0full) * 0x101010101010101ull >> 56; } if (sizeof (T) == 16) @@ -851,7 +988,7 @@ static inline void * hb_memset (void *s, int c, unsigned int n) { /* It's illegal to pass NULL to memset(), even if n is zero. */ - if (unlikely (!n)) return 0; + if (unlikely (!n)) return s; return memset (s, c, n); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-array.hh b/src/3rdparty/harfbuzz-ng/src/hb-array.hh index e82c0815..760f9025 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-array.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-array.hh @@ -75,11 +75,25 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> */ typedef Type& __item_t__; static constexpr bool is_random_access_iterator = true; + static constexpr bool has_fast_len = true; + Type& __item__ () const + { + if (unlikely (!length)) return CrapOrNull (Type); + return *arrayZ; + } Type& __item_at__ (unsigned i) const { if (unlikely (i >= length)) return CrapOrNull (Type); return arrayZ[i]; } + void __next__ () + { + if (unlikely (!length)) + return; + length--; + backwards_length++; + arrayZ++; + } void __forward__ (unsigned n) { if (unlikely (n > length)) @@ -88,6 +102,14 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> backwards_length += n; arrayZ += n; } + void __prev__ () + { + if (unlikely (!backwards_length)) + return; + length++; + backwards_length--; + arrayZ--; + } void __rewind__ (unsigned n) { if (unlikely (n > backwards_length)) @@ -122,9 +144,14 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> uint32_t hash () const { - uint32_t current = 0; + // FNV-1a hash function + // https://github.com/harfbuzz/harfbuzz/pull/4228 + uint32_t current = /*cbf29ce4*/0x84222325; for (auto &v : *this) - current = current * 31 + hb_hash (v); + { + current = current ^ hb_hash (v); + current = current * 16777619; + } return current; } @@ -322,6 +349,7 @@ struct hb_sorted_array_t : HB_ITER_USING (iter_base_t); static constexpr bool is_random_access_iterator = true; static constexpr bool is_sorted_iterator = true; + static constexpr bool has_fast_len = true; hb_sorted_array_t () = default; hb_sorted_array_t (const hb_sorted_array_t&) = default; @@ -449,41 +477,21 @@ inline bool hb_array_t::operator == (const hb_array_t inline uint32_t hb_array_t::hash () const { - uint32_t current = 0; - unsigned i = 0; - -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; - for (; i + 4 <= this->length; i += 4) - current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v); -#endif - - for (; i < this->length; i++) - current = current * 31 + hb_hash (this->arrayZ[i]); - return current; + // https://github.com/harfbuzz/harfbuzz/pull/4228 + return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */); } template <> inline uint32_t hb_array_t::hash () const { - uint32_t current = 0; - unsigned i = 0; - -#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \ - ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) - struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; - for (; i + 4 <= this->length; i += 4) - current = current * 31 + hb_hash ((uint32_t) ((packed_uint32_t *) &this->arrayZ[i])->v); -#endif - - for (; i < this->length; i++) - current = current * 31 + hb_hash (this->arrayZ[i]); - return current; + // https://github.com/harfbuzz/harfbuzz/pull/4228 + return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */); } +#endif typedef hb_array_t hb_bytes_t; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh index a6283de1..303dfe6d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-atomic.hh @@ -204,6 +204,7 @@ struct hb_atomic_ptr_t hb_atomic_ptr_t () = default; constexpr hb_atomic_ptr_t (T* v) : v (v) {} + hb_atomic_ptr_t (const hb_atomic_ptr_t &other) = delete; void init (T* v_ = nullptr) { set_relaxed (v_); } void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh b/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh index 9edefd97..f5414725 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bimap.hh @@ -39,10 +39,10 @@ struct hb_bimap_t back_map.reset (); } - void resize (unsigned pop) + void alloc (unsigned pop) { - forw_map.resize (pop); - back_map.resize (pop); + forw_map.alloc (pop); + back_map.alloc (pop); } bool in_error () const { return forw_map.in_error () || back_map.in_error (); } @@ -83,7 +83,6 @@ struct hb_bimap_t unsigned int get_population () const { return forw_map.get_population (); } - protected: hb_map_t forw_map; hb_map_t back_map; @@ -94,9 +93,31 @@ struct hb_bimap_t auto iter () const HB_AUTO_RETURN (+ forw_map.iter()) }; -/* Inremental bimap: only lhs is given, rhs is incrementally assigned */ -struct hb_inc_bimap_t : hb_bimap_t +/* Incremental bimap: only lhs is given, rhs is incrementally assigned */ +struct hb_inc_bimap_t { + bool in_error () const { return forw_map.in_error () || back_map.in_error (); } + + unsigned int get_population () const { return forw_map.get_population (); } + + void reset () + { + forw_map.reset (); + back_map.reset (); + } + + void alloc (unsigned pop) + { + forw_map.alloc (pop); + back_map.alloc (pop); + } + + void clear () + { + forw_map.clear (); + back_map.resize (0); + } + /* Add a mapping from lhs to rhs with a unique value if lhs is unknown. * Return the rhs value as the result. */ @@ -105,32 +126,42 @@ struct hb_inc_bimap_t : hb_bimap_t hb_codepoint_t rhs = forw_map[lhs]; if (rhs == HB_MAP_VALUE_INVALID) { - rhs = next_value++; - set (lhs, rhs); + rhs = back_map.length; + forw_map.set (lhs, rhs); + back_map.push (lhs); } return rhs; } hb_codepoint_t skip () - { return next_value++; } + { + hb_codepoint_t start = back_map.length; + back_map.push (HB_MAP_VALUE_INVALID); + return start; + } hb_codepoint_t skip (unsigned count) - { return next_value += count; } + { + hb_codepoint_t start = back_map.length; + back_map.alloc (back_map.length + count); + for (unsigned i = 0; i < count; i++) + back_map.push (HB_MAP_VALUE_INVALID); + return start; + } hb_codepoint_t get_next_value () const - { return next_value; } + { return back_map.length; } void add_set (const hb_set_t *set) { - hb_codepoint_t i = HB_SET_VALUE_INVALID; - while (hb_set_next (set, &i)) add (i); + for (auto i : *set) add (i); } /* Create an identity map. */ bool identity (unsigned int size) { clear (); - for (hb_codepoint_t i = 0; i < size; i++) set (i, i); + for (hb_codepoint_t i = 0; i < size; i++) add (i); return !in_error (); } @@ -145,20 +176,30 @@ struct hb_inc_bimap_t : hb_bimap_t { hb_codepoint_t count = get_population (); hb_vector_t work; - work.resize (count); + if (unlikely (!work.resize (count, false))) return; for (hb_codepoint_t rhs = 0; rhs < count; rhs++) - work[rhs] = back_map[rhs]; + work.arrayZ[rhs] = back_map[rhs]; work.qsort (cmp_id); clear (); for (hb_codepoint_t rhs = 0; rhs < count; rhs++) - set (work[rhs], rhs); + add (work.arrayZ[rhs]); } + hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); } + hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map[rhs]; } + + hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); } + bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); } + protected: - unsigned int next_value = 0; + hb_map_t forw_map; + hb_vector_t back_map; + + public: + auto keys () const HB_AUTO_RETURN (+ back_map.iter()) }; #endif /* HB_BIMAP_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh index 9b027ac5..869c6789 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh @@ -89,14 +89,18 @@ struct hb_vector_size_t struct hb_bit_page_t { - void init0 () { v.init0 (); } - void init1 () { v.init1 (); } + void init0 () { v.init0 (); population = 0; } + void init1 () { v.init1 (); population = PAGE_BITS; } + + void dirty () { population = UINT_MAX; } static inline constexpr unsigned len () { return ARRAY_LENGTH_CONST (v); } + operator bool () const { return !is_empty (); } bool is_empty () const { + if (has_population ()) return !population; return + hb_iter (v) | hb_none @@ -104,14 +108,11 @@ struct hb_bit_page_t } uint32_t hash () const { - return - + hb_iter (v) - | hb_reduce ([] (uint32_t h, const elt_t &_) { return h * 31 + hb_hash (_); }, (uint32_t) 0u) - ; + return hb_bytes_t ((const char *) &v, sizeof (v)).hash (); } - void add (hb_codepoint_t g) { elt (g) |= mask (g); } - void del (hb_codepoint_t g) { elt (g) &= ~mask (g); } + void add (hb_codepoint_t g) { elt (g) |= mask (g); dirty (); } + void del (hb_codepoint_t g) { elt (g) &= ~mask (g); dirty (); } void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); } bool get (hb_codepoint_t g) const { return elt (g) & mask (g); } @@ -123,20 +124,21 @@ struct hb_bit_page_t *la |= (mask (b) << 1) - mask(a); else { - *la |= ~(mask (a) - 1); + *la |= ~(mask (a) - 1llu); la++; hb_memset (la, 0xff, (char *) lb - (char *) la); - *lb |= ((mask (b) << 1) - 1); + *lb |= ((mask (b) << 1) - 1llu); } + dirty (); } void del_range (hb_codepoint_t a, hb_codepoint_t b) { elt_t *la = &elt (a); elt_t *lb = &elt (b); if (la == lb) - *la &= ~((mask (b) << 1) - mask(a)); + *la &= ~((mask (b) << 1llu) - mask(a)); else { *la &= mask (a) - 1; @@ -144,8 +146,9 @@ struct hb_bit_page_t hb_memset (la, 0, (char *) lb - (char *) la); - *lb &= ~((mask (b) << 1) - 1); + *lb &= ~((mask (b) << 1) - 1llu); } + dirty (); } void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v) { if (v) add_range (a, b); else del_range (a, b); } @@ -216,6 +219,7 @@ struct hb_bit_page_t return count; } + bool operator == (const hb_bit_page_t &other) const { return is_equal (other); } bool is_equal (const hb_bit_page_t &other) const { for (unsigned i = 0; i < len (); i++) @@ -223,20 +227,28 @@ struct hb_bit_page_t return false; return true; } + bool operator <= (const hb_bit_page_t &larger_page) const { return is_subset (larger_page); } bool is_subset (const hb_bit_page_t &larger_page) const { + if (has_population () && larger_page.has_population () && + population > larger_page.population) + return false; + for (unsigned i = 0; i < len (); i++) if (~larger_page.v[i] & v[i]) return false; return true; } + bool has_population () const { return population != UINT_MAX; } unsigned int get_population () const { - return + if (has_population ()) return population; + population = + hb_iter (v) | hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u) ; + return population; } bool next (hb_codepoint_t *codepoint) const @@ -332,9 +344,9 @@ struct hb_bit_page_t const elt_t& elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; } static constexpr elt_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); } + mutable unsigned population; vector_t v; }; -static_assert (hb_bit_page_t::PAGE_BITS == sizeof (hb_bit_page_t) * 8, ""); #endif /* HB_BIT_PAGE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh index 1eb1b1c2..e765a479 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set-invertible.hh @@ -136,7 +136,7 @@ struct hb_bit_set_invertible_t /* Sink interface. */ hb_bit_set_invertible_t& operator << (hb_codepoint_t v) { add (v); return *this; } - hb_bit_set_invertible_t& operator << (const hb_pair_t& range) + hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range) { add_range (range.first, range.second); return *this; } bool intersects (hb_codepoint_t first, hb_codepoint_t last) const @@ -162,7 +162,7 @@ struct hb_bit_set_invertible_t auto it1 = iter (); auto it2 = other.iter (); return hb_all (+ hb_zip (it1, it2) - | hb_map ([](hb_pair_t _) { return _.first == _.second; })); + | hb_map ([](hb_codepoint_pair_t _) { return _.first == _.second; })); } } @@ -345,6 +345,7 @@ struct hb_bit_set_invertible_t struct iter_t : hb_iter_with_fallback_t { static constexpr bool is_sorted_iterator = true; + static constexpr bool has_fast_len = true; iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t), bool init = true) : s (&s_), v (INVALID), l(0) { @@ -363,7 +364,7 @@ struct hb_bit_set_invertible_t unsigned __len__ () const { return l; } iter_t end () const { return iter_t (*s, false); } bool operator != (const iter_t& o) const - { return s != o.s || v != o.v; } + { return v != o.v || s != o.s; } protected: const hb_bit_set_invertible_t *s; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh index c30b2af7..1dbcce5c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh @@ -30,7 +30,6 @@ #include "hb.hh" #include "hb-bit-page.hh" -#include "hb-machinery.hh" struct hb_bit_set_t @@ -134,7 +133,11 @@ struct hb_bit_set_t { uint32_t h = 0; for (auto &map : page_map) - h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]); + { + auto &page = pages.arrayZ[map.index]; + if (unlikely (page.is_empty ())) continue; + h = h * 31 + hb_hash (map.major) + hb_hash (page); + } return h; } @@ -179,6 +182,16 @@ struct hb_bit_set_t return true; } + /* Duplicated here from hb-machinery.hh to avoid including it. */ + template + static inline const Type& StructAtOffsetUnaligned(const void *P, unsigned int offset) + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" + return * reinterpret_cast ((const char *) P + offset); +#pragma GCC diagnostic pop + } + template void set_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T)) { @@ -342,7 +355,7 @@ struct hb_bit_set_t /* Sink interface. */ hb_bit_set_t& operator << (hb_codepoint_t v) { add (v); return *this; } - hb_bit_set_t& operator << (const hb_pair_t& range) + hb_bit_set_t& operator << (const hb_codepoint_pair_t& range) { add_range (range.first, range.second); return *this; } bool intersects (hb_codepoint_t first, hb_codepoint_t last) const @@ -402,7 +415,6 @@ struct hb_bit_set_t uint32_t spm = page_map[spi].major; uint32_t lpm = larger_set.page_map[lpi].major; auto sp = page_at (spi); - auto lp = larger_set.page_at (lpi); if (spm < lpm && !sp.is_empty ()) return false; @@ -410,6 +422,7 @@ struct hb_bit_set_t if (lpm < spm) continue; + auto lp = larger_set.page_at (lpi); if (!sp.is_subset (lp)) return false; @@ -549,6 +562,7 @@ struct hb_bit_set_t count--; page_map.arrayZ[count] = page_map.arrayZ[a]; page_at (count).v = op (page_at (a).v, other.page_at (b).v); + page_at (count).dirty (); } else if (page_map.arrayZ[a - 1].major > other.page_map.arrayZ[b - 1].major) { @@ -567,7 +581,7 @@ struct hb_bit_set_t count--; page_map.arrayZ[count].major = other.page_map.arrayZ[b].major; page_map.arrayZ[count].index = next_page++; - page_at (count).v = other.page_at (b).v; + page_at (count) = other.page_at (b); } } } @@ -585,7 +599,7 @@ struct hb_bit_set_t count--; page_map.arrayZ[count].major = other.page_map.arrayZ[b].major; page_map.arrayZ[count].index = next_page++; - page_at (count).v = other.page_at (b).v; + page_at (count) = other.page_at (b); } assert (!count); resize (newCount); @@ -623,6 +637,7 @@ struct hb_bit_set_t *codepoint = INVALID; return false; } + last_page_lookup = i; } const auto* pages_array = pages.arrayZ; @@ -632,7 +647,6 @@ struct hb_bit_set_t if (pages_array[current.index].next (codepoint)) { *codepoint += current.major * page_t::PAGE_BITS; - last_page_lookup = i; return true; } i++; @@ -649,7 +663,6 @@ struct hb_bit_set_t return true; } } - last_page_lookup = 0; *codepoint = INVALID; return false; } @@ -863,6 +876,7 @@ struct hb_bit_set_t struct iter_t : hb_iter_with_fallback_t { static constexpr bool is_sorted_iterator = true; + static constexpr bool has_fast_len = true; iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t), bool init = true) : s (&s_), v (INVALID), l(0) { @@ -899,7 +913,7 @@ struct hb_bit_set_t /* The extra page_map length is necessary; can't just rely on vector here, * since the next check would be tricked because a null page also has - * major==0, which we can't distinguish from an actualy major==0 page... */ + * major==0, which we can't distinguish from an actually major==0 page... */ unsigned i = last_page_lookup; if (likely (i < page_map.length)) { @@ -921,7 +935,7 @@ struct hb_bit_set_t memmove (page_map.arrayZ + i + 1, page_map.arrayZ + i, (page_map.length - 1 - i) * page_map.item_size); - page_map[i] = map; + page_map.arrayZ[i] = map; } last_page_lookup = i; @@ -933,7 +947,7 @@ struct hb_bit_set_t /* The extra page_map length is necessary; can't just rely on vector here, * since the next check would be tricked because a null page also has - * major==0, which we can't distinguish from an actualy major==0 page... */ + * major==0, which we can't distinguish from an actually major==0 page... */ unsigned i = last_page_lookup; if (likely (i < page_map.length)) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc index f111b2d8..15a53919 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-verify.cc @@ -162,14 +162,8 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer, hb_buffer_set_flags (fragment, flags); hb_buffer_append (fragment, text_buffer, text_start, text_end); - if (!hb_shape_full (font, fragment, features, num_features, shapers)) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); - hb_buffer_destroy (reconstruction); - hb_buffer_destroy (fragment); - return false; - } - else if (!fragment->successful || fragment->shaping_failed) + if (!hb_shape_full (font, fragment, features, num_features, shapers) || + fragment->successful || fragment->shaping_failed) { hb_buffer_destroy (reconstruction); hb_buffer_destroy (fragment); @@ -185,15 +179,18 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer, } bool ret = true; - hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); - if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + if (likely (reconstruction->successful)) { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed."); - ret = false; + hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); + if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed."); + ret = false; - /* Return the reconstructed result instead so it can be inspected. */ - hb_buffer_set_length (buffer, 0); - hb_buffer_append (buffer, reconstruction, 0, -1); + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); + } } hb_buffer_destroy (reconstruction); @@ -316,28 +313,13 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, /* * Shape the two fragment streams. */ - if (!hb_shape_full (font, fragments[0], features, num_features, shapers)) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); - ret = false; + if (!hb_shape_full (font, fragments[0], features, num_features, shapers) || + !fragments[0]->successful || fragments[0]->shaping_failed) goto out; - } - else if (!fragments[0]->successful || fragments[0]->shaping_failed) - { - ret = true; + + if (!hb_shape_full (font, fragments[1], features, num_features, shapers) || + !fragments[1]->successful || fragments[1]->shaping_failed) goto out; - } - if (!hb_shape_full (font, fragments[1], features, num_features, shapers)) - { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); - ret = false; - goto out; - } - else if (!fragments[1]->successful || fragments[1]->shaping_failed) - { - ret = true; - goto out; - } if (!forward) { @@ -377,21 +359,23 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, hb_buffer_reverse (reconstruction); } - /* - * Diff results. - */ - diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); - if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + if (likely (reconstruction->successful)) { - buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed."); - ret = false; + /* + * Diff results. + */ + diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); + if (diff & ~HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed."); + ret = false; - /* Return the reconstructed result instead so it can be inspected. */ - hb_buffer_set_length (buffer, 0); - hb_buffer_append (buffer, reconstruction, 0, -1); + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); + } } - out: hb_buffer_destroy (reconstruction); hb_buffer_destroy (fragments[0]); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc index 616cee80..934c6c21 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc @@ -268,7 +268,7 @@ hb_buffer_t::similar (const hb_buffer_t &src) unicode = hb_unicode_funcs_reference (src.unicode); flags = src.flags; cluster_level = src.cluster_level; - replacement = src.invisible; + replacement = src.replacement; invisible = src.invisible; not_found = src.not_found; } @@ -499,12 +499,12 @@ hb_buffer_t::set_masks (hb_mask_t value, unsigned int cluster_start, unsigned int cluster_end) { - hb_mask_t not_mask = ~mask; - value &= mask; - if (!mask) return; + hb_mask_t not_mask = ~mask; + value &= mask; + unsigned int count = len; for (unsigned int i = 0; i < count; i++) if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end) @@ -1327,7 +1327,7 @@ hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer) * Sets the #hb_codepoint_t that replaces characters not found in * the font during shaping. * - * The not-found glyph defaults to zero, sometimes knows as the + * The not-found glyph defaults to zero, sometimes known as the * ".notdef" glyph. This API allows for differentiating the two. * * Since: 3.1.0 @@ -2076,7 +2076,7 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g * hb_buffer_diff: * @buffer: a buffer. * @reference: other buffer to compare to. - * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1. + * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepoint_t) -1. * @position_fuzz: allowed absolute difference in position values. * * If dottedcircle_glyph is (hb_codepoint_t) -1 then #HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h index bff78543..3573127f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h @@ -99,7 +99,7 @@ typedef struct hb_glyph_info_t { * layout, by avoiding re-shaping of each line * after line-breaking, by limiting the * reshaping to a small piece around the - * breaking positin only, even if the breaking + * breaking position only, even if the breaking * position carries the * #HB_GLYPH_FLAG_UNSAFE_TO_BREAK or when * hyphenation or other text transformation diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh index 5a43cabc..f04ad58f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.hh @@ -464,13 +464,16 @@ struct hb_buffer_t start, end, true); } +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1) { if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) return; _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, start, end, - true); + false); } void unsafe_to_break_from_outbuffer (unsigned int start = 0, unsigned int end = -1) { @@ -478,6 +481,9 @@ struct hb_buffer_t start, end, true, true); } +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1) { if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) @@ -493,6 +499,13 @@ struct hb_buffer_t HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size); + HB_NODISCARD bool resize (unsigned length) + { + assert (!have_output); + if (unlikely (!ensure (length))) return false; + len = length; + return true; + } HB_NODISCARD bool ensure (unsigned int size) { return likely (!size || size < allocated) ? true : enlarge (size); } @@ -553,7 +566,7 @@ struct hb_buffer_t bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4) { #ifdef HB_NO_BUFFER_MESSAGE - return true; + return true; #else if (likely (!messaging ())) return true; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh index 8371465c..6d8a54cf 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh @@ -62,14 +62,12 @@ struct hb_cache_t static_assert ((key_bits >= cache_bits), ""); static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), ""); - hb_cache_t () { init (); } - - void init () { clear (); } + hb_cache_t () { clear (); } void clear () { - for (unsigned i = 0; i < ARRAY_LENGTH (values); i++) - values[i] = -1; + for (auto &v : values) + v = -1; } bool get (unsigned int key, unsigned int *value) const diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc b/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc index 0f94d816..ec1499e8 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-cairo-utils.cc @@ -80,7 +80,7 @@ hb_cairo_read_blob (void *closure, if (r->offset + length > size) return CAIRO_STATUS_READ_ERROR; - memcpy (data, d + r->offset, length); + hb_memcpy (data, d + r->offset, length); r->offset += length; return CAIRO_STATUS_SUCCESS; @@ -763,7 +763,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops, } //assert (angles[0] + k * span <= 0 && 0 < angles[n_stops - 1] + k * span); - span = fabs (span); + span = fabsf (span); for (signed l = k; l < 1000; l++) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc b/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc index f005afd1..f4f9f54a 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-cairo.cc @@ -166,6 +166,32 @@ hb_cairo_pop_transform (hb_paint_funcs_t *pfuncs HB_UNUSED, cairo_restore (cr); } +static hb_bool_t +hb_cairo_paint_color_glyph (hb_paint_funcs_t *pfuncs HB_UNUSED, + void *paint_data, + hb_codepoint_t glyph, + hb_font_t *font, + void *user_data HB_UNUSED) +{ + hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data; + cairo_t *cr = c->cr; + + cairo_save (cr); + + hb_position_t x_scale, y_scale; + hb_font_get_scale (font, &x_scale, &y_scale); + cairo_scale (cr, x_scale, y_scale); + + cairo_glyph_t cairo_glyph = { glyph, 0, 0 }; + cairo_set_scaled_font (cr, c->scaled_font); + cairo_set_font_size (cr, 1); + cairo_show_glyphs (cr, &cairo_glyph, 1); + + cairo_restore (cr); + + return true; +} + static void hb_cairo_push_clip_glyph (hb_paint_funcs_t *pfuncs HB_UNUSED, void *paint_data, @@ -397,6 +423,7 @@ static struct hb_cairo_paint_funcs_lazy_loader_t : hb_paint_funcs_lazy_loader_t< hb_paint_funcs_set_push_transform_func (funcs, hb_cairo_push_transform, nullptr, nullptr); hb_paint_funcs_set_pop_transform_func (funcs, hb_cairo_pop_transform, nullptr, nullptr); + hb_paint_funcs_set_color_glyph_func (funcs, hb_cairo_paint_color_glyph, nullptr, nullptr); hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_cairo_push_clip_glyph, nullptr, nullptr); hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_cairo_push_clip_rectangle, nullptr, nullptr); hb_paint_funcs_set_pop_clip_func (funcs, hb_cairo_pop_clip, nullptr, nullptr); @@ -956,7 +983,7 @@ hb_cairo_glyphs_from_buffer (hb_buffer_t *buffer, if (clusters && *num_clusters && utf8) { - memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0])); + hb_memset ((void *) *clusters, 0, *num_clusters * sizeof ((*clusters)[0])); hb_bool_t backward = HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (buffer)); *cluster_flags = backward ? CAIRO_TEXT_CLUSTER_FLAG_BACKWARD : (cairo_text_cluster_flags_t) 0; unsigned int cluster = 0; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh index 949bfebf..1d1f10f2 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-common.hh @@ -26,6 +26,8 @@ #ifndef HB_CFF_INTERP_COMMON_HH #define HB_CFF_INTERP_COMMON_HH +extern HB_INTERNAL const unsigned char *endchar_str; + namespace CFF { using namespace OT; @@ -336,8 +338,6 @@ struct byte_str_ref_t hb_ubytes_t str; }; -using byte_str_array_t = hb_vector_t; - /* stack */ template struct cff_stack_t diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh index f40be51f..28a777eb 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-cff-interp-cs-common.hh @@ -883,14 +883,12 @@ struct cs_interpreter_t : interpreter_t unsigned max_ops = HB_CFF_MAX_OPS; for (;;) { - if (unlikely (!--max_ops)) + OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); + if (unlikely (SUPER::env.in_error () || !--max_ops)) { SUPER::env.set_error (); - break; - } - OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); - if (unlikely (SUPER::env.in_error ())) return false; + } if (SUPER::env.is_endchar ()) break; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.cc b/src/3rdparty/harfbuzz-ng/src/hb-common.cc index 282a8e4d..bd4cd88e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-common.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-common.cc @@ -815,7 +815,7 @@ parse_tag (const char **pp, const char *end, hb_tag_t *tag) } const char *p = *pp; - while (*pp < end && (ISALNUM(**pp) || **pp == '_')) + while (*pp < end && (**pp != ' ' && **pp != '=' && **pp != '[')) (*pp)++; if (p == *pp || *pp - p > 4) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.h b/src/3rdparty/harfbuzz-ng/src/hb-common.h index a5da4e76..a9fe666b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-common.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-common.h @@ -104,6 +104,16 @@ typedef int hb_bool_t; * **/ typedef uint32_t hb_codepoint_t; + +/** + * HB_CODEPOINT_INVALID: + * + * Unused #hb_codepoint_t value. + * + * Since: 8.0.0 + */ +#define HB_CODEPOINT_INVALID ((hb_codepoint_t) -1) + /** * hb_position_t: * diff --git a/src/3rdparty/harfbuzz-ng/src/hb-config.hh b/src/3rdparty/harfbuzz-ng/src/hb-config.hh index 52adaad4..816c55c7 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-config.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-config.hh @@ -44,14 +44,14 @@ #ifdef HB_TINY #define HB_LEAN #define HB_MINI +#define HB_OPTIMIZE_SIZE +#define HB_OPTIMIZE_SIZE_MORE +#define HB_MINIMIZE_MEMORY_USAGE #define HB_NO_MT #define HB_NO_UCD_UNASSIGNED #ifndef NDEBUG #define NDEBUG #endif -#ifndef __OPTIMIZE_SIZE__ -#define __OPTIMIZE_SIZE__ -#endif #endif #ifdef HB_LEAN @@ -97,6 +97,12 @@ #define HB_NO_BORING_EXPANSION #endif +#ifdef __OPTIMIZE_SIZE__ +#ifndef HB_OPTIMIZE_SIZE +#define HB_OPTIMIZE_SIZE +#endif +#endif + #if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H) #ifndef HB_CONFIG_OVERRIDE_H #define HB_CONFIG_OVERRIDE_H "config-override.h" @@ -108,7 +114,8 @@ #ifdef HB_NO_BORING_EXPANSION #define HB_NO_BEYOND_64K -#define HB_NO_AVAR2 +#define HB_NO_CUBIC_GLYF +#define HB_NO_VAR_COMPOSITES #endif #ifdef HB_DISABLE_DEPRECATED @@ -175,21 +182,27 @@ #define HB_NO_OT_SHAPER_MYANMAR_ZAWGYI #endif -#ifdef NDEBUG -#ifndef HB_NDEBUG -#define HB_NDEBUG -#endif +#ifdef HB_OPTIMIZE_SIZE_MORE +#define HB_NO_OT_RULESETS_FAST_PATH #endif -#ifdef __OPTIMIZE_SIZE__ -#ifndef HB_OPTIMIZE_SIZE -#define HB_OPTIMIZE_SIZE -#endif +#ifdef HB_MINIMIZE_MEMORY_USAGE +#define HB_NO_GDEF_CACHE +#define HB_NO_OT_LAYOUT_LOOKUP_CACHE +#define HB_NO_OT_FONT_ADVANCE_CACHE +#define HB_NO_OT_FONT_CMAP_CACHE #endif #ifdef HB_OPTIMIZE_SIZE -#define HB_NO_OT_LAYOUT_LOOKUP_CACHE +#define HB_OPTIMIZE_SIZE_VAL 1 +#else +#define HB_OPTIMIZE_SIZE_VAL 0 #endif +#ifdef HB_MINIMIZE_MEMORY_USAGE +#define HB_MINIMIZE_MEMORY_USAGE_VAL 1 +#else +#define HB_MINIMIZE_MEMORY_USAGE_VAL 0 +#endif #endif /* HB_CONFIG_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh index 0ac4515f..559db406 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh @@ -265,8 +265,9 @@ static inline void _hb_warn_no_return (bool returned) } } template <> -/*static*/ inline void _hb_warn_no_return (bool returned HB_UNUSED) -{} +/*static*/ inline void _hb_warn_no_return (bool returned HB_UNUSED) {} +template <> +/*static*/ inline void _hb_warn_no_return (bool returned HB_UNUSED) {} template struct hb_auto_trace_t @@ -389,6 +390,10 @@ struct hb_no_trace_t { #define HB_DEBUG_UNISCRIBE (HB_DEBUG+0) #endif +#ifndef HB_DEBUG_WASM +#define HB_DEBUG_WASM (HB_DEBUG+0) +#endif + /* * With tracing. */ @@ -446,12 +451,26 @@ struct hb_no_trace_t { #define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0) #endif +#ifndef HB_DEBUG_PAINT +#define HB_DEBUG_PAINT (HB_DEBUG+0) +#endif +#if HB_DEBUG_PAINT +#define TRACE_PAINT(this) \ + HB_UNUSED hb_auto_trace_t trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + " ") +#else +#define TRACE_PAINT(this) HB_UNUSED hb_no_trace_t trace +#endif + + #ifndef HB_DEBUG_DISPATCH #define HB_DEBUG_DISPATCH ( \ HB_DEBUG_APPLY + \ HB_DEBUG_SANITIZE + \ HB_DEBUG_SERIALIZE + \ HB_DEBUG_SUBSET + \ + HB_DEBUG_PAINT + \ 0) #endif #if HB_DEBUG_DISPATCH diff --git a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h index b032a941..9fcce6d9 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h @@ -255,6 +255,52 @@ HB_EXTERN hb_position_t hb_font_get_glyph_v_kerning (hb_font_t *font, hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); + +/** + * hb_font_get_glyph_shape_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @draw_funcs: The draw functions to send the shape data to + * @draw_data: The data accompanying the draw functions + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * Since: 4.0.0 + * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead + **/ +typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data); + +/** + * hb_font_funcs_set_glyph_shape_func: + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets the implementation function for #hb_font_get_glyph_shape_func_t, + * which is the same as #hb_font_draw_glyph_func_t. + * + * Since: 4.0.0 + * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead + **/ +HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_func) +HB_EXTERN void +hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_shape_func_t func, + void *user_data, hb_destroy_func_t destroy); + +HB_DEPRECATED_FOR (hb_font_draw_glyph) +HB_EXTERN void +hb_font_get_glyph_shape (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data); + + #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-draw.hh b/src/3rdparty/harfbuzz-ng/src/hb-draw.hh index 768f51a8..25dee126 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-draw.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-draw.hh @@ -93,50 +93,57 @@ struct hb_draw_funcs_t !user_data ? nullptr : user_data->close_path); } - void move_to (void *draw_data, hb_draw_state_t &st, - float to_x, float to_y) + void + HB_ALWAYS_INLINE + move_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) { - if (st.path_open) close_path (draw_data, st); + if (unlikely (st.path_open)) close_path (draw_data, st); st.current_x = to_x; st.current_y = to_y; } - void line_to (void *draw_data, hb_draw_state_t &st, - float to_x, float to_y) + void + HB_ALWAYS_INLINE + line_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) { - if (!st.path_open) start_path (draw_data, st); + if (unlikely (!st.path_open)) start_path (draw_data, st); emit_line_to (draw_data, st, to_x, to_y); st.current_x = to_x; st.current_y = to_y; } void + HB_ALWAYS_INLINE quadratic_to (void *draw_data, hb_draw_state_t &st, float control_x, float control_y, float to_x, float to_y) { - if (!st.path_open) start_path (draw_data, st); + if (unlikely (!st.path_open)) start_path (draw_data, st); emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); st.current_x = to_x; st.current_y = to_y; } void + HB_ALWAYS_INLINE cubic_to (void *draw_data, hb_draw_state_t &st, float control1_x, float control1_y, float control2_x, float control2_y, float to_x, float to_y) { - if (!st.path_open) start_path (draw_data, st); + if (unlikely (!st.path_open)) start_path (draw_data, st); emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); st.current_x = to_x; st.current_y = to_y; } void + HB_ALWAYS_INLINE close_path (void *draw_data, hb_draw_state_t &st) { - if (st.path_open) + if (likely (st.path_open)) { if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y)) emit_line_to (draw_data, st, st.path_start_x, st.path_start_y); @@ -168,6 +175,7 @@ struct hb_draw_session_t ~hb_draw_session_t () { close_path (); } + HB_ALWAYS_INLINE void move_to (float to_x, float to_y) { if (likely (not_slanted)) @@ -177,6 +185,7 @@ struct hb_draw_session_t funcs->move_to (draw_data, st, to_x + to_y * slant, to_y); } + HB_ALWAYS_INLINE void line_to (float to_x, float to_y) { if (likely (not_slanted)) @@ -187,6 +196,7 @@ struct hb_draw_session_t to_x + to_y * slant, to_y); } void + HB_ALWAYS_INLINE quadratic_to (float control_x, float control_y, float to_x, float to_y) { @@ -200,6 +210,7 @@ struct hb_draw_session_t to_x + to_y * slant, to_y); } void + HB_ALWAYS_INLINE cubic_to (float control1_x, float control1_y, float control2_x, float control2_y, float to_x, float to_y) @@ -215,6 +226,7 @@ struct hb_draw_session_t control2_x + control2_y * slant, control2_y, to_x + to_y * slant, to_y); } + HB_ALWAYS_INLINE void close_path () { funcs->close_path (draw_data, st); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-font.cc index 68851311..00f1f6d3 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-font.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-font.cc @@ -1066,7 +1066,7 @@ hb_font_get_nominal_glyph (hb_font_t *font, * @glyph_stride: The stride between successive glyph IDs * * Fetches the nominal glyph IDs for a sequence of Unicode code points. Glyph - * IDs must be returned in a #hb_codepoint_t output parameter. Stopes at the + * IDs must be returned in a #hb_codepoint_t output parameter. Stops at the * first unsupported glyph ID. * * Return value: the number of code points processed @@ -1389,6 +1389,7 @@ hb_font_get_glyph_from_name (hb_font_t *font, return font->get_glyph_from_name (name, len, glyph); } +#ifndef HB_DISABLE_DEPRECATED /** * hb_font_get_glyph_shape: * @font: #hb_font_t to work upon @@ -1410,6 +1411,7 @@ hb_font_get_glyph_shape (hb_font_t *font, { hb_font_draw_glyph (font, glyph, dfuncs, draw_data); } +#endif /** * hb_font_draw_glyph: @@ -2648,7 +2650,6 @@ hb_font_set_variations (hb_font_t *font, if (axes[axis_index].axisTag == tag) design_coords[axis_index] = v; } - font->face->table.avar->map_coords (normalized, coords_length); hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized); _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length); @@ -2720,8 +2721,6 @@ hb_font_set_variation (hb_font_t *font, if (axes[axis_index].axisTag == tag) design_coords[axis_index] = value; - font->face->table.avar->map_coords (normalized, coords_length); - hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized); _hb_font_adopt_var_coords (font, normalized, design_coords, coords_length); @@ -3058,6 +3057,7 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, #endif +#ifndef HB_DISABLE_DEPRECATED void hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_shape_func_t func, @@ -3066,3 +3066,4 @@ hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, { hb_font_funcs_set_draw_glyph_func (ffuncs, func, user_data, destroy); } +#endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.h b/src/3rdparty/harfbuzz-ng/src/hb-font.h index f3b589bd..3c2355af 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-font.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-font.h @@ -485,25 +485,6 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void * hb_codepoint_t *glyph, void *user_data); -/** - * hb_font_get_glyph_shape_func_t: - * @font: #hb_font_t to work upon - * @font_data: @font user data pointer - * @glyph: The glyph ID to query - * @draw_funcs: The draw functions to send the shape data to - * @draw_data: The data accompanying the draw functions - * @user_data: User data pointer passed by the caller - * - * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. - * - * Since: 4.0.0 - * Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead - **/ -typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data, - hb_codepoint_t glyph, - hb_draw_funcs_t *draw_funcs, void *draw_data, - void *user_data); - /** * hb_font_draw_glyph_func_t: * @font: #hb_font_t to work upon @@ -803,24 +784,6 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_from_name_func_t func, void *user_data, hb_destroy_func_t destroy); -/** - * hb_font_funcs_set_glyph_shape_func: - * @ffuncs: A font-function structure - * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign - * @user_data: Data to pass to @func - * @destroy: (nullable): The function to call when @user_data is not needed anymore - * - * Sets the implementation function for #hb_font_get_glyph_shape_func_t, - * which is the same as #hb_font_draw_glyph_func_t. - * - * Since: 4.0.0 - * Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead - **/ -HB_EXTERN void -hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, - hb_font_get_glyph_shape_func_t func, - void *user_data, hb_destroy_func_t destroy); - /** * hb_font_funcs_set_draw_glyph_func: * @ffuncs: A font-function structure @@ -828,8 +791,7 @@ hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, * @user_data: Data to pass to @func * @destroy: (nullable): The function to call when @user_data is not needed anymore * - * Sets the implementation function for #hb_font_draw_glyph_func_t, - * which is the same as #hb_font_get_glyph_shape_func_t. + * Sets the implementation function for #hb_font_draw_glyph_func_t. * * Since: 7.0.0 **/ @@ -934,11 +896,6 @@ hb_font_get_glyph_from_name (hb_font_t *font, const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); -HB_EXTERN void -hb_font_get_glyph_shape (hb_font_t *font, - hb_codepoint_t glyph, - hb_draw_funcs_t *dfuncs, void *draw_data); - HB_EXTERN void hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh b/src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh index fa5712f9..1afbbbb1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh @@ -105,6 +105,8 @@ struct hb_ft_paint_context_t FT_Color *palette; unsigned palette_index; hb_color_t foreground; + hb_map_t current_glyphs; + hb_map_t current_layers; int depth_left = HB_MAX_NESTING_LEVEL; int edge_count = HB_COLRV1_MAX_EDGE_COUNT; }; @@ -220,9 +222,18 @@ _hb_ft_paint (hb_ft_paint_context_t *c, &paint.u.colr_layers.layer_iterator, &other_paint)) { + unsigned i = paint.u.colr_layers.layer_iterator.layer; + + if (unlikely (c->current_layers.has (i))) + continue; + + c->current_layers.add (i); + c->funcs->push_group (c->data); c->recurse (other_paint); c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER); + + c->current_layers.del (i); } } break; @@ -320,8 +331,27 @@ _hb_ft_paint (hb_ft_paint_context_t *c, break; case FT_COLR_PAINTFORMAT_COLR_GLYPH: { + hb_codepoint_t gid = paint.u.colr_glyph.glyphID; + + if (unlikely (c->current_glyphs.has (gid))) + return; + + c->current_glyphs.add (gid); + + c->funcs->push_inverse_root_transform (c->data, c->font); + c->ft_font->lock.unlock (); + if (c->funcs->color_glyph (c->data, gid, c->font)) + { + c->ft_font->lock.lock (); + c->funcs->pop_transform (c->data); + c->current_glyphs.del (gid); + return; + } + c->ft_font->lock.lock (); + c->funcs->pop_transform (c->data); + FT_OpaquePaint other_paint = {0}; - if (FT_Get_Color_Glyph_Paint (ft_face, paint.u.colr_glyph.glyphID, + if (FT_Get_Color_Glyph_Paint (ft_face, gid, FT_COLOR_NO_ROOT_TRANSFORM, &other_paint)) { @@ -350,6 +380,8 @@ _hb_ft_paint (hb_ft_paint_context_t *c, if (has_clip_box) c->funcs->pop_clip (c->data); + + c->current_glyphs.del (gid); } } break; @@ -474,6 +506,7 @@ hb_ft_paint_glyph_colr (hb_font_t *font, hb_ft_paint_context_t c (ft_font, font, paint_funcs, paint_data, palette, palette_index, foreground); + c.current_glyphs.add (gid); bool is_bounded = true; FT_ClipBox clip_box; @@ -497,6 +530,7 @@ hb_ft_paint_glyph_colr (hb_font_t *font, hb_ft_paint_context_t ce (ft_font, font, extents_funcs, &extents_data, palette, palette_index, foreground); + ce.current_glyphs.add (gid); ce.funcs->push_root_transform (ce.data, font); ce.recurse (paint); ce.funcs->pop_transform (ce.data); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc index 1105862f..6ca3f854 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ft.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ft.cc @@ -114,7 +114,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; ft_font->cached_serial = (unsigned) -1; - ft_font->advance_cache.init (); + new (&ft_font->advance_cache) hb_ft_advance_cache_t; return ft_font; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc index 332cc848..d66de0b2 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-gobject-structs.cc @@ -29,7 +29,7 @@ #ifdef HAVE_GOBJECT -/** +/* * SECTION:hb-gobject * @title: hb-gobject * @short_description: GObject integration support diff --git a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc index 9e068f8d..7ea03862 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc @@ -248,6 +248,21 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, gr_fref_set_feature_value (fref, features[i].value, feats); } + hb_direction_t direction = buffer->props.direction; + hb_direction_t horiz_dir = hb_script_get_horizontal_direction (buffer->props.script); + /* TODO vertical: + * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType + * Ogham fonts are supposed to be implemented BTT or not. Need to research that + * first. */ + if ((HB_DIRECTION_IS_HORIZONTAL (direction) && + direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) || + (HB_DIRECTION_IS_VERTICAL (direction) && + direction != HB_DIRECTION_TTB)) + { + hb_buffer_reverse_clusters (buffer); + direction = HB_DIRECTION_REVERSE (direction); + } + gr_segment *seg = nullptr; const gr_slot *is; unsigned int ci = 0, ic = 0; @@ -261,21 +276,11 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, for (unsigned int i = 0; i < buffer->len; ++i) chars[i] = buffer->info[i].codepoint; - /* TODO ensure_native_direction. */ - - hb_tag_t script_tag[HB_OT_MAX_TAGS_PER_SCRIPT]; - unsigned int count = HB_OT_MAX_TAGS_PER_SCRIPT; - hb_ot_tags_from_script_and_language (hb_buffer_get_script (buffer), - HB_LANGUAGE_INVALID, - &count, - script_tag, - nullptr, nullptr); - seg = gr_make_seg (nullptr, grface, - count ? script_tag[count - 1] : HB_OT_TAG_DEFAULT_SCRIPT, + HB_TAG_NONE, // https://github.com/harfbuzz/harfbuzz/issues/3439#issuecomment-1442650148 feats, gr_utf32, chars, buffer->len, - 2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0)); + 2 | (direction == HB_DIRECTION_RTL ? 1 : 0)); if (unlikely (!seg)) { if (feats) gr_featureval_destroy (feats); @@ -327,7 +332,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, float yscale = (float) font->y_scale / upem; yscale *= yscale / xscale; unsigned int curradv = 0; - if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (HB_DIRECTION_IS_BACKWARD (direction)) { curradv = gr_slot_origin_X(gr_seg_first_slot(seg)) * xscale; clusters[0].advance = gr_seg_advance_X(seg) * xscale - curradv; @@ -356,16 +361,17 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, c->num_chars = before - c->base_char; c->base_glyph = ic; c->num_glyphs = 0; - if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (HB_DIRECTION_IS_BACKWARD (direction)) { c->advance = curradv - gr_slot_origin_X(is) * xscale; curradv -= c->advance; } else { + auto origin_X = gr_slot_origin_X (is) * xscale; c->advance = 0; - clusters[ci].advance += gr_slot_origin_X(is) * xscale - curradv; - curradv += clusters[ci].advance; + clusters[ci].advance += origin_X - curradv; + curradv = origin_X; } ci++; } @@ -375,7 +381,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, clusters[ci].num_chars = after + 1 - clusters[ci].base_char; } - if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (HB_DIRECTION_IS_BACKWARD (direction)) clusters[ci].advance += curradv; else clusters[ci].advance += gr_seg_advance_X(seg) * xscale - curradv; @@ -397,7 +403,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, unsigned int currclus = UINT_MAX; const hb_glyph_info_t *info = buffer->info; hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, nullptr); - if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) + if (!HB_DIRECTION_IS_BACKWARD (direction)) { curradvx = 0; for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_segment (is)) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh index b123b2f2..61e05180 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh @@ -63,6 +63,7 @@ struct hb_iter_t static constexpr bool is_iterator = true; static constexpr bool is_random_access_iterator = false; static constexpr bool is_sorted_iterator = false; + static constexpr bool has_fast_len = false; // Should be checked in combination with is_random_access_iterator. private: /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ @@ -393,7 +394,7 @@ struct hb_map_iter_t : private: Iter it; - hb_reference_wrapper f; + mutable hb_reference_wrapper f; }; template @@ -456,8 +457,8 @@ struct hb_filter_iter_t : private: Iter it; - hb_reference_wrapper p; - hb_reference_wrapper f; + mutable hb_reference_wrapper p; + mutable hb_reference_wrapper f; }; template struct hb_filter_iter_factory_t @@ -841,7 +842,7 @@ struct template auto operator () (Iterable&& it, unsigned count) const HB_AUTO_RETURN - ( hb_zip (hb_range (count), it) | hb_map (hb_second) ) + ( hb_zip (hb_range (count), it) | hb_map_retains_sorting (hb_second) ) /* Specialization arrays. */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-kern.hh b/src/3rdparty/harfbuzz-ng/src/hb-kern.hh index 9ea945ca..0462a0ea 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-kern.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-kern.hh @@ -53,7 +53,7 @@ struct hb_kern_machine_t return; buffer->unsafe_to_concat (); - OT::hb_ot_apply_context_t c (1, font, buffer); + OT::hb_ot_apply_context_t c (1, font, buffer, hb_blob_get_empty ()); c.set_lookup_mask (kern_mask); c.set_lookup_props (OT::LookupFlag::IgnoreMarks); auto &skippy_iter = c.iter_input; @@ -70,7 +70,7 @@ struct hb_kern_machine_t continue; } - skippy_iter.reset (idx, 1); + skippy_iter.reset (idx); unsigned unsafe_to; if (!skippy_iter.next (&unsafe_to)) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-limits.hh b/src/3rdparty/harfbuzz-ng/src/hb-limits.hh index 0f60e9e2..25c1e71e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-limits.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-limits.hh @@ -89,6 +89,10 @@ #endif +#ifndef HB_GLYF_VAR_COMPOSITE_MAX_AXES +#define HB_GLYF_VAR_COMPOSITE_MAX_AXES 4096 +#endif + #ifndef HB_GLYF_MAX_POINTS #define HB_GLYF_MAX_POINTS 20000 #endif @@ -102,7 +106,7 @@ #endif #ifndef HB_COLRV1_MAX_EDGE_COUNT -#define HB_COLRV1_MAX_EDGE_COUNT 1024 +#define HB_COLRV1_MAX_EDGE_COUNT 65536 #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh index 1084725a..ecff94f1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh @@ -180,6 +180,9 @@ struct hb_lazy_loader_t : hb_data_wrapper_t hb_lazy_loader_t >::value Funcs; + hb_lazy_loader_t () = default; + hb_lazy_loader_t (const hb_lazy_loader_t &other) = delete; + void init0 () {} /* Init, when memory is already set to 0. No-op for us. */ void init () { instance.set_relaxed (nullptr); } void fini () { do_destroy (instance.get_acquire ()); init (); } @@ -278,7 +281,11 @@ struct hb_lazy_loader_t : hb_data_wrapper_t template struct hb_face_lazy_loader_t : hb_lazy_loader_t, - hb_face_t, WheresFace> {}; + hb_face_t, WheresFace> +{ + // Hack; have them here for API parity with hb_table_lazy_loader_t + hb_blob_t *get_blob () { return this->get ()->get_blob (); } +}; template struct hb_table_lazy_loader_t : hb_lazy_loader_t (face); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.cc b/src/3rdparty/harfbuzz-ng/src/hb-map.cc index 5d67cd9a..0dc9246f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-map.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-map.cc @@ -365,7 +365,7 @@ hb_map_update (hb_map_t *map, * @key: (out): Key retrieved * @value: (out): Value retrieved * - * Fetches the next key/value paire in @map. + * Fetches the next key/value pair in @map. * * Set @idx to -1 to get started. * diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.h b/src/3rdparty/harfbuzz-ng/src/hb-map.h index e928628f..0ae17171 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-map.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-map.h @@ -44,7 +44,7 @@ HB_BEGIN_DECLS * * Since: 1.7.7 */ -#define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1) +#define HB_MAP_VALUE_INVALID HB_CODEPOINT_INVALID /** * hb_map_t: diff --git a/src/3rdparty/harfbuzz-ng/src/hb-map.hh b/src/3rdparty/harfbuzz-ng/src/hb-map.hh index 041b8829..6ea41665 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-map.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-map.hh @@ -45,9 +45,9 @@ struct hb_hashmap_t hb_hashmap_t () { init (); } ~hb_hashmap_t () { fini (); } - hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (o.population); hb_copy (o, *this); } + hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { alloc (o.population); hb_copy (o, *this); } hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); } - hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); resize (o.population); hb_copy (o, *this); return *this; } + hb_hashmap_t& operator= (const hb_hashmap_t& o) { reset (); alloc (o.population); hb_copy (o, *this); return *this; } hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; } hb_hashmap_t (std::initializer_list> lst) : hb_hashmap_t () @@ -60,29 +60,32 @@ struct hb_hashmap_t hb_hashmap_t (const Iterable &o) : hb_hashmap_t () { auto iter = hb_iter (o); - if (iter.is_random_access_iterator) - resize (hb_len (iter)); + if (iter.is_random_access_iterator || iter.has_fast_len) + alloc (hb_len (iter)); hb_copy (iter, *this); } struct item_t { K key; - uint32_t hash : 30; + uint32_t is_real_ : 1; uint32_t is_used_ : 1; - uint32_t is_tombstone_ : 1; + uint32_t hash : 30; V value; item_t () : key (), + is_real_ (false), is_used_ (false), hash (0), - is_used_ (false), is_tombstone_ (false), value () {} + // Needed for https://github.com/harfbuzz/harfbuzz/issues/4138 + K& get_key () { return key; } + V& get_value () { return value; } + bool is_used () const { return is_used_; } void set_used (bool is_used) { is_used_ = is_used; } - bool is_tombstone () const { return is_tombstone_; } - void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; } - bool is_real () const { return is_used_ && !is_tombstone_; } + void set_real (bool is_real) { is_real_ = is_real; } + bool is_real () const { return is_real_; } template @@ -98,10 +101,15 @@ struct hb_hashmap_t bool operator == (const K &o) const { return hb_deref (key) == hb_deref (o); } bool operator == (const item_t &o) const { return *this == o.key; } hb_pair_t get_pair() const { return hb_pair_t (key, value); } - hb_pair_t get_pair_ref() const { return hb_pair_t (key, value); } + hb_pair_t get_pair_ref() { return hb_pair_t (key, value); } uint32_t total_hash () const { return (hash * 31) + hb_hash (value); } + + static constexpr bool is_trivial = std::is_trivially_constructible::value && + std::is_trivially_destructible::value && + std::is_trivially_constructible::value && + std::is_trivially_destructible::value; }; hb_object_header_t header; @@ -110,6 +118,7 @@ struct hb_hashmap_t unsigned int occupancy; /* Including tombstones. */ unsigned int mask; unsigned int prime; + unsigned int max_chain_length; item_t *items; friend void swap (hb_hashmap_t& a, hb_hashmap_t& b) @@ -123,6 +132,7 @@ struct hb_hashmap_t hb_swap (a.occupancy, b.occupancy); hb_swap (a.mask, b.mask); hb_swap (a.prime, b.prime); + hb_swap (a.max_chain_length, b.max_chain_length); hb_swap (a.items, b.items); } void init () @@ -133,16 +143,19 @@ struct hb_hashmap_t population = occupancy = 0; mask = 0; prime = 0; + max_chain_length = 0; items = nullptr; } void fini () { hb_object_fini (this); - if (likely (items)) { + if (likely (items)) + { unsigned size = mask + 1; - for (unsigned i = 0; i < size; i++) - items[i].~item_t (); + if (!item_t::is_trivial) + for (unsigned i = 0; i < size; i++) + items[i].~item_t (); hb_free (items); items = nullptr; } @@ -157,7 +170,7 @@ struct hb_hashmap_t bool in_error () const { return !successful; } - bool resize (unsigned new_population = 0) + bool alloc (unsigned new_population = 0) { if (unlikely (!successful)) return false; @@ -171,8 +184,11 @@ struct hb_hashmap_t successful = false; return false; } - for (auto &_ : hb_iter (new_items, new_size)) - new (&_) item_t (); + if (!item_t::is_trivial) + for (auto &_ : hb_iter (new_items, new_size)) + new (&_) item_t (); + else + hb_memset (new_items, 0, (size_t) new_size * sizeof (item_t)); unsigned int old_size = size (); item_t *old_items = items; @@ -181,6 +197,7 @@ struct hb_hashmap_t population = occupancy = 0; mask = new_size - 1; prime = prime_for (power); + max_chain_length = power * 2; items = new_items; /* Insert back old items. */ @@ -192,7 +209,8 @@ struct hb_hashmap_t old_items[i].hash, std::move (old_items[i].value)); } - old_items[i].~item_t (); + if (!item_t::is_trivial) + old_items[i].~item_t (); } hb_free (old_items); @@ -201,72 +219,129 @@ struct hb_hashmap_t } template - bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool is_delete=false) + bool set_with_hash (KK&& key, uint32_t hash, VV&& value, bool overwrite = true) { if (unlikely (!successful)) return false; - if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; - item_t &item = item_for_hash (key, hash); + if (unlikely ((occupancy + occupancy / 2) >= mask && !alloc ())) return false; - if (is_delete && !(item == key)) - return true; /* Trying to delete non-existent key. */ + hash &= 0x3FFFFFFF; // We only store lower 30bit of hash + unsigned int tombstone = (unsigned int) -1; + unsigned int i = hash % prime; + unsigned length = 0; + unsigned step = 0; + while (items[i].is_used ()) + { + if ((std::is_integral::value || items[i].hash == hash) && + items[i] == key) + { + if (!overwrite) + return false; + else + break; + } + if (!items[i].is_real () && tombstone == (unsigned) -1) + tombstone = i; + i = (i + ++step) & mask; + length++; + } + + item_t &item = items[tombstone == (unsigned) -1 ? i : tombstone]; if (item.is_used ()) { occupancy--; - if (!item.is_tombstone ()) - population--; + population -= item.is_real (); } item.key = std::forward (key); item.value = std::forward (value); item.hash = hash; item.set_used (true); - item.set_tombstone (is_delete); + item.set_real (true); occupancy++; - if (!is_delete) - population++; + population++; + + if (unlikely (length > max_chain_length) && occupancy * 8 > mask) + alloc (mask - 8); // This ensures we jump to next larger size return true; } template - bool set (const K &key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward (value)); } + bool set (const K &key, VV&& value, bool overwrite = true) { return set_with_hash (key, hb_hash (key), std::forward (value), overwrite); } template - bool set (K &&key, VV&& value) { return set_with_hash (std::move (key), hb_hash (key), std::forward (value)); } + bool set (K &&key, VV&& value, bool overwrite = true) + { + uint32_t hash = hb_hash (key); + return set_with_hash (std::move (key), hash, std::forward (value), overwrite); + } + bool add (const K &key) + { + uint32_t hash = hb_hash (key); + return set_with_hash (key, hash, item_t::default_value ()); + } const V& get_with_hash (const K &key, uint32_t hash) const { - if (unlikely (!items)) return item_t::default_value (); - auto &item = item_for_hash (key, hash); - return item.is_real () && item == key ? item.value : item_t::default_value (); + if (!items) return item_t::default_value (); + auto *item = fetch_item (key, hb_hash (key)); + if (item) + return item->value; + return item_t::default_value (); } const V& get (const K &key) const { - if (unlikely (!items)) return item_t::default_value (); + if (!items) return item_t::default_value (); return get_with_hash (key, hb_hash (key)); } - void del (const K &key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); } + void del (const K &key) + { + if (!items) return; + auto *item = fetch_item (key, hb_hash (key)); + if (item) + { + item->set_real (false); + population--; + } + } /* Has interface. */ const V& operator [] (K k) const { return get (k); } template - bool has (K key, VV **vp = nullptr) const + bool has (const K &key, VV **vp = nullptr) const { - if (unlikely (!items)) - return false; - auto &item = item_for_hash (key, hb_hash (key)); - if (item.is_real () && item == key) + if (!items) return false; + auto *item = fetch_item (key, hb_hash (key)); + if (item) { - if (vp) *vp = std::addressof (item.value); + if (vp) *vp = std::addressof (item->value); return true; } - else - return false; + return false; + } + item_t *fetch_item (const K &key, uint32_t hash) const + { + hash &= 0x3FFFFFFF; // We only store lower 30bit of hash + unsigned int i = hash % prime; + unsigned step = 0; + while (items[i].is_used ()) + { + if ((std::is_integral::value || items[i].hash == hash) && + items[i] == key) + { + if (items[i].is_real ()) + return &items[i]; + else + return nullptr; + } + i = (i + ++step) & mask; + } + return nullptr; } /* Projection. */ - V operator () (K k) const { return get (k); } + const V& operator () (K k) const { return get (k); } unsigned size () const { return mask ? mask + 1 : 0; } @@ -339,23 +414,21 @@ struct hb_hashmap_t auto keys_ref () const HB_AUTO_RETURN ( + iter_items () - | hb_map (&item_t::key) + | hb_map (&item_t::get_key) ) auto keys () const HB_AUTO_RETURN ( - + iter_items () - | hb_map (&item_t::key) + + keys_ref () | hb_map (hb_ridentity) ) auto values_ref () const HB_AUTO_RETURN ( + iter_items () - | hb_map (&item_t::value) + | hb_map (&item_t::get_value) ) auto values () const HB_AUTO_RETURN ( - + iter_items () - | hb_map (&item_t::value) + + values_ref () | hb_map (hb_ridentity) ) @@ -393,23 +466,6 @@ struct hb_hashmap_t hb_hashmap_t& operator << (const hb_pair_t& v) { set (std::move (v.first), std::move (v.second)); return *this; } - item_t& item_for_hash (const K &key, uint32_t hash) const - { - hash &= 0x3FFFFFFF; // We only store lower 30bit of hash - unsigned int i = hash % prime; - unsigned int step = 0; - unsigned int tombstone = (unsigned) -1; - while (items[i].is_used ()) - { - if (items[i].hash == hash && items[i] == key) - return items[i]; - if (tombstone == (unsigned) -1 && items[i].is_tombstone ()) - tombstone = i; - i = (i + ++step) & mask; - } - return items[tombstone == (unsigned) -1 ? i : tombstone]; - } - static unsigned int prime_for (unsigned int shift) { /* Following comment and table copied from glib. */ @@ -480,7 +536,7 @@ struct hb_map_t : hb_hashmap_t> lst) : hashmap (lst) {} + hb_map_t (std::initializer_list lst) : hashmap (lst) {} template hb_map_t (const Iterable &o) : hashmap (o) {} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-meta.hh b/src/3rdparty/harfbuzz-ng/src/hb-meta.hh index 31aa7fa6..52ff4a84 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-meta.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-meta.hh @@ -153,8 +153,8 @@ struct hb_reference_wrapper hb_reference_wrapper (T v) : v (v) {} bool operator == (const hb_reference_wrapper& o) const { return v == o.v; } bool operator != (const hb_reference_wrapper& o) const { return v != o.v; } - operator T () const { return v; } - T get () const { return v; } + operator T& () { return v; } + T& get () { return v; } T v; }; template @@ -163,8 +163,8 @@ struct hb_reference_wrapper hb_reference_wrapper (T& v) : v (std::addressof (v)) {} bool operator == (const hb_reference_wrapper& o) const { return v == o.v; } bool operator != (const hb_reference_wrapper& o) const { return v != o.v; } - operator T& () const { return *v; } - T& get () const { return *v; } + operator T& () { return *v; } + T& get () { return *v; } T* v; }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh b/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh index b4a8cc62..0184279c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-multimap.hh @@ -38,10 +38,10 @@ struct hb_multimap_t { void add (hb_codepoint_t k, hb_codepoint_t v) { - hb_codepoint_t *i; - if (multiples_indices.has (k, &i)) + hb_vector_t *m; + if (multiples.has (k, &m)) { - multiples_values[*i].push (v); + m->push (v); return; } @@ -51,12 +51,7 @@ struct hb_multimap_t hb_codepoint_t old = *old_v; singulars.del (k); - multiples_indices.set (k, multiples_values.length); - auto *vec = multiples_values.push (); - - vec->push (old); - vec->push (v); - + multiples.set (k, hb_vector_t {old, v}); return; } @@ -69,22 +64,31 @@ struct hb_multimap_t if (singulars.has (k, &v)) return hb_array (v, 1); - hb_codepoint_t *i; - if (multiples_indices.has (k, &i)) - return multiples_values[*i].as_array (); + hb_vector_t *m; + if (multiples.has (k, &m)) + return m->as_array (); return hb_array_t (); } bool in_error () const { - return singulars.in_error () || multiples_indices.in_error () || multiples_values.in_error (); + if (singulars.in_error () || multiples.in_error ()) + return true; + for (const auto &m : multiples.values_ref ()) + if (m.in_error ()) + return true; + return false; + } + + void alloc (unsigned size) + { + singulars.alloc (size); } protected: hb_map_t singulars; - hb_map_t multiples_indices; - hb_vector_t> multiples_values; + hb_hashmap_t> multiples; }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-null.hh b/src/3rdparty/harfbuzz-ng/src/hb-null.hh index 0d7f4da7..854485d3 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-null.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-null.hh @@ -37,7 +37,7 @@ /* Global nul-content Null pool. Enlarge as necessary. */ -#define HB_NULL_POOL_SIZE 448 +#define HB_NULL_POOL_SIZE 640 template struct _hb_has_min_size : hb_false_type {}; @@ -85,7 +85,7 @@ using hb_null_size = _hb_null_size; template struct _hb_static_size : hb_integral_constant {}; template -struct _hb_static_size> : hb_integral_constant {}; +struct _hb_static_size> : hb_integral_constant {}; template using hb_static_size = _hb_static_size; #define hb_static_size(T) hb_static_size::value @@ -176,7 +176,7 @@ template static inline Type& Crap () { static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); Type *obj = reinterpret_cast (_hb_CrapPool); - memcpy (obj, &Null (Type), sizeof (*obj)); + memcpy (obj, std::addressof (Null (Type)), sizeof (*obj)); return *obj; } template @@ -211,11 +211,11 @@ struct hb_nonnull_ptr_t T * operator = (T *v_) { return v = v_; } T * operator -> () const { return get (); } T & operator * () const { return *get (); } - T ** operator & () const { return &v; } + T ** operator & () const { return std::addressof (v); } /* Only auto-cast to const types. */ template operator const C * () const { return get (); } operator const char * () const { return (const char *) get (); } - T * get () const { return v ? v : const_cast (&Null (T)); } + T * get () const { return v ? v : const_cast (std::addressof (Null (T))); } T * get_raw () const { return v; } private: diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh index 13570a46..04f144a7 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-file.hh @@ -131,7 +131,7 @@ typedef struct OpenTypeOffsetTable sfnt_version = sfnt_tag; /* Take space for numTables, searchRange, entrySelector, RangeShift * and the TableRecords themselves. */ - unsigned num_items = it.len (); + unsigned num_items = hb_len (it); if (unlikely (!tables.serialize (c, num_items))) return_trace (false); const char *dir_end = (const char *) c->head; @@ -145,7 +145,7 @@ typedef struct OpenTypeOffsetTable unsigned len = blob->length; /* Allocate room for the table and copy it. */ - char *start = (char *) c->allocate_size (len); + char *start = (char *) c->allocate_size (len, false); if (unlikely (!start)) return false; TableRecord &rec = tables.arrayZ[i]; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh index 4c9bfebc..d3fdd1ca 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type.hh @@ -312,6 +312,8 @@ struct _hb_has_null template struct OffsetTo : Offset { + using target_t = Type; + // Make sure Type is not unbounded; works only for types that are fully defined at OffsetTo time. static_assert (has_null == false || (hb_has_null_size (Type) || !hb_has_min_size (Type)), ""); @@ -416,12 +418,15 @@ struct OffsetTo : Offset { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); - if (unlikely (this->is_null ())) return_trace (true); + //if (unlikely (this->is_null ())) return_trace (true); if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false); return_trace (true); } template +#ifndef HB_OPTIMIZE_SIZE + HB_ALWAYS_INLINE +#endif bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -462,24 +467,16 @@ struct UnsizedArrayOf HB_DELETE_CREATE_COPY_ASSIGN (UnsizedArrayOf); - const Type& operator [] (int i_) const + const Type& operator [] (unsigned int i) const { - unsigned int i = (unsigned int) i_; - const Type *p = &arrayZ[i]; - if (unlikely ((const void *) p < (const void *) arrayZ)) return Null (Type); /* Overflowed. */ - _hb_compiler_memory_r_barrier (); - return *p; + return arrayZ[i]; } - Type& operator [] (int i_) + Type& operator [] (unsigned int i) { - unsigned int i = (unsigned int) i_; - Type *p = &arrayZ[i]; - if (unlikely ((const void *) p < (const void *) arrayZ)) return Crap (Type); /* Overflowed. */ - _hb_compiler_memory_r_barrier (); - return *p; + return arrayZ[i]; } - unsigned int get_size (unsigned int len) const + static unsigned int get_size (unsigned int len) { return len * Type::static_size; } template operator T * () { return arrayZ; } @@ -533,6 +530,7 @@ struct UnsizedArrayOf } template + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -721,6 +719,7 @@ struct ArrayOf } template + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -736,7 +735,7 @@ struct ArrayOf bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (len.sanitize (c) && c->check_array (arrayZ, len)); + return_trace (len.sanitize (c) && c->check_array_sized (arrayZ, len, sizeof (LenType))); } public: @@ -797,7 +796,7 @@ template using List16OfOffset16To = List16OfOffsetTo; /* An array starting at second element. */ -template +template struct HeadlessArrayOf { static constexpr unsigned item_size = Type::static_size; @@ -861,6 +860,7 @@ struct HeadlessArrayOf } template + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -878,7 +878,7 @@ struct HeadlessArrayOf { TRACE_SANITIZE (this); return_trace (lenP1.sanitize (c) && - (!lenP1 || c->check_array (arrayZ, lenP1 - 1))); + (!lenP1 || c->check_array_sized (arrayZ, lenP1 - 1, sizeof (LenType)))); } public: @@ -887,6 +887,7 @@ struct HeadlessArrayOf public: DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); }; +template using HeadlessArray16Of = HeadlessArrayOf; /* An array storing length-1. */ template @@ -912,6 +913,7 @@ struct ArrayOfM1 { return lenM1.static_size + (lenM1 + 1) * Type::static_size; } template + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); @@ -929,7 +931,7 @@ struct ArrayOfM1 { TRACE_SANITIZE (this); return_trace (lenM1.sanitize (c) && - (c->check_array (arrayZ, lenM1 + 1))); + (c->check_array_sized (arrayZ, lenM1 + 1, sizeof (LenType)))); } public: @@ -1096,6 +1098,7 @@ struct VarSizedBinSearchArrayOf { return header.static_size + header.nUnits * header.unitSize; } template + HB_ALWAYS_INLINE bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh index f22824fc..923a32b2 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh @@ -48,12 +48,24 @@ static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offs struct code_pair_t { - hb_codepoint_t code; + unsigned code; hb_codepoint_t glyph; }; + using str_buff_t = hb_vector_t; using str_buff_vec_t = hb_vector_t; +using glyph_to_sid_map_t = hb_vector_t; + +struct length_f_t +{ + template + unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); } + + unsigned operator () (unsigned _) const { return _; } +} +HB_FUNCOBJ (length_f); /* CFF INDEX */ template @@ -62,42 +74,52 @@ struct CFFIndex unsigned int offset_array_size () const { return offSize * (count + 1); } - CFFIndex *copy (hb_serialize_context_t *c) const - { - TRACE_SERIALIZE (this); - unsigned int size = get_size (); - CFFIndex *out = c->allocate_size (size, false); - if (likely (out)) - hb_memcpy (out, this, size); - return_trace (out); - } - template bool serialize (hb_serialize_context_t *c, - const Iterable &iterable) + const Iterable &iterable, + const unsigned *p_data_size = nullptr) { TRACE_SERIALIZE (this); + unsigned data_size; + if (p_data_size) + data_size = *p_data_size; + else + total_size (iterable, &data_size); + auto it = hb_iter (iterable); - serialize_header(c, + it | hb_map (hb_iter) | hb_map (hb_len)); + if (unlikely (!serialize_header (c, +it, data_size))) return_trace (false); + unsigned char *ret = c->allocate_size (data_size, false); + if (unlikely (!ret)) return_trace (false); for (const auto &_ : +it) - hb_iter (_).copy (c); + { + unsigned len = _.length; + if (!len) + continue; + if (len <= 1) + { + *ret++ = *_.arrayZ; + continue; + } + hb_memcpy (ret, _.arrayZ, len); + ret += len; + } return_trace (true); } template bool serialize_header (hb_serialize_context_t *c, - Iterator it) + Iterator it, + unsigned data_size) { TRACE_SERIALIZE (this); - unsigned total = + it | hb_reduce (hb_add, 0); - unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8; + unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8; /* serialize CFFIndex header */ if (unlikely (!c->extend_min (this))) return_trace (false); - this->count = it.len (); + this->count = hb_len (it); if (!this->count) return_trace (true); if (unlikely (!c->extend (this->offSize))) return_trace (false); this->offSize = off_size; @@ -106,25 +128,88 @@ struct CFFIndex /* serialize indices */ unsigned int offset = 1; - unsigned int i = 0; - for (unsigned _ : +it) + if (HB_OPTIMIZE_SIZE_VAL) { - set_offset_at (i++, offset); - offset += _; + unsigned int i = 0; + for (const auto &_ : +it) + { + set_offset_at (i++, offset); + offset += length_f (_); + } + set_offset_at (i, offset); } - set_offset_at (i, offset); + else + switch (off_size) + { + case 1: + { + HBUINT8 *p = (HBUINT8 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + case 2: + { + HBUINT16 *p = (HBUINT16 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + case 3: + { + HBUINT24 *p = (HBUINT24 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + case 4: + { + HBUINT32 *p = (HBUINT32 *) offsets; + for (const auto &_ : +it) + { + *p++ = offset; + offset += length_f (_); + } + *p = offset; + } + break; + default: + break; + } + assert (offset == data_size + 1); return_trace (true); } template - static unsigned total_size (const Iterable &iterable) + static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr) { - auto it = + hb_iter (iterable) | hb_map (hb_iter) | hb_map (hb_len); - if (!it) return 0; + auto it = + hb_iter (iterable); + if (!it) + { + if (data_size) *data_size = 0; + return min_size; + } + + unsigned total = 0; + for (const auto &_ : +it) + total += length_f (_); + + if (data_size) *data_size = total; - unsigned total = + it | hb_reduce (hb_add, 0); unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8; return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total; @@ -133,13 +218,16 @@ struct CFFIndex void set_offset_at (unsigned int index, unsigned int offset) { assert (index <= count); - HBUINT8 *p = offsets + offSize * index + offSize; + unsigned int size = offSize; - for (; size; size--) + const HBUINT8 *p = offsets; + switch (size) { - --p; - *p = offset & 0xFF; - offset >>= 8; + case 1: ((HBUINT8 *) p)[index] = offset; break; + case 2: ((HBUINT16 *) p)[index] = offset; break; + case 3: ((HBUINT24 *) p)[index] = offset; break; + case 4: ((HBUINT32 *) p)[index] = offset; break; + default: return; } } @@ -149,37 +237,30 @@ struct CFFIndex assert (index <= count); unsigned int size = offSize; - const HBUINT8 *p = offsets + size * index; + const HBUINT8 *p = offsets; switch (size) { - case 1: return * (HBUINT8 *) p; - case 2: return * (HBUINT16 *) p; - case 3: return * (HBUINT24 *) p; - case 4: return * (HBUINT32 *) p; + case 1: return ((HBUINT8 *) p)[index]; + case 2: return ((HBUINT16 *) p)[index]; + case 3: return ((HBUINT24 *) p)[index]; + case 4: return ((HBUINT32 *) p)[index]; default: return 0; } } - unsigned int length_at (unsigned int index) const - { - unsigned offset0 = offset_at (index); - unsigned offset1 = offset_at (index + 1); - if (unlikely (offset1 < offset0 || offset1 > offset_at (count))) - return 0; - return offset1 - offset0; - } - const unsigned char *data_base () const - { return (const unsigned char *) this + min_size + offSize.static_size + offset_array_size (); } + { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); } public: hb_ubytes_t operator [] (unsigned int index) const { if (unlikely (index >= count)) return hb_ubytes_t (); _hb_compiler_memory_r_barrier (); - unsigned length = length_at (index); - if (unlikely (!length)) return hb_ubytes_t (); - return hb_ubytes_t (data_base () + offset_at (index) - 1, length); + unsigned offset0 = offset_at (index); + unsigned offset1 = offset_at (index + 1); + if (unlikely (offset1 < offset0 || offset1 > offset_at (count))) + return hb_ubytes_t (); + return hb_ubytes_t (data_base () + offset0, offset1 - offset0); } unsigned int get_size () const @@ -197,7 +278,7 @@ struct CFFIndex (count < count + 1u && c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 && c->check_array (offsets, offSize, count + 1u) && - c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count) - 1))))); + c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count)))))); } public: @@ -211,47 +292,6 @@ struct CFFIndex DEFINE_SIZE_MIN (COUNT::static_size); }; -template -struct CFFIndexOf : CFFIndex -{ - template - bool serialize (hb_serialize_context_t *c, - unsigned int offSize_, - const DATA *dataArray, - unsigned int dataArrayLen, - const hb_vector_t &dataSizeArray, - const PARAM1 ¶m1, - const PARAM2 ¶m2) - { - TRACE_SERIALIZE (this); - /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (this))) return_trace (false); - this->count = dataArrayLen; - this->offSize = offSize_; - if (unlikely (!c->allocate_size (offSize_ * (dataArrayLen + 1), false))) - return_trace (false); - - /* serialize indices */ - unsigned int offset = 1; - unsigned int i = 0; - for (; i < dataArrayLen; i++) - { - this->set_offset_at (i, offset); - offset += dataSizeArray[i]; - } - this->set_offset_at (i, offset); - - /* serialize data */ - for (unsigned int i = 0; i < dataArrayLen; i++) - { - TYPE *dest = c->start_embed (); - if (unlikely (!dest || !dest->serialize (c, dataArray[i], param1, param2))) - return_trace (false); - } - return_trace (true); - } -}; - /* Top Dict, Font Dict, Private Dict */ struct Dict : UnsizedByteStr { @@ -327,7 +367,7 @@ struct table_info_t }; template -struct FDArray : CFFIndexOf +struct FDArray : CFFIndex { template bool serialize (hb_serialize_context_t *c, @@ -338,7 +378,11 @@ struct FDArray : CFFIndexOf /* serialize INDEX data */ hb_vector_t sizes; + if (it.is_random_access_iterator) + sizes.alloc (hb_len (it)); + c->push (); + char *data_base = c->head; + it | hb_map ([&] (const hb_pair_t &_) { @@ -348,10 +392,16 @@ struct FDArray : CFFIndexOf }) | hb_sink (sizes) ; + unsigned data_size = c->head - data_base; c->pop_pack (false); + if (unlikely (sizes.in_error ())) return_trace (false); + + /* It just happens that the above is packed right after the header below. + * Such a hack. */ + /* serialize INDEX header */ - return_trace (CFFIndex::serialize_header (c, hb_iter (sizes))); + return_trace (CFFIndex::serialize_header (c, hb_iter (sizes), data_size)); } }; @@ -368,8 +418,11 @@ struct FDSelect0 { return_trace (true); } - hb_codepoint_t get_fd (hb_codepoint_t glyph) const - { return (hb_codepoint_t) fds[glyph]; } + unsigned get_fd (hb_codepoint_t glyph) const + { return fds[glyph]; } + + hb_pair_t get_fd_range (hb_codepoint_t glyph) const + { return {fds[glyph], glyph + 1}; } unsigned int get_size (unsigned int num_glyphs) const { return HBUINT8::static_size * num_glyphs; } @@ -427,12 +480,20 @@ struct FDSelect3_4 return +1; } - hb_codepoint_t get_fd (hb_codepoint_t glyph) const + unsigned get_fd (hb_codepoint_t glyph) const { auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range); return range ? range->fd : ranges[nRanges () - 1].fd; } + hb_pair_t get_fd_range (hb_codepoint_t glyph) const + { + auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range); + unsigned fd = range ? range->fd : ranges[nRanges () - 1].fd; + hb_codepoint_t end = range ? range[1].first : ranges[nRanges () - 1].first; + return {fd, end}; + } + GID_TYPE &nRanges () { return ranges.len; } GID_TYPE nRanges () const { return ranges.len; } GID_TYPE &sentinel () { return StructAfter (ranges[nRanges () - 1]); } @@ -469,7 +530,7 @@ struct FDSelect } } - hb_codepoint_t get_fd (hb_codepoint_t glyph) const + unsigned get_fd (hb_codepoint_t glyph) const { if (this == &Null (FDSelect)) return 0; @@ -480,6 +541,18 @@ struct FDSelect default:return 0; } } + /* Returns pair of fd and one after last glyph in range. */ + hb_pair_t get_fd_range (hb_codepoint_t glyph) const + { + if (this == &Null (FDSelect)) return {0, 1}; + + switch (format) + { + case 0: return u.format0.get_fd_range (glyph); + case 3: return u.format3.get_fd_range (glyph); + default:return {0, 1}; + } + } bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc index 5040c746..66df28aa 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.cc @@ -574,11 +574,11 @@ bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, h struct get_seac_param_t { - get_seac_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) {} + get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {} bool has_seac () const { return base && accent; } - const OT::cff1::accelerator_t *cff; + const OT::cff1::accelerator_subset_t *cff; hb_codepoint_t base = 0; hb_codepoint_t accent = 0; }; @@ -596,7 +596,7 @@ struct cff1_cs_opset_seac_t : cff1_cs_opset_t= num_glyphs))) return false; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh index f461a230..1e81dcb5 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-table.hh @@ -28,7 +28,7 @@ #define HB_OT_CFF1_TABLE_HH #include "hb-ot-cff-common.hh" -#include "hb-subset-cff1.hh" +#include "hb-subset-cff-common.hh" #include "hb-draw.hh" #include "hb-paint.hh" @@ -44,7 +44,7 @@ namespace CFF { * CFF -- Compact Font Format (CFF) * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf */ -#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ') +#define HB_OT_TAG_CFF1 HB_TAG('C','F','F',' ') #define CFF_UNDEF_SID CFF_UNDEF_CODE @@ -52,7 +52,6 @@ enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 }; enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 }; typedef CFFIndex CFF1Index; -template struct CFF1IndexOf : CFFIndexOf {}; typedef CFFIndex CFF1Index; typedef CFF1Index CFF1CharStrings; @@ -110,6 +109,7 @@ struct Encoding1 { hb_codepoint_t get_code (hb_codepoint_t glyph) const { + /* TODO: Add cache like get_sid. */ assert (glyph > 0); glyph--; for (unsigned int i = 0; i < nRanges (); i++) @@ -173,11 +173,7 @@ struct Encoding bool serialize (hb_serialize_context_t *c, const Encoding &src) { TRACE_SERIALIZE (this); - unsigned int size = src.get_size (); - Encoding *dest = c->allocate_size (size); - if (unlikely (!dest)) return_trace (false); - hb_memcpy (dest, &src, size); - return_trace (true); + return_trace (c->embed (src)); } /* serialize a subset Encoding */ @@ -312,26 +308,29 @@ struct Encoding }; /* Charset */ -struct Charset0 { - bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const +struct Charset0 +{ + bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c)); + if (num_charset_entries) *num_charset_entries = num_glyphs; + return_trace (sids.sanitize (c, num_glyphs - 1)); } hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const { if (unlikely (glyph >= num_glyphs)) return 0; - if (glyph == 0) + if (unlikely (glyph == 0)) return 0; else return sids[glyph - 1]; } - void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const { + mapping->resize (num_glyphs, false); for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++) - mapping->set (gid, sids[gid - 1]); + mapping->arrayZ[gid] = {sids[gid - 1], gid}; } hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const @@ -347,13 +346,13 @@ struct Charset0 { return 0; } - unsigned int get_size (unsigned int num_glyphs) const + static unsigned int get_size (unsigned int num_glyphs) { assert (num_glyphs > 0); - return HBUINT16::static_size * (num_glyphs - 1); + return UnsizedArrayOf::get_size (num_glyphs - 1); } - HBUINT16 sids[HB_VAR_ARRAY]; + UnsizedArrayOf sids; DEFINE_SIZE_ARRAY(0, sids); }; @@ -374,38 +373,62 @@ struct Charset_Range { template struct Charset1_2 { - bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const + bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); num_glyphs--; - for (unsigned int i = 0; num_glyphs > 0; i++) + unsigned i; + for (i = 0; num_glyphs > 0; i++) { if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1))) return_trace (false); num_glyphs -= (ranges[i].nLeft + 1); } + if (num_charset_entries) + *num_charset_entries = i; return_trace (true); } - hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const + hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs, + code_pair_t *cache = nullptr) const { if (unlikely (glyph >= num_glyphs)) return 0; - if (glyph == 0) return 0; - glyph--; - for (unsigned int i = 0;; i++) + unsigned i; + hb_codepoint_t start_glyph; + if (cache && likely (cache->glyph <= glyph)) { - if (glyph <= ranges[i].nLeft) - return (hb_codepoint_t) ranges[i].first + glyph; - glyph -= (ranges[i].nLeft + 1); + i = cache->code; + start_glyph = cache->glyph; + } + else + { + if (unlikely (glyph == 0)) return 0; + i = 0; + start_glyph = 1; + } + glyph -= start_glyph; + for (;; i++) + { + unsigned count = ranges[i].nLeft; + if (glyph <= count) + { + if (cache) + *cache = {i, start_glyph}; + return ranges[i].first + glyph; + } + count++; + start_glyph += count; + glyph -= count; } return 0; } - void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const { + mapping->resize (num_glyphs, false); hb_codepoint_t gid = 1; if (gid >= num_glyphs) return; @@ -413,8 +436,9 @@ struct Charset1_2 { { hb_codepoint_t sid = ranges[i].first; unsigned count = ranges[i].nLeft + 1; + unsigned last = gid + count; for (unsigned j = 0; j < count; j++) - mapping->set (gid++, sid++); + mapping->arrayZ[gid++] = {sid++, last - 1}; if (gid >= num_glyphs) break; @@ -439,21 +463,26 @@ struct Charset1_2 { unsigned int get_size (unsigned int num_glyphs) const { - unsigned int size = HBUINT8::static_size; - int glyph = (int)num_glyphs; + int glyph = (int) num_glyphs; + unsigned num_ranges = 0; assert (glyph > 0); glyph--; for (unsigned int i = 0; glyph > 0; i++) { glyph -= (ranges[i].nLeft + 1); - size += Charset_Range::static_size; + num_ranges++; } - return size; + return get_size_for_ranges (num_ranges); } - Charset_Range ranges[HB_VAR_ARRAY]; + static unsigned int get_size_for_ranges (unsigned int num_ranges) + { + return UnsizedArrayOf >::get_size (num_ranges); + } + + UnsizedArrayOf> ranges; DEFINE_SIZE_ARRAY (0, ranges); }; @@ -469,11 +498,7 @@ struct Charset bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs) { TRACE_SERIALIZE (this); - unsigned int size = src.get_size (num_glyphs); - Charset *dest = c->allocate_size (size); - if (unlikely (!dest)) return_trace (false); - hb_memcpy (dest, &src, size); - return_trace (true); + return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs))); } /* serialize a subset Charset */ @@ -490,13 +515,13 @@ struct Charset { case 0: { - Charset0 *fmt0 = c->allocate_size (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1)); + Charset0 *fmt0 = c->allocate_size (Charset0::get_size (num_glyphs), false); if (unlikely (!fmt0)) return_trace (false); unsigned int glyph = 0; for (unsigned int i = 0; i < sid_ranges.length; i++) { - hb_codepoint_t sid = sid_ranges[i].code; - for (int left = (int)sid_ranges[i].glyph; left >= 0; left--) + hb_codepoint_t sid = sid_ranges.arrayZ[i].code; + for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--) fmt0->sids[glyph++] = sid++; } } @@ -504,29 +529,35 @@ struct Charset case 1: { - Charset1 *fmt1 = c->allocate_size (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length); + Charset1 *fmt1 = c->allocate_size (Charset1::get_size_for_ranges (sid_ranges.length), false); if (unlikely (!fmt1)) return_trace (false); + hb_codepoint_t all_glyphs = 0; for (unsigned int i = 0; i < sid_ranges.length; i++) { - if (unlikely (!(sid_ranges[i].glyph <= 0xFF))) - return_trace (false); - fmt1->ranges[i].first = sid_ranges[i].code; - fmt1->ranges[i].nLeft = sid_ranges[i].glyph; + auto &_ = sid_ranges.arrayZ[i]; + all_glyphs |= _.glyph; + fmt1->ranges[i].first = _.code; + fmt1->ranges[i].nLeft = _.glyph; } + if (unlikely (!(all_glyphs <= 0xFF))) + return_trace (false); } break; case 2: { - Charset2 *fmt2 = c->allocate_size (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length); + Charset2 *fmt2 = c->allocate_size (Charset2::get_size_for_ranges (sid_ranges.length), false); if (unlikely (!fmt2)) return_trace (false); + hb_codepoint_t all_glyphs = 0; for (unsigned int i = 0; i < sid_ranges.length; i++) { - if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF))) - return_trace (false); - fmt2->ranges[i].first = sid_ranges[i].code; - fmt2->ranges[i].nLeft = sid_ranges[i].glyph; + auto &_ = sid_ranges.arrayZ[i]; + all_glyphs |= _.glyph; + fmt2->ranges[i].first = _.code; + fmt2->ranges[i].nLeft = _.glyph; } + if (unlikely (!(all_glyphs <= 0xFFFF))) + return_trace (false); } break; @@ -545,18 +576,19 @@ struct Charset } } - hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const + hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs, + code_pair_t *cache = nullptr) const { switch (format) { case 0: return u.format0.get_sid (glyph, num_glyphs); - case 1: return u.format1.get_sid (glyph, num_glyphs); - case 2: return u.format2.get_sid (glyph, num_glyphs); + case 1: return u.format1.get_sid (glyph, num_glyphs, cache); + case 2: return u.format2.get_sid (glyph, num_glyphs, cache); default:return 0; } } - void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const { switch (format) { @@ -578,7 +610,7 @@ struct Charset } } - bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) @@ -586,9 +618,9 @@ struct Charset switch (format) { - case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ())); - case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ())); - case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ())); + case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries)); + case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries)); + case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries)); default:return_trace (false); } } @@ -606,10 +638,10 @@ struct Charset struct CFF1StringIndex : CFF1Index { bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings, - const hb_inc_bimap_t &sidmap) + const hb_vector_t &sidmap) { TRACE_SERIALIZE (this); - if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0))) + if (unlikely ((strings.count == 0) || (sidmap.length == 0))) { if (unlikely (!c->extend_min (this->count))) return_trace (false); @@ -617,15 +649,13 @@ struct CFF1StringIndex : CFF1Index return_trace (true); } - byte_str_array_t bytesArray; - if (!bytesArray.resize (sidmap.get_population ())) - return_trace (false); - for (unsigned int i = 0; i < strings.count; i++) - { - hb_codepoint_t j = sidmap[i]; - if (j != HB_MAP_VALUE_INVALID) - bytesArray[j] = strings[i]; - } + if (unlikely (sidmap.in_error ())) return_trace (false); + + // Save this in a vector since serialize() iterates it twice. + hb_vector_t bytesArray (+ hb_iter (sidmap) + | hb_map (strings)); + + if (unlikely (bytesArray.in_error ())) return_trace (false); bool result = CFF1Index::serialize (c, bytesArray); return_trace (result); @@ -932,7 +962,7 @@ struct cff1_private_dict_opset_t : dict_opset_t } }; -struct cff1_private_dict_opset_subset : dict_opset_t +struct cff1_private_dict_opset_subset_t : dict_opset_t { static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval) { @@ -978,7 +1008,7 @@ typedef dict_interpreter_t cff1_font_dict_interpreter_t; typedef CFF1Index CFF1NameIndex; -typedef CFF1IndexOf CFF1TopDictIndex; +typedef CFF1Index CFF1TopDictIndex; struct cff1_font_dict_values_mod_t { @@ -1019,7 +1049,7 @@ using namespace CFF; struct cff1 { - static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1; + static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF1; bool sanitize (hb_sanitize_context_t *c) const { @@ -1031,8 +1061,12 @@ struct cff1 template struct accelerator_templ_t { - void init (hb_face_t *face) + static constexpr hb_tag_t tableTag = cff1::tableTag; + + accelerator_templ_t (hb_face_t *face) { + if (!face) return; + topDict.init (); fontDicts.init (); privateDicts.init (); @@ -1046,22 +1080,22 @@ struct cff1 const OT::cff1 *cff = this->blob->template as (); if (cff == &Null (OT::cff1)) - { fini (); return; } + goto fail; nameIndex = &cff->nameIndex (cff); if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc)) - { fini (); return; } + goto fail; topDictIndex = &StructAtOffset (nameIndex, nameIndex->get_size ()); if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0)) - { fini (); return; } + goto fail; { /* parse top dict */ const hb_ubytes_t topDictStr = (*topDictIndex)[0]; - if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!topDictStr.sanitize (&sc))) goto fail; cff1_top_dict_interp_env_t env (topDictStr); cff1_top_dict_interpreter_t top_interp (env); - if (unlikely (!top_interp.interpret (topDict))) { fini (); return; } + if (unlikely (!top_interp.interpret (topDict))) goto fail; } if (is_predef_charset ()) @@ -1069,7 +1103,7 @@ struct cff1 else { charset = &StructAtOffsetOrNull (cff, topDict.CharsetOffset); - if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; } + if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries))) goto fail; } fdCount = 1; @@ -1079,7 +1113,7 @@ struct cff1 fdSelect = &StructAtOffsetOrNull (cff, topDict.FDSelectOffset); if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) || (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count))) - { fini (); return; } + goto fail; fdCount = fdArray->count; } @@ -1092,36 +1126,36 @@ struct cff1 encoding = &Null (Encoding); if (is_CID ()) { - if (unlikely (charset == &Null (Charset))) { fini (); return; } + if (unlikely (charset == &Null (Charset))) goto fail; } else { if (!is_predef_encoding ()) { encoding = &StructAtOffsetOrNull (cff, topDict.EncodingOffset); - if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; } + if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) goto fail; } } stringIndex = &StructAtOffset (topDictIndex, topDictIndex->get_size ()); if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc)) - { fini (); return; } + goto fail; globalSubrs = &StructAtOffset (stringIndex, stringIndex->get_size ()); if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc)) - { fini (); return; } + goto fail; charStrings = &StructAtOffsetOrNull (cff, topDict.charStringsOffset); if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc))) - { fini (); return; } + goto fail; num_glyphs = charStrings->count; if (num_glyphs != sc.get_num_glyphs ()) - { fini (); return; } + goto fail; if (unlikely (!privateDicts.resize (fdCount))) - { fini (); return; } + goto fail; for (unsigned int i = 0; i < fdCount; i++) privateDicts[i].init (); @@ -1131,27 +1165,27 @@ struct cff1 for (unsigned int i = 0; i < fdCount; i++) { hb_ubytes_t fontDictStr = (*fdArray)[i]; - if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!fontDictStr.sanitize (&sc))) goto fail; cff1_font_dict_values_t *font; cff1_top_dict_interp_env_t env (fontDictStr); cff1_font_dict_interpreter_t font_interp (env); font = fontDicts.push (); - if (unlikely (fontDicts.in_error ())) { fini (); return; } + if (unlikely (fontDicts.in_error ())) goto fail; font->init (); - if (unlikely (!font_interp.interpret (*font))) { fini (); return; } + if (unlikely (!font_interp.interpret (*font))) goto fail; PRIVDICTVAL *priv = &privateDicts[i]; const hb_ubytes_t privDictStr = StructAtOffset (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!privDictStr.sanitize (&sc))) goto fail; num_interp_env_t env2 (privDictStr); dict_interpreter_t priv_interp (env2); priv->init (); - if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } + if (unlikely (!priv_interp.interpret (*priv))) goto fail; priv->localSubrs = &StructAtOffsetOrNull (&privDictStr, priv->subrsOffset); if (priv->localSubrs != &Null (CFF1Subrs) && unlikely (!priv->localSubrs->sanitize (&sc))) - { fini (); return; } + goto fail; } } else /* non-CID */ @@ -1160,20 +1194,25 @@ struct cff1 PRIVDICTVAL *priv = &privateDicts[0]; const hb_ubytes_t privDictStr = StructAtOffset (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } + if (unlikely (!privDictStr.sanitize (&sc))) goto fail; num_interp_env_t env (privDictStr); dict_interpreter_t priv_interp (env); priv->init (); - if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } + if (unlikely (!priv_interp.interpret (*priv))) goto fail; priv->localSubrs = &StructAtOffsetOrNull (&privDictStr, priv->subrsOffset); if (priv->localSubrs != &Null (CFF1Subrs) && unlikely (!priv->localSubrs->sanitize (&sc))) - { fini (); return; } + goto fail; } - } - void fini () + return; + + fail: + _fini (); + } + ~accelerator_templ_t () { _fini (); } + void _fini () { sc.end_processing (); topDict.fini (); @@ -1183,6 +1222,8 @@ struct cff1 blob = nullptr; } + hb_blob_t *get_blob () const { return blob; } + bool is_valid () const { return blob; } bool is_CID () const { return topDict.is_CID (); } @@ -1203,13 +1244,14 @@ struct cff1 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; } - hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const + hb_codepoint_t glyph_to_code (hb_codepoint_t glyph, + code_pair_t *glyph_to_sid_cache = nullptr) const { if (encoding != &Null (Encoding)) return encoding->get_code (glyph); else { - hb_codepoint_t sid = glyph_to_sid (glyph); + hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache); if (sid == 0) return 0; hb_codepoint_t code = 0; switch (topDict.EncodingOffset) @@ -1227,12 +1269,14 @@ struct cff1 } } - hb_map_t *create_glyph_to_sid_map () const + glyph_to_sid_map_t *create_glyph_to_sid_map () const { if (charset != &Null (Charset)) { - hb_map_t *mapping = hb_map_create (); - mapping->set (0, 0); + auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t)); + if (unlikely (!mapping)) return nullptr; + mapping = new (mapping) glyph_to_sid_map_t (); + mapping->push (code_pair_t {0, 1}); charset->collect_glyph_to_sid_map (mapping, num_glyphs); return mapping; } @@ -1240,10 +1284,11 @@ struct cff1 return nullptr; } - hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const + hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph, + code_pair_t *cache = nullptr) const { if (charset != &Null (Charset)) - return charset->get_sid (glyph, num_glyphs); + return charset->get_sid (glyph, num_glyphs, cache); else { hb_codepoint_t sid = 0; @@ -1312,19 +1357,17 @@ struct cff1 hb_vector_t privateDicts; unsigned int num_glyphs = 0; + unsigned int num_charset_entries = 0; }; struct accelerator_t : accelerator_templ_t { - accelerator_t (hb_face_t *face) + accelerator_t (hb_face_t *face) : SUPER (face) { - SUPER::init (face); - glyph_names.set_relaxed (nullptr); if (!is_valid ()) return; if (is_CID ()) return; - } ~accelerator_t () { @@ -1334,8 +1377,6 @@ struct cff1 names->fini (); hb_free (names); } - - SUPER::fini (); } bool get_glyph_name (hb_codepoint_t glyph, @@ -1386,9 +1427,10 @@ struct cff1 /* TODO */ /* fill glyph names */ + code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) { - hb_codepoint_t sid = glyph_to_sid (gid); + hb_codepoint_t sid = glyph_to_sid (gid, &glyph_to_sid_cache); gname_t gname; gname.sid = sid; if (sid < cff1_std_strings_length) @@ -1426,7 +1468,6 @@ struct cff1 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const; - HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; private: @@ -1453,9 +1494,24 @@ struct cff1 typedef accelerator_templ_t SUPER; }; - struct accelerator_subset_t : accelerator_templ_t {}; + struct accelerator_subset_t : accelerator_templ_t + { + accelerator_subset_t (hb_face_t *face) : SUPER (face) {} + ~accelerator_subset_t () + { + if (cff_accelerator) + cff_subset_accelerator_t::destroy (cff_accelerator); + } - bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); } + HB_INTERNAL bool subset (hb_subset_context_t *c) const; + HB_INTERNAL bool serialize (hb_serialize_context_t *c, + struct cff1_subset_plan &plan) const; + HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; + + mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr; + + typedef accelerator_templ_t SUPER; + }; protected: HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid); @@ -1479,6 +1535,10 @@ struct cff1_accelerator_t : cff1::accelerator_t { cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {} }; +struct cff1_subset_accelerator_t : cff1::accelerator_subset_t { + cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {} +}; + } /* namespace OT */ #endif /* HB_OT_CFF1_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh index b9a8819a..af24bb99 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff2-table.hh @@ -28,7 +28,7 @@ #define HB_OT_CFF2_TABLE_HH #include "hb-ot-cff-common.hh" -#include "hb-subset-cff2.hh" +#include "hb-subset-cff-common.hh" #include "hb-draw.hh" #include "hb-paint.hh" @@ -38,10 +38,9 @@ namespace CFF { * CFF2 -- Compact Font Format (CFF) Version 2 * https://docs.microsoft.com/en-us/typography/opentype/spec/cff2 */ -#define HB_OT_TAG_cff2 HB_TAG('C','F','F','2') +#define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2') typedef CFFIndex CFF2Index; -template struct CFF2IndexOf : CFFIndexOf {}; typedef CFF2Index CFF2CharStrings; typedef Subrs CFF2Subrs; @@ -379,7 +378,7 @@ using namespace CFF; struct cff2 { - static constexpr hb_tag_t tableTag = HB_OT_TAG_cff2; + static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF2; bool sanitize (hb_sanitize_context_t *c) const { @@ -391,8 +390,12 @@ struct cff2 template struct accelerator_templ_t { + static constexpr hb_tag_t tableTag = cff2::tableTag; + accelerator_templ_t (hb_face_t *face) { + if (!face) return; + topDict.init (); fontDicts.init (); privateDicts.init (); @@ -464,7 +467,6 @@ struct cff2 goto fail; } - return; fail: @@ -481,11 +483,13 @@ struct cff2 blob = nullptr; } - hb_map_t *create_glyph_to_sid_map () const + hb_vector_t *create_glyph_to_sid_map () const { return nullptr; } + hb_blob_t *get_blob () const { return blob; } + bool is_valid () const { return blob; } protected: @@ -518,9 +522,24 @@ struct cff2 HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; }; - typedef accelerator_templ_t accelerator_subset_t; + struct accelerator_subset_t : accelerator_templ_t + { + accelerator_subset_t (hb_face_t *face) : SUPER (face) {} + ~accelerator_subset_t () + { + if (cff_accelerator) + cff_subset_accelerator_t::destroy (cff_accelerator); + } - bool subset (hb_subset_context_t *c) const { return hb_subset_cff2 (c); } + HB_INTERNAL bool subset (hb_subset_context_t *c) const; + HB_INTERNAL bool serialize (hb_serialize_context_t *c, + struct cff2_subset_plan &plan, + hb_array_t normalized_coords) const; + + mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr; + + typedef accelerator_templ_t SUPER; + }; public: FixedVersion version; /* Version of CFF2 table. set to 0x0200u */ @@ -535,6 +554,10 @@ struct cff2_accelerator_t : cff2::accelerator_t { cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_t (face) {} }; +struct cff2_subset_accelerator_t : cff2::accelerator_subset_t { + cff2_subset_accelerator_t (hb_face_t *face) : cff2::accelerator_subset_t (face) {} +}; + } /* namespace OT */ #endif /* HB_OT_CFF2_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh index cf5ccd53..30401b19 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh @@ -277,10 +277,10 @@ struct CmapSubtableFormat4 } } writer(c); - writer.end_code_ = c->allocate_size (HBUINT16::static_size * segcount); - c->allocate_size (2); // padding - writer.start_code_ = c->allocate_size (HBUINT16::static_size * segcount); - writer.id_delta_ = c->allocate_size (HBINT16::static_size * segcount); + writer.end_code_ = c->allocate_size (HBUINT16::static_size * segcount, false); + (void) c->allocate_size (2); // padding + writer.start_code_ = c->allocate_size (HBUINT16::static_size * segcount, false); + writer.id_delta_ = c->allocate_size (HBINT16::static_size * segcount, false); if (unlikely (!writer.end_code_ || !writer.start_code_ || !writer.id_delta_)) return false; @@ -325,7 +325,7 @@ struct CmapSubtableFormat4 { auto format4_iter = + it - | hb_filter ([&] (const hb_pair_t _) + | hb_filter ([&] (const hb_codepoint_pair_t _) { return _.first <= 0xFFFF; }) ; @@ -335,7 +335,7 @@ struct CmapSubtableFormat4 if (unlikely (!c->extend_min (this))) return; this->format = 4; - hb_vector_t> cp_to_gid { + hb_vector_t cp_to_gid { format4_iter }; @@ -757,8 +757,7 @@ struct CmapSubtableLongSegmented hb_codepoint_t gid = this->groups[i].glyphID; if (!gid) { - /* Intention is: if (hb_is_same (T, CmapSubtableFormat13)) continue; */ - if (! T::group_get_glyph (this->groups[i], end)) continue; + if (T::formatNumber == 13) continue; start++; gid++; } @@ -766,11 +765,13 @@ struct CmapSubtableLongSegmented if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs)) end = start + (hb_codepoint_t) num_glyphs - gid; + mapping->alloc (mapping->get_population () + end - start + 1); + for (unsigned cp = start; cp <= end; cp++) { unicodes->add (cp); mapping->set (cp, gid); - gid++; + gid += T::increment; } } } @@ -794,6 +795,9 @@ struct CmapSubtableLongSegmented struct CmapSubtableFormat12 : CmapSubtableLongSegmented { + static constexpr int increment = 1; + static constexpr int formatNumber = 12; + static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group, hb_codepoint_t u) { return likely (group.startCharCode <= group.endCharCode) ? @@ -866,6 +870,9 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented struct CmapSubtableFormat13 : CmapSubtableLongSegmented { + static constexpr int increment = 0; + static constexpr int formatNumber = 13; + static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group, hb_codepoint_t u HB_UNUSED) { return group.glyphID; } @@ -917,8 +924,7 @@ struct DefaultUVS : SortedArray32Of DefaultUVS* copy (hb_serialize_context_t *c, const hb_set_t *unicodes) const { - DefaultUVS *out = c->start_embed (); - if (unlikely (!out)) return nullptr; + auto *out = c->start_embed (); auto snap = c->snapshot (); HBUINT32 len; @@ -931,8 +937,7 @@ struct DefaultUVS : SortedArray32Of hb_codepoint_t start = HB_SET_VALUE_INVALID; hb_codepoint_t end = HB_SET_VALUE_INVALID; - for (hb_codepoint_t u = HB_SET_VALUE_INVALID; - unicodes->next (&u);) + for (auto u : *unicodes) { if (!as_array ().bsearch (u)) continue; @@ -1067,9 +1072,7 @@ struct NonDefaultUVS : SortedArray32Of const hb_set_t *glyphs_requested, const hb_map_t *glyph_map) const { - NonDefaultUVS *out = c->start_embed (); - if (unlikely (!out)) return nullptr; - + auto *out = c->start_embed (); auto it = + as_array () | hb_filter ([&] (const UVSMapping& _) @@ -1767,7 +1770,6 @@ struct cmap TRACE_SUBSET (this); cmap *cmap_prime = c->serializer->start_embed (); - if (unlikely (!c->serializer->check_success (cmap_prime))) return_trace (false); auto encodingrec_iter = + hb_iter (encodingRecord) @@ -1798,7 +1800,7 @@ struct cmap auto it = + c->plan->unicode_to_new_gid_list.iter () - | hb_filter ([&] (const hb_pair_t _) + | hb_filter ([&] (const hb_codepoint_pair_t _) { return (_.second != HB_MAP_VALUE_INVALID); }) ; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc index 06f7092a..b3677c6a 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc @@ -38,8 +38,8 @@ #include "hb-ot-cmap-table.hh" #include "hb-ot-glyf-table.hh" -#include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" +#include "hb-ot-cff1-table.hh" #include "hb-ot-hmtx-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise. @@ -64,13 +64,17 @@ using hb_ot_font_cmap_cache_t = hb_cache_t<21, 16, 8, true>; using hb_ot_font_advance_cache_t = hb_cache_t<24, 16, 8, true>; +#ifndef HB_NO_OT_FONT_CMAP_CACHE static hb_user_data_key_t hb_ot_font_cmap_cache_user_data_key; +#endif struct hb_ot_font_t { const hb_ot_face_t *ot_face; +#ifndef HB_NO_OT_FONT_CMAP_CACHE hb_ot_font_cmap_cache_t *cmap_cache; +#endif /* h_advance caching */ mutable hb_atomic_int_t cached_coords_serial; @@ -86,6 +90,7 @@ _hb_ot_font_create (hb_font_t *font) ot_font->ot_face = &font->face->table; +#ifndef HB_NO_OT_FONT_CMAP_CACHE // retry: auto *cmap_cache = (hb_ot_font_cmap_cache_t *) hb_face_get_user_data (font->face, &hb_ot_font_cmap_cache_user_data_key); @@ -93,7 +98,7 @@ _hb_ot_font_create (hb_font_t *font) { cmap_cache = (hb_ot_font_cmap_cache_t *) hb_malloc (sizeof (hb_ot_font_cmap_cache_t)); if (unlikely (!cmap_cache)) goto out; - cmap_cache->init (); + new (cmap_cache) hb_ot_font_cmap_cache_t (); if (unlikely (!hb_face_set_user_data (font->face, &hb_ot_font_cmap_cache_user_data_key, cmap_cache, @@ -112,6 +117,7 @@ _hb_ot_font_create (hb_font_t *font) } out: ot_font->cmap_cache = cmap_cache; +#endif return ot_font; } @@ -136,7 +142,11 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; - return ot_face->cmap->get_nominal_glyph (unicode, glyph, ot_font->cmap_cache); + hb_ot_font_cmap_cache_t *cmap_cache = nullptr; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cmap_cache = ot_font->cmap_cache; +#endif + return ot_face->cmap->get_nominal_glyph (unicode, glyph, cmap_cache); } static unsigned int @@ -151,10 +161,14 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; + hb_ot_font_cmap_cache_t *cmap_cache = nullptr; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cmap_cache = ot_font->cmap_cache; +#endif return ot_face->cmap->get_nominal_glyphs (count, first_unicode, unicode_stride, first_glyph, glyph_stride, - ot_font->cmap_cache); + cmap_cache); } static hb_bool_t @@ -167,9 +181,13 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; const hb_ot_face_t *ot_face = ot_font->ot_face; + hb_ot_font_cmap_cache_t *cmap_cache = nullptr; +#ifndef HB_NO_OT_FONT_CMAP_CACHE + cmap_cache = ot_font->cmap_cache; +#endif return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph, - ot_font->cmap_cache); + cmap_cache); } static void @@ -188,7 +206,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, hb_position_t *orig_first_advance = first_advance; -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) const OT::HVAR &HVAR = *hmtx.var_table; const OT::VariationStore &varStore = &HVAR + HVAR.varStore; OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr; @@ -212,8 +230,8 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, use_cache = false; goto out; } + new (cache) hb_ot_font_advance_cache_t; - cache->init (); if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache))) { hb_free (cache); @@ -237,7 +255,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, { /* Use cache. */ if (ot_font->cached_coords_serial.get_acquire () != (int) font->serial_coords) { - ot_font->advance_cache->init (); + ot_font->advance_cache->clear (); ot_font->cached_coords_serial.set_release (font->serial_coords); } @@ -258,7 +276,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, } } -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) OT::VariationStore::destroy_cache (varStore_cache); #endif @@ -293,7 +311,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, if (vmtx.has_data ()) { -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) const OT::VVAR &VVAR = *vmtx.var_table; const OT::VariationStore &varStore = &VVAR + VVAR.varStore; OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr; @@ -308,7 +326,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); } -#ifndef HB_NO_VAR +#if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE) OT::VariationStore::destroy_cache (varStore_cache); #endif } @@ -418,8 +436,8 @@ hb_ot_get_glyph_extents (hb_font_t *font, #endif if (ot_face->glyf->get_extents (font, glyph, extents)) return true; #ifndef HB_NO_OT_FONT_CFF - if (ot_face->cff1->get_extents (font, glyph, extents)) return true; if (ot_face->cff2->get_extents (font, glyph, extents)) return true; + if (ot_face->cff1->get_extents (font, glyph, extents)) return true; #endif return false; @@ -507,8 +525,8 @@ hb_ot_draw_glyph (hb_font_t *font, embolden ? &outline : draw_data, font->slant_xy); if (!font->face->table.glyf->get_path (font, glyph, draw_session)) #ifndef HB_NO_CFF - if (!font->face->table.cff1->get_path (font, glyph, draw_session)) if (!font->face->table.cff2->get_path (font, glyph, draw_session)) + if (!font->face->table.cff1->get_path (font, glyph, draw_session)) #endif {} } @@ -547,8 +565,8 @@ hb_ot_paint_glyph (hb_font_t *font, #endif if (font->face->table.glyf->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; #ifndef HB_NO_CFF - if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; + if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return; #endif } #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh index 3bfd7550..cbcf6f5f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hdmx-table.hh @@ -46,21 +46,23 @@ struct DeviceRecord template - bool serialize (hb_serialize_context_t *c, unsigned pixelSize, Iterator it) + bool serialize (hb_serialize_context_t *c, + unsigned pixelSize, + Iterator it, + const hb_vector_t new_to_old_gid_list, + unsigned num_glyphs) { TRACE_SERIALIZE (this); - unsigned length = it.len (); - - if (unlikely (!c->extend (this, length))) return_trace (false); + if (unlikely (!c->extend (this, num_glyphs))) return_trace (false); this->pixelSize = pixelSize; this->maxWidth = + it | hb_reduce (hb_max, 0u); - + it - | hb_sink (widthsZ.as_array (length)); + for (auto &_ : new_to_old_gid_list) + widthsZ[_.first] = *it++; return_trace (true); } @@ -89,7 +91,11 @@ struct hdmx template - bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it) + bool serialize (hb_serialize_context_t *c, + unsigned version, + Iterator it, + const hb_vector_t &new_to_old_gid_list, + unsigned num_glyphs) { TRACE_SERIALIZE (this); @@ -97,10 +103,10 @@ struct hdmx this->version = version; this->numRecords = it.len (); - this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0); + this->sizeDeviceRecord = DeviceRecord::get_size (num_glyphs); for (const hb_item_type& _ : +it) - c->start_embed ()->serialize (c, _.first, _.second); + c->start_embed ()->serialize (c, _.first, _.second, new_to_old_gid_list, num_glyphs); return_trace (c->successful ()); } @@ -110,31 +116,30 @@ struct hdmx { TRACE_SUBSET (this); - hdmx *hdmx_prime = c->serializer->start_embed (); - if (unlikely (!hdmx_prime)) return_trace (false); + auto *hdmx_prime = c->serializer->start_embed (); + unsigned num_input_glyphs = get_num_glyphs (); auto it = + hb_range ((unsigned) numRecords) - | hb_map ([c, this] (unsigned _) + | hb_map ([c, num_input_glyphs, this] (unsigned _) { const DeviceRecord *device_record = &StructAtOffset (&firstDeviceRecord, _ * sizeDeviceRecord); auto row = - + hb_range (c->plan->num_output_glyphs ()) - | hb_map (c->plan->reverse_glyph_map) - | hb_map ([this, c, device_record] (hb_codepoint_t _) + + hb_iter (c->plan->new_to_old_gid_list) + | hb_map ([num_input_glyphs, device_record] (hb_codepoint_pair_t _) { - if (c->plan->is_empty_glyph (_)) - return Null (HBUINT8); - return device_record->widthsZ.as_array (get_num_glyphs ()) [_]; + return device_record->widthsZ.as_array (num_input_glyphs) [_.second]; }) ; return hb_pair ((unsigned) device_record->pixelSize, +row); }) ; - hdmx_prime->serialize (c->serializer, version, it); + hdmx_prime->serialize (c->serializer, version, it, + c->plan->new_to_old_gid_list, + c->plan->num_output_glyphs ()); return_trace (true); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh index 835a1a58..89640b43 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh @@ -83,7 +83,7 @@ struct hmtxvmtx bool subset_update_header (hb_subset_context_t *c, unsigned int num_hmetrics, const hb_hashmap_t> *mtx_map, - const hb_map_t *bounds_map) const + const hb_vector_t &bounds_vec) const { hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table (c->plan->source, H::tableTag); hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob); @@ -114,6 +114,7 @@ struct hmtxvmtx HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET, caretOffset); } + bool empty = true; int min_lsb = 0x7FFF; int min_rsb = 0x7FFF; int max_extent = -0x7FFF; @@ -125,9 +126,10 @@ struct hmtxvmtx int lsb = _.second.second; max_adv = hb_max (max_adv, adv); - if (bounds_map->has (gid)) + if (bounds_vec[gid] != 0xFFFFFFFF) { - unsigned bound_width = bounds_map->get (gid); + empty = false; + unsigned bound_width = bounds_vec[gid]; int rsb = adv - lsb - bound_width; int extent = lsb + bound_width; min_lsb = hb_min (min_lsb, lsb); @@ -137,7 +139,7 @@ struct hmtxvmtx } table->advanceMax = max_adv; - if (!bounds_map->is_empty ()) + if (!empty) { table->minLeadingBearing = min_lsb; table->minTrailingBearing = min_rsb; @@ -156,32 +158,32 @@ struct hmtxvmtx hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, Iterator it, - unsigned num_long_metrics) + const hb_vector_t new_to_old_gid_list, + unsigned num_long_metrics, + unsigned total_num_metrics) { - unsigned idx = 0; - for (auto _ : it) + LongMetric* long_metrics = c->allocate_size (num_long_metrics * LongMetric::static_size); + FWORD* short_metrics = c->allocate_size ((total_num_metrics - num_long_metrics) * FWORD::static_size); + if (!long_metrics || !short_metrics) return; + + short_metrics -= num_long_metrics; + + for (auto _ : new_to_old_gid_list) { - if (idx < num_long_metrics) + hb_codepoint_t gid = _.first; + auto mtx = *it++; + + if (gid < num_long_metrics) { - LongMetric lm; - lm.advance = _.first; - lm.sb = _.second; - if (unlikely (!c->embed (&lm))) return; - } - else if (idx < 0x10000u) - { - FWORD *sb = c->allocate_size (FWORD::static_size); - if (unlikely (!sb)) return; - *sb = _.second; + LongMetric& lm = long_metrics[gid]; + lm.advance = mtx.first; + lm.sb = mtx.second; } + // TODO(beyond-64k): This assumes that maxp.numGlyphs is 0xFFFF. + else if (gid < 0x10000u) + short_metrics[gid] = mtx.second; else - { - // TODO: This does not do tail optimization. - UFWORD *adv = c->allocate_size (UFWORD::static_size); - if (unlikely (!adv)) return; - *adv = _.first; - } - idx++; + ((UFWORD*) short_metrics)[gid] = mtx.first; } } @@ -189,8 +191,7 @@ struct hmtxvmtx { TRACE_SUBSET (this); - T *table_prime = c->serializer->start_embed (); - if (unlikely (!table_prime)) return_trace (false); + auto *table_prime = c->serializer->start_embed (); accelerator_t _mtx (c->plan->source); unsigned num_long_metrics; @@ -199,6 +200,8 @@ struct hmtxvmtx /* Determine num_long_metrics to encode. */ auto& plan = c->plan; + // TODO Don't consider retaingid holes here. + num_long_metrics = hb_min (plan->num_output_glyphs (), 0xFFFFu); unsigned int last_advance = get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 1, _mtx); while (num_long_metrics > 1 && @@ -209,31 +212,36 @@ struct hmtxvmtx } auto it = - + hb_range (c->plan->num_output_glyphs ()) - | hb_map ([c, &_mtx, mtx_map] (unsigned _) + + hb_iter (c->plan->new_to_old_gid_list) + | hb_map ([c, &_mtx, mtx_map] (hb_codepoint_pair_t _) { - if (!mtx_map->has (_)) + hb_codepoint_t new_gid = _.first; + hb_codepoint_t old_gid = _.second; + + hb_pair_t *v = nullptr; + if (!mtx_map->has (new_gid, &v)) { - hb_codepoint_t old_gid; - if (!c->plan->old_gid_for_new_gid (_, &old_gid)) - return hb_pair (0u, 0); int lsb = 0; if (!_mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb)) (void) _glyf_get_leading_bearing_without_var_unscaled (c->plan->source, old_gid, !T::is_horizontal, &lsb); return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb); } - return mtx_map->get (_); + return *v; }) ; - table_prime->serialize (c->serializer, it, num_long_metrics); + table_prime->serialize (c->serializer, + it, + c->plan->new_to_old_gid_list, + num_long_metrics, + c->plan->num_output_glyphs ()); if (unlikely (c->serializer->in_error ())) return_trace (false); // Amend header num hmetrics if (unlikely (!subset_update_header (c, num_long_metrics, mtx_map, - T::is_horizontal ? &c->plan->bounds_width_map : &c->plan->bounds_height_map))) + T::is_horizontal ? c->plan->bounds_width_vec : c->plan->bounds_height_vec))) return_trace (false); return_trace (true); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh index 8179e5ac..2b7e9e4b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-base-table.hh @@ -170,8 +170,8 @@ struct FeatMinMaxRecord { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - minCoord.sanitize (c, this) && - maxCoord.sanitize (c, this))); + minCoord.sanitize (c, base) && + maxCoord.sanitize (c, base))); } protected: @@ -187,7 +187,6 @@ struct FeatMinMaxRecord * of MinMax table (may be NULL) */ public: DEFINE_SIZE_STATIC (8); - }; struct MinMax @@ -274,7 +273,7 @@ struct BaseLangSysRecord { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - minMax.sanitize (c, this))); + minMax.sanitize (c, base))); } protected: @@ -297,7 +296,8 @@ struct BaseScript const BaseCoord &get_base_coord (int baseline_tag_index) const { return (this+baseValues).get_base_coord (baseline_tag_index); } - bool has_data () const { return baseValues; } + bool has_values () const { return baseValues; } + bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ } bool sanitize (hb_sanitize_context_t *c) const { @@ -383,7 +383,7 @@ struct Axis const BaseCoord **coord) const { const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); - if (!base_script.has_data ()) + if (!base_script.has_values ()) { *coord = nullptr; return false; @@ -410,7 +410,7 @@ struct Axis const BaseCoord **max_coord) const { const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag); - if (!base_script.has_data ()) + if (!base_script.has_min_max ()) { *min_coord = *max_coord = nullptr; return false; @@ -425,8 +425,8 @@ struct Axis { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - (this+baseTagList).sanitize (c) && - (this+baseScriptList).sanitize (c))); + baseTagList.sanitize (c, this) && + baseScriptList.sanitize (c, this))); } protected: @@ -473,14 +473,13 @@ struct BASE return true; } - /* TODO: Expose this separately sometime? */ bool get_min_max (hb_font_t *font, hb_direction_t direction, hb_tag_t script_tag, hb_tag_t language_tag, hb_tag_t feature_tag, hb_position_t *min, - hb_position_t *max) + hb_position_t *max) const { const BaseCoord *min_coord, *max_coord; if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh index 52b7dc25..2cc50980 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh @@ -55,19 +55,22 @@ static bool ClassDef_remap_and_serialize ( hb_serialize_context_t *c, const hb_set_t &klasses, bool use_class_zero, - hb_sorted_vector_t> &glyph_and_klass, /* IN/OUT */ + hb_sorted_vector_t &glyph_and_klass, /* IN/OUT */ hb_map_t *klass_map /*IN/OUT*/); struct hb_collect_feature_substitutes_with_var_context_t { const hb_map_t *axes_index_tag_map; - const hb_hashmap_t *axes_location; + const hb_hashmap_t *axes_location; hb_hashmap_t> *record_cond_idx_map; hb_hashmap_t *feature_substitutes_map; + bool& insert_catch_all_feature_variation_record; // not stored in subset_plan hb_set_t *feature_indices; bool apply; + bool variation_applied; + bool universal; unsigned cur_record_idx; hb_hashmap_t, unsigned> *conditionset_map; }; @@ -189,7 +192,7 @@ struct hb_collect_variation_indices_context_t : hb_set_t *layout_variation_indices; hb_hashmap_t> *varidx_delta_map; - hb_font_t *font; + hb_vector_t *normalized_coords; const VariationStore *var_store; const hb_set_t *glyph_set; const hb_map_t *gpos_lookups; @@ -197,14 +200,14 @@ struct hb_collect_variation_indices_context_t : hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_, hb_hashmap_t> *varidx_delta_map_, - hb_font_t *font_, + hb_vector_t *normalized_coords_, const VariationStore *var_store_, const hb_set_t *glyph_set_, const hb_map_t *gpos_lookups_, float *store_cache_) : layout_variation_indices (layout_variation_indices_), varidx_delta_map (varidx_delta_map_), - font (font_), + normalized_coords (normalized_coords_), var_store (var_store_), glyph_set (glyph_set_), gpos_lookups (gpos_lookups_), @@ -807,7 +810,7 @@ struct Feature { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); out->featureParams.serialize_subset (c, featureParams, this, tag); @@ -981,7 +984,7 @@ struct RecordListOfFeature : RecordListOf { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + hb_enumerate (*this) | hb_filter (l->feature_index_map, hb_first) @@ -1078,7 +1081,7 @@ struct LangSys { TRACE_SUBSET (this); auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); const uint32_t *v; out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu; @@ -1188,7 +1191,7 @@ struct Script return false; auto *out = c->serializer->start_embed (*this); - if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); bool defaultLang = false; if (has_default_lang_sys ()) @@ -1247,7 +1250,7 @@ struct RecordListOfScript : RecordListOf