SDL2_ttf-2.22.0/0000755000076500000240000000000014553227661012171 5ustar valvestaffSDL2_ttf-2.22.0/configure.ac0000644000076500000240000002565314553227631014467 0ustar valvestaffdnl Process this file with autoconf to produce a configure script. dnl Set various version strings - taken gratefully from the GTk sources # See docs/release_checklist.md m4_define([MAJOR_VERSION_MACRO], [2]) m4_define([MINOR_VERSION_MACRO], [22]) m4_define([MICRO_VERSION_MACRO], [0]) AC_INIT([SDL2_ttf], [MAJOR_VERSION_MACRO.MINOR_VERSION_MACRO.MICRO_VERSION_MACRO], [https://github.com/libsdl-org/SDL_ttf/issues], [SDL2_ttf]) AC_CONFIG_MACRO_DIR([acinclude]) AC_CONFIG_SRCDIR([SDL_ttf.c]) AC_SUBST([MAJOR_VERSION], MAJOR_VERSION_MACRO) AC_SUBST([MINOR_VERSION], MINOR_VERSION_MACRO) AC_SUBST([MICRO_VERSION], MICRO_VERSION_MACRO) BINARY_AGE=`expr $MINOR_VERSION \* 100 + $MICRO_VERSION` AS_CASE(["$MINOR_VERSION"], [*@<:@02468@:>@], dnl Stable branch, 2.20.1 -> libSDL2_ttf-2.0.so.0.2000.1 [INTERFACE_AGE="$MICRO_VERSION"], [*], dnl Development branch, 2.19.1 -> libSDL2_ttf-2.0.so.0.1901.0 [INTERFACE_AGE=0]) dnl libtool versioning LT_INIT([win32-dll]) # For historical reasons, the library name redundantly includes the major # version twice: libSDL2_ttf-2.0.so.0. # TODO: in SDL 3, stop using -release, which will simplify it to # libSDL3_ttf.so.0 LT_RELEASE=2.0 # Increment this if there is an incompatible change - but if that happens, # we should rename the library from SDL2 to SDL3, at which point this would # reset to 0 anyway. LT_MAJOR=0 LT_AGE=`expr $BINARY_AGE - $INTERFACE_AGE` LT_CURRENT=`expr $LT_MAJOR + $LT_AGE` LT_REVISION=$INTERFACE_AGE LT_EXTRA="" m4_pattern_allow([^LT_MAJOR$]) AC_SUBST(LT_RELEASE) AC_SUBST(LT_CURRENT) AC_SUBST(LT_REVISION) AC_SUBST(LT_AGE) AC_SUBST(LT_EXTRA) dnl For use in static assertions AC_DEFINE_UNQUOTED([SDL_BUILD_MAJOR_VERSION], $MAJOR_VERSION, [ ]) AC_DEFINE_UNQUOTED([SDL_BUILD_MINOR_VERSION], $MINOR_VERSION, [ ]) AC_DEFINE_UNQUOTED([SDL_BUILD_MICRO_VERSION], $MICRO_VERSION, [ ]) dnl Detect the canonical build and host environments AC_CANONICAL_HOST dnl Setup for automake AM_INIT_AUTOMAKE([1.16 foreign subdir-objects tar-ustar]) dnl Check for tools AC_PROG_CC AC_PROG_CXX AC_CHECK_TOOL(RC,[windres],[:]) AC_SYS_LARGEFILE AC_PROG_INSTALL AC_PROG_MAKE_SET case "$host" in *-*-beos*) ac_default_prefix=/boot/develop/tools/gnupro ;; *-*-cygwin* | *-*-mingw*) if test "$build" != "$host"; then # cross-compiling # Default cross-compile location ac_default_prefix=/usr/local/cross-tools/$host else # Look for the location of the tools and install there if test "$BUILD_PREFIX" != ""; then ac_default_prefix=$BUILD_PREFIX fi fi use_version_rc=true LT_EXTRA="-Wl,version.o" ;; *-*-os2*) # disable static builds on os/2 enable_static=no # -DBUILD_SDL is needed for DECLSPEC CFLAGS="$CFLAGS -DBUILD_SDL" # OS/2 does not support a DLL name longer than 8 characters. LT_EXTRA="-os2dllname SDL2ttf" ;; esac AM_CONDITIONAL(USE_VERSION_RC, test x$use_version_rc = xtrue) SUMMARY="\nSDL2_ttf Configure Summary:\n" dnl Check for SDL SDL_VERSION=2.0.10 AC_SUBST(SDL_VERSION) AM_PATH_SDL2($SDL_VERSION, :, AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]) ) CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" CheckNoUndef() { AC_MSG_CHECKING(for linker option --no-undefined) have_no_undefined=no case "${host_os}" in dnl Skip this on platforms where it is just simply busted. openbsd*) ;; darwin*) have_no_undefined="-Wl,-undefined,error" LDFLAGS="$LDFLAGS -Wl,-undefined,error" ;; *) save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,--no-undefined" AC_LINK_IFELSE([AC_LANG_PROGRAM], [have_no_undefined=yes],[LDFLAGS="$save_LDFLAGS"]) ;; esac AC_MSG_RESULT($have_no_undefined) } dnl See if GCC's -Wall is supported. CheckWarnAll() { AC_MSG_CHECKING(for GCC -Wall option) have_gcc_Wall=no save_CFLAGS="$CFLAGS" CFLAGS="$save_CFLAGS -Wall" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int x = 0;])], [have_gcc_Wall=yes]) AC_MSG_RESULT($have_gcc_Wall) CFLAGS="$save_CFLAGS" if test x$have_gcc_Wall = xyes; then CFLAGS="$CFLAGS -Wall" CXXFLAGS="$CXXFLAGS -Wall" dnl Haiku headers use multicharacter constants all over the place. Ignore these warnings when using -Wall. AC_MSG_CHECKING(for necessary GCC -Wno-multichar option) need_gcc_Wno_multichar=no case "$host" in *-*-haiku*) need_gcc_Wno_multichar=yes ;; esac AC_MSG_RESULT($need_gcc_Wno_multichar) if test x$need_gcc_Wno_multichar = xyes; then CFLAGS="$CFLAGS -Wno-multichar" CXXFLAGS="$CXXFLAGS -Wno-multichar" fi fi } dnl See if GCC's -fvisibility=hidden is supported (gcc4 and later, usually). CheckVisibilityHidden() { AC_MSG_CHECKING(for GCC -fvisibility=hidden option) have_gcc_fvisibility=no case "$host" in *-*-cygwin* | *-*-mingw* | *-*-os2*) AC_MSG_RESULT([ignored for $host_os]) return ;; esac visibility_CFLAGS="-fvisibility=hidden" save_CFLAGS="$CFLAGS" CFLAGS="$save_CFLAGS $visibility_CFLAGS -Werror" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if !defined(__GNUC__) || __GNUC__ < 4 #error SDL only uses visibility attributes in GCC 4 or newer #endif ]],[])], [have_gcc_fvisibility=yes],[]) AC_MSG_RESULT($have_gcc_fvisibility) CFLAGS="$save_CFLAGS" if test x$have_gcc_fvisibility = xyes; then CFLAGS="$CFLAGS $visibility_CFLAGS" CXXFLAGS="$CXXFLAGS $visibility_CFLAGS" fi } dnl check for GCC warning options CheckWarnAll dnl check for GCC visibility attributes CheckVisibilityHidden AC_SUBST([SDL2TTF_VENDORED]) AC_SUBST([TTF_USE_HARFBUZZ]) SDL2TTF_VENDORED=0 TTF_LIBS= TTF_CPPFLAGS= PC_REQUIRES= PC_LIBS= dnl Check for the FreeType 2 library AC_ARG_ENABLE(freetype-builtin, [AS_HELP_STRING([--enable-freetype-builtin], [Use included version of FreeType [default=yes]])], [], enable_freetype_builtin=yes) if test x$enable_freetype_builtin = xyes; then SUMMARY="${SUMMARY}Using included FreeType : YES\n" else PKG_CHECK_MODULES([FT2], [freetype2 >= 7.0.1], [ PC_REQUIRES="freetype2 $PC_REQUIRES" ], [dnl AC_CHECK_FT2(,,[AC_MSG_ERROR([dnl *** Unable to find FreeType2 library (https://www.freetype.org)])] ) PC_LIBS="$FT2_LIBS $PC_LIBS" ]) TTF_CFLAGS="$TTF_CFLAGS $FT2_CFLAGS" TTF_LIBS="$TTF_LIBS $FT2_LIBS" SUMMARY="${SUMMARY}Using included FreeType : NO\n" fi AM_CONDITIONAL(USE_BUILTIN_FREETYPE, test x$enable_freetype_builtin = xyes) dnl Check for the HarfBuzz library AC_ARG_ENABLE(harfbuzz, [AS_HELP_STRING([--enable-harfbuzz], [Enable HarfBuzz [default=yes]])], [], enable_harfbuzz=yes) AC_ARG_ENABLE(harfbuzz-builtin, [AS_HELP_STRING([--enable-harfbuzz-builtin], [Use included version of HarfBuzz [default=yes]])], [], enable_harfbuzz_builtin=yes) TTF_USE_HARFBUZZ=0 if test x$enable_harfbuzz = xyes; then AC_DEFINE(TTF_USE_HARFBUZZ, 1, []) TTF_USE_HARFBUZZ=1 SUMMARY="${SUMMARY}Using HarfBuzz : YES\n" if test x$enable_harfbuzz_builtin = xyes; then SDL2TTF_VENDORED=1 SUMMARY="${SUMMARY}Using included HarfBuzz : YES\n" AX_CXX_COMPILE_STDCXX(11) AC_CHECK_ALIGNOF([struct{char;}]) case "$host" in *-*-mingw*) hb_os_win32=yes CXXFLAGS="$CXXFLAGS -static-libgcc -static-libstdc++" CFLAGS="$CFLAGS -static-libgcc" # for uniscribe support: TTF_LIBS="$TTF_LIBS -lusp10 -lgdi32 -lrpcrt4" PC_LIBS="$PC_LIBS -lusp10 -lgdi32 -lrpcrt4" ;; *) # compiler might optimize sinf+cosf into sincosf TTF_LIBS="$TTF_LIBS -lm" ;; esac case "$host" in arm-*-*) if test "x$ac_cv_alignof_struct_char__" != x1; then CXXFLAGS="$CXXFLAGS -mstructure-size-boundary=8" fi ;; esac # silence a lot of harfbuzz warnings: CXXFLAGS="$CXXFLAGS -Wno-unused-result" # prevent linking to libstdc++ : CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions -fno-threadsafe-statics" else SUMMARY="${SUMMARY}Using included HarfBuzz : NO\n" PKG_CHECK_MODULES([HB], [harfbuzz >= 2.3.1], harfbuzz=yes, harfbuzz=no) if test x$harfbuzz = xyes; then save_CFLAGS="$CFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $HB_CFLAGS" LIBS="$LIBS $HB_LIBS" AC_MSG_CHECKING(for freetype support in harfbuzz) harbuzz_has_freetype=no AC_LINK_IFELSE([AC_LANG_PROGRAM([],[[ void* hb_ft_font_create(void*, void*); return !hb_ft_font_create((void*)0, (void*)0);]]) ],[harbuzz_has_freetype=yes]) CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" AC_MSG_RESULT($harbuzz_has_freetype) if test x$harbuzz_has_freetype = xno; then harfbuzz=no AC_MSG_ERROR([dnl *** HarfBuzz library was built without FreeType support.)]) fi fi if test x$harfbuzz = xyes; then AC_DEFINE(TTF_USE_HARFBUZZ, 1, []) PC_REQUIRES="harfbuzz $PC_REQUIRES" TTF_CFLAGS="$TTF_CFLAGS $HB_CFLAGS" TTF_LIBS="$TTF_LIBS $HB_LIBS" SUMMARY="${SUMMARY}Using harfbuzz : YES\n" else AC_MSG_ERROR([dnl *** Unable to find HarfBuzz library (https://harfbuzz.github.io)]) fi fi else AC_DEFINE(TTF_USE_HARFBUZZ, 0, []) SUMMARY="${SUMMARY}Using HarfBuzz : NO\n" enable_harfbuzz_builtin=no fi AM_CONDITIONAL(OS_WIN32, test x$hb_os_win32 = xyes) AM_CONDITIONAL(USE_BUILTIN_HARFBUZZ, test x$enable_harfbuzz_builtin = xyes) dnl check for LD --no-undefined option CheckNoUndef dnl Check for OpenGL case "$host" in *-*-cygwin* | *-*-mingw*) MATHLIB="" SYS_GL_LIBS="-lopengl32" ;; *-*-beos*) MATHLIB="" SYS_GL_LIBS="-lGL" ;; *-*-darwin*) MATHLIB="" SYS_GL_LIBS="-Wl,-framework,OpenGL" ;; *-*-aix*) if test x$ac_cv_c_compiler_gnu = xyes; then CFLAGS="-mthreads" fi SYS_GL_LIBS="" ;; *) MATHLIB="-lm" AC_PATH_X AC_PATH_XTRA if test x$have_x = xyes; then CFLAGS="$CFLAGS $X_CFLAGS" SYS_GL_LIBS="$X_LIBS -lGL" else SYS_GL_LIBS="-lGL" fi ;; esac AC_MSG_CHECKING(for OpenGL support) have_opengl=no save_LIBS="$LIBS" LIBS="$LIBS $SYS_GL_LIBS" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include "SDL_opengl.h" ]], [[ glOrtho(-2.0, 2.0, -2.0, 2.0, -20.0, 20.0); ]])], [have_opengl=yes],[]) AC_MSG_RESULT($have_opengl) LIBS="$save_LIBS" if test x$have_opengl = xyes; then CFLAGS="$CFLAGS -DHAVE_OPENGL" GL_LIBS="$SYS_GL_LIBS" else GL_LIBS="" fi AC_SUBST([GL_LIBS]) AC_SUBST([MATHLIB]) AC_SUBST([TTF_CFLAGS]) AC_SUBST([TTF_LIBS]) AC_SUBST([PC_REQUIRES]) AC_SUBST([PC_LIBS]) dnl Calculate the location of the prefix, relative to the cmake folder pkg_cmakedir='$libdir/cmake/SDL2_ttf' AX_COMPUTE_RELATIVE_PATHS([pkg_cmakedir:prefix:cmake_prefix_relpath]) AC_SUBST([cmake_prefix_relpath]) # Finally create all the generated files AC_CONFIG_FILES([ Makefile sdl2_ttf-config.cmake sdl2_ttf-config-version.cmake SDL2_ttf.spec SDL2_ttf.pc ]) AC_CONFIG_COMMANDS([summary], [printf "$SUMMARY"], [SUMMARY="$SUMMARY"]) AC_OUTPUT SDL2_ttf-2.22.0/Android.mk0000644000076500000240000000251414551277723014106 0ustar valvestaff# Save the local path SDL_TTF_LOCAL_PATH := $(call my-dir) # Enable this if you want to use HarfBuzz SUPPORT_HARFBUZZ ?= true HARFBUZZ_LIBRARY_PATH := external/harfbuzz FREETYPE_LIBRARY_PATH := external/freetype # Build freetype library ifneq ($(FREETYPE_LIBRARY_PATH),) include $(SDL_TTF_LOCAL_PATH)/$(FREETYPE_LIBRARY_PATH)/Android.mk endif # Build the library ifeq ($(SUPPORT_HARFBUZZ),true) include $(SDL_TTF_LOCAL_PATH)/$(HARFBUZZ_LIBRARY_PATH)/Android.mk endif # Restore local path LOCAL_PATH := $(SDL_TTF_LOCAL_PATH) include $(CLEAR_VARS) LOCAL_MODULE := SDL2_ttf LOCAL_C_INCLUDES := $(LOCAL_PATH) LOCAL_SRC_FILES := SDL_ttf.c.neon LOCAL_CFLAGS += -O2 ifneq ($(FREETYPE_LIBRARY_PATH),) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FREETYPE_LIBRARY_PATH)/include LOCAL_STATIC_LIBRARIES += freetype endif ifeq ($(SUPPORT_HARFBUZZ),true) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(HARFBUZZ_LIBRARY_PATH)/src LOCAL_CFLAGS += -DTTF_USE_HARFBUZZ LOCAL_STATIC_LIBRARIES += harfbuzz endif LOCAL_SHARED_LIBRARIES := SDL2 LOCAL_EXPORT_C_INCLUDES += $(LOCAL_C_INCLUDES) include $(BUILD_SHARED_LIBRARY) ########################### # # SDL2_ttf static library # ########################### LOCAL_MODULE := SDL2_ttf_static LOCAL_MODULE_FILENAME := libSDL2_ttf LOCAL_LDLIBS := LOCAL_EXPORT_LDLIBS := include $(BUILD_STATIC_LIBRARY) SDL2_ttf-2.22.0/SDL2_ttf.spec.in0000644000076500000240000000261214551277723015036 0ustar valvestaff%define name @PACKAGE@ %define version @VERSION@ %define release 1 Summary: Simple DirectMedia Layer - Sample TrueType Font Library Name: %{name} Version: %{version} Release: %{release} Source0: %{name}-%{version}.tar.gz License: LGPL Group: System Environment/Libraries BuildRoot: /var/tmp/%{name}-buildroot Prefix: %{_prefix} Packager: Hakan Tandogan #BuildRequires: SDL2-devel #BuildRequires: freetype-devel %description This library allows you to use TrueType fonts to render text in SDL applications. %package devel Summary: Libraries, includes and more to develop SDL applications. Group: Development/Libraries Requires: %{name} Requires: SDL2-devel %description devel This library allows you to use TrueType fonts to render text in SDL applications. %prep rm -rf ${RPM_BUILD_ROOT} %setup %build CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} make %install rm -rf $RPM_BUILD_ROOT make install prefix=$RPM_BUILD_ROOT/%{prefix} %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc README.txt CHANGES.txt LICENSE.txt %{prefix}/lib/lib*.so.* %files devel %defattr(-,root,root) %{prefix}/lib/lib*.a %{prefix}/lib/lib*.la %{prefix}/lib/lib*.so %{prefix}/include/*/ %{prefix}/lib/pkgconfig/*.pc %changelog * Wed Jan 19 2000 Sam Lantinga - converted to get package information from configure * Sun Jan 16 2000 Hakan Tandogan - initial spec file SDL2_ttf-2.22.0/CMakeLists.txt0000644000076500000240000003741214553227631014735 0ustar valvestaffcmake_minimum_required(VERSION 3.16) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") # See docs/release_checklist.md set(MAJOR_VERSION 2) set(MINOR_VERSION 22) set(MICRO_VERSION 0) set(SDL_REQUIRED_VERSION 2.0.10) include(PrivateSdlFunctions) sdl_calculate_derived_version_variables() if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) message(FATAL_ERROR "Prevented in-tree built. Please create a build directory outside of the SDL_ttf source code and call cmake from there") endif() project(SDL2_ttf LANGUAGES C VERSION "${FULL_VERSION}" ) message(STATUS "Configuring ${PROJECT_NAME} ${PROJECT_VERSION}") if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set(SDL2TTF_ROOTPROJECT ON) else() set(SDL2TTF_ROOTPROJECT OFF) endif() # Set defaults preventing destination file conflicts set(SDL2TTF_DEBUG_POSTFIX "d" CACHE STRING "Name suffix for debug builds") mark_as_advanced(SDL2TTF_DEBUG_POSTFIX) # Assume MSVC projects don't have a package manager and need vendored dependencies (by default). # Most other platforms have some kind of package manager. # FIXME: consider a package manager such as conan/vcpkg instead of vendoring if(ANDROID OR MSVC) set(vendored_default TRUE) else() set(vendored_default FALSE) endif() set(sdl2ttf_install_enableable ON) if ((TARGET SDL2 OR TARGET SDL2-static) AND SDL2_DISABLE_INSTALL) # Cannot install SDL2_mixer when SDL2 is built in same built, and is not installed. set(sdl2ttf_install_enableable OFF) endif() include(CMakeDependentOption) include(CMakePackageConfigHelpers) include(GNUInstallDirs) include(CheckSymbolExists) option(CMAKE_POSITION_INDEPENDENT_CODE "Build static libraries with -fPIC" ON) option(BUILD_SHARED_LIBS "Build the library as a shared library" ON) option(SDL2TTF_SAMPLES "Build the SDL2_ttf sample program(s)" ${SDL2TTF_ROOTPROJECT}) cmake_dependent_option(SDL2TTF_INSTALL "Enable SDL2_ttf install target" ${SDL2TTF_ROOTPROJECT} "${sdl2ttf_install_enableable}" OFF) option(SDL2TTF_VENDORED "Use vendored third-party libraries" ${vendored_default}) # For style consistency, create a SDL2TTF_FREETYPE CMake variable. This variable is NOT configurable. set(SDL2TTF_FREETYPE ON) set(SDL2TTF_FREETYPE_VENDORED "${SDL2TTF_VENDORED}") option(SDL2TTF_HARFBUZZ "Use harfbuzz to improve text shaping" OFF) set(SDL2TTF_HARFBUZZ_VENDORED "${SDL2TTF_VENDORED}") # Save BUILD_SHARED_LIBS variable set(SDL2TTF_BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS}") if(SDL2TTF_BUILD_SHARED_LIBS) set(sdl2_ttf_export_name SDL2_ttf) set(sdl2_ttf_install_name_infix shared) set(sdl2_target_name SDL2::SDL2) else() set(sdl2_ttf_export_name SDL2_ttf-static) set(sdl2_ttf_install_name_infix static) set(sdl2_target_name SDL2::SDL2-static) endif() sdl_find_sdl2(${sdl2_target_name} ${SDL_REQUIRED_VERSION}) # Enable large file support on 32-bit glibc, so that the vendored libraries # can access files with large inode numbers check_symbol_exists("__GLIBC__" "stdlib.h" LIBC_IS_GLIBC) if (LIBC_IS_GLIBC AND CMAKE_SIZEOF_VOID_P EQUAL 4) add_compile_definitions(_FILE_OFFSET_BITS=64) endif() add_library(SDL2_ttf SDL_ttf.c SDL_ttf.h ) add_library(SDL2_ttf::${sdl2_ttf_export_name} ALIAS SDL2_ttf) target_include_directories(SDL2_ttf PUBLIC "$" "$" ) target_compile_definitions(SDL2_ttf PRIVATE BUILD_SDL SDL_BUILD_MAJOR_VERSION=${MAJOR_VERSION} SDL_BUILD_MINOR_VERSION=${MINOR_VERSION} SDL_BUILD_MICRO_VERSION=${MICRO_VERSION} ) target_link_libraries(SDL2_ttf PRIVATE $) if(WIN32 AND SDL2TTF_BUILD_SHARED_LIBS) target_sources(SDL2_ttf PRIVATE version.rc ) endif() set_target_properties(SDL2_ttf PROPERTIES DEFINE_SYMBOL DLL_EXPORT EXPORT_NAME ${sdl2_ttf_export_name} C_VISIBILITY_PRESET "hidden" ) if(NOT ANDROID) set_target_properties(SDL2_ttf PROPERTIES DEBUG_POSTFIX "${SDL2TTF_DEBUG_POSTFIX}" ) if(APPLE) # the SOVERSION property corresponds to the compatibility version and VERSION corresponds to the current version # https://cmake.org/cmake/help/latest/prop_tgt/SOVERSION.html#mach-o-versions set_target_properties(SDL2_ttf PROPERTIES SOVERSION "${DYLIB_COMPATIBILITY_VERSION}" VERSION "${DYLIB_CURRENT_VERSION}" ) else() set_target_properties(SDL2_ttf PROPERTIES SOVERSION "${LT_MAJOR}" VERSION "${LT_VERSION}" ) endif() endif() if(SDL2TTF_BUILD_SHARED_LIBS AND (APPLE OR (UNIX AND NOT ANDROID))) add_custom_command(TARGET SDL2_ttf POST_BUILD COMMAND "${CMAKE_COMMAND}" -E create_symlink "$" "libSDL2_ttf$<$:${SDL2TTF_DEBUG_POSTFIX}>$" # BYPRODUCTS "libSDL2_ttf$<$:${SDL2TTF_DEBUG_POSTFIX}>$" # Needs CMake 3.20 WORKING_DIRECTORY "${PROJECT_BINARY_DIR}" ) endif() if(SDL2TTF_BUILD_SHARED_LIBS) if(WIN32 OR OS2) set_target_properties(SDL2_ttf PROPERTIES PREFIX "" ) endif() if(OS2) # OS/2 doesn't support a DLL name longer than 8 characters. set_target_properties(SDL2_ttf PROPERTIES OUTPUT_NAME "SDL2ttf" ) elseif(UNIX AND NOT ANDROID) set_target_properties(SDL2_ttf PROPERTIES OUTPUT_NAME "SDL2_ttf-${LT_RELEASE}" ) endif() endif() if(SDL2TTF_BUILD_SHARED_LIBS) # Use `Compatible Interface Properties` to ensure a shared SDL2_ttf is linked to a shared SDL2 library set_property(TARGET SDL2_ttf PROPERTY INTERFACE_SDL2_SHARED ${SDL2TTF_BUILD_SHARED_LIBS}) set_property(TARGET SDL2_ttf APPEND PROPERTY COMPATIBLE_INTERFACE_BOOL SDL2_SHARED) endif() if(SDL2TTF_BUILD_SHARED_LIBS) sdl_target_link_options_no_undefined(SDL2_ttf) endif() if(SDL2TTF_BUILD_SHARED_LIBS) # Make sure static library dependencies are built with -fPIC when building a shared SDL2_ttf set(CMAKE_POSITION_INDEPENDENT_CODE ON) endif() set(INSTALL_EXTRA_TARGETS) set(PC_LIBS) set(PC_REQUIRES) # Build freetype and harfbuzz as a static library set(BUILD_SHARED_LIBS OFF) if(SDL2TTF_HARFBUZZ) if(SDL2TTF_HARFBUZZ_VENDORED) message(STATUS "${PROJECT_NAME}: Using vendored harfbuzz library") # HB_BUILD_UTILS variable is used by harfbuzz set(HB_BUILD_UTILS OFF CACHE BOOL "harfbuzz build utils" FORCE) # SKIP_INSTALL_LIBRARIES variable is used by harfbuzz set(SKIP_INSTALL_LIBRARIES ON CACHE BOOL "harfbuzz install option" FORCE) # HB_HAVE_FREETYPE variable is used by harfbuzz set(HB_HAVE_FREETYPE ${SDL2TTF_FREETYPE} CACHE BOOL "harfbuzz freetype helpers" FORCE) if(NOT EXISTS "${PROJECT_SOURCE_DIR}/external/harfbuzz/CMakeLists.txt") message(FATAL_ERROR "No harfbuzz sources found. Install a harfbuzz development package or run the download script in the external folder.") endif() add_subdirectory(external/harfbuzz EXCLUDE_FROM_ALL) # harfbuzz is a c++ project, enable c++ here to ensure linking to the c++ standard library enable_language(CXX) if(NOT SDL2TTF_BUILD_SHARED_LIBS) list(APPEND INSTALL_EXTRA_TARGETS harfbuzz) list(APPEND PC_LIBS -l$) endif() if(NOT TARGET harfbuzz::harfbuzz) add_library(harfbuzz::harfbuzz ALIAS harfbuzz) endif() else() message(STATUS "${PROJECT_NAME}: Using system harfbuzz library") find_package(harfbuzz REQUIRED) list(APPEND PC_REQUIRES harfbuzz) endif() target_compile_definitions(SDL2_ttf PRIVATE TTF_USE_HARFBUZZ=1) target_link_libraries(SDL2_ttf PRIVATE harfbuzz::harfbuzz) endif() if(SDL2TTF_FREETYPE) if(SDL2TTF_FREETYPE_VENDORED) message(STATUS "${PROJECT_NAME}: Using vendored freetype library") # FT_DISABLE_ZLIB variable is used by freetype set(FT_DISABLE_ZLIB ON CACHE BOOL "freetype zlib option") # FT_DISABLE_BZIP2 variable is used by freetype set(FT_DISABLE_BZIP2 ON CACHE BOOL "freetype bzip2 option") # FT_DISABLE_PNG variable is used by freetype set(FT_DISABLE_PNG ON CACHE BOOL "freetype png option") # FT_DISABLE_BROTLI variable is used by freetype set(FT_DISABLE_BROTLI ON CACHE BOOL "freetype option") if(SDL2TTF_HARFBUZZ) # FT_DISABLE_HARFBUZZ variable is used by freetype set(FT_DISABLE_HARFBUZZ OFF CACHE BOOL "freetype harfbuzz option" FORCE) # FT_REQUIRE_HARFBUZZ variable is used by freetype set(FT_REQUIRE_HARFBUZZ ON CACHE BOOL "freetype harfbuzz option" FORCE) else() # FT_DISABLE_HARFBUZZ variable is used by freetype set(FT_DISABLE_HARFBUZZ ON CACHE BOOL "freetype harfbuzz option" FORCE) # FT_REQUIRE_HARFBUZZ variable is used by freetype set(FT_REQUIRE_HARFBUZZ OFF CACHE BOOL "freetype harfbuzz option" FORCE) endif() if(NOT EXISTS "${PROJECT_SOURCE_DIR}/external/freetype/CMakeLists.txt") message(FATAL_ERROR "No freetype sources found. Install a freetype development package or run the download script in the external folder.") endif() add_subdirectory(external/freetype EXCLUDE_FROM_ALL) if(NOT TARGET Freetype::Freetype) add_library(Freetype::Freetype ALIAS freetype) endif() if(NOT SDL2TTF_BUILD_SHARED_LIBS) list(APPEND INSTALL_EXTRA_TARGETS freetype) list(APPEND PC_LIBS -l$) endif() else() message(STATUS "${PROJECT_NAME}: Using system freetype library") find_package(Freetype REQUIRED) list(APPEND PC_REQUIRES freetype2) endif() target_link_libraries(SDL2_ttf PRIVATE Freetype::Freetype) endif() # Restore BUILD_SHARED_LIBS variable set(BUILD_SHARED_LIBS ${SDL2TTF_BUILD_SHARED_LIBS}) if (APPLE) # TODO: Use DYLIB_COMPATIBILITY_VERSION, DYLIB_CURRENT_VERSION here elseif (UNIX AND NOT APPLE AND NOT ANDROID) set_target_properties(SDL2_ttf PROPERTIES SOVERSION "${LT_MAJOR}" VERSION "${LT_VERSION}" ) endif() if (BUILD_SHARED_LIBS) if (WIN32 OR OS2) set_target_properties(SDL2_ttf PROPERTIES PREFIX "" ) endif() if (OS2) # OS/2 doesn't support a DLL name longer than 8 characters. set_target_properties(SDL2_ttf PROPERTIES OUTPUT_NAME "SDL2ttf" ) elseif (UNIX AND NOT APPLE AND NOT ANDROID) set_target_properties(SDL2_ttf PROPERTIES OUTPUT_NAME "SDL2_ttf-${LT_RELEASE}" ) endif() endif() # Restore BUILD_SHARED_LIBS variable set(BUILD_SHARED_LIBS "${SDL2TTF_BUILD_SHARED_LIBS}") if(SDL2TTF_INSTALL) install( TARGETS SDL2_ttf EXPORT SDL2_ttfTargets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT library RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT library ) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/SDL_ttf.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/SDL2" COMPONENT devel ) if(INSTALL_EXTRA_TARGETS) install(TARGETS ${INSTALL_EXTRA_TARGETS} EXPORT SDL2_ttfTargets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT library RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT library PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" COMPONENT devel ) endif() if(WIN32 AND NOT MINGW) set(SDLTTF_INSTALL_CMAKEDIR_DEFAULT "cmake") else() set(SDLTTF_INSTALL_CMAKEDIR_DEFAULT "${CMAKE_INSTALL_LIBDIR}/cmake/SDL2_ttf") endif() set(SDLTTF_INSTALL_CMAKEDIR "${SDLTTF_INSTALL_CMAKEDIR_DEFAULT}" CACHE STRING "Location where to install SDL2_ttfConfig.cmake") configure_package_config_file(SDL2_ttfConfig.cmake.in SDL2_ttfConfig.cmake INSTALL_DESTINATION "${SDLTTF_INSTALL_CMAKEDIR}" ) write_basic_package_version_file("${PROJECT_BINARY_DIR}/SDL2_ttfConfigVersion.cmake" VERSION ${FULL_VERSION} COMPATIBILITY AnyNewerVersion ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttfConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttfConfigVersion.cmake" DESTINATION ${SDLTTF_INSTALL_CMAKEDIR} COMPONENT devel ) install(EXPORT SDL2_ttfTargets FILE SDL2_ttf-${sdl2_ttf_install_name_infix}-targets.cmake NAMESPACE SDL2_ttf:: DESTINATION "${SDLTTF_INSTALL_CMAKEDIR}" COMPONENT devel ) set(prefix "${CMAKE_INSTALL_PREFIX}") set(exec_prefix "\${prefix}") set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") set(PACKAGE "${PROJECT_NAME}") set(VERSION ${FULL_VERSION}) set(SDL_VERSION ${SDL_REQUIRED_VERSION}) string(JOIN " " PC_REQUIRES ${PC_REQUIRES}) string(JOIN " " PC_LIBS ${PC_LIBS}) configure_file("${PROJECT_SOURCE_DIR}/SDL2_ttf.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttf.pc.intermediate" @ONLY) file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttf-$.pc" INPUT "${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttf.pc.intermediate") set(PC_DESTDIR) if(CMAKE_SYSTEM_NAME MATCHES FreeBSD) # FreeBSD uses ${PREFIX}/libdata/pkgconfig set(PC_DESTDIR "libdata/pkgconfig") else() set(PC_DESTDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig") endif() # Always install SDL2_ttf.pc file: libraries might be different between config modes install(CODE " # FIXME: use file(COPY_FILE) if CMake 3.21+ execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy_if_different \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttf-$.pc\" \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttf.pc\") file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${PC_DESTDIR}\" TYPE FILE FILES \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_ttf.pc\")" COMPONENT devel) if(SDL2TTF_BUILD_SHARED_LIBS AND (APPLE OR (UNIX AND NOT ANDROID))) install(FILES "${PROJECT_BINARY_DIR}/libSDL2_ttf$<$:${SDL2TTF_DEBUG_POSTFIX}>$" DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel ) endif() install(FILES "LICENSE.txt" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${PROJECT_NAME}" COMPONENT library ) endif() if(SDL2TTF_SAMPLES) add_executable(glfont glfont.c) add_executable(showfont showfont.c) find_package(SDL2main QUIET) set(OpenGL_GL_PREFERENCE GLVND) find_package(OpenGL) if(TARGET OpenGL::OpenGL) target_compile_definitions(glfont PRIVATE HAVE_OPENGL) target_link_libraries(glfont PRIVATE OpenGL::OpenGL) elseif(TARGET OpenGL::GL) target_compile_definitions(glfont PRIVATE HAVE_OPENGL) target_link_libraries(glfont PRIVATE OpenGL::GL) endif() foreach(prog glfont showfont) if(MINGW) target_link_libraries(${prog} PRIVATE mingw32) target_link_options(${prog} PRIVATE -mwindows) endif() target_link_libraries(${prog} PRIVATE SDL2_ttf::${sdl2_ttf_export_name}) if(TARGET SDL2::SDL2main) target_link_libraries(${prog} PRIVATE SDL2::SDL2main) endif() target_link_libraries(${prog} PRIVATE ${sdl2_target_name}) endforeach() endif() add_library(SDL2::ttf INTERFACE IMPORTED GLOBAL) set_target_properties(SDL2::ttf PROPERTIES INTERFACE_LINK_LIBRARIES "SDL2_ttf" ) if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.17") set_target_properties(SDL2::ttf PROPERTIES DEPRECATION "Use SDL2_ttf::SDL2_ttf or SDL2_ttf::SDL2_ttf-static instead" ) endif() SDL2_ttf-2.22.0/cmake/0000755000076500000240000000000014553227661013251 5ustar valvestaffSDL2_ttf-2.22.0/cmake/FindSDL2main.cmake0000644000076500000240000000120014551277723016420 0ustar valvestaff# FIXME: this should be provided by SDL2 include(FindPackageHandleStandardArgs) include("${CMAKE_CURRENT_LIST_DIR}/CommonFindSDL2.cmake") find_library(SDL2_MAIN_LIBRARY NAMES SDL2main HINTS ${SDL2_DIR} ENV SDL2_DIR PATH_SUFFIXES ${_lib_suffixes} ) find_package_handle_standard_args(SDL2main REQUIRED_VARS SDL2_MAIN_LIBRARY ) if(SDL2main_FOUND) if(NOT TARGET SDL2::SDL2main) add_library(SDL2::SDL2main UNKNOWN IMPORTED) set_target_properties(SDL2::SDL2main PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" IMPORTED_LOCATION "${SDL2_MAIN_LIBRARY}" ) endif() endif() SDL2_ttf-2.22.0/cmake/test/0000755000076500000240000000000014553227661014230 5ustar valvestaffSDL2_ttf-2.22.0/cmake/test/CMakeLists.txt0000644000076500000240000000351214551277723016773 0ustar valvestaff# This cmake build script is meant for verifying the various CMake configuration script. cmake_minimum_required(VERSION 3.12) project(sdl_test LANGUAGES C) cmake_policy(SET CMP0074 NEW) # Override CMAKE_FIND_ROOT_PATH_MODE to allow search for SDL2_ttf outside of sysroot set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER) include(FeatureSummary) option(TEST_SHARED "Test linking to shared SDL2_ttf library" ON) add_feature_info("TEST_SHARED" TEST_SHARED "Test linking with shared library") option(TEST_STATIC "Test linking to static SDL2_ttf libary" ON) add_feature_info("TEST_STATIC" TEST_STATIC "Test linking with static library") if(TEST_SHARED) # FIXME: in the distant future, must become REQUIRED find_package(SDL2 CONFIG COMPONENTS SDL2) # FIXME: and the following should be removed if(NOT TARGET SDL2::SDL2) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/..") include(PrivateSdlFunctions) sdl_find_sdl2(SDL2::SDL2 2.0) endif() find_package(SDL2_ttf REQUIRED CONFIG) add_executable(main_shared main.c) target_link_libraries(main_shared PRIVATE SDL2::SDL2 SDL2_ttf::SDL2_ttf) endif() if(TEST_STATIC) # FIXME: in the distant future, must become REQUIRED find_package(SDL2 CONFIG COMPONENTS SDL2-static) # FIXME: and the following should be removed if(NOT TARGET SDL2::SDL2-static) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/..") include(PrivateSdlFunctions) sdl_find_sdl2(SDL2::SDL2-static 2.0) endif() # some static vendored libraries use c++ (enable CXX after `find_package` might show a warning) enable_language(CXX) find_package(SDL2_ttf REQUIRED CONFIG) add_executable(main_static main.c) target_link_libraries(main_static PRIVATE SDL2::SDL2-static SDL2_ttf::SDL2_ttf-static) endif() feature_summary(WHAT ALL) SDL2_ttf-2.22.0/cmake/test/main.c0000644000076500000240000000063214551277723015323 0ustar valvestaff#define SDL_MAIN_HANDLED #include "SDL.h" #include "SDL_ttf.h" #include int main(int argc, char *argv[]) { SDL_SetMainReady(); if (SDL_Init(0) < 0) { fprintf(stderr, "could not initialize sdl2: %s\n", SDL_GetError()); return 1; } if (TTF_Init() == -1) { fprintf(stderr, "TTF_Init: %s\n", TTF_GetError()); } TTF_Quit(); SDL_Quit(); return 0; } SDL2_ttf-2.22.0/cmake/FindPrivateSDL2.cmake0000644000076500000240000000311014551277723017110 0ustar valvestaff# FIXME: this should be provided by SDL2 include(FindPackageHandleStandardArgs) include("${CMAKE_CURRENT_LIST_DIR}/CommonFindSDL2.cmake") find_library(SDL2_LIBRARY NAMES SDL2 HINTS ${SDL2_DIR} ENV SDL2_DIR PATH_SUFFIXES ${_lib_suffixes} ) find_path(SDL2_INCLUDE_DIR NAMES SDL_haptic.h PATH_SUFFIXES SDL2 HINTS ${SDL2_DIR} ENV SDL2_DIR PATH_SUFFIXES ${_inc_suffixes} ) set(SDL2_VERSION) if(SDL2_INCLUDE_DIR) file(READ "${SDL2_INCLUDE_DIR}/SDL_version.h" _sdl_version_h) string(REGEX MATCH "#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)" _sdl2_major_re "${_sdl_version_h}") set(_sdl2_major "${CMAKE_MATCH_1}") string(REGEX MATCH "#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)" _sdl2_minor_re "${_sdl_version_h}") set(_sdl2_minor "${CMAKE_MATCH_1}") string(REGEX MATCH "#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)" _sdl2_patch_re "${_sdl_version_h}") set(_sdl2_patch "${CMAKE_MATCH_1}") if(_sdl2_major_re AND _sdl2_minor_re AND _sdl2_patch_re) set(SDL2_VERSION "${_sdl2_major}.${_sdl2_minor}.${_sdl2_patch}") endif() endif() find_package_handle_standard_args(PrivateSDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR VERSION_VAR SDL2_VERSION ) if(PrivateSDL2_FOUND) if(NOT TARGET PrivateSDL2::PrivateSDL2) add_library(PrivateSDL2::PrivateSDL2 UNKNOWN IMPORTED) set_target_properties(PrivateSDL2::PrivateSDL2 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIR}" IMPORTED_LINK_INTERFACE_LANGUAGES "C" IMPORTED_LOCATION "${SDL2_LIBRARY}" ) endif() endif() SDL2_ttf-2.22.0/cmake/CommonFindSDL2.cmake0000644000076500000240000000121614551277723016733 0ustar valvestaff# Common variables for FindSDL2*.cmake modules set(_inc_suffixes include) set(_lib_suffixes) if(MSVC) if(CMAKE_SIZEOF_VOID_P EQUAL 4) list(APPEND _lib_suffixes "lib/x86") endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8) list(APPEND _lib_suffixes "lib/x64") endif() endif() if(MINGW) if(CMAKE_SIZEOF_VOID_P EQUAL 4) list(APPEND _lib_suffixes "i686-w64-mingw32/lib") list(APPEND _inc_suffixes "i686-w64-mingw32/include") endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8) list(APPEND _lib_suffixes "x86_46-w64-mingw32/lib") list(APPEND _inc_suffixes "x86_46-w64-mingw32/include") endif() endif()SDL2_ttf-2.22.0/cmake/PrivateSdlFunctions.cmake0000644000076500000240000003042714551277723020231 0ustar valvestaff# This file is shared amongst SDL_image/SDL_mixer/SDL_ttf macro(sdl_calculate_derived_version_variables) if(NOT DEFINED MAJOR_VERSION OR NOT DEFINED MINOR_VERSION OR NOT DEFINED MICRO_VERSION) message(FATAL_ERROR "MAJOR_VERSION, MINOR_VERSION and MICRO_VERSION need to be defined") endif() set(FULL_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}") # Calculate a libtool-like version number math(EXPR BINARY_AGE "${MINOR_VERSION} * 100 + ${MICRO_VERSION}") math(EXPR IS_DEVELOPMENT "${MINOR_VERSION} % 2") if(IS_DEVELOPMENT) # Development branch, 2.5.1 -> libSDL2_XXXXX-2.0.so.0.501.0 set(INTERFACE_AGE 0) else() # Stable branch, 2.6.1 -> libSDL2_XXXXX-2.0.so.0.600.1 set(INTERFACE_AGE ${MICRO_VERSION}) endif() # Increment this if there is an incompatible change - but if that happens, # we should rename the library from SDL2 to SDL3, at which point this would # reset to 0 anyway. set(LT_MAJOR "0") math(EXPR LT_AGE "${BINARY_AGE} - ${INTERFACE_AGE}") math(EXPR LT_CURRENT "${LT_MAJOR} + ${LT_AGE}") set(LT_REVISION "${INTERFACE_AGE}") # For historical reasons, the library name redundantly includes the major # version twice: libSDL2_XXXXX-2.0.so.0. # TODO: in SDL 3, set the OUTPUT_NAME to plain SDL3_XXXXX, which will simplify # it to libSDL2_XXXXX.so.0 set(LT_RELEASE "2.0") set(LT_VERSION "${LT_MAJOR}.${LT_AGE}.${LT_REVISION}") # The following should match the versions in the Xcode project file. # Each version is 1 higher than you might expect, for compatibility # with libtool: macOS ABI versioning is 1-based, unlike other platforms # which are normally 0-based. math(EXPR DYLIB_CURRENT_VERSION_MAJOR "${LT_MAJOR} + ${LT_AGE} + 1") math(EXPR DYLIB_CURRENT_VERSION_MINOR "${LT_REVISION}") set(DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION_MAJOR}.${DYLIB_CURRENT_VERSION_MINOR}.0") set(DYLIB_COMPATIBILITY_VERSION "${DYLIB_CURRENT_VERSION_MAJOR}.0.0") endmacro() macro(sdl_find_sdl2 TARGET VERSION) if(NOT TARGET ${TARGET}) # FIXME: can't add REQUIRED since not all SDL2 installs ship SDL2ConfigVersion.cmake (or sdl2-config-version.cmake) find_package(SDL2 ${VERSION} QUIET) endif() if(NOT TARGET ${TARGET}) # FIXME: can't add REQUIRED since not all SDL2 installs ship SDL2Config.cmake (or sdl2-config.cmake) find_package(SDL2 QUIET) if(SDL2_FOUND) message(WARNING "Could not verify SDL2 version. Assuming SDL2 has version of at least ${VERSION}.") endif() endif() # Use Private FindSDL2.cmake module to find SDL2 for installations where no SDL2Config.cmake is available, # or for those installations where no target is generated. if(NOT TARGET ${TARGET}) message(STATUS "Using private SDL2 find module") find_package(PrivateSDL2 ${VERSION} REQUIRED) add_library(${TARGET} INTERFACE IMPORTED) set_target_properties(${TARGET} PROPERTIES INTERFACE_LINK_LIBRARIES "PrivateSDL2::PrivateSDL2" ) endif() endmacro() function(read_absolute_symlink DEST PATH) file(READ_SYMLINK "${PATH}" p) if(NOT IS_ABSOLUTE "${p}") get_filename_component(pdir "${PATH}" DIRECTORY) set(p "${pdir}/${p}") endif() get_filename_component(p "${p}" ABSOLUTE) set("${DEST}" "${p}" PARENT_SCOPE) endfunction() function(win32_implib_identify_dll DEST IMPLIB) cmake_parse_arguments(ARGS "NOTFATAL" "" "" ${ARGN}) if(CMAKE_DLLTOOL) execute_process( COMMAND "${CMAKE_DLLTOOL}" --identify "${IMPLIB}" RESULT_VARIABLE retcode OUTPUT_VARIABLE stdout ERROR_VARIABLE stderr) if(NOT retcode EQUAL 0) if(NOT ARGS_NOTFATAL) message(FATAL_ERROR "${CMAKE_DLLTOOL} failed.") else() set("${DEST}" "${DEST}-NOTFOUND" PARENT_SCOPE) return() endif() endif() string(STRIP "${stdout}" result) set(${DEST} "${result}" PARENT_SCOPE) elseif(MSVC) get_filename_component(CMAKE_C_COMPILER_DIRECTORY "${CMAKE_C_COMPILER}" DIRECTORY CACHE) find_program(CMAKE_DUMPBIN NAMES dumpbin PATHS "${CMAKE_C_COMPILER_DIRECTORY}") if(CMAKE_DUMPBIN) execute_process( COMMAND "${CMAKE_DUMPBIN}" "-headers" "${IMPLIB}" RESULT_VARIABLE retcode OUTPUT_VARIABLE stdout ERROR_VARIABLE stderr) if(NOT retcode EQUAL 0) if(NOT ARGS_NOTFATAL) message(FATAL_ERROR "dumpbin failed.") else() set(${DEST} "${DEST}-NOTFOUND" PARENT_SCOPE) return() endif() endif() string(REGEX MATCH "DLL name[ ]+:[ ]+([^\n]+)\n" match "${stdout}") if(NOT match) if(NOT ARGS_NOTFATAL) message(FATAL_ERROR "dumpbin did not find any associated dll for ${IMPLIB}.") else() set(${DEST} "${DEST}-NOTFOUND" PARENT_SCOPE) return() endif() endif() set(result "${CMAKE_MATCH_1}") set(${DEST} "${result}" PARENT_SCOPE) else() message(FATAL_ERROR "Cannot find dumpbin, please set CMAKE_DUMPBIN cmake variable") endif() else() if(NOT ARGS_NOTFATAL) message(FATAL_ERROR "Don't know how to identify dll from import library. Set CMAKE_DLLTOOL (for mingw) or CMAKE_DUMPBIN (for MSVC)") else() set(${DEST} "${DEST}-NOTFOUND") endif() endif() endfunction() function(get_actual_target) set(dst "${ARGV0}") set(target "${${dst}}") get_target_property(alias "${target}" ALIASED_TARGET) while(alias) set(target "${alias}") get_target_property(alias "${target}" ALIASED_TARGET) endwhile() set("${dst}" "${target}" PARENT_SCOPE) endfunction() function(target_get_dynamic_library DEST TARGET) set(result) get_actual_target(TARGET) if(WIN32) # Use the target dll of the import library set(props_to_check IMPORTED_IMPLIB) if(CMAKE_BUILD_TYPE) list(APPEND props_to_check IMPORTED_IMPLIB_${CMAKE_BUILD_TYPE}) endif() list(APPEND props_to_check IMPORTED_LOCATION) if(CMAKE_BUILD_TYPE) list(APPEND props_to_check IMPORTED_LOCATION_${CMAKE_BUILD_TYPE}) endif() foreach (config_type ${CMAKE_CONFIGURATION_TYPES} RELEASE DEBUG RELWITHDEBINFO MINSIZEREL) list(APPEND props_to_check IMPORTED_IMPLIB_${config_type}) list(APPEND props_to_check IMPORTED_LOCATION_${config_type}) endforeach() foreach(prop_to_check ${props_to_check}) if(NOT result) get_target_property(propvalue "${TARGET}" ${prop_to_check}) if(propvalue AND EXISTS "${propvalue}") win32_implib_identify_dll(result "${propvalue}" NOTFATAL) endif() endif() endforeach() else() # 1. find the target library a file might be symbolic linking to # 2. find all other files in the same folder that symolic link to it # 3. sort all these files, and select the 1st item on Linux, and last on Macos set(location_properties IMPORTED_LOCATION) if(CMAKE_BUILD_TYPE) list(APPEND location_properties IMPORTED_LOCATION_${CMAKE_BUILD_TYPE}) endif() foreach (config_type ${CMAKE_CONFIGURATION_TYPES} RELEASE DEBUG RELWITHDEBINFO MINSIZEREL) list(APPEND location_properties IMPORTED_LOCATION_${config_type}) endforeach() if(APPLE) set(valid_shared_library_regex "\\.[0-9]+\\.dylib$") else() set(valid_shared_library_regex "\\.so\\.([0-9.]+)?[0-9]") endif() foreach(location_property ${location_properties}) if(NOT result) get_target_property(library_path "${TARGET}" ${location_property}) if(EXISTS "${library_path}") get_filename_component(library_path "${library_path}" ABSOLUTE) while (IS_SYMLINK "${library_path}") read_absolute_symlink(library_path "${library_path}") endwhile() get_filename_component(libdir "${library_path}" DIRECTORY) file(GLOB subfiles "${libdir}/*") set(similar_files "${library_path}") foreach(subfile ${subfiles}) if(IS_SYMLINK "${subfile}") read_absolute_symlink(subfile_target "${subfile}") while (IS_SYMLINK "${subfile_target}") read_absolute_symlink(subfile_target "${subfile_target}") endwhile() get_filename_component(subfile_target "${subfile_target}" ABSOLUTE) if(subfile_target STREQUAL library_path AND subfile MATCHES "${valid_shared_library_regex}") list(APPEND similar_files "${subfile}") endif() endif() endforeach() list(SORT similar_files) set(index 0) if(APPLE) list(LENGTH similar_files len) math(EXPR index "${len}-1") endif() list(GET similar_files ${index} item) get_filename_component(result "${item}" NAME) endif() endif() endforeach() endif() if(result) string(TOLOWER "${result}" result_lower) if(WIN32 OR OS2) if(NOT result_lower MATCHES ".*dll") message(FATAL_ERROR "\"${result}\" is not a .dll library") endif() elseif(APPLE) if(NOT result_lower MATCHES ".*dylib.*") message(FATAL_ERROR "\"${result}\" is not a .dylib shared library") endif() else() if(NOT result_lower MATCHES ".*so.*") message(FATAL_ERROR "\"${result}\" is not a .so shared library") endif() endif() else() get_target_property(target_type ${TARGET} TYPE) if(target_type MATCHES "SHARED_LIBRARY|MODULE_LIBRARY") # OK elseif(target_type MATCHES "STATIC_LIBRARY|OBJECT_LIBRARY|INTERFACE_LIBRARY|EXECUTABLE") message(SEND_ERROR "${TARGET} is not a shared library, but has type=${target_type}") else() message(WARNING "Unable to extract dynamic library from target=${TARGET}, type=${target_type}.") endif() # TARGET_SONAME_FILE is not allowed for DLL target platforms. if(WIN32) set(result "$") else() set(result "$") endif() endif() set(${DEST} ${result} PARENT_SCOPE) endfunction() macro(sdl_check_project_in_subfolder relative_subfolder name vendored_option) if(NOT EXISTS "${PROJECT_SOURCE_DIR}/${relative_subfolder}/CMakeLists.txt") message(FATAL_ERROR "No cmake project for ${name} found in ${relative_subfolder}.\n" "Run the download script in the external folder, or re-configure with -D${vendored_option}=OFF to use system packages.") endif() endmacro() macro(sdl_check_linker_flag flag var) # FIXME: Use CheckLinkerFlag module once cmake minimum version >= 3.18 include(CMakePushCheckState) include(CheckCSourceCompiles) cmake_push_check_state(RESET) set(CMAKE_REQUIRED_LINK_OPTIONS "${flag}") check_c_source_compiles("int main() { return 0; }" ${var}) cmake_pop_check_state() endmacro() function(sdl_target_link_options_no_undefined TARGET) if(NOT MSVC) if(CMAKE_C_COMPILER_ID MATCHES "AppleClang") target_link_options(${TARGET} PRIVATE "-Wl,-undefined,error") else() sdl_check_linker_flag("-Wl,--no-undefined" HAVE_WL_NO_UNDEFINED) if(HAVE_WL_NO_UNDEFINED AND NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") AND WIN32)) target_link_options(${TARGET} PRIVATE "-Wl,--no-undefined") endif() endif() endif() endfunction() SDL2_ttf-2.22.0/cmake/Findharfbuzz.cmake0000644000076500000240000000223114551277710016703 0ustar valvestaff# Create our own Findharfbuzz.cmake module because harfbuzz-config.cmake, # distributed along e.g. msys2-mingw64 does not support anything other then APPLE and UNIX. include(FindPackageHandleStandardArgs) find_library(harfbuzz_LIBRARY NAMES harfbuzz ) find_path(harfbuzz_INCLUDE_PATH NAMES hb.h PATH_SUFFIXES harfbuzz ) set(harfbuzz_COMPILE_FLAGS "" CACHE STRING "Extra compile flags of harfbuzz") set(harfbuzz_LINK_LIBRARIES "" CACHE STRING "Extra link libraries of harfbuzz") set(harfbuzz_LINK_FLAGS "" CACHE STRING "Extra link flags of harfbuzz") find_package_handle_standard_args(harfbuzz REQUIRED_VARS harfbuzz_LIBRARY harfbuzz_INCLUDE_PATH ) if (harfbuzz_FOUND) if (NOT TARGET harfbuzz::harfbuzz) add_library(harfbuzz::harfbuzz UNKNOWN IMPORTED) set_target_properties(harfbuzz::harfbuzz PROPERTIES IMPORTED_LOCATION "${harfbuzz_LIBRARY}" INTERFACE_INCLUDE_DIRECTORIES "${harfbuzz_INCLUDE_PATH}" COMPILE_FLAGS "${harfbuzz_COMPILE_FLAGS}" INTERFACE_LINK_LIBRARIES "${harfbuzz_LINK_LIBRARIES}" INTERFACE_LINK_FLAGS "${harfbuzz_LINK_FLAGS}" ) endif() endif() SDL2_ttf-2.22.0/SDL2_ttfConfig.cmake.in0000644000076500000240000000313414551277723016312 0ustar valvestaff# sdl2_ttf cmake project-config input for CMakeLists.txt script include(FeatureSummary) set_package_properties(SDL2_ttf PROPERTIES URL "https://www.libsdl.org/projects/SDL_ttf/" DESCRIPTION "Support for TrueType (.ttf) font files with Simple Directmedia Layer" ) set(SDL2_ttf_FOUND ON) set(SDL2TTF_VENDORED @SDL2TTF_VENDORED@) set(SDL2TTF_HARFBUZZ @SDL2TTF_HARFBUZZ@) set(SDL2TTF_FREETYPE @SDL2TTF_FREETYPE@) set(SDL2TTF_SDL2_REQUIRED_VERSION @SDL_REQUIRED_VERSION@) include(CMakeFindDependencyMacro) if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2_ttf-shared-targets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/SDL2_ttf-shared-targets.cmake") endif() if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2_ttf-static-targets.cmake") if(SDL2TTF_VENDORED) include(CheckLanguage) check_language(CXX) if(NOT CMAKE_CXX_COMPILER AND NOT _sdl2ttf_nowarning) message(WARNING "CXX language not enabled. Linking to SDL2_ttf::SDL2_ttf-static might fail.") endif() endif() include("${CMAKE_CURRENT_LIST_DIR}/SDL2_ttf-static-targets.cmake") endif() if(NOT SDL2TTF_VENDORED) set(_sdl_cmake_module_path "${CMAKE_MODULE_PATH}") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") if(TARGET SDL2_ttf::SDL2_ttf-static) if(SDL2TTF_FREETYPE) find_dependency(Freetype) endif() if(SDL2TTF_HARFBUZZ) list(APPEND harfbuzz_ROOT "${CMAKE_CURRENT_LIST_DIR}") find_dependency(harfbuzz) endif() endif() set(CMAKE_MODULE_PATH "${_sdl_cmake_module_path}") unset(_sdl_cmake_module_path) endif() SDL2_ttf-2.22.0/acinclude/0000755000076500000240000000000014553227661014120 5ustar valvestaffSDL2_ttf-2.22.0/acinclude/pkg.m40000644000076500000240000002400714551277723015150 0ustar valvestaff# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 12 (pkg-config-0.29.2) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.2]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR SDL2_ttf-2.22.0/acinclude/freetype2.m40000644000076500000240000001426714551277723016303 0ustar valvestaff# Configure paths for FreeType2 # Marcelo Magallon 2001-10-26, based on `gtk.m4` by Owen Taylor # # Copyright (C) 2001-2021 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. # # As a special exception to the FreeType project license, this file may be # distributed as part of a program that contains a configuration script # generated by Autoconf, under the same distribution terms as the rest of # that program. # # serial 6 # AC_CHECK_FT2([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) # Test for FreeType 2, and define FT2_CFLAGS and FT2_LIBS. # MINIMUM-VERSION is what libtool reports; the default is '7.0.1' (this is # FreeType 2.0.4). # # To make this code work with older autoconf versions, `AS_HELP_STRING` is # not quoted. # AC_DEFUN([AC_CHECK_FT2], [# Get the cflags and libraries from the freetype-config script # AC_ARG_WITH([ft-prefix], AS_HELP_STRING([--with-ft-prefix=PREFIX], [Prefix where FreeType is installed (optional)]), [ft_config_prefix="$withval"], [ft_config_prefix=""]) AC_ARG_WITH([ft-exec-prefix], AS_HELP_STRING([--with-ft-exec-prefix=PREFIX], [Exec prefix where FreeType is installed (optional)]), [ft_config_exec_prefix="$withval"], [ft_config_exec_prefix=""]) AC_ARG_ENABLE([freetypetest], AS_HELP_STRING([--disable-freetypetest], [Do not try to compile and run a test FreeType program]), [], [enable_fttest=yes]) if test x$ft_config_exec_prefix != x ; then ft_config_args="$ft_config_args --exec-prefix=$ft_config_exec_prefix" if test x${FT2_CONFIG+set} != xset ; then FT2_CONFIG=$ft_config_exec_prefix/bin/freetype-config fi fi if test x$ft_config_prefix != x ; then ft_config_args="$ft_config_args --prefix=$ft_config_prefix" if test x${FT2_CONFIG+set} != xset ; then FT2_CONFIG=$ft_config_prefix/bin/freetype-config fi fi if test "x$FT2_CONFIG" = x ; then AC_PATH_TOOL([FT2_CONFIG], [freetype-config], [no]) fi min_ft_version=m4_if([$1], [], [7.0.1], [$1]) AC_MSG_CHECKING([for FreeType -- version >= $min_ft_version]) no_ft="" if test "$FT2_CONFIG" = "no" ; then no_ft=yes else FT2_CFLAGS=`$FT2_CONFIG $ft_config_args --cflags` FT2_LIBS=`$FT2_CONFIG $ft_config_args --libs` ft_config_major_version=`$FT2_CONFIG $ft_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` ft_config_minor_version=`$FT2_CONFIG $ft_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` ft_config_micro_version=`$FT2_CONFIG $ft_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` ft_min_major_version=`echo $min_ft_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` ft_min_minor_version=`echo $min_ft_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` ft_min_micro_version=`echo $min_ft_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test x$enable_fttest = xyes ; then ft_config_is_lt="" if test $ft_config_major_version -lt $ft_min_major_version ; then ft_config_is_lt=yes else if test $ft_config_major_version -eq $ft_min_major_version ; then if test $ft_config_minor_version -lt $ft_min_minor_version ; then ft_config_is_lt=yes else if test $ft_config_minor_version -eq $ft_min_minor_version ; then if test $ft_config_micro_version -lt $ft_min_micro_version ; then ft_config_is_lt=yes fi fi fi fi fi if test x$ft_config_is_lt = xyes ; then no_ft=yes else ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $FT2_CFLAGS" LIBS="$FT2_LIBS $LIBS" # # Sanity checks for the results of freetype-config to some extent. # AC_RUN_IFELSE([ AC_LANG_SOURCE([[ #include #include #include #include int main() { FT_Library library; FT_Error error; error = FT_Init_FreeType(&library); if (error) return 1; else { FT_Done_FreeType(library); return 0; } } ]]) ], [], [no_ft=yes], [echo $ECHO_N "cross compiling; assuming OK... $ECHO_C"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi # test $ft_config_version -lt $ft_min_version fi # test x$enable_fttest = xyes fi # test "$FT2_CONFIG" = "no" if test x$no_ft = x ; then AC_MSG_RESULT([yes]) m4_if([$2], [], [:], [$2]) else AC_MSG_RESULT([no]) if test "$FT2_CONFIG" = "no" ; then AC_MSG_WARN([ The freetype-config script installed by FreeType 2 could not be found. If FreeType 2 was installed in PREFIX, make sure PREFIX/bin is in your path, or set the FT2_CONFIG environment variable to the full path to freetype-config. ]) else if test x$ft_config_is_lt = xyes ; then AC_MSG_WARN([ Your installed version of the FreeType 2 library is too old. If you have different versions of FreeType 2, make sure that correct values for --with-ft-prefix or --with-ft-exec-prefix are used, or set the FT2_CONFIG environment variable to the full path to freetype-config. ]) else AC_MSG_WARN([ The FreeType test program failed to run. If your system uses shared libraries and they are installed outside the normal system library path, make sure the variable LD_LIBRARY_PATH (or whatever is appropriate for your system) is correctly set. ]) fi fi FT2_CFLAGS="" FT2_LIBS="" m4_if([$3], [], [:], [$3]) fi AC_SUBST([FT2_CFLAGS]) AC_SUBST([FT2_LIBS])]) # end of freetype2.m4 SDL2_ttf-2.22.0/acinclude/ax_normalize_path.m40000644000076500000240000001134214551277723020071 0ustar valvestaff# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_normalize_path.html # =========================================================================== # # SYNOPSIS # # AX_NORMALIZE_PATH(VARNAME, [REFERENCE_STRING]) # # DESCRIPTION # # Perform some cleanups on the value of $VARNAME (interpreted as a path): # # - empty paths are changed to '.' # - trailing slashes are removed # - repeated slashes are squeezed except a leading doubled slash '//' # (which might indicate a networked disk on some OS). # # REFERENCE_STRING is used to turn '/' into '\' and vice-versa: if # REFERENCE_STRING contains some backslashes, all slashes and backslashes # are turned into backslashes, otherwise they are all turned into slashes. # # This makes processing of DOS filenames quite easier, because you can # turn a filename to the Unix notation, make your processing, and turn it # back to original notation. # # filename='A:\FOO\\BAR\' # old_filename="$filename" # # Switch to the unix notation # AX_NORMALIZE_PATH([filename], ["/"]) # # now we have $filename = 'A:/FOO/BAR' and we can process it as if # # it was a Unix path. For instance let's say that you want # # to append '/subpath': # filename="$filename/subpath" # # finally switch back to the original notation # AX_NORMALIZE_PATH([filename], ["$old_filename"]) # # now $filename equals to 'A:\FOO\BAR\subpath' # # One good reason to make all path processing with the unix convention is # that backslashes have a special meaning in many cases. For instance # # expr 'A:\FOO' : 'A:\Foo' # # will return 0 because the second argument is a regex in which # backslashes have to be backslashed. In other words, to have the two # strings to match you should write this instead: # # expr 'A:\Foo' : 'A:\\Foo' # # Such behavior makes DOS filenames extremely unpleasant to work with. So # temporary turn your paths to the Unix notation, and revert them to the # original notation after the processing. See the macro # AX_COMPUTE_RELATIVE_PATHS for a concrete example of this. # # REFERENCE_STRING defaults to $VARIABLE, this means that slashes will be # converted to backslashes if $VARIABLE already contains some backslashes # (see $thirddir below). # # firstdir='/usr/local//share' # seconddir='C:\Program Files\\' # thirddir='C:\home/usr/' # AX_NORMALIZE_PATH([firstdir]) # AX_NORMALIZE_PATH([seconddir]) # AX_NORMALIZE_PATH([thirddir]) # # $firstdir = '/usr/local/share' # # $seconddir = 'C:\Program Files' # # $thirddir = 'C:\home\usr' # # LICENSE # # Copyright (c) 2008 Alexandre Duret-Lutz # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 8 AU_ALIAS([ADL_NORMALIZE_PATH], [AX_NORMALIZE_PATH]) AC_DEFUN([AX_NORMALIZE_PATH], [case ":[$]$1:" in # change empty paths to '.' ::) $1='.' ;; # strip trailing slashes :*[[\\/]]:) $1=`echo "[$]$1" | sed 's,[[\\/]]*[$],,'` ;; :*:) ;; esac # squeeze repeated slashes case ifelse($2,,"[$]$1",$2) in # if the path contains any backslashes, turn slashes into backslashes *\\*) $1=`echo "[$]$1" | sed 's,\(.\)[[\\/]][[\\/]]*,\1\\\\,g'` ;; # if the path contains slashes, also turn backslashes into slashes *) $1=`echo "[$]$1" | sed 's,\(.\)[[\\/]][[\\/]]*,\1/,g'` ;; esac]) SDL2_ttf-2.22.0/acinclude/ax_recursive_eval.m40000644000076500000240000000455014551277723020076 0ustar valvestaff# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_recursive_eval.html # =========================================================================== # # SYNOPSIS # # AX_RECURSIVE_EVAL(VALUE, RESULT) # # DESCRIPTION # # Interpolate the VALUE in loop until it doesn't change, and set the # result to $RESULT. WARNING: It's easy to get an infinite loop with some # unsane input. # # LICENSE # # Copyright (c) 2008 Alexandre Duret-Lutz # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 1 AC_DEFUN([AX_RECURSIVE_EVAL], [_lcl_receval="$1" $2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" _lcl_receval_old='' while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do _lcl_receval_old="[$]_lcl_receval" eval _lcl_receval="\"[$]_lcl_receval\"" done echo "[$]_lcl_receval")`]) SDL2_ttf-2.22.0/acinclude/ax_cxx_compile_stdcxx.m40000644000076500000240000005041514551277723020770 0ustar valvestaff# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and # CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for # the respective C++ standard version. # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for no added switch, and then for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is # required and that the macro should error out if no mode with that # support is found. If specified 'optional', then configuration proceeds # regardless, after defining HAVE_CXX${VERSION} if and only if a # supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016, 2018 Krzesimir Nowak # Copyright (c) 2019 Enji Cooper # Copyright (c) 2020 Jason Merrill # Copyright (c) 2021 Jörn Heusipp # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 14 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], [$1], [20], [ax_cxx_compile_alternatives="20"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], [$2], [noext], [], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], [$3], [optional], [ax_cxx_compile_cxx$1_required=false], [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl ac_success=no m4_if([$2], [], [dnl AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, ax_cv_cxx_compile_cxx$1, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [ax_cv_cxx_compile_cxx$1=yes], [ax_cv_cxx_compile_cxx$1=no])]) if test x$ax_cv_cxx_compile_cxx$1 = xyes; then ac_success=yes fi]) m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi]) m4_if([$2], [ext], [], [dnl if test x$ac_success = xno; then dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done if test x$ac_success = xyes; then break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx$1_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi fi if test x$ac_success = xno; then HAVE_CXX$1=0 AC_MSG_NOTICE([No compiler with C++$1 support was found]) else HAVE_CXX$1=1 AC_DEFINE(HAVE_CXX$1,1, [define if the compiler supports basic C++$1 syntax]) fi AC_SUBST(HAVE_CXX$1) ]) dnl Test body for checking C++11 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) dnl Test body for checking C++17 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) dnl Test body for checking C++20 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 ) dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201103L #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual ~Base() {} virtual void f() {} }; struct Derived : public Base { virtual ~Derived() override {} virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L ]]) dnl Tests for new features in C++14 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L ]]) dnl Tests for new features in C++17 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201703L #error "This is not a C++17 compiler" #else #include #include #include namespace cxx17 { namespace test_constexpr_lambdas { constexpr int foo = [](){return 42;}(); } namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } namespace test_template_argument_deduction_for_class_templates { template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } namespace test_structured_bindings { int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } namespace test_exception_spec_type_system { struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus < 201703L ]]) dnl Tests for new features in C++20 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 202002L #error "This is not a C++20 compiler" #else #include namespace cxx20 { // As C++20 supports feature test macros in the standard, there is no // immediate need to actually test for feature availability on the // Autoconf side. } // namespace cxx20 #endif // __cplusplus < 202002L ]]) SDL2_ttf-2.22.0/acinclude/ax_compute_relative_paths.m40000644000076500000240000001605414551277723021630 0ustar valvestaff# ============================================================================== # https://www.gnu.org/software/autoconf-archive/ax_compute_relative_paths.html # ============================================================================== # # SYNOPSIS # # AX_COMPUTE_RELATIVE_PATHS(PATH_LIST) # # DESCRIPTION # # PATH_LIST is a space-separated list of colon-separated triplets of the # form 'FROM:TO:RESULT'. This function iterates over these triplets and # set $RESULT to the relative path from $FROM to $TO. Note that $FROM and # $TO needs to be absolute filenames for this macro to success. # # For instance, # # first=/usr/local/bin # second=/usr/local/share # AX_COMPUTE_RELATIVE_PATHS([first:second:fs second:first:sf]) # # $fs is set to ../share # # $sf is set to ../bin # # $FROM and $TO are both eval'ed recursively and normalized, this means # that you can call this macro with autoconf's dirnames like `prefix' or # `datadir'. For example: # # AX_COMPUTE_RELATIVE_PATHS([bindir:datadir:bin_to_data]) # # AX_COMPUTE_RELATIVE_PATHS should also works with DOS filenames. # # You may want to use this macro in order to make your package # relocatable. Instead of hardcoding $datadir into your programs just # encode $bin_to_data and try to determine $bindir at run-time. # # This macro requires AX_NORMALIZE_PATH and AX_RECURSIVE_EVAL. # # LICENSE # # Copyright (c) 2008 Alexandre Duret-Lutz # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 12 AU_ALIAS([ADL_COMPUTE_RELATIVE_PATHS], [AX_COMPUTE_RELATIVE_PATHS]) AC_DEFUN([AX_COMPUTE_RELATIVE_PATHS], [for _lcl_i in $1; do _lcl_from=\[$]`echo "[$]_lcl_i" | sed 's,:.*$,,'` _lcl_to=\[$]`echo "[$]_lcl_i" | sed 's,^[[^:]]*:,,' | sed 's,:[[^:]]*$,,'` _lcl_result_var=`echo "[$]_lcl_i" | sed 's,^.*:,,'` AX_RECURSIVE_EVAL([[$]_lcl_from], [_lcl_from]) AX_RECURSIVE_EVAL([[$]_lcl_to], [_lcl_to]) _lcl_notation="$_lcl_from$_lcl_to" AX_NORMALIZE_PATH([_lcl_from],['/']) AX_NORMALIZE_PATH([_lcl_to],['/']) AX_COMPUTE_RELATIVE_PATH([_lcl_from], [_lcl_to], [_lcl_result_tmp]) AX_NORMALIZE_PATH([_lcl_result_tmp],["[$]_lcl_notation"]) eval $_lcl_result_var='[$]_lcl_result_tmp' done]) ## Note: ## ***** ## The following helper macros are too fragile to be used out ## of AX_COMPUTE_RELATIVE_PATHS (mainly because they assume that ## paths are normalized), that's why I'm keeping them in the same file. ## Still, some of them maybe worth to reuse. dnl AX_COMPUTE_RELATIVE_PATH(FROM, TO, RESULT) dnl =========================================== dnl Compute the relative path to go from $FROM to $TO and set the value dnl of $RESULT to that value. This function work on raw filenames dnl (for instead it will considerate /usr//local and /usr/local as dnl two distinct paths), you should really use AX_COMPUTE_RELATIVE_PATHS dnl instead to have the paths sanitized automatically. dnl dnl For instance: dnl first_dir=/somewhere/on/my/disk/bin dnl second_dir=/somewhere/on/another/disk/share dnl AX_COMPUTE_RELATIVE_PATH(first_dir, second_dir, first_to_second) dnl will set $first_to_second to '../../../another/disk/share'. AC_DEFUN([AX_COMPUTE_RELATIVE_PATH], [AX_COMPUTE_COMMON_PATH([$1], [$2], [_lcl_common_prefix]) AX_COMPUTE_BACK_PATH([$1], [_lcl_common_prefix], [_lcl_first_rel]) AX_COMPUTE_SUFFIX_PATH([$2], [_lcl_common_prefix], [_lcl_second_suffix]) $3="[$]_lcl_first_rel[$]_lcl_second_suffix"]) dnl AX_COMPUTE_COMMON_PATH(LEFT, RIGHT, RESULT) dnl ============================================ dnl Compute the common path to $LEFT and $RIGHT and set the result to $RESULT. dnl dnl For instance: dnl first_path=/somewhere/on/my/disk/bin dnl second_path=/somewhere/on/another/disk/share dnl AX_COMPUTE_COMMON_PATH(first_path, second_path, common_path) dnl will set $common_path to '/somewhere/on'. AC_DEFUN([AX_COMPUTE_COMMON_PATH], [$3='' _lcl_second_prefix_match='' while test "[$]_lcl_second_prefix_match" != 0; do _lcl_first_prefix=`expr "x[$]$1" : "x\([$]$3/*[[^/]]*\)"` _lcl_second_prefix_match=`expr "x[$]$2" : "x[$]_lcl_first_prefix"` if test "[$]_lcl_second_prefix_match" != 0; then if test "[$]_lcl_first_prefix" != "[$]$3"; then $3="[$]_lcl_first_prefix" else _lcl_second_prefix_match=0 fi fi done]) dnl AX_COMPUTE_SUFFIX_PATH(PATH, SUBPATH, RESULT) dnl ============================================== dnl Subtract $SUBPATH from $PATH, and set the resulting suffix dnl (or the empty string if $SUBPATH is not a subpath of $PATH) dnl to $RESULT. dnl dnl For instance: dnl first_path=/somewhere/on/my/disk/bin dnl second_path=/somewhere/on dnl AX_COMPUTE_SUFFIX_PATH(first_path, second_path, common_path) dnl will set $common_path to '/my/disk/bin'. AC_DEFUN([AX_COMPUTE_SUFFIX_PATH], [$3=`expr "x[$]$1" : "x[$]$2/*\(.*\)"`]) dnl AX_COMPUTE_BACK_PATH(PATH, SUBPATH, RESULT) dnl ============================================ dnl Compute the relative path to go from $PATH to $SUBPATH, knowing that dnl $SUBPATH is a subpath of $PATH (any other words, only repeated '../' dnl should be needed to move from $PATH to $SUBPATH) and set the value dnl of $RESULT to that value. If $SUBPATH is not a subpath of PATH, dnl set $RESULT to the empty string. dnl dnl For instance: dnl first_path=/somewhere/on/my/disk/bin dnl second_path=/somewhere/on dnl AX_COMPUTE_BACK_PATH(first_path, second_path, back_path) dnl will set $back_path to '../../../'. AC_DEFUN([AX_COMPUTE_BACK_PATH], [AX_COMPUTE_SUFFIX_PATH([$1], [$2], [_lcl_first_suffix]) $3='' _lcl_tmp='xxx' while test "[$]_lcl_tmp" != ''; do _lcl_tmp=`expr "x[$]_lcl_first_suffix" : "x[[^/]]*/*\(.*\)"` if test "[$]_lcl_first_suffix" != ''; then _lcl_first_suffix="[$]_lcl_tmp" $3="../[$]$3" fi done]) SDL2_ttf-2.22.0/acinclude/tar.m40000644000076500000240000001132114551277723015150 0ustar valvestaff# Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' dnl SDL: No following the symlinks: removed tar 'h' and cpio/pax '-L' switches m4_if([$1], [v7], [am__tar='$${TAR-tar} cof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test x$am_uid = xunknown; then AC_MSG_WARN([ancient id detected; assuming current UID is ok, but dist-ustar might not work]) elif test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test x$gm_gid = xunknown; then AC_MSG_WARN([ancient id detected; assuming current GID is ok, but dist-ustar might not work]) elif test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -cf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -cf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar cf - "$$tardir"' am__tar_='tar cf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -x $1 -w "$$tardir"' am__tar_='pax -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1' am__tar_='find "$tardir" -print | cpio -o -H $1' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR SDL2_ttf-2.22.0/acinclude/sdl2.m40000644000076500000240000001471314551277723015236 0ustar valvestaff# Configure paths for SDL # Sam Lantinga 9/21/99 # stolen from Manish Singh # stolen back from Frank Belew # stolen from Manish Singh # Shamelessly stolen from Owen Taylor # serial 2 dnl AM_PATH_SDL2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS dnl AC_DEFUN([AM_PATH_SDL2], [dnl dnl Get the cflags and libraries from the sdl2-config script dnl AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], sdl_prefix="$withval", sdl_prefix="") AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], sdl_exec_prefix="$withval", sdl_exec_prefix="") AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], , enable_sdltest=yes) min_sdl_version=ifelse([$1], ,2.0.0,$1) if test "x$sdl_prefix$sdl_exec_prefix" = x ; then PKG_CHECK_MODULES([SDL], [sdl2 >= $min_sdl_version], [sdl_pc=yes], [sdl_pc=no]) else sdl_pc=no if test x$sdl_exec_prefix != x ; then sdl_config_args="$sdl_config_args --exec-prefix=$sdl_exec_prefix" if test x${SDL2_CONFIG+set} != xset ; then SDL2_CONFIG=$sdl_exec_prefix/bin/sdl2-config fi fi if test x$sdl_prefix != x ; then sdl_config_args="$sdl_config_args --prefix=$sdl_prefix" if test x${SDL2_CONFIG+set} != xset ; then SDL2_CONFIG=$sdl_prefix/bin/sdl2-config fi fi fi if test "x$sdl_pc" = xyes ; then no_sdl="" SDL2_CONFIG="pkg-config sdl2" else as_save_PATH="$PATH" if test "x$prefix" != xNONE && test "$cross_compiling" != yes; then PATH="$prefix/bin:$prefix/usr/bin:$PATH" fi AC_PATH_PROG(SDL2_CONFIG, sdl2-config, no, [$PATH]) PATH="$as_save_PATH" AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) no_sdl="" if test "$SDL2_CONFIG" = "no" ; then no_sdl=yes else SDL_CFLAGS=`$SDL2_CONFIG $sdl_config_args --cflags` SDL_LIBS=`$SDL2_CONFIG $sdl_config_args --libs` sdl_major_version=`$SDL2_CONFIG $sdl_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` sdl_minor_version=`$SDL2_CONFIG $sdl_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` sdl_micro_version=`$SDL2_CONFIG $sdl_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test "x$enable_sdltest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_CXXFLAGS="$CXXFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $SDL_CFLAGS" CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" dnl dnl Now check if the installed SDL is sufficiently new. (Also sanity dnl checks the results of sdl2-config to some extent dnl rm -f conf.sdltest AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include "SDL.h" int main (int argc, char *argv[]) { int major, minor, micro; FILE *fp = fopen("conf.sdltest", "w"); if (fp) fclose(fp); if (sscanf("$min_sdl_version", "%d.%d.%d", &major, &minor, µ) != 3) { printf("%s, bad version string\n", "$min_sdl_version"); exit(1); } if (($sdl_major_version > major) || (($sdl_major_version == major) && ($sdl_minor_version > minor)) || (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) { return 0; } else { printf("\n*** 'sdl2-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); printf("*** of SDL required is %d.%d.%d. If sdl2-config is correct, then it is\n", major, minor, micro); printf("*** best to upgrade to the required version.\n"); printf("*** If sdl2-config was wrong, set the environment variable SDL2_CONFIG\n"); printf("*** to point to the correct copy of sdl2-config, and remove the file\n"); printf("*** config.cache before re-running configure\n"); return 1; } } ]])], [], [no_sdl=yes], [echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" CXXFLAGS="$ac_save_CXXFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_sdl" = x ; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi fi if test "x$no_sdl" = x ; then ifelse([$2], , :, [$2]) else if test "$SDL2_CONFIG" = "no" ; then echo "*** The sdl2-config script installed by SDL could not be found" echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the SDL2_CONFIG environment variable to the" echo "*** full path to sdl2-config." else if test -f conf.sdltest ; then : else echo "*** Could not run SDL test program, checking why..." CFLAGS="$CFLAGS $SDL_CFLAGS" CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include "SDL.h" int main(int argc, char *argv[]) { return 0; } #undef main #define main K_and_R_C_main ]], [[ return 0; ]])], [ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding SDL or finding the wrong" echo "*** version of SDL. If it is not finding SDL, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], [ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means SDL was incorrectly installed" echo "*** or that you have moved SDL since it was installed. In the latter case, you" echo "*** may want to edit the sdl2-config script: $SDL2_CONFIG" ]) CFLAGS="$ac_save_CFLAGS" CXXFLAGS="$ac_save_CXXFLAGS" LIBS="$ac_save_LIBS" fi fi SDL_CFLAGS="" SDL_LIBS="" ifelse([$3], , :, [$3]) fi AC_SUBST(SDL_CFLAGS) AC_SUBST(SDL_LIBS) rm -f conf.sdltest ]) SDL2_ttf-2.22.0/SDL_ttf.h0000644000076500000240000025240014553227631013641 0ustar valvestaff/* SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts Copyright (C) 2001-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /** * \file SDL_ttf.h * * Header file for SDL_ttf library * * This library is a wrapper around the excellent FreeType 2.0 library, * available at: https://www.freetype.org/ * * Note: In many places, SDL_ttf will say "glyph" when it means "code point." * Unicode is hard, we learn as we go, and we apologize for adding to the * confusion. * */ #ifndef SDL_TTF_H_ #define SDL_TTF_H_ #include "SDL.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { #endif /** * Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL */ #define SDL_TTF_MAJOR_VERSION 2 #define SDL_TTF_MINOR_VERSION 22 #define SDL_TTF_PATCHLEVEL 0 /** * This macro can be used to fill a version structure with the compile-time * version of the SDL_ttf library. */ #define SDL_TTF_VERSION(X) \ { \ (X)->major = SDL_TTF_MAJOR_VERSION; \ (X)->minor = SDL_TTF_MINOR_VERSION; \ (X)->patch = SDL_TTF_PATCHLEVEL; \ } /** * Backwards compatibility */ #define TTF_MAJOR_VERSION SDL_TTF_MAJOR_VERSION #define TTF_MINOR_VERSION SDL_TTF_MINOR_VERSION #define TTF_PATCHLEVEL SDL_TTF_PATCHLEVEL #define TTF_VERSION(X) SDL_TTF_VERSION(X) #if SDL_TTF_MAJOR_VERSION < 3 && SDL_MAJOR_VERSION < 3 /** * This is the version number macro for the current SDL_ttf version. * * In versions higher than 2.9.0, the minor version overflows into * the thousands digit: for example, 2.23.0 is encoded as 4300. * This macro will not be available in SDL 3.x or SDL_ttf 3.x. * * \deprecated, use SDL_TTF_VERSION_ATLEAST or SDL_TTF_VERSION instead. */ #define SDL_TTF_COMPILEDVERSION \ SDL_VERSIONNUM(SDL_TTF_MAJOR_VERSION, SDL_TTF_MINOR_VERSION, SDL_TTF_PATCHLEVEL) #endif /* SDL_TTF_MAJOR_VERSION < 3 && SDL_MAJOR_VERSION < 3 */ /** * This macro will evaluate to true if compiled with SDL_ttf at least X.Y.Z. */ #define SDL_TTF_VERSION_ATLEAST(X, Y, Z) \ ((SDL_TTF_MAJOR_VERSION >= X) && \ (SDL_TTF_MAJOR_VERSION > X || SDL_TTF_MINOR_VERSION >= Y) && \ (SDL_TTF_MAJOR_VERSION > X || SDL_TTF_MINOR_VERSION > Y || SDL_TTF_PATCHLEVEL >= Z)) /* Make sure this is defined (only available in newer SDL versions) */ #ifndef SDL_DEPRECATED #define SDL_DEPRECATED #endif /** * Query the version of SDL_ttf that the program is linked against. * * This function gets the version of the dynamically linked SDL_ttf library. * This is separate from the SDL_TTF_VERSION() macro, which tells you what * version of the SDL_ttf headers you compiled against. * * This returns static internal data; do not free or modify it! * * \returns a pointer to the version information. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC const SDL_version * SDLCALL TTF_Linked_Version(void); /** * Query the version of the FreeType library in use. * * TTF_Init() should be called before calling this function. * * \param major to be filled in with the major version number. Can be NULL. * \param minor to be filled in with the minor version number. Can be NULL. * \param patch to be filled in with the param version number. Can be NULL. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_Init */ extern DECLSPEC void SDLCALL TTF_GetFreeTypeVersion(int *major, int *minor, int *patch); /** * Query the version of the HarfBuzz library in use. * * If HarfBuzz is not available, the version reported is 0.0.0. * * \param major to be filled in with the major version number. Can be NULL. * \param minor to be filled in with the minor version number. Can be NULL. * \param patch to be filled in with the param version number. Can be NULL. * * \since This function is available since SDL_ttf 2.0.18. */ extern DECLSPEC void SDLCALL TTF_GetHarfBuzzVersion(int *major, int *minor, int *patch); /** * ZERO WIDTH NO-BREAKSPACE (Unicode byte order mark) */ #define UNICODE_BOM_NATIVE 0xFEFF #define UNICODE_BOM_SWAPPED 0xFFFE /** * Tell SDL_ttf whether UNICODE text is generally byteswapped. * * A UNICODE BOM character in a string will override this setting for the * remainder of that string. * * \param swapped boolean to indicate whether text is byteswapped * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC void SDLCALL TTF_ByteSwappedUNICODE(SDL_bool swapped); /** * The internal structure containing font information. Opaque data! */ typedef struct _TTF_Font TTF_Font; /** * Initialize SDL_ttf. * * You must successfully call this function before it is safe to call any * other function in this library, with one exception: a human-readable error * message can be retrieved from TTF_GetError() if this function fails. * * SDL must be initialized before calls to functions in this library, because * this library uses utility functions from the SDL library. * * It is safe to call this more than once; the library keeps a counter of init * calls, and decrements it on each call to TTF_Quit, so you must pair your * init and quit calls. * * \returns 0 on success, -1 on error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_Quit */ extern DECLSPEC int SDLCALL TTF_Init(void); /** * Create a font from a file, using a specified point size. * * Some .fon fonts will have several sizes embedded in the file, so the point * size becomes the index of choosing which size. If the value is too high, * the last indexed size will be the default. * * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. * * \param file path to font file. * \param ptsize point size to use for the newly-opened font. * \returns a valid TTF_Font, or NULL on error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_CloseFont */ extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFont(const char *file, int ptsize); /** * Create a font from a file, using a specified face index. * * Some .fon fonts will have several sizes embedded in the file, so the point * size becomes the index of choosing which size. If the value is too high, * the last indexed size will be the default. * * Some fonts have multiple "faces" included. The index specifies which face * to use from the font file. Font files with only one face should specify * zero for the index. * * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. * * \param file path to font file. * \param ptsize point size to use for the newly-opened font. * \param index index of the face in the font file. * \returns a valid TTF_Font, or NULL on error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_CloseFont */ extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndex(const char *file, int ptsize, long index); /** * Create a font from an SDL_RWops, using a specified point size. * * Some .fon fonts will have several sizes embedded in the file, so the point * size becomes the index of choosing which size. If the value is too high, * the last indexed size will be the default. * * If `freesrc` is non-zero, the RWops will be automatically closed once * the font is closed. Otherwise you should close the RWops yourself after * closing the font. * * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. * * \param src an SDL_RWops to provide a font file's data. * \param freesrc non-zero to close the RWops when the font is closed, zero to leave it open. * \param ptsize point size to use for the newly-opened font. * \returns a valid TTF_Font, or NULL on error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_CloseFont */ extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontRW(SDL_RWops *src, int freesrc, int ptsize); /** * Create a font from an SDL_RWops, using a specified face index. * * Some .fon fonts will have several sizes embedded in the file, so the point * size becomes the index of choosing which size. If the value is too high, * the last indexed size will be the default. * * If `freesrc` is non-zero, the RWops will be automatically closed once * the font is closed. Otherwise you should close the RWops yourself after * closing the font. * * Some fonts have multiple "faces" included. The index specifies which face * to use from the font file. Font files with only one face should specify * zero for the index. * * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. * * \param src an SDL_RWops to provide a font file's data. * \param freesrc non-zero to close the RWops when the font is closed, zero to leave it open. * \param ptsize point size to use for the newly-opened font. * \param index index of the face in the font file. * \returns a valid TTF_Font, or NULL on error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_CloseFont */ extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndexRW(SDL_RWops *src, int freesrc, int ptsize, long index); /** * Create a font from a file, using target resolutions (in DPI). * * DPI scaling only applies to scalable fonts (e.g. TrueType). * * Some .fon fonts will have several sizes embedded in the file, so the point * size becomes the index of choosing which size. If the value is too high, * the last indexed size will be the default. * * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. * * \param file path to font file. * \param ptsize point size to use for the newly-opened font. * \param hdpi the target horizontal DPI. * \param vdpi the target vertical DPI. * \returns a valid TTF_Font, or NULL on error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_CloseFont */ extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontDPI(const char *file, int ptsize, unsigned int hdpi, unsigned int vdpi); /** * Create a font from a file, using target resolutions (in DPI). * * DPI scaling only applies to scalable fonts (e.g. TrueType). * * Some .fon fonts will have several sizes embedded in the file, so the point * size becomes the index of choosing which size. If the value is too high, * the last indexed size will be the default. * * Some fonts have multiple "faces" included. The index specifies which face * to use from the font file. Font files with only one face should specify * zero for the index. * * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. * * \param file path to font file. * \param ptsize point size to use for the newly-opened font. * \param index index of the face in the font file. * \param hdpi the target horizontal DPI. * \param vdpi the target vertical DPI. * \returns a valid TTF_Font, or NULL on error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_CloseFont */ extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndexDPI(const char *file, int ptsize, long index, unsigned int hdpi, unsigned int vdpi); /** * Opens a font from an SDL_RWops with target resolutions (in DPI). * * DPI scaling only applies to scalable fonts (e.g. TrueType). * * Some .fon fonts will have several sizes embedded in the file, so the point * size becomes the index of choosing which size. If the value is too high, * the last indexed size will be the default. * * If `freesrc` is non-zero, the RWops will be automatically closed once * the font is closed. Otherwise you should close the RWops yourself after * closing the font. * * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. * * \param src an SDL_RWops to provide a font file's data. * \param freesrc non-zero to close the RWops when the font is closed, zero to leave it open. * \param ptsize point size to use for the newly-opened font. * \param hdpi the target horizontal DPI. * \param vdpi the target vertical DPI. * \returns a valid TTF_Font, or NULL on error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_CloseFont */ extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontDPIRW(SDL_RWops *src, int freesrc, int ptsize, unsigned int hdpi, unsigned int vdpi); /** * Opens a font from an SDL_RWops with target resolutions (in DPI). * * DPI scaling only applies to scalable fonts (e.g. TrueType). * * Some .fon fonts will have several sizes embedded in the file, so the point * size becomes the index of choosing which size. If the value is too high, * the last indexed size will be the default. * * If `freesrc` is non-zero, the RWops will be automatically closed once * the font is closed. Otherwise you should close the RWops yourself after * closing the font. * * Some fonts have multiple "faces" included. The index specifies which face * to use from the font file. Font files with only one face should specify * zero for the index. * * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. * * \param src an SDL_RWops to provide a font file's data. * \param freesrc non-zero to close the RWops when the font is closed, zero to leave it open. * \param ptsize point size to use for the newly-opened font. * \param index index of the face in the font file. * \param hdpi the target horizontal DPI. * \param vdpi the target vertical DPI. * \returns a valid TTF_Font, or NULL on error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_CloseFont */ extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndexDPIRW(SDL_RWops *src, int freesrc, int ptsize, long index, unsigned int hdpi, unsigned int vdpi); /** * Set a font's size dynamically. * * This clears already-generated glyphs, if any, from the cache. * * \param font the font to resize. * \param ptsize the new point size. * \returns 0 if successful, -1 on error * * \since This function is available since SDL_ttf 2.0.18. */ extern DECLSPEC int SDLCALL TTF_SetFontSize(TTF_Font *font, int ptsize); /** * Set font size dynamically with target resolutions (in DPI). * * This clears already-generated glyphs, if any, from the cache. * * \param font the font to resize. * \param ptsize the new point size. * \param hdpi the target horizontal DPI. * \param vdpi the target vertical DPI. * \returns 0 if successful, -1 on error. * * \since This function is available since SDL_ttf 2.0.18. */ extern DECLSPEC int SDLCALL TTF_SetFontSizeDPI(TTF_Font *font, int ptsize, unsigned int hdpi, unsigned int vdpi); /** * Font style flags */ #define TTF_STYLE_NORMAL 0x00 #define TTF_STYLE_BOLD 0x01 #define TTF_STYLE_ITALIC 0x02 #define TTF_STYLE_UNDERLINE 0x04 #define TTF_STYLE_STRIKETHROUGH 0x08 /** * Query a font's current style. * * The font styles are a set of bit flags, OR'd together: * * - `TTF_STYLE_NORMAL` (is zero) * - `TTF_STYLE_BOLD` * - `TTF_STYLE_ITALIC` * - `TTF_STYLE_UNDERLINE` * - `TTF_STYLE_STRIKETHROUGH` * * \param font the font to query. * \returns the current font style, as a set of bit flags. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_SetFontStyle */ extern DECLSPEC int SDLCALL TTF_GetFontStyle(const TTF_Font *font); /** * Set a font's current style. * * Setting the style clears already-generated glyphs, if any, from the cache. * * The font styles are a set of bit flags, OR'd together: * * - `TTF_STYLE_NORMAL` (is zero) * - `TTF_STYLE_BOLD` * - `TTF_STYLE_ITALIC` * - `TTF_STYLE_UNDERLINE` * - `TTF_STYLE_STRIKETHROUGH` * * \param font the font to set a new style on. * \param style the new style values to set, OR'd together. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_GetFontStyle */ extern DECLSPEC void SDLCALL TTF_SetFontStyle(TTF_Font *font, int style); /** * Query a font's current outline. * * \param font the font to query. * \returns the font's current outline value. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_SetFontOutline */ extern DECLSPEC int SDLCALL TTF_GetFontOutline(const TTF_Font *font); /** * Set a font's current outline. * * \param font the font to set a new outline on. * \param outline positive outline value, 0 to default. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_GetFontOutline */ extern DECLSPEC void SDLCALL TTF_SetFontOutline(TTF_Font *font, int outline); /** * Hinting flags */ #define TTF_HINTING_NORMAL 0 #define TTF_HINTING_LIGHT 1 #define TTF_HINTING_MONO 2 #define TTF_HINTING_NONE 3 #define TTF_HINTING_LIGHT_SUBPIXEL 4 /** * Query a font's current FreeType hinter setting. * * The hinter setting is a single value: * * - `TTF_HINTING_NORMAL` * - `TTF_HINTING_LIGHT` * - `TTF_HINTING_MONO` * - `TTF_HINTING_NONE` * - `TTF_HINTING_LIGHT_SUBPIXEL` (available in SDL_ttf 2.0.18 and later) * * \param font the font to query. * \returns the font's current hinter value. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_SetFontHinting */ extern DECLSPEC int SDLCALL TTF_GetFontHinting(const TTF_Font *font); /** * Set a font's current hinter setting. * * Setting it clears already-generated glyphs, if any, from the cache. * * The hinter setting is a single value: * * - `TTF_HINTING_NORMAL` * - `TTF_HINTING_LIGHT` * - `TTF_HINTING_MONO` * - `TTF_HINTING_NONE` * - `TTF_HINTING_LIGHT_SUBPIXEL` (available in SDL_ttf 2.0.18 and later) * * \param font the font to set a new hinter setting on. * \param hinting the new hinter setting. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_GetFontHinting */ extern DECLSPEC void SDLCALL TTF_SetFontHinting(TTF_Font *font, int hinting); /** * Special layout option for rendering wrapped text */ #define TTF_WRAPPED_ALIGN_LEFT 0 #define TTF_WRAPPED_ALIGN_CENTER 1 #define TTF_WRAPPED_ALIGN_RIGHT 2 /** * Query a font's current wrap alignment option. * * The wrap alignment option can be one of the following: * * - `TTF_WRAPPED_ALIGN_LEFT` * - `TTF_WRAPPED_ALIGN_CENTER` * - `TTF_WRAPPED_ALIGN_RIGHT` * * \param font the font to query. * \returns the font's current wrap alignment option. * * \since This function is available since SDL_ttf 2.20.0. * * \sa TTF_SetFontWrappedAlign */ extern DECLSPEC int SDLCALL TTF_GetFontWrappedAlign(const TTF_Font *font); /** * Set a font's current wrap alignment option. * * The wrap alignment option can be one of the following: * * - `TTF_WRAPPED_ALIGN_LEFT` * - `TTF_WRAPPED_ALIGN_CENTER` * - `TTF_WRAPPED_ALIGN_RIGHT` * * \param font the font to set a new wrap alignment option on. * \param align the new wrap alignment option. * * \since This function is available since SDL_ttf 2.20.0. * * \sa TTF_GetFontWrappedAlign */ extern DECLSPEC void SDLCALL TTF_SetFontWrappedAlign(TTF_Font *font, int align); /** * Query the total height of a font. * * This is usually equal to point size. * * \param font the font to query. * \returns the font's height. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC int SDLCALL TTF_FontHeight(const TTF_Font *font); /** * Query the offset from the baseline to the top of a font. * * This is a positive value, relative to the baseline. * * \param font the font to query. * \returns the font's ascent. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC int SDLCALL TTF_FontAscent(const TTF_Font *font); /** * Query the offset from the baseline to the bottom of a font. * * This is a negative value, relative to the baseline. * * \param font the font to query. * \returns the font's descent. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC int SDLCALL TTF_FontDescent(const TTF_Font *font); /** * Query the recommended spacing between lines of text for a font. * * \param font the font to query. * \returns the font's recommended spacing. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC int SDLCALL TTF_FontLineSkip(const TTF_Font *font); /** * Query whether or not kerning is allowed for a font. * * \param font the font to query. * \returns non-zero if kerning is enabled, zero otherwise. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC int SDLCALL TTF_GetFontKerning(const TTF_Font *font); /** * Set if kerning is allowed for a font. * * Newly-opened fonts default to allowing kerning. This is generally a good * policy unless you have a strong reason to disable it, as it tends to * produce better rendering (with kerning disabled, some fonts might render * the word `kerning` as something that looks like `keming` for example). * * \param font the font to set kerning on. * \param allowed non-zero to allow kerning, zero to disallow. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC void SDLCALL TTF_SetFontKerning(TTF_Font *font, int allowed); /** * Query the number of faces of a font. * * \param font the font to query. * \returns the number of FreeType font faces. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC long SDLCALL TTF_FontFaces(const TTF_Font *font); /** * Query whether a font is fixed-width. * * A "fixed-width" font means all glyphs are the same width across; a * lowercase 'i' will be the same size across as a capital 'W', for example. * This is common for terminals and text editors, and other apps that treat * text as a grid. Most other things (WYSIWYG word processors, web pages, etc) * are more likely to not be fixed-width in most cases. * * \param font the font to query. * \returns non-zero if fixed-width, zero if not. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC int SDLCALL TTF_FontFaceIsFixedWidth(const TTF_Font *font); /** * Query a font's family name. * * This string is dictated by the contents of the font file. * * Note that the returned string is to internal storage, and should not be * modifed or free'd by the caller. The string becomes invalid, with the rest * of the font, when `font` is handed to TTF_CloseFont(). * * \param font the font to query. * \returns the font's family name. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC const char * SDLCALL TTF_FontFaceFamilyName(const TTF_Font *font); /** * Query a font's style name. * * This string is dictated by the contents of the font file. * * Note that the returned string is to internal storage, and should not be * modifed or free'd by the caller. The string becomes invalid, with the rest * of the font, when `font` is handed to TTF_CloseFont(). * * \param font the font to query. * \returns the font's style name. * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC const char * SDLCALL TTF_FontFaceStyleName(const TTF_Font *font); /** * Check whether a glyph is provided by the font for a 16-bit codepoint. * * Note that this version of the function takes a 16-bit character code, which * covers the Basic Multilingual Plane, but is insufficient to cover the * entire set of possible Unicode values, including emoji glyphs. You should * use TTF_GlyphIsProvided32() instead, which offers the same functionality * but takes a 32-bit codepoint instead. * * The only reason to use this function is that it was available since the * beginning of time, more or less. * * \param font the font to query. * \param ch the character code to check. * \returns non-zero if font provides a glyph for this character, zero if not. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_GlyphIsProvided32 */ extern DECLSPEC int SDLCALL TTF_GlyphIsProvided(TTF_Font *font, Uint16 ch); /** * Check whether a glyph is provided by the font for a 32-bit codepoint. * * This is the same as TTF_GlyphIsProvided(), but takes a 32-bit character * instead of 16-bit, and thus can query a larger range. If you are sure * you'll have an SDL_ttf that's version 2.0.18 or newer, there's no reason * not to use this function exclusively. * * \param font the font to query. * \param ch the character code to check. * \returns non-zero if font provides a glyph for this character, zero if not. * * \since This function is available since SDL_ttf 2.0.18. */ extern DECLSPEC int SDLCALL TTF_GlyphIsProvided32(TTF_Font *font, Uint32 ch); /** * Query the metrics (dimensions) of a font's 16-bit glyph. * * To understand what these metrics mean, here is a useful link: * * https://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html * * Note that this version of the function takes a 16-bit character code, which * covers the Basic Multilingual Plane, but is insufficient to cover the * entire set of possible Unicode values, including emoji glyphs. You should * use TTF_GlyphMetrics32() instead, which offers the same functionality but * takes a 32-bit codepoint instead. * * The only reason to use this function is that it was available since the * beginning of time, more or less. * * \param font the font to query. * \param ch the character code to check. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_GlyphMetrics32 */ extern DECLSPEC int SDLCALL TTF_GlyphMetrics(TTF_Font *font, Uint16 ch, int *minx, int *maxx, int *miny, int *maxy, int *advance); /** * Query the metrics (dimensions) of a font's 32-bit glyph. * * To understand what these metrics mean, here is a useful link: * * https://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html * * This is the same as TTF_GlyphMetrics(), but takes a 32-bit character * instead of 16-bit, and thus can query a larger range. If you are sure * you'll have an SDL_ttf that's version 2.0.18 or newer, there's no reason * not to use this function exclusively. * * \param font the font to query. * \param ch the character code to check. * * \since This function is available since SDL_ttf 2.0.18. */ extern DECLSPEC int SDLCALL TTF_GlyphMetrics32(TTF_Font *font, Uint32 ch, int *minx, int *maxx, int *miny, int *maxy, int *advance); /** * Calculate the dimensions of a rendered string of Latin1 text. * * This will report the width and height, in pixels, of the space that the * specified string will take to fully render. * * This does not need to render the string to do this calculation. * * You almost certainly want TTF_SizeUTF8() unless you're sure you have a * 1-byte Latin1 encoding. US ASCII characters will work with either function, * but most other Unicode characters packed into a `const char *` will need * UTF-8. * * \param font the font to query. * \param text text to calculate, in Latin1 encoding. * \param w will be filled with width, in pixels, on return. * \param h will be filled with height, in pixels, on return. * \returns 0 if successful, -1 on error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_SizeUTF8 * \sa TTF_SizeUNICODE */ extern DECLSPEC int SDLCALL TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h); /** * Calculate the dimensions of a rendered string of UTF-8 text. * * This will report the width and height, in pixels, of the space that the * specified string will take to fully render. * * This does not need to render the string to do this calculation. * * \param font the font to query. * \param text text to calculate, in UTF-8 encoding. * \param w will be filled with width, in pixels, on return. * \param h will be filled with height, in pixels, on return. * \returns 0 if successful, -1 on error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_SizeUNICODE */ extern DECLSPEC int SDLCALL TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h); /** * Calculate the dimensions of a rendered string of UCS-2 text. * * This will report the width and height, in pixels, of the space that the * specified string will take to fully render. * * This does not need to render the string to do this calculation. * * Please note that this function is named "Unicode" but currently expects * UCS-2 encoding (16 bits per codepoint). This does not give you access to * large Unicode values, such as emoji glyphs. These codepoints are accessible * through the UTF-8 version of this function. * * \param font the font to query. * \param text text to calculate, in UCS-2 encoding. * \param w will be filled with width, in pixels, on return. * \param h will be filled with height, in pixels, on return. * \returns 0 if successful, -1 on error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_SizeUTF8 */ extern DECLSPEC int SDLCALL TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h); /** * Calculate how much of a Latin1 string will fit in a given width. * * This reports the number of characters that can be rendered before reaching * `measure_width`. * * This does not need to render the string to do this calculation. * * You almost certainly want TTF_MeasureUTF8() unless you're sure you have a * 1-byte Latin1 encoding. US ASCII characters will work with either function, * but most other Unicode characters packed into a `const char *` will need * UTF-8. * * \param font the font to query. * \param text text to calculate, in Latin1 encoding. * \param measure_width maximum width, in pixels, available for the string. * \param count on return, filled with number of characters that can be * rendered. * \param extent on return, filled with latest calculated width. * \returns 0 if successful, -1 on error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_MeasureText * \sa TTF_MeasureUTF8 * \sa TTF_MeasureUNICODE */ extern DECLSPEC int SDLCALL TTF_MeasureText(TTF_Font *font, const char *text, int measure_width, int *extent, int *count); /** * Calculate how much of a UTF-8 string will fit in a given width. * * This reports the number of characters that can be rendered before reaching * `measure_width`. * * This does not need to render the string to do this calculation. * * \param font the font to query. * \param text text to calculate, in UTF-8 encoding. * \param measure_width maximum width, in pixels, available for the string. * \param count on return, filled with number of characters that can be * rendered. * \param extent on return, filled with latest calculated width. * \returns 0 if successful, -1 on error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_MeasureText * \sa TTF_MeasureUTF8 * \sa TTF_MeasureUNICODE */ extern DECLSPEC int SDLCALL TTF_MeasureUTF8(TTF_Font *font, const char *text, int measure_width, int *extent, int *count); /** * Calculate how much of a UCS-2 string will fit in a given width. * * This reports the number of characters that can be rendered before reaching * `measure_width`. * * This does not need to render the string to do this calculation. * * Please note that this function is named "Unicode" but currently expects * UCS-2 encoding (16 bits per codepoint). This does not give you access to * large Unicode values, such as emoji glyphs. These codepoints are accessible * through the UTF-8 version of this function. * * \param font the font to query. * \param text text to calculate, in UCS-2 encoding. * \param measure_width maximum width, in pixels, available for the string. * \param count on return, filled with number of characters that can be * rendered. * \param extent on return, filled with latest calculated width. * \returns 0 if successful, -1 on error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_MeasureText * \sa TTF_MeasureUTF8 * \sa TTF_MeasureUNICODE */ extern DECLSPEC int SDLCALL TTF_MeasureUNICODE(TTF_Font *font, const Uint16 *text, int measure_width, int *extent, int *count); /** * Render Latin1 text at fast quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel * will be set to the text color. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderText_Solid_Wrapped() instead if you need to wrap the output to * multiple lines. * * This will not wrap on newline characters. * * You almost certainly want TTF_RenderUTF8_Solid() unless you're sure you * have a 1-byte Latin1 encoding. US ASCII characters will work with either * function, but most other Unicode characters packed into a `const char *` * will need UTF-8. * * You can render at other quality levels with TTF_RenderText_Shaded, * TTF_RenderText_Blended, and TTF_RenderText_LCD. * * \param font the font to render with. * \param text text to render, in Latin1 encoding. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderUTF8_Solid * \sa TTF_RenderUNICODE_Solid */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Solid(TTF_Font *font, const char *text, SDL_Color fg); /** * Render UTF-8 text at fast quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel * will be set to the text color. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderUTF8_Solid_Wrapped() instead if you need to wrap the output to * multiple lines. * * This will not wrap on newline characters. * * You can render at other quality levels with TTF_RenderUTF8_Shaded, * TTF_RenderUTF8_Blended, and TTF_RenderUTF8_LCD. * * \param font the font to render with. * \param text text to render, in UTF-8 encoding. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderUTF8_Shaded * \sa TTF_RenderUTF8_Blended * \sa TTF_RenderUTF8_LCD */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Solid(TTF_Font *font, const char *text, SDL_Color fg); /** * Render UCS-2 text at fast quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel * will be set to the text color. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderUNICODE_Solid_Wrapped() instead if you need to wrap the output to * multiple lines. * * This will not wrap on newline characters. * * Please note that this function is named "Unicode" but currently expects * UCS-2 encoding (16 bits per codepoint). This does not give you access to * large Unicode values, such as emoji glyphs. These codepoints are accessible * through the UTF-8 version of this function. * * You can render at other quality levels with TTF_RenderUNICODE_Shaded, * TTF_RenderUNICODE_Blended, and TTF_RenderUNICODE_LCD. * * \param font the font to render with. * \param text text to render, in UCS-2 encoding. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderUTF8_Solid */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Solid(TTF_Font *font, const Uint16 *text, SDL_Color fg); /** * Render word-wrapped Latin1 text at fast quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel * will be set to the text color. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * You almost certainly want TTF_RenderUTF8_Solid_Wrapped() unless you're sure * you have a 1-byte Latin1 encoding. US ASCII characters will work with * either function, but most other Unicode characters packed into a `const * char *` will need UTF-8. * * You can render at other quality levels with TTF_RenderText_Shaded_Wrapped, * TTF_RenderText_Blended_Wrapped, and TTF_RenderText_LCD_Wrapped. * * \param font the font to render with. * \param text text to render, in Latin1 encoding. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderUTF8_Solid_Wrapped * \sa TTF_RenderUNICODE_Solid_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Solid_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, Uint32 wrapLength); /** * Render word-wrapped UTF-8 text at fast quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel * will be set to the text color. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * You can render at other quality levels with TTF_RenderUTF8_Shaded_Wrapped, * TTF_RenderUTF8_Blended_Wrapped, and TTF_RenderUTF8_LCD_Wrapped. * * \param font the font to render with. * \param text text to render, in UTF-8 encoding. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderUTF8_Shaded_Wrapped * \sa TTF_RenderUTF8_Blended_Wrapped * \sa TTF_RenderUTF8_LCD_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Solid_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, Uint32 wrapLength); /** * Render word-wrapped UCS-2 text at fast quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel * will be set to the text color. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * Please note that this function is named "Unicode" but currently expects * UCS-2 encoding (16 bits per codepoint). This does not give you access to * large Unicode values, such as emoji glyphs. These codepoints are accessible * through the UTF-8 version of this function. * * You can render at other quality levels with * TTF_RenderUNICODE_Shaded_Wrapped, TTF_RenderUNICODE_Blended_Wrapped, and * TTF_RenderUNICODE_LCD_Wrapped. * * \param font the font to render with. * \param text text to render, in UCS-2 encoding. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderUTF8_Solid_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Solid_Wrapped(TTF_Font *font, const Uint16 *text, SDL_Color fg, Uint32 wrapLength); /** * Render a single 16-bit glyph at fast quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel * will be set to the text color. * * The glyph is rendered without any padding or centering in the X direction, * and aligned normally in the Y direction. * * Note that this version of the function takes a 16-bit character code, which * covers the Basic Multilingual Plane, but is insufficient to cover the * entire set of possible Unicode values, including emoji glyphs. You should * use TTF_RenderGlyph32_Solid() instead, which offers the same functionality * but takes a 32-bit codepoint instead. * * The only reason to use this function is that it was available since the * beginning of time, more or less. * * You can render at other quality levels with TTF_RenderGlyph_Shaded, * TTF_RenderGlyph_Blended, and TTF_RenderGlyph_LCD. * * \param font the font to render with. * \param ch the character to render. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderGlyph32_Solid */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Solid(TTF_Font *font, Uint16 ch, SDL_Color fg); /** * Render a single 32-bit glyph at fast quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel * will be set to the text color. * * The glyph is rendered without any padding or centering in the X direction, * and aligned normally in the Y direction. * * This is the same as TTF_RenderGlyph_Solid(), but takes a 32-bit character * instead of 16-bit, and thus can render a larger range. If you are sure * you'll have an SDL_ttf that's version 2.0.18 or newer, there's no reason * not to use this function exclusively. * * You can render at other quality levels with TTF_RenderGlyph32_Shaded, * TTF_RenderGlyph32_Blended, and TTF_RenderGlyph32_LCD. * * \param font the font to render with. * \param ch the character to render. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderGlyph32_Shaded * \sa TTF_RenderGlyph32_Blended * \sa TTF_RenderGlyph32_LCD */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph32_Solid(TTF_Font *font, Uint32 ch, SDL_Color fg); /** * Render Latin1 text at high quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the specified background color, while other pixels have * varying degrees of the foreground color. This function returns the new * surface, or NULL if there was an error. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderText_Shaded_Wrapped() instead if you need to wrap the output to * multiple lines. * * This will not wrap on newline characters. * * You almost certainly want TTF_RenderUTF8_Shaded() unless you're sure you * have a 1-byte Latin1 encoding. US ASCII characters will work with either * function, but most other Unicode characters packed into a `const char *` * will need UTF-8. * * You can render at other quality levels with TTF_RenderText_Solid, * TTF_RenderText_Blended, and TTF_RenderText_LCD. * * \param font the font to render with. * \param text text to render, in Latin1 encoding. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderUTF8_Shaded * \sa TTF_RenderUNICODE_Shaded */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg); /** * Render UTF-8 text at high quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the specified background color, while other pixels have * varying degrees of the foreground color. This function returns the new * surface, or NULL if there was an error. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderUTF8_Shaded_Wrapped() instead if you need to wrap the output to * multiple lines. * * This will not wrap on newline characters. * * You can render at other quality levels with TTF_RenderUTF8_Solid, * TTF_RenderUTF8_Blended, and TTF_RenderUTF8_LCD. * * \param font the font to render with. * \param text text to render, in UTF-8 encoding. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderUNICODE_Shaded */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Shaded(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg); /** * Render UCS-2 text at high quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the specified background color, while other pixels have * varying degrees of the foreground color. This function returns the new * surface, or NULL if there was an error. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderUNICODE_Shaded_Wrapped() instead if you need to wrap the output * to multiple lines. * * This will not wrap on newline characters. * * Please note that this function is named "Unicode" but currently expects * UCS-2 encoding (16 bits per codepoint). This does not give you access to * large Unicode values, such as emoji glyphs. These codepoints are accessible * through the UTF-8 version of this function. * * You can render at other quality levels with TTF_RenderUNICODE_Solid, * TTF_RenderUNICODE_Blended, and TTF_RenderUNICODE_LCD. * * \param font the font to render with. * \param text text to render, in UCS-2 encoding. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderUTF8_Shaded */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Shaded(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg); /** * Render word-wrapped Latin1 text at high quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the specified background color, while other pixels have * varying degrees of the foreground color. This function returns the new * surface, or NULL if there was an error. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * You almost certainly want TTF_RenderUTF8_Shaded_Wrapped() unless you're * sure you have a 1-byte Latin1 encoding. US ASCII characters will work with * either function, but most other Unicode characters packed into a `const * char *` will need UTF-8. * * You can render at other quality levels with TTF_RenderText_Solid_Wrapped, * TTF_RenderText_Blended_Wrapped, and TTF_RenderText_LCD_Wrapped. * * \param font the font to render with. * \param text text to render, in Latin1 encoding. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderUTF8_Shaded_Wrapped * \sa TTF_RenderUNICODE_Shaded_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength); /** * Render word-wrapped UTF-8 text at high quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the specified background color, while other pixels have * varying degrees of the foreground color. This function returns the new * surface, or NULL if there was an error. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * You can render at other quality levels with TTF_RenderUTF8_Solid_Wrapped, * TTF_RenderUTF8_Blended_Wrapped, and TTF_RenderUTF8_LCD_Wrapped. * * \param font the font to render with. * \param text text to render, in UTF-8 encoding. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderUTF8_Solid_Wrapped * \sa TTF_RenderUTF8_Blended_Wrapped * \sa TTF_RenderUTF8_LCD_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Shaded_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength); /** * Render word-wrapped UCS-2 text at high quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the specified background color, while other pixels have * varying degrees of the foreground color. This function returns the new * surface, or NULL if there was an error. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * Please note that this function is named "Unicode" but currently expects * UCS-2 encoding (16 bits per codepoint). This does not give you access to * large Unicode values, such as emoji glyphs. These codepoints are accessible * through the UTF-8 version of this function. * * You can render at other quality levels with * TTF_RenderUNICODE_Solid_Wrapped, TTF_RenderUNICODE_Blended_Wrapped, and * TTF_RenderUNICODE_LCD_Wrapped. * * \param font the font to render with. * \param text text to render, in UCS-2 encoding. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderUTF8_Shaded_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Shaded_Wrapped(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength); /** * Render a single 16-bit glyph at high quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the specified background color, while other pixels have * varying degrees of the foreground color. This function returns the new * surface, or NULL if there was an error. * * The glyph is rendered without any padding or centering in the X direction, * and aligned normally in the Y direction. * * Note that this version of the function takes a 16-bit character code, which * covers the Basic Multilingual Plane, but is insufficient to cover the * entire set of possible Unicode values, including emoji glyphs. You should * use TTF_RenderGlyph32_Shaded() instead, which offers the same functionality * but takes a 32-bit codepoint instead. * * The only reason to use this function is that it was available since the * beginning of time, more or less. * * You can render at other quality levels with TTF_RenderGlyph_Solid, * TTF_RenderGlyph_Blended, and TTF_RenderGlyph_LCD. * * \param font the font to render with. * \param ch the character to render. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderGlyph32_Shaded */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Shaded(TTF_Font *font, Uint16 ch, SDL_Color fg, SDL_Color bg); /** * Render a single 32-bit glyph at high quality to a new 8-bit surface. * * This function will allocate a new 8-bit, palettized surface. The surface's * 0 pixel will be the specified background color, while other pixels have * varying degrees of the foreground color. This function returns the new * surface, or NULL if there was an error. * * The glyph is rendered without any padding or centering in the X direction, * and aligned normally in the Y direction. * * This is the same as TTF_RenderGlyph_Shaded(), but takes a 32-bit character * instead of 16-bit, and thus can render a larger range. If you are sure * you'll have an SDL_ttf that's version 2.0.18 or newer, there's no reason * not to use this function exclusively. * * You can render at other quality levels with TTF_RenderGlyph32_Solid, * TTF_RenderGlyph32_Blended, and TTF_RenderGlyph32_LCD. * * \param font the font to render with. * \param ch the character to render. * \param fg the foreground color for the text. * \returns a new 8-bit, palettized surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderGlyph32_Solid * \sa TTF_RenderGlyph32_Blended * \sa TTF_RenderGlyph32_LCD */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph32_Shaded(TTF_Font *font, Uint32 ch, SDL_Color fg, SDL_Color bg); /** * Render Latin1 text at high quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, using alpha * blending to dither the font with the given color. This function returns the * new surface, or NULL if there was an error. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderText_Blended_Wrapped() instead if you need to wrap the output to * multiple lines. * * This will not wrap on newline characters. * * You almost certainly want TTF_RenderUTF8_Blended() unless you're sure you * have a 1-byte Latin1 encoding. US ASCII characters will work with either * function, but most other Unicode characters packed into a `const char *` * will need UTF-8. * * You can render at other quality levels with TTF_RenderText_Solid, * TTF_RenderText_Blended, and TTF_RenderText_LCD. * * \param font the font to render with. * \param text text to render, in Latin1 encoding. * \param fg the foreground color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderUTF8_Shaded * \sa TTF_RenderUNICODE_Shaded */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended(TTF_Font *font, const char *text, SDL_Color fg); /** * Render UTF-8 text at high quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, using alpha * blending to dither the font with the given color. This function returns the * new surface, or NULL if there was an error. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderUTF8_Blended_Wrapped() instead if you need to wrap the output to * multiple lines. * * This will not wrap on newline characters. * * You can render at other quality levels with TTF_RenderUTF8_Solid, * TTF_RenderUTF8_Shaded, and TTF_RenderUTF8_LCD. * * \param font the font to render with. * \param text text to render, in UTF-8 encoding. * \param fg the foreground color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderUNICODE_Blended */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Blended(TTF_Font *font, const char *text, SDL_Color fg); /** * Render UCS-2 text at high quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, using alpha * blending to dither the font with the given color. This function returns the * new surface, or NULL if there was an error. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderUNICODE_Blended_Wrapped() instead if you need to wrap the output * to multiple lines. * * This will not wrap on newline characters. * * Please note that this function is named "Unicode" but currently expects * UCS-2 encoding (16 bits per codepoint). This does not give you access to * large Unicode values, such as emoji glyphs. These codepoints are accessible * through the UTF-8 version of this function. * * You can render at other quality levels with TTF_RenderUNICODE_Solid, * TTF_RenderUNICODE_Shaded, and TTF_RenderUNICODE_LCD. * * \param font the font to render with. * \param text text to render, in UCS-2 encoding. * \param fg the foreground color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderUTF8_Blended */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Blended(TTF_Font *font, const Uint16 *text, SDL_Color fg); /** * Render word-wrapped Latin1 text at high quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, using alpha * blending to dither the font with the given color. This function returns the * new surface, or NULL if there was an error. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * You almost certainly want TTF_RenderUTF8_Blended_Wrapped() unless you're * sure you have a 1-byte Latin1 encoding. US ASCII characters will work with * either function, but most other Unicode characters packed into a `const * char *` will need UTF-8. * * You can render at other quality levels with TTF_RenderText_Solid_Wrapped, * TTF_RenderText_Shaded_Wrapped, and TTF_RenderText_LCD_Wrapped. * * \param font the font to render with. * \param text text to render, in Latin1 encoding. * \param fg the foreground color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderUTF8_Blended_Wrapped * \sa TTF_RenderUNICODE_Blended_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, Uint32 wrapLength); /** * Render word-wrapped UTF-8 text at high quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, using alpha * blending to dither the font with the given color. This function returns the * new surface, or NULL if there was an error. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * You can render at other quality levels with TTF_RenderUTF8_Solid_Wrapped, * TTF_RenderUTF8_Shaded_Wrapped, and TTF_RenderUTF8_LCD_Wrapped. * * \param font the font to render with. * \param text text to render, in UTF-8 encoding. * \param fg the foreground color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderUTF8_Solid_Wrapped * \sa TTF_RenderUTF8_Shaded_Wrapped * \sa TTF_RenderUTF8_LCD_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Blended_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, Uint32 wrapLength); /** * Render word-wrapped UCS-2 text at high quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, using alpha * blending to dither the font with the given color. This function returns the * new surface, or NULL if there was an error. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * Please note that this function is named "Unicode" but currently expects * UCS-2 encoding (16 bits per codepoint). This does not give you access to * large Unicode values, such as emoji glyphs. These codepoints are accessible * through the UTF-8 version of this function. * * You can render at other quality levels with * TTF_RenderUNICODE_Solid_Wrapped, TTF_RenderUNICODE_Shaded_Wrapped, and * TTF_RenderUNICODE_LCD_Wrapped. * * \param font the font to render with. * \param text text to render, in UCS-2 encoding. * \param fg the foreground color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderUTF8_Blended_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Blended_Wrapped(TTF_Font *font, const Uint16 *text, SDL_Color fg, Uint32 wrapLength); /** * Render a single 16-bit glyph at high quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, using alpha * blending to dither the font with the given color. This function returns the * new surface, or NULL if there was an error. * * The glyph is rendered without any padding or centering in the X direction, * and aligned normally in the Y direction. * * Note that this version of the function takes a 16-bit character code, which * covers the Basic Multilingual Plane, but is insufficient to cover the * entire set of possible Unicode values, including emoji glyphs. You should * use TTF_RenderGlyph32_Blended() instead, which offers the same * functionality but takes a 32-bit codepoint instead. * * The only reason to use this function is that it was available since the * beginning of time, more or less. * * You can render at other quality levels with TTF_RenderGlyph_Solid, * TTF_RenderGlyph_Shaded, and TTF_RenderGlyph_LCD. * * \param font the font to render with. * \param ch the character to render. * \param fg the foreground color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_RenderGlyph32_Blended */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg); /** * Render a single 32-bit glyph at high quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, using alpha * blending to dither the font with the given color. This function returns the * new surface, or NULL if there was an error. * * The glyph is rendered without any padding or centering in the X direction, * and aligned normally in the Y direction. * * This is the same as TTF_RenderGlyph_Blended(), but takes a 32-bit character * instead of 16-bit, and thus can render a larger range. If you are sure * you'll have an SDL_ttf that's version 2.0.18 or newer, there's no reason * not to use this function exclusively. * * You can render at other quality levels with TTF_RenderGlyph32_Solid, * TTF_RenderGlyph32_Shaded, and TTF_RenderGlyph32_LCD. * * \param font the font to render with. * \param ch the character to render. * \param fg the foreground color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_RenderGlyph32_Solid * \sa TTF_RenderGlyph32_Shaded * \sa TTF_RenderGlyph32_LCD */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph32_Blended(TTF_Font *font, Uint32 ch, SDL_Color fg); /** * Render Latin1 text at LCD subpixel quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, and render * alpha-blended text using FreeType's LCD subpixel rendering. This function * returns the new surface, or NULL if there was an error. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderText_LCD_Wrapped() instead if you need to wrap the output to * multiple lines. * * This will not wrap on newline characters. * * You almost certainly want TTF_RenderUTF8_LCD() unless you're sure you have * a 1-byte Latin1 encoding. US ASCII characters will work with either * function, but most other Unicode characters packed into a `const char *` * will need UTF-8. * * You can render at other quality levels with TTF_RenderText_Solid, * TTF_RenderText_Shaded, and TTF_RenderText_Blended. * * \param font the font to render with. * \param text text to render, in Latin1 encoding. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.20.0. * * \sa TTF_RenderUTF8_LCD * \sa TTF_RenderUNICODE_LCD */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg); /** * Render UTF-8 text at LCD subpixel quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, and render * alpha-blended text using FreeType's LCD subpixel rendering. This function * returns the new surface, or NULL if there was an error. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderUTF8_LCD_Wrapped() instead if you need to wrap the output to * multiple lines. * * This will not wrap on newline characters. * * You can render at other quality levels with TTF_RenderUTF8_Solid, * TTF_RenderUTF8_Shaded, and TTF_RenderUTF8_Blended. * * \param font the font to render with. * \param text text to render, in UTF-8 encoding. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.20.0. * * \sa TTF_RenderUNICODE_LCD */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_LCD(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg); /** * Render UCS-2 text at LCD subpixel quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, and render * alpha-blended text using FreeType's LCD subpixel rendering. This function * returns the new surface, or NULL if there was an error. * * This will not word-wrap the string; you'll get a surface with a single line * of text, as long as the string requires. You can use * TTF_RenderUNICODE_LCD_Wrapped() instead if you need to wrap the output to * multiple lines. * * This will not wrap on newline characters. * * Please note that this function is named "Unicode" but currently expects * UCS-2 encoding (16 bits per codepoint). This does not give you access to * large Unicode values, such as emoji glyphs. These codepoints are accessible * through the UTF-8 version of this function. * * You can render at other quality levels with TTF_RenderUNICODE_Solid, * TTF_RenderUNICODE_Shaded, and TTF_RenderUNICODE_Blended. * * \param font the font to render with. * \param text text to render, in UCS-2 encoding. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.20.0. * * \sa TTF_RenderUTF8_LCD */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_LCD(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg); /** * Render word-wrapped Latin1 text at LCD subpixel quality to a new ARGB * surface. * * This function will allocate a new 32-bit, ARGB surface, and render * alpha-blended text using FreeType's LCD subpixel rendering. This function * returns the new surface, or NULL if there was an error. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * You almost certainly want TTF_RenderUTF8_LCD_Wrapped() unless you're sure * you have a 1-byte Latin1 encoding. US ASCII characters will work with * either function, but most other Unicode characters packed into a `const * char *` will need UTF-8. * * You can render at other quality levels with TTF_RenderText_Solid_Wrapped, * TTF_RenderText_Shaded_Wrapped, and TTF_RenderText_Blended_Wrapped. * * \param font the font to render with. * \param text text to render, in Latin1 encoding. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.20.0. * * \sa TTF_RenderUTF8_LCD_Wrapped * \sa TTF_RenderUNICODE_LCD_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength); /** * Render word-wrapped UTF-8 text at LCD subpixel quality to a new ARGB * surface. * * This function will allocate a new 32-bit, ARGB surface, and render * alpha-blended text using FreeType's LCD subpixel rendering. This function * returns the new surface, or NULL if there was an error. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * You can render at other quality levels with TTF_RenderUTF8_Solid_Wrapped, * TTF_RenderUTF8_Shaded_Wrapped, and TTF_RenderUTF8_Blended_Wrapped. * * \param font the font to render with. * \param text text to render, in UTF-8 encoding. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.20.0. * * \sa TTF_RenderUTF8_Solid_Wrapped * \sa TTF_RenderUTF8_Shaded_Wrapped * \sa TTF_RenderUTF8_Blended_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_LCD_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength); /** * Render word-wrapped UCS-2 text at LCD subpixel quality to a new ARGB * surface. * * This function will allocate a new 32-bit, ARGB surface, and render * alpha-blended text using FreeType's LCD subpixel rendering. This function * returns the new surface, or NULL if there was an error. * * Text is wrapped to multiple lines on line endings and on word boundaries if * it extends beyond `wrapLength` in pixels. * * If wrapLength is 0, this function will only wrap on newline characters. * * Please note that this function is named "Unicode" but currently expects * UCS-2 encoding (16 bits per codepoint). This does not give you access to * large Unicode values, such as emoji glyphs. These codepoints are accessible * through the UTF-8 version of this function. * * You can render at other quality levels with * TTF_RenderUNICODE_Solid_Wrapped, TTF_RenderUNICODE_Shaded_Wrapped, and * TTF_RenderUNICODE_Blended_Wrapped. * * \param font the font to render with. * \param text text to render, in UCS-2 encoding. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.20.0. * * \sa TTF_RenderUTF8_LCD_Wrapped */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_LCD_Wrapped(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength); /** * Render a single 16-bit glyph at LCD subpixel quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, and render * alpha-blended text using FreeType's LCD subpixel rendering. This function * returns the new surface, or NULL if there was an error. * * The glyph is rendered without any padding or centering in the X direction, * and aligned normally in the Y direction. * * Note that this version of the function takes a 16-bit character code, which * covers the Basic Multilingual Plane, but is insufficient to cover the * entire set of possible Unicode values, including emoji glyphs. You should * use TTF_RenderGlyph32_LCD() instead, which offers the same functionality * but takes a 32-bit codepoint instead. * * This function only exists for consistency with the existing API at the time * of its addition. * * You can render at other quality levels with TTF_RenderGlyph_Solid, * TTF_RenderGlyph_Shaded, and TTF_RenderGlyph_Blended. * * \param font the font to render with. * \param ch the character to render. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.20.0. * * \sa TTF_RenderGlyph32_LCD */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_LCD(TTF_Font *font, Uint16 ch, SDL_Color fg, SDL_Color bg); /** * Render a single 32-bit glyph at LCD subpixel quality to a new ARGB surface. * * This function will allocate a new 32-bit, ARGB surface, and render * alpha-blended text using FreeType's LCD subpixel rendering. This function * returns the new surface, or NULL if there was an error. * * The glyph is rendered without any padding or centering in the X direction, * and aligned normally in the Y direction. * * This is the same as TTF_RenderGlyph_LCD(), but takes a 32-bit character * instead of 16-bit, and thus can render a larger range. Between the two, you * should always use this function. * * You can render at other quality levels with TTF_RenderGlyph32_Solid, * TTF_RenderGlyph32_Shaded, and TTF_RenderGlyph32_Blended. * * \param font the font to render with. * \param ch the character to render. * \param fg the foreground color for the text. * \param bg the background color for the text. * \returns a new 32-bit, ARGB surface, or NULL if there was an error. * * \since This function is available since SDL_ttf 2.20.0. * * \sa TTF_RenderGlyph32_Solid * \sa TTF_RenderGlyph32_Shaded * \sa TTF_RenderGlyph32_Blended */ extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph32_LCD(TTF_Font *font, Uint32 ch, SDL_Color fg, SDL_Color bg); /* For compatibility with previous versions, here are the old functions */ #define TTF_RenderText(font, text, fg, bg) \ TTF_RenderText_Shaded(font, text, fg, bg) #define TTF_RenderUTF8(font, text, fg, bg) \ TTF_RenderUTF8_Shaded(font, text, fg, bg) #define TTF_RenderUNICODE(font, text, fg, bg) \ TTF_RenderUNICODE_Shaded(font, text, fg, bg) /** * Dispose of a previously-created font. * * Call this when done with a font. This function will free any resources * associated with it. It is safe to call this function on NULL, for example * on the result of a failed call to TTF_OpenFont(). * * The font is not valid after being passed to this function. String pointers * from functions that return information on this font, such as * TTF_FontFaceFamilyName() and TTF_FontFaceStyleName(), are no longer valid * after this call, as well. * * \param font the font to dispose of. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_OpenFont * \sa TTF_OpenFontIndexDPIRW * \sa TTF_OpenFontRW * \sa TTF_OpenFontDPI * \sa TTF_OpenFontDPIRW * \sa TTF_OpenFontIndex * \sa TTF_OpenFontIndexDPI * \sa TTF_OpenFontIndexDPIRW * \sa TTF_OpenFontIndexRW */ extern DECLSPEC void SDLCALL TTF_CloseFont(TTF_Font *font); /** * Deinitialize SDL_ttf. * * You must call this when done with the library, to free internal resources. * It is safe to call this when the library isn't initialized, as it will just * return immediately. * * Once you have as many quit calls as you have had successful calls to * TTF_Init, the library will actually deinitialize. * * Please note that this does not automatically close any fonts that are still * open at the time of deinitialization, and it is possibly not safe to close * them afterwards, as parts of the library will no longer be initialized to * deal with it. A well-written program should call TTF_CloseFont() on any * open fonts before calling this function! * * \since This function is available since SDL_ttf 2.0.12. */ extern DECLSPEC void SDLCALL TTF_Quit(void); /** * Check if SDL_ttf is initialized. * * This reports the number of times the library has been initialized by a call * to TTF_Init(), without a paired deinitialization request from TTF_Quit(). * * In short: if it's greater than zero, the library is currently initialized * and ready to work. If zero, it is not initialized. * * Despite the return value being a signed integer, this function should not * return a negative number. * * \returns the current number of initialization calls, that need to * eventually be paired with this many calls to TTF_Quit(). * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_Init * \sa TTF_Quit */ extern DECLSPEC int SDLCALL TTF_WasInit(void); /** * Query the kerning size of two glyphs indices. * * \deprecated This function accidentally requires FreeType font indexes, * not codepoints, which we don't expose through this API, so * it could give wildly incorrect results, especially with * non-ASCII values. Going forward, please use * TTF_GetFontKerningSizeGlyphs() instead, which does what you * probably expected this function to do. * * \param font the font to query. * \param prev_index the font index, NOT codepoint, of the previous character. * \param index the font index, NOT codepoint, of the current character. * \returns The kerning size between the two specified characters, in pixels, or -1 on error. * * \since This function is available since SDL_ttf 2.0.12. * * \sa TTF_GetFontKerningSizeGlyphs */ extern SDL_DEPRECATED DECLSPEC int TTF_GetFontKerningSize(TTF_Font *font, int prev_index, int index); /** * Query the kerning size of two 16-bit glyphs. * * Note that this version of the function takes 16-bit character * codes, which covers the Basic Multilingual Plane, but is insufficient * to cover the entire set of possible Unicode values, including emoji * glyphs. You should use TTF_GetFontKerningSizeGlyphs32() instead, which * offers the same functionality but takes a 32-bit codepoints instead. * * The only reason to use this function is that it was available since * the beginning of time, more or less. * * \param font the font to query. * \param previous_ch the previous character's code, 16 bits. * \param ch the current character's code, 16 bits. * \returns The kerning size between the two specified characters, in pixels, or -1 on error. * * \since This function is available since SDL_ttf 2.0.14. * * \sa TTF_GetFontKerningSizeGlyphs32 */ extern DECLSPEC int TTF_GetFontKerningSizeGlyphs(TTF_Font *font, Uint16 previous_ch, Uint16 ch); /** * Query the kerning size of two 32-bit glyphs. * * This is the same as TTF_GetFontKerningSizeGlyphs(), but takes 32-bit * characters instead of 16-bit, and thus can manage a larger range. If * you are sure you'll have an SDL_ttf that's version 2.0.18 or newer, * there's no reason not to use this function exclusively. * * \param font the font to query. * \param previous_ch the previous character's code, 32 bits. * \param ch the current character's code, 32 bits. * \returns The kerning size between the two specified characters, in pixels, or -1 on error. * * \since This function is available since SDL_ttf 2.0.18. */ extern DECLSPEC int TTF_GetFontKerningSizeGlyphs32(TTF_Font *font, Uint32 previous_ch, Uint32 ch); /** * Enable Signed Distance Field rendering for a font. * * This works with the Blended APIs. SDF is a technique that * helps fonts look sharp even when scaling and rotating. * * This clears already-generated glyphs, if any, from the cache. * * \param font the font to set SDF support on. * \param on_off SDL_TRUE to enable SDF, SDL_FALSE to disable. * * \returns 0 on success, -1 on error. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_GetFontSDF */ extern DECLSPEC int TTF_SetFontSDF(TTF_Font *font, SDL_bool on_off); /** * Query whether Signed Distance Field rendering is enabled for a font. * * \param font the font to query * * \returns SDL_TRUE if enabled, SDL_FALSE otherwise. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_SetFontSDF */ extern DECLSPEC SDL_bool TTF_GetFontSDF(const TTF_Font *font); /** * Report SDL_ttf errors * * \sa TTF_GetError */ #define TTF_SetError SDL_SetError /** * Get last SDL_ttf error * * \sa TTF_SetError */ #define TTF_GetError SDL_GetError /** * Direction flags * * \sa TTF_SetFontDirection */ typedef enum { TTF_DIRECTION_LTR = 0, /* Left to Right */ TTF_DIRECTION_RTL, /* Right to Left */ TTF_DIRECTION_TTB, /* Top to Bottom */ TTF_DIRECTION_BTT /* Bottom to Top */ } TTF_Direction; /** * Set a global direction to be used for text shaping. * * \deprecated This function expects an hb_direction_t value, from HarfBuzz, * cast to an int, and affects all fonts globally. Please use * TTF_SetFontDirection() instead, which uses an enum supplied by * SDL_ttf itself and operates on a per-font basis. * * This is a global setting; fonts will favor a value set with * TTF_SetFontDirection(), but if they have not had one explicitly * set, they will use the value specified here. * * The default value is `HB_DIRECTION_LTR` (left-to-right text * flow). * * \param direction an hb_direction_t value. * \returns 0, or -1 if SDL_ttf is not compiled with HarfBuzz support. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_SetFontDirection */ extern SDL_DEPRECATED DECLSPEC int SDLCALL TTF_SetDirection(int direction); /* hb_direction_t */ /** * Set a global script to be used for text shaping. * * \deprecated This function expects an hb_script_t value, from HarfBuzz, cast * to an int, and affects all fonts globally. Please use * TTF_SetFontScriptName() instead, which accepts a string that is * converted to an equivalent int internally, and operates on a * per-font basis. * * This is a global setting; fonts will favor a value set with * TTF_SetFontScriptName(), but if they have not had one * explicitly set, they will use the value specified here. * * The default value is `HB_SCRIPT_UNKNOWN`. * * \returns 0, or -1 if SDL_ttf is not compiled with HarfBuzz support. * * \since This function is available since SDL_ttf 2.0.18. * * \sa TTF_SetFontScriptName */ extern SDL_DEPRECATED DECLSPEC int SDLCALL TTF_SetScript(int script); /* hb_script_t */ /** * Set direction to be used for text shaping by a font. * * Any value supplied here will override the global direction set with the * deprecated TTF_SetDirection(). * * Possible direction values are: * * - `TTF_DIRECTION_LTR` (Left to Right) * - `TTF_DIRECTION_RTL` (Right to Left) * - `TTF_DIRECTION_TTB` (Top to Bottom) * - `TTF_DIRECTION_BTT` (Bottom to Top) * * If SDL_ttf was not built with HarfBuzz support, this function returns -1. * * \param font the font to specify a direction for. * \param direction the new direction for text to flow. * \returns 0 on success, or -1 on error. * * \since This function is available since SDL_ttf 2.20.0. */ extern DECLSPEC int SDLCALL TTF_SetFontDirection(TTF_Font *font, TTF_Direction direction); /** * Set script to be used for text shaping by a font. * * Any value supplied here will override the global script set with the * deprecated TTF_SetScript(). * * The supplied script value must be a null-terminated string of exactly four * characters. * * If SDL_ttf was not built with HarfBuzz support, this function returns -1. * * \param font the font to specify a direction for. * \param script null-terminated string of exactly 4 characters. * \returns 0 on success, or -1 on error. * * \since This function is available since SDL_ttf 2.20.0. */ extern DECLSPEC int SDLCALL TTF_SetFontScriptName(TTF_Font *font, const char *script); /* Ends C function definitions when using C++ */ #ifdef __cplusplus } #endif #include "close_code.h" #endif /* SDL_TTF_H_ */ /* vi: set ts=4 sw=4 expandtab: */ SDL2_ttf-2.22.0/sdl2_ttf-config-version.cmake.in0000644000076500000240000000060514551277723020252 0ustar valvestaff# sdl2_ttf cmake project-config-version input for ./configure scripts set(PACKAGE_VERSION "@MAJOR_VERSION@.@MINOR_VERSION@.@MICRO_VERSION@") if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) else() set(PACKAGE_VERSION_COMPATIBLE TRUE) if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) set(PACKAGE_VERSION_EXACT TRUE) endif() endif() SDL2_ttf-2.22.0/.gitmodules0000644000076500000240000000040514551331661014337 0ustar valvestaff[submodule "external/freetype"] path = external/freetype url = https://github.com/libsdl-org/freetype.git branch = VER-2-13-2-SDL [submodule "external/harfbuzz"] path = external/harfbuzz url = https://github.com/libsdl-org/harfbuzz.git branch = 8.1.1-SDL SDL2_ttf-2.22.0/mingw/0000755000076500000240000000000014553227661013312 5ustar valvestaffSDL2_ttf-2.22.0/mingw/pkg-support/0000755000076500000240000000000014551277723015607 5ustar valvestaffSDL2_ttf-2.22.0/mingw/pkg-support/cmake/0000755000076500000240000000000014551277723016667 5ustar valvestaffSDL2_ttf-2.22.0/mingw/pkg-support/cmake/sdl2_ttf-config-version.cmake0000644000076500000240000000144214551277723024341 0ustar valvestaff# SDL2_ttf CMake version configuration file: # This file is meant to be placed in a cmake subfolder of SDL2_ttf-devel-2.x.y-mingw if(CMAKE_SIZEOF_VOID_P EQUAL 4) set(sdl2_ttf_config_path "${CMAKE_CURRENT_LIST_DIR}/../i686-w64-mingw32/lib/cmake/SDL2_ttf/sdl2_ttf-config-version.cmake") elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) set(sdl2_ttf_config_path "${CMAKE_CURRENT_LIST_DIR}/../x86_64-w64-mingw32/lib/cmake/SDL2_ttf/sdl2_ttf-config-version.cmake") else("${CMAKE_SIZEOF_VOID_P}" STREQUAL "") set(PACKAGE_VERSION_UNSUITABLE TRUE) return() endif() if(NOT EXISTS "${sdl2_ttf_config_path}") message(WARNING "${sdl2_ttf_config_path} does not exist: MinGW development package is corrupted") set(PACKAGE_VERSION_UNSUITABLE TRUE) return() endif() include("${sdl2_ttf_config_path}") SDL2_ttf-2.22.0/mingw/pkg-support/cmake/sdl2_ttf-config.cmake0000644000076500000240000000136414551277723022661 0ustar valvestaff# SDL2_ttf CMake configuration file: # This file is meant to be placed in a cmake subfolder of SDL2_ttf-devel-2.x.y-mingw if(CMAKE_SIZEOF_VOID_P EQUAL 4) set(sdl2_ttf_config_path "${CMAKE_CURRENT_LIST_DIR}/../i686-w64-mingw32/lib/cmake/SDL2_ttf/sdl2_ttf-config.cmake") elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) set(sdl2_ttf_config_path "${CMAKE_CURRENT_LIST_DIR}/../x86_64-w64-mingw32/lib/cmake/SDL2_ttf/sdl2_ttf-config.cmake") else("${CMAKE_SIZEOF_VOID_P}" STREQUAL "") set(SDL2_ttf_FOUND FALSE) return() endif() if(NOT EXISTS "${sdl2_ttf_config_path}") message(WARNING "${sdl2_ttf_config_path} does not exist: MinGW development package is corrupted") set(SDL2_ttf_FOUND FALSE) return() endif() include("${sdl2_ttf_config_path}") SDL2_ttf-2.22.0/Makefile.am0000644000076500000240000001455014551300141014211 0ustar valvestaff# Makefile.am for the SDL truetype font loading library and viewer ACLOCAL_AMFLAGS = -I acinclude lib_LTLIBRARIES = libSDL2_ttf.la libSDL2_ttfincludedir = $(includedir)/SDL2 libSDL2_ttfinclude_HEADERS = \ SDL_ttf.h libSDL2_ttf_la_SOURCES = \ SDL_ttf.c $(LOCAL_FT2_SOURCES) $(LOCAL_HB_SOURCES) libSDL2_ttf_la_CPPFLAGS = $(TTF_CFLAGS) $(LOCAL_FT2_FLAGS) $(LOCAL_HB_FLAGS) FREETYPE_PATH = external/freetype FREETYPE_SOURCES = \ $(FREETYPE_PATH)/src/autofit/autofit.c \ $(FREETYPE_PATH)/src/base/ftbase.c \ $(FREETYPE_PATH)/src/base/ftbbox.c \ $(FREETYPE_PATH)/src/base/ftbdf.c \ $(FREETYPE_PATH)/src/base/ftbitmap.c \ $(FREETYPE_PATH)/src/base/ftcid.c \ $(FREETYPE_PATH)/src/base/ftdebug.c \ $(FREETYPE_PATH)/src/base/ftfstype.c \ $(FREETYPE_PATH)/src/base/ftgasp.c \ $(FREETYPE_PATH)/src/base/ftglyph.c \ $(FREETYPE_PATH)/src/base/ftgxval.c \ $(FREETYPE_PATH)/src/base/ftinit.c \ $(FREETYPE_PATH)/src/base/ftmm.c \ $(FREETYPE_PATH)/src/base/ftotval.c \ $(FREETYPE_PATH)/src/base/ftpatent.c \ $(FREETYPE_PATH)/src/base/ftpfr.c \ $(FREETYPE_PATH)/src/base/ftstroke.c \ $(FREETYPE_PATH)/src/base/ftsynth.c \ $(FREETYPE_PATH)/src/base/ftsystem.c \ $(FREETYPE_PATH)/src/base/fttype1.c \ $(FREETYPE_PATH)/src/base/ftwinfnt.c \ $(FREETYPE_PATH)/src/bdf/bdf.c \ $(FREETYPE_PATH)/src/bzip2/ftbzip2.c \ $(FREETYPE_PATH)/src/cache/ftcache.c \ $(FREETYPE_PATH)/src/cff/cff.c \ $(FREETYPE_PATH)/src/cid/type1cid.c \ $(FREETYPE_PATH)/src/gzip/ftgzip.c \ $(FREETYPE_PATH)/src/lzw/ftlzw.c \ $(FREETYPE_PATH)/src/pcf/pcf.c \ $(FREETYPE_PATH)/src/pfr/pfr.c \ $(FREETYPE_PATH)/src/psaux/psaux.c \ $(FREETYPE_PATH)/src/pshinter/pshinter.c \ $(FREETYPE_PATH)/src/psnames/psmodule.c \ $(FREETYPE_PATH)/src/raster/raster.c \ $(FREETYPE_PATH)/src/sdf/sdf.c \ $(FREETYPE_PATH)/src/sfnt/sfnt.c \ $(FREETYPE_PATH)/src/smooth/smooth.c \ $(FREETYPE_PATH)/src/svg/svg.c \ $(FREETYPE_PATH)/src/truetype/truetype.c \ $(FREETYPE_PATH)/src/type1/type1.c \ $(FREETYPE_PATH)/src/type42/type42.c \ $(FREETYPE_PATH)/src/winfonts/winfnt.c if USE_BUILTIN_FREETYPE LOCAL_FT2_FLAGS = -I$(srcdir)/$(FREETYPE_PATH)/include -DFT2_BUILD_LIBRARY -DFT_PUBLIC_FUNCTION_ATTRIBUTE= LOCAL_FT2_SOURCES = $(FREETYPE_SOURCES) endif HARFBUZZ_PATH = external/harfbuzz HARFBUZZ_SOURCES = \ $(HARFBUZZ_PATH)/src/hb-aat-layout.cc \ $(HARFBUZZ_PATH)/src/hb-aat-map.cc \ $(HARFBUZZ_PATH)/src/hb-blob.cc \ $(HARFBUZZ_PATH)/src/hb-buffer-serialize.cc \ $(HARFBUZZ_PATH)/src/hb-buffer-verify.cc \ $(HARFBUZZ_PATH)/src/hb-buffer.cc \ $(HARFBUZZ_PATH)/src/hb-common.cc \ $(HARFBUZZ_PATH)/src/hb-draw.cc \ $(HARFBUZZ_PATH)/src/hb-face.cc \ $(HARFBUZZ_PATH)/src/hb-fallback-shape.cc \ $(HARFBUZZ_PATH)/src/hb-font.cc \ $(HARFBUZZ_PATH)/src/hb-ft.cc \ $(HARFBUZZ_PATH)/src/hb-number.cc \ $(HARFBUZZ_PATH)/src/hb-ot-cff1-table.cc \ $(HARFBUZZ_PATH)/src/hb-ot-cff2-table.cc \ $(HARFBUZZ_PATH)/src/hb-ot-color.cc \ $(HARFBUZZ_PATH)/src/hb-ot-face.cc \ $(HARFBUZZ_PATH)/src/hb-ot-font.cc \ $(HARFBUZZ_PATH)/src/hb-ot-layout.cc \ $(HARFBUZZ_PATH)/src/hb-ot-map.cc \ $(HARFBUZZ_PATH)/src/hb-ot-math.cc \ $(HARFBUZZ_PATH)/src/hb-ot-metrics.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-arabic.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-default.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-hangul.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-hebrew.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-indic.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-indic-table.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-khmer.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-myanmar.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-syllabic.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-thai.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-use.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shaper-vowel-constraints.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shape.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shape-fallback.cc \ $(HARFBUZZ_PATH)/src/hb-ot-shape-normalize.cc \ $(HARFBUZZ_PATH)/src/hb-ot-tag.cc \ $(HARFBUZZ_PATH)/src/hb-ot-var.cc \ $(HARFBUZZ_PATH)/src/hb-outline.cc \ $(HARFBUZZ_PATH)/src/hb-paint.cc \ $(HARFBUZZ_PATH)/src/hb-paint-extents.cc \ $(HARFBUZZ_PATH)/src/hb-set.cc \ $(HARFBUZZ_PATH)/src/hb-shape-plan.cc \ $(HARFBUZZ_PATH)/src/hb-shape.cc \ $(HARFBUZZ_PATH)/src/hb-shaper.cc \ $(HARFBUZZ_PATH)/src/hb-static.cc \ $(HARFBUZZ_PATH)/src/hb-ucd.cc \ $(HARFBUZZ_PATH)/src/hb-coretext.cc \ $(HARFBUZZ_PATH)/src/hb-gdi.cc \ $(HARFBUZZ_PATH)/src/hb-uniscribe.cc \ $(HARFBUZZ_PATH)/src/hb-unicode.cc if USE_BUILTIN_HARFBUZZ LOCAL_HB_FLAGS = -I$(srcdir)/$(HARFBUZZ_PATH) -I$(srcdir)/$(HARFBUZZ_PATH)/src -DHAVE_CONFIG_H -DFT_CONFIG_OPTION_USE_HARFBUZZ LOCAL_HB_SOURCES = $(HARFBUZZ_SOURCES) if OS_WIN32 LINKER = $(CXXLINK) else LINKER = $(LINK) endif else LINKER = $(LINK) endif libSDL2_ttf_la_LDFLAGS = \ -no-undefined \ -release $(LT_RELEASE) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) $(LT_EXTRA) if USE_VERSION_RC libSDL2_ttf_la_DEPENDENCIES = version.o endif libSDL2_ttf_la_LINK = $(LINKER) $(libSDL2_ttf_la_LDFLAGS) libSDL2_ttf_la_LIBADD = $(TTF_LIBS) @MATHLIB@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = SDL2_ttf.pc .rc.o: $(RC) $< $@ EXTRA_DIST = \ .gitmodules \ Android.mk \ CHANGES.txt \ CMakeLists.txt \ LICENSE.txt \ Makefile.os2 \ README.txt \ SDL2_ttf.pc.in \ SDL2_ttf.spec.in \ SDL2_ttfConfig.cmake.in \ VisualC \ VisualC-WinRT \ Xcode \ autogen.sh \ cmake \ external \ mingw \ sdl2_ttf-config-version.cmake.in \ sdl2_ttf-config.cmake.in \ version.rc noinst_PROGRAMS = showfont glfont showfont_LDADD = libSDL2_ttf.la glfont_LDADD = libSDL2_ttf.la @GL_LIBS@ @MATHLIB@ # Rule to build tar-gzipped distribution package $(PACKAGE)-$(VERSION).tar.gz: distcheck # Rule to build RPM distribution package rpm: $(PACKAGE)-$(VERSION).tar.gz rpmbuild -ta $(PACKAGE)-$(VERSION).tar.gz distclean-local: -rm -rf `find $(srcdir) -name .deps` dist-hook: -rm -rf `find $(distdir) -name .deps` -rm -rf `find $(distdir)/external -name '.git*'` -rm -rf `find $(distdir)/external -name '.ci*'` -rm -rf `find $(distdir)/external -name .dirstamp` -rm -rf $(distdir)/external/harfbuzz/test install-data-local: $(MKDIR_P) $(DESTDIR)$(libdir)/cmake/SDL2_ttf $(INSTALL) -m 644 sdl2_ttf-config.cmake $(DESTDIR)$(libdir)/cmake/SDL2_ttf $(INSTALL) -m 644 sdl2_ttf-config-version.cmake $(DESTDIR)$(libdir)/cmake/SDL2_ttf uninstall-hook: rm $(DESTDIR)$(libdir)/cmake/SDL2_ttf/sdl2_ttf-config.cmake rm $(DESTDIR)$(libdir)/cmake/SDL2_ttf/sdl2_ttf-config-version.cmake rm -r $(DESTDIR)$(libdir)/cmake/SDL2_ttf SDL2_ttf-2.22.0/Makefile.os20000644000076500000240000000520014553227631014325 0ustar valvestaff# Open Watcom makefile to build SDL2ttf.dll for OS/2 # wmake -f Makefile.os2 # # Remember to edit DEPS_INC and DEPS_LIB below to meet # your own environment!. LIBNAME = SDL2ttf MAJOR_VERSION = 2 MINOR_VERSION = 22 MICRO_VERSION = 0 VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION) TITLENAME = $(LIBNAME) $(VERSION) LIBFILE = $(LIBNAME).lib DLLFILE = $(LIBNAME).dll LNKFILE = $(LIBNAME).lnk # change DEPS_INC in order to point to the dependency headers. DEPS_INC=-IC:\SDL2DEV\h\SDL2 -IC:\SDL2DEV\h # change DEPS_LIB in order to point to the dependency libraries. DEPS_LIB=C:\SDL2DEV\lib SRCS = SDL_ttf.c OBJS = $(SRCS:.c=.obj) # assuming freetype is built without FT_CONFIG_OPTION_SYSTEM_ZLIB # if not, add zlib.lib to LIBS LIBS = freetype.lib SDL2.lib CFLAGS_BASE = -bt=os2 -d0 -q -bm -5s -fp5 -fpi87 -sg -oeatxh -ei -j # warnings: CFLAGS_BASE+= -wx # include paths: CFLAGS_BASE+= -I$(%WATCOM)/h/os2 -I$(%WATCOM)/h CFLAGS_BASE+= -I. $(DEPS_INC) CFLAGS =$(CFLAGS_BASE) # to build a dll: CFLAGS+= -bd # for DECLSPEC: CFLAGS+= -DBUILD_SDL # ignore many 'W201: Unreachable code' warnings: CFLAGS+= -wcd=201 # newer OpenWatcom versions enable W303 by default CFLAGS+= -wcd=303 # For the static assertions in SDL_ttf.c CFLAGS+= -DSDL_BUILD_MAJOR_VERSION=$(MAJOR_VERSION) CFLAGS+= -DSDL_BUILD_MINOR_VERSION=$(MINOR_VERSION) CFLAGS+= -DSDL_BUILD_MICRO_VERSION=$(MICRO_VERSION) all: $(LIBFILE) showfont.exe $(LIBFILE): $(DLLFILE) @echo * Create library: $@... wlib -b -n -q -c -pa -s -t -zld -ii -io $@ $(DLLFILE) $(DLLFILE): $(OBJS) $(LNKFILE) @echo * Link: $@ wlink @$(LNKFILE) $(LNKFILE): @%create $@ @%append $@ SYSTEM os2v2_dll INITINSTANCE TERMINSTANCE @%append $@ NAME $(LIBNAME) @for %i in ($(OBJS)) do @%append $@ FILE %i @%append $@ OPTION QUIET @%append $@ OPTION DESCRIPTION '@$#libsdl org:$(VERSION)$#@Simple DirectMedia Layer truetype font library' @%append $@ LIBPATH $(DEPS_LIB) @for %i in ($(LIBS)) do @%append $@ LIB %i @%append $@ OPTION MAP=$* @%append $@ OPTION ELIMINATE @%append $@ OPTION MANYAUTODATA @%append $@ OPTION OSNAME='OS/2 and eComStation' @%append $@ OPTION SHOWDEAD .c.obj: wcc386 $(CFLAGS) -fo=$^@ $< showfont.obj: showfont.c wcc386 $(CFLAGS_BASE) -fo=$^@ $< showfont.exe: $(LIBFILE) showfont.obj wlink SYS os2v2 OP q LIBPATH $(DEPS_LIB) LIBR {$(LIBFILE) SDL2.lib} F {showfont.obj} N showfont.exe clean: .SYMBOLIC @echo * Clean: $(TITLENAME) @if exist *.obj rm *.obj @if exist *.err rm *.err @if exist $(LNKFILE) rm $(LNKFILE) distclean: .SYMBOLIC clean @if exist $(DLLFILE) rm $(DLLFILE) @if exist $(LIBFILE) rm $(LIBFILE) @if exist *.map rm *.map @if exist *.exe rm *.exe SDL2_ttf-2.22.0/showfont.c0000644000076500000240000003156214551331661014205 0ustar valvestaff/* showfont: An example of using the SDL_ttf library with 2D graphics. Copyright (C) 2001-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* A simple program to test the text rendering feature of the TTF library */ #include "SDL.h" #include "SDL_ttf.h" #include #include #include #define DEFAULT_PTSIZE 18 #define DEFAULT_TEXT "The quick brown fox jumped over the lazy dog" #define WIDTH 640 #define HEIGHT 480 #define TTF_SHOWFONT_USAGE \ "Usage: %s [-solid] [-shaded] [-blended] [-wrapped] [-utf8|-unicode] [-b] [-i] [-u] [-s] [-outline size] [-hintlight|-hintmono|-hintnone] [-nokerning] [-wrap] [-fgcol r,g,b,a] [-bgcol r,g,b,a] .ttf [ptsize] [text]\n" typedef enum { TextRenderSolid, TextRenderShaded, TextRenderBlended } TextRenderMethod; typedef struct { SDL_Texture *caption; SDL_Rect captionRect; SDL_Texture *message; SDL_Rect messageRect; } Scene; static void draw_scene(SDL_Renderer *renderer, Scene *scene) { /* Clear the background to background color */ SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, scene->caption, NULL, &scene->captionRect); SDL_RenderCopy(renderer, scene->message, NULL, &scene->messageRect); SDL_RenderPresent(renderer); } static void cleanup(int exitcode) { TTF_Quit(); SDL_Quit(); exit(exitcode); } int main(int argc, char *argv[]) { char *argv0 = argv[0]; SDL_Window *window; SDL_Renderer *renderer; TTF_Font *font; SDL_Surface *text = NULL; Scene scene; int ptsize; int i, done; SDL_Color white = { 0xFF, 0xFF, 0xFF, 0 }; SDL_Color black = { 0x00, 0x00, 0x00, 0 }; SDL_Color *forecol; SDL_Color *backcol; SDL_Event event; TextRenderMethod rendermethod; int renderstyle; int outline; int hinting; int kerning; int wrap; int dump; enum { RENDER_LATIN1, RENDER_UTF8, RENDER_UNICODE } rendertype; char *message, string[128]; /* Look for special execution mode */ dump = 0; /* Look for special rendering types */ rendermethod = TextRenderShaded; renderstyle = TTF_STYLE_NORMAL; rendertype = RENDER_LATIN1; outline = 0; hinting = TTF_HINTING_NORMAL; kerning = 1; /* Default is black and white */ forecol = &black; backcol = &white; for (i=1; argv[i] && argv[i][0] == '-'; ++i) { if (SDL_strcmp(argv[i], "-solid") == 0) { rendermethod = TextRenderSolid; } else if (SDL_strcmp(argv[i], "-shaded") == 0) { rendermethod = TextRenderShaded; } else if (SDL_strcmp(argv[i], "-blended") == 0) { rendermethod = TextRenderBlended; } else if (SDL_strcmp(argv[i], "-utf8") == 0) { rendertype = RENDER_UTF8; } else if (SDL_strcmp(argv[i], "-unicode") == 0) { rendertype = RENDER_UNICODE; } else if (SDL_strcmp(argv[i], "-b") == 0) { renderstyle |= TTF_STYLE_BOLD; } else if (SDL_strcmp(argv[i], "-i") == 0) { renderstyle |= TTF_STYLE_ITALIC; } else if (SDL_strcmp(argv[i], "-u") == 0) { renderstyle |= TTF_STYLE_UNDERLINE; } else if (SDL_strcmp(argv[i], "-s") == 0) { renderstyle |= TTF_STYLE_STRIKETHROUGH; } else if (SDL_strcmp(argv[i], "-outline") == 0) { if (SDL_sscanf(argv[++i], "%d", &outline) != 1) { SDL_Log(TTF_SHOWFONT_USAGE, argv0); return(1); } } else if (SDL_strcmp(argv[i], "-hintlight") == 0) { hinting = TTF_HINTING_LIGHT; } else if (SDL_strcmp(argv[i], "-hintmono") == 0) { hinting = TTF_HINTING_MONO; } else if (SDL_strcmp(argv[i], "-hintnone") == 0) { hinting = TTF_HINTING_NONE; } else if (SDL_strcmp(argv[i], "-nokerning") == 0) { kerning = 0; } else if (SDL_strcmp(argv[i], "-wrap") == 0) { wrap = 1; } else if (SDL_strcmp(argv[i], "-dump") == 0) { dump = 1; } else if (SDL_strcmp(argv[i], "-fgcol") == 0) { int r, g, b, a = 0xFF; if (SDL_sscanf(argv[++i], "%d,%d,%d,%d", &r, &g, &b, &a) < 3) { SDL_Log(TTF_SHOWFONT_USAGE, argv0); return(1); } forecol->r = (Uint8)r; forecol->g = (Uint8)g; forecol->b = (Uint8)b; forecol->a = (Uint8)a; } else if (SDL_strcmp(argv[i], "-bgcol") == 0) { int r, g, b, a = 0xFF; if (SDL_sscanf(argv[++i], "%d,%d,%d,%d", &r, &g, &b, &a) < 3) { SDL_Log(TTF_SHOWFONT_USAGE, argv0); return(1); } backcol->r = (Uint8)r; backcol->g = (Uint8)g; backcol->b = (Uint8)b; backcol->a = (Uint8)a; } else { SDL_Log(TTF_SHOWFONT_USAGE, argv0); return(1); } } argv += i; argc -= i; /* Check usage */ if (!argv[0]) { SDL_Log(TTF_SHOWFONT_USAGE, argv0); return(1); } /* Initialize the TTF library */ if (TTF_Init() < 0) { SDL_Log("Couldn't initialize TTF: %s\n",SDL_GetError()); SDL_Quit(); return(2); } /* Open the font file with the requested point size */ ptsize = 0; if (argc > 1) { ptsize = atoi(argv[1]); } if (ptsize == 0) { i = 2; ptsize = DEFAULT_PTSIZE; } else { i = 3; } font = TTF_OpenFont(argv[0], ptsize); if (font == NULL) { SDL_Log("Couldn't load %d pt font from %s: %s\n", ptsize, argv[0], SDL_GetError()); cleanup(2); } TTF_SetFontStyle(font, renderstyle); TTF_SetFontOutline(font, outline); TTF_SetFontKerning(font, kerning); TTF_SetFontHinting(font, hinting); if(dump) { for(i = 48; i < 123; i++) { SDL_Surface* glyph = NULL; glyph = TTF_RenderGlyph_Shaded(font, i, *forecol, *backcol); if(glyph) { char outname[64]; SDL_snprintf(outname, sizeof(outname), "glyph-%d.bmp", i); SDL_SaveBMP(glyph, outname); } } cleanup(0); } /* Create a window */ if (SDL_CreateWindowAndRenderer(WIDTH, HEIGHT, 0, &window, &renderer) < 0) { SDL_Log("SDL_CreateWindowAndRenderer() failed: %s\n", SDL_GetError()); cleanup(2); } /* Show which font file we're looking at */ SDL_snprintf(string, sizeof(string), "Font file: %s", argv[0]); /* possible overflow */ switch (rendermethod) { case TextRenderSolid: text = TTF_RenderText_Solid(font, string, *forecol); break; case TextRenderShaded: text = TTF_RenderText_Shaded(font, string, *forecol, *backcol); break; case TextRenderBlended: text = TTF_RenderText_Blended(font, string, *forecol); break; } if (text != NULL) { scene.captionRect.x = 4; scene.captionRect.y = 4; scene.captionRect.w = text->w; scene.captionRect.h = text->h; scene.caption = SDL_CreateTextureFromSurface(renderer, text); SDL_FreeSurface(text); } /* Render and center the message */ if (argc > 2) { message = argv[2]; } else { message = DEFAULT_TEXT; } switch (rendertype) { case RENDER_LATIN1: switch (rendermethod) { case TextRenderSolid: if (wrap) { text = TTF_RenderText_Solid_Wrapped(font, message, *forecol, 0); } else { text = TTF_RenderText_Solid(font, message, *forecol); } break; case TextRenderShaded: if (wrap) { text = TTF_RenderText_Shaded_Wrapped(font, message, *forecol, *backcol, 0); } else { text = TTF_RenderText_Shaded(font, message, *forecol, *backcol); } break; case TextRenderBlended: if (wrap) { text = TTF_RenderText_Blended_Wrapped(font, message, *forecol, 0); } else { text = TTF_RenderText_Blended(font, message, *forecol); } break; } break; case RENDER_UTF8: switch (rendermethod) { case TextRenderSolid: if (wrap) { text = TTF_RenderUTF8_Solid_Wrapped(font, message, *forecol, 0); } else { text = TTF_RenderUTF8_Solid(font, message, *forecol); } break; case TextRenderShaded: if (wrap) { text = TTF_RenderUTF8_Shaded_Wrapped(font, message, *forecol, *backcol, 0); } else { text = TTF_RenderUTF8_Shaded(font, message, *forecol, *backcol); } break; case TextRenderBlended: if (wrap) { text = TTF_RenderUTF8_Blended_Wrapped(font, message, *forecol, 0); } else { text = TTF_RenderUTF8_Blended(font, message, *forecol); } break; } break; case RENDER_UNICODE: { Uint16 *unicode_text = SDL_iconv_utf8_ucs2(message); switch (rendermethod) { case TextRenderSolid: if (wrap) { text = TTF_RenderUNICODE_Solid_Wrapped(font, unicode_text, *forecol, 0); } else { text = TTF_RenderUNICODE_Solid(font, unicode_text, *forecol); } break; case TextRenderShaded: if (wrap) { text = TTF_RenderUNICODE_Shaded_Wrapped(font, unicode_text, *forecol, *backcol, 0); } else { text = TTF_RenderUNICODE_Shaded(font, unicode_text, *forecol, *backcol); } break; case TextRenderBlended: if (wrap) { text = TTF_RenderUNICODE_Blended_Wrapped(font, unicode_text, *forecol, 0); } else { text = TTF_RenderUNICODE_Blended(font, unicode_text, *forecol); } break; } SDL_free(unicode_text); } break; } if (text == NULL) { SDL_Log("Couldn't render text: %s\n", SDL_GetError()); TTF_CloseFont(font); cleanup(2); } scene.messageRect.x = (WIDTH - text->w)/2; scene.messageRect.y = (HEIGHT - text->h)/2; scene.messageRect.w = text->w; scene.messageRect.h = text->h; scene.message = SDL_CreateTextureFromSurface(renderer, text); SDL_Log("Font is generally %d big, and string is %d big\n", TTF_FontHeight(font), text->h); draw_scene(renderer, &scene); /* Wait for a keystroke, and blit text on mouse press */ done = 0; while (!done) { if (SDL_WaitEvent(&event) < 0) { SDL_Log("SDL_PullEvent() error: %s\n", SDL_GetError()); done = 1; continue; } switch (event.type) { case SDL_MOUSEBUTTONDOWN: scene.messageRect.x = event.button.x - text->w/2; scene.messageRect.y = event.button.y - text->h/2; scene.messageRect.w = text->w; scene.messageRect.h = text->h; draw_scene(renderer, &scene); break; case SDL_KEYDOWN: case SDL_QUIT: done = 1; break; default: break; } } SDL_FreeSurface(text); TTF_CloseFont(font); SDL_DestroyTexture(scene.caption); SDL_DestroyTexture(scene.message); cleanup(0); /* Not reached, but fixes compiler warnings */ return 0; } /* vi: set ts=4 sw=4 expandtab: */ SDL2_ttf-2.22.0/CHANGES.txt0000644000076500000240000000764714551331661014012 0ustar valvestaff2.22.0: * Updated to FreeType version 2.13.2 and HarfBuzz version 8.1.1 2.20.0: * Added support for building with CMake * Added TTF_GetFontWrappedAlign() and TTF_SetFontWrappedAlign() to set alignment on wrapped text * Added functions to render using FreeType LCD algorithm: TTF_RenderText_LCD() TTF_RenderUTF8_LCD() TTF_RenderUNICODE_LCD() TTF_RenderText_LCD_Wrapped() TTF_RenderUTF8_LCD_Wrapped() TTF_RenderUNICODE_LCD_Wrapped() TTF_RenderGlyph_LCD() TTF_RenderGlyph32_LCD() * Added TTF_SetFontDirection() and TTF_SetFontScriptName() for additional control over fonts using HarfBuzz * Updated to FreeType version 2.12.1 and HarfBuzz version 2.9.1, fixing CVE-2018-25032 * Fixed crash when loading fonts at certain sizes on Windows * Fix memory corruption loading malformed TTF files (CVE-2022-27470) 2.0.18: Ozkan Sezer - Wed Jan 5 14:15:46 PST 2022 * Added TTF_GetFreeTypeVersion() and TTF_GetHarfBuzzVersion() Sylvain - Jan 16, 2021 * Added support for Signed Distance Field rendering with TTF_SetFontSDF() and TTF_GetFontSDF() David Ludwig - Dec 28, 2019 * Added optional DPI-scaling of fonts, with the following new functions: TTF_OpenFontDPI() TTF_OpenFontIndexDPI() TTF_OpenFontDPIRW() TTF_OpenFontIndexDPIRW() TTF_SetFontSizeDPI() Weard Anaether - Dec 2, 2019 * Added 32-bit character support with: TTF_RenderGlyph32_Solid() TTF_RenderGlyph32_Shaded() TTF_RenderGlyph32_Blended() TTF_GetFontKerningSizeGlyphs32() Arthur Danskin - Sep 3, 2019 * Added 32-bit character support with TTF_GlyphIsProvided32() and TTF_GlyphMetrics32() Sylvain - Apr 5, 2019 * Added functions to set direction and script when using Harfbuzz: TTF_SetDirection() TTF_SetScript() Sylvain - Mar 25, 2019 * Added extended API for text measurement: TTF_MeasureText() TTF_MeasureUTF8() TTF_MeasureUNICODE() Sylvain - Jan 31, 2019 * Added TTF_SetFontSize() to set font size dynamically * Added 'Shaded' and 'Solid' text wrapped functions: TTF_RenderText_Solid_Wrapped() TTF_RenderUTF8_Solid_Wrapped() TTF_RenderUNICODE_Solid_Wrapped() TTF_RenderText_Shaded_Wrapped() TTF_RenderUTF8_Shaded_Wrapped() TTF_RenderUNICODE_Shaded_Wrapped() * Added TTF_HINTING_LIGHT_SUBPIXEL for better results at small text sizes at a performance cost 2.0.15: Sam Lantinga - Fri Oct 26 13:26:54 PDT 2018 * Updated to FreeType version 2.9.1 Sam Lantinga - Sun Sep 10 00:18:45 PDT 2017 * Text rendering functions now use the alpha component of the text colors Sam Lantinga - Sat Sep 9 22:21:55 PDT 2017 * Added support for characters greater than 0xFFFF (e.g. emoji) in the UTF-8 APIs 2.0.14: Ryan Gordon - Fri Jan 29 12:53:29 PST 2016 * Deprecated TTF_GetFontKerningSize() which takes font glyph indices and added TTF_GetFontKerningSizeGlyphs() which takes characters 2.0.13: Sylvain - Sat Jun 28 11:42:42 2014 * Fixed bug rendering text starting with a glyph with negative starting offset beuc - Sun Jun 15 18:27:28 2014 * Fixed regression loading non-scalable fonts Sam Lantinga - Sun Jun 15 18:21:04 PDT 2014 * TTF_GetFontKerningSize() gets kerning between two characters, not two glyph indices David Ludwig - Sun Apr 13 22:28:26 2014 * Added support for building for Windows RT and Windows Phone 2.0.12: Sam Lantinga - Sat Jun 1 19:11:26 PDT 2013 * Updated for SDL 2.0 release 2.0.11: Sam Lantinga - Sat Dec 31 10:49:42 EST 2011 * SDL_ttf is now under the zlib license Peter Kosyh - Mon Feb 28 14:57:03 PST 2011 * Improved font glyph caching for non-latin languages Erik Snoek - Wed Jan 12 09:10:15 PST 2011 * Added API to get kerning info: TTF_GetFontKerningSize() Sam Lantinga - Mon Jan 10 10:58:34 2011 -0800 * Added Android.mk to build on the Android platform 2.0.10: Adam Strzelecki - Wed Oct 21 21:02:37 PDT 2009 * Find the Unicode or symbol character map if it's available in the font SDL2_ttf-2.22.0/README.txt0000644000076500000240000000201014551277723013662 0ustar valvestaff SDL_ttf 2.0 The latest version of this library is available from GitHub: https://github.com/libsdl-org/SDL_ttf/releases This library is a wrapper around the FreeType and Harfbuzz libraries, allowing you to use TrueType fonts to render text in SDL applications. See the header file SDL_ttf.h and the example showfont.c for documentation on this library. This documentation is also available online at https://wiki.libsdl.org/SDL_ttf Be careful when including fonts with your application, as many of them are copyrighted. The Microsoft fonts, for example, are not freely redistributable and even the free "web" fonts they provide are only redistributable in their special executable installer form (May 1998). There are plenty of freeware and shareware fonts available on the Internet though, and may suit your purposes. This library is under the zlib license, see the file "LICENSE.txt" for details. Portions of this software are copyright © 2013 The FreeType Project (www.freetype.org). All rights reserved. SDL2_ttf-2.22.0/sdl2_ttf-config.cmake.in0000644000076500000240000000674714551277723016604 0ustar valvestaff# sdl2_ttf cmake project-config input for ./configure scripts include(FeatureSummary) set_package_properties(SDL2_ttf PROPERTIES URL "https://www.libsdl.org/projects/SDL_ttf/" DESCRIPTION "Support for TrueType (.ttf) font files with Simple Directmedia Layer" ) set(SDL2_ttf_FOUND TRUE) set(SDL2TTF_HARFBUZZ @TTF_USE_HARFBUZZ@) set(SDL2TTF_FREETYPE TRUE) set(SDL2TTF_VENDORED @SDL2TTF_VENDORED@) set(SDL2TTF_SDL2_REQUIRED_VERSION @SDL_VERSION@) get_filename_component(CMAKE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR} REALPATH) get_filename_component(prefix "${CMAKE_CURRENT_LIST_DIR}/@cmake_prefix_relpath@" ABSOLUTE) set(exec_prefix "@exec_prefix@") set(bindir "@bindir@") set(includedir "@includedir@") set(libdir "@libdir@") set(_sdl2ttf_extra_static_libraries "@TTF_LIBS@ @PC_LIBS@") string(STRIP "${_sdl2ttf_extra_static_libraries}" _sdl2ttf_extra_static_libraries) set(_sdl2ttf_bindir "${bindir}") set(_sdl2ttf_libdir "${libdir}") set(_sdl2ttf_incdir "${includedir}/SDL2") # Convert _sdl2ttf_extra_static_libraries to list and keep only libraries string(REGEX MATCHALL "(-[lm]([-a-zA-Z0-9._]+))|(-Wl,[^ ]*framework[^ ]*)" _sdl2ttf_extra_static_libraries "${_sdl2ttf_extra_static_libraries}") string(REGEX REPLACE "^-l" "" _sdl2ttf_extra_static_libraries "${_sdl2ttf_extra_static_libraries}") string(REGEX REPLACE ";-l" ";" _sdl2ttf_extra_static_libraries "${_sdl2ttf_extra_static_libraries}") unset(prefix) unset(exec_prefix) unset(bindir) unset(includedir) unset(libdir) include(CMakeFindDependencyMacro) if(NOT TARGET SDL2_ttf::SDL2_ttf) if(WIN32) set(_sdl2ttf_dll "${_sdl2ttf_bindir}/SDL2_ttf.dll") set(_sdl2ttf_imp "${_sdl2ttf_libdir}/${CMAKE_STATIC_LIBRARY_PREFIX}SDL2_ttf.dll${CMAKE_STATIC_LIBRARY_SUFFIX}") if(EXISTS "${_sdl2ttf_dll}" AND EXISTS "${_sdl2ttf_imp}") add_library(SDL2_ttf::SDL2_ttf SHARED IMPORTED) set_target_properties(SDL2_ttf::SDL2_ttf PROPERTIES IMPORTED_LOCATION "${_sdl2ttf_dll}" IMPORTED_IMPLIB "${_sdl2ttf_imp}" ) endif() unset(_sdl2ttf_dll) unset(_sdl2ttf_imp) else() set(_sdl2ttf_shl "${_sdl2ttf_libdir}/${CMAKE_SHARED_LIBRARY_PREFIX}SDL2_ttf${CMAKE_SHARED_LIBRARY_SUFFIX}") if(EXISTS "${_sdl2ttf_shl}") add_library(SDL2_ttf::SDL2_ttf SHARED IMPORTED) set_target_properties(SDL2_ttf::SDL2_ttf PROPERTIES IMPORTED_LOCATION "${_sdl2ttf_shl}" ) endif() endif() if(TARGET SDL2_ttf::SDL2_ttf) set_target_properties(SDL2_ttf::SDL2_ttf PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_sdl2ttf_incdir}" COMPATIBLE_INTERFACE_BOOL "SDL2_SHARED" INTERFACE_SDL2_SHARED "ON" ) endif() endif() if(NOT TARGET SDL2_ttf::SDL2_ttf-static) set(_sdl2ttf_stl "${_sdl2ttf_libdir}/${CMAKE_STATIC_LIBRARY_PREFIX}SDL2_ttf${CMAKE_STATIC_LIBRARY_SUFFIX}") if(EXISTS "${_sdl2ttf_stl}") add_library(SDL2_ttf::SDL2_ttf-static STATIC IMPORTED) set_target_properties(SDL2_ttf::SDL2_ttf-static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_sdl2ttf_incdir}" IMPORTED_LOCATION "${_sdl2ttf_stl}" INTERFACE_LINK_LIBRARIES "${_sdl2ttf_extra_static_libraries}" ) endif() unset(_sdl2ttf_stl) endif() unset(_sdl2ttf_extra_static_libraries) unset(_sdl2ttf_bindir) unset(_sdl2ttf_libdir) unset(_sdl2ttf_incdir) SDL2_ttf-2.22.0/SDL2_ttf.pc.in0000644000076500000240000000052514551277723014507 0ustar valvestaffprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: SDL2_ttf Description: ttf library for Simple DirectMedia Layer with FreeType 2 support Version: @VERSION@ Requires: sdl2 >= @SDL_VERSION@ Libs: -L${libdir} -lSDL2_ttf Cflags: -I${includedir}/SDL2 Requires.private: @PC_REQUIRES@ Libs.private: @PC_LIBS@ SDL2_ttf-2.22.0/version.rc0000644000076500000240000000171614553227631014206 0ustar valvestaff #include "winresrc.h" LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 2,22,0,0 PRODUCTVERSION 2,22,0,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "SDL_ttf\0" VALUE "FileVersion", "2, 22, 0, 0\0" VALUE "InternalName", "SDL_ttf\0" VALUE "LegalCopyright", "Copyright (C) 2024 Sam Lantinga\0" VALUE "OriginalFilename", "SDL_ttf.dll\0" VALUE "ProductName", "Simple DirectMedia Layer\0" VALUE "ProductVersion", "2, 22, 0, 0\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END SDL2_ttf-2.22.0/LICENSE.txt0000644000076500000240000000155614551277710014021 0ustar valvestaffCopyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. SDL2_ttf-2.22.0/glfont.c0000644000076500000240000003503114551277723013632 0ustar valvestaff/* glfont: An example of using the SDL_ttf library with OpenGL. Copyright (C) 2001-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* A simple program to test the text rendering feature of the TTF library */ /* quiet windows compiler warnings */ #define _CRT_SECURE_NO_WARNINGS #include #include #include #include "SDL.h" #include "SDL_ttf.h" #ifdef HAVE_OPENGL #include "SDL_opengl.h" #define DEFAULT_PTSIZE 18 #define DEFAULT_TEXT "The quick brown fox jumped over the lazy dog" #define WIDTH 640 #define HEIGHT 480 #define TTF_GLFONT_USAGE \ "Usage: %s [-utf8|-unicode] [-b] [-i] [-u] [-fgcol r,g,b] [-bgcol r,g,b] \ .ttf [ptsize] [text]\n" static void SDL_GL_Enter2DMode(int width, int height) { /* Note, there may be other things you need to change, depending on how you have your OpenGL state set up. */ glPushAttrib(GL_ENABLE_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); /* This allows alpha blending of 2D textures with the scene */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0, (GLdouble)width, (GLdouble)height, 0.0, 0.0, 1.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } static void SDL_GL_Leave2DMode() { glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); } /* Quick utility function for texture creation */ static int power_of_two(int input) { int value = 1; while (value < input) { value <<= 1; } return value; } static GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord) { GLuint texture; int w, h; SDL_Surface *image; SDL_Rect area; Uint8 saved_alpha; SDL_BlendMode saved_mode; /* Use the surface width and height expanded to powers of 2 */ w = power_of_two(surface->w); h = power_of_two(surface->h); texcoord[0] = 0.0f; /* Min X */ texcoord[1] = 0.0f; /* Min Y */ texcoord[2] = (GLfloat)surface->w / w; /* Max X */ texcoord[3] = (GLfloat)surface->h / h; /* Max Y */ image = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, SDL_PIXELFORMAT_RGBA32); if (image == NULL) { return 0; } /* Save the alpha blending attributes */ SDL_GetSurfaceAlphaMod(surface, &saved_alpha); SDL_SetSurfaceAlphaMod(surface, 0xFF); SDL_GetSurfaceBlendMode(surface, &saved_mode); SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE); /* Copy the surface into the GL texture image */ area.x = 0; area.y = 0; area.w = surface->w; area.h = surface->h; SDL_BlitSurface(surface, &area, image, &area); /* Restore the alpha blending attributes */ SDL_SetSurfaceAlphaMod(surface, saved_alpha); SDL_SetSurfaceBlendMode(surface, saved_mode); /* Create an OpenGL texture for the image */ glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels); SDL_FreeSurface(image); /* No longer needed */ return texture; } static void cleanup(int exitcode) { TTF_Quit(); SDL_Quit(); exit(exitcode); } int main(int argc, char *argv[]) { char *argv0 = argv[0]; SDL_Window *window; SDL_GLContext context; TTF_Font *font; SDL_Surface *text = NULL; int ptsize; int i, done; SDL_Color white = { 0xFF, 0xFF, 0xFF, 0 }; SDL_Color black = { 0x00, 0x00, 0x00, 0 }; SDL_Color *forecol; SDL_Color *backcol; GLenum gl_error; GLuint texture; int x, y, w, h; GLfloat texcoord[4]; GLfloat texMinX, texMinY; GLfloat texMaxX, texMaxY; float color[8][3]= {{ 1.0, 1.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, { 0.0, 1.0, 1.0}, { 1.0, 1.0, 1.0}, { 1.0, 0.0, 1.0}, { 0.0, 0.0, 1.0}}; float cube[8][3]= {{ 0.5, 0.5, -0.5}, { 0.5, -0.5, -0.5}, {-0.5, -0.5, -0.5}, {-0.5, 0.5, -0.5}, {-0.5, 0.5, 0.5}, { 0.5, 0.5, 0.5}, { 0.5, -0.5, 0.5}, {-0.5, -0.5, 0.5}}; SDL_Event event; int renderstyle; int dump; enum { RENDER_LATIN1, RENDER_UTF8, RENDER_UNICODE } rendertype; char *message; /* Look for special execution mode */ dump = 0; /* Look for special rendering types */ renderstyle = TTF_STYLE_NORMAL; rendertype = RENDER_LATIN1; /* Default is black and white */ forecol = &black; backcol = &white; for (i=1; argv[i] && argv[i][0] == '-'; ++i) { if (strcmp(argv[i], "-utf8") == 0) { rendertype = RENDER_UTF8; } else if (strcmp(argv[i], "-unicode") == 0) { rendertype = RENDER_UNICODE; } else if (strcmp(argv[i], "-b") == 0) { renderstyle |= TTF_STYLE_BOLD; } else if (strcmp(argv[i], "-i") == 0) { renderstyle |= TTF_STYLE_ITALIC; } else if (strcmp(argv[i], "-u") == 0) { renderstyle |= TTF_STYLE_UNDERLINE; } else if (strcmp(argv[i], "-dump") == 0) { dump = 1; } else if (strcmp(argv[i], "-fgcol") == 0) { int r, g, b; if (sscanf (argv[++i], "%d,%d,%d", &r, &g, &b) != 3) { fprintf(stderr, TTF_GLFONT_USAGE, argv0); return(1); } forecol->r = (Uint8)r; forecol->g = (Uint8)g; forecol->b = (Uint8)b; } else if (strcmp(argv[i], "-bgcol") == 0) { int r, g, b; if (sscanf (argv[++i], "%d,%d,%d", &r, &g, &b) != 3) { fprintf(stderr, TTF_GLFONT_USAGE, argv0); return(1); } backcol->r = (Uint8)r; backcol->g = (Uint8)g; backcol->b = (Uint8)b; } else { fprintf(stderr, TTF_GLFONT_USAGE, argv0); return(1); } } argv += i; argc -= i; /* Check usage */ if (!argv[0]) { fprintf(stderr, TTF_GLFONT_USAGE, argv0); return(1); } /* Initialize the TTF library */ if (TTF_Init() < 0) { fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError()); SDL_Quit(); return(2); } /* Open the font file with the requested point size */ ptsize = 0; if (argc > 1) { ptsize = atoi(argv[1]); } if (ptsize == 0) { i = 2; ptsize = DEFAULT_PTSIZE; } else { i = 3; } font = TTF_OpenFont(argv[0], ptsize); if (font == NULL) { fprintf(stderr, "Couldn't load %d pt font from %s: %s\n", ptsize, argv[0], SDL_GetError()); cleanup(2); } TTF_SetFontStyle(font, renderstyle); if(dump) { for(i = 48; i < 123; i++) { SDL_Surface* glyph = NULL; glyph = TTF_RenderGlyph_Shaded(font, i, *forecol, *backcol); if(glyph) { char outname[64]; sprintf(outname, "glyph-%d.bmp", i); SDL_SaveBMP(glyph, outname); } } cleanup(0); } /* Set a 640x480 video mode */ window = SDL_CreateWindow("glfont", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_OPENGL); if (window == NULL) { fprintf(stderr, "Couldn't create window: %s\n", SDL_GetError()); cleanup(2); } context = SDL_GL_CreateContext(window); if (context == NULL) { fprintf(stderr, "Couldn't create OpenGL context: %s\n", SDL_GetError()); cleanup(2); } /* Render and center the message */ if (argc > 2) { message = argv[2]; } else { message = DEFAULT_TEXT; } switch (rendertype) { case RENDER_LATIN1: text = TTF_RenderText_Blended(font, message, *forecol); break; case RENDER_UTF8: text = TTF_RenderUTF8_Blended(font, message, *forecol); break; case RENDER_UNICODE: { /* This doesn't actually work because you can't pass UNICODE text in via command line, AFAIK, but... */ Uint16 unicode_text[BUFSIZ]; int index; for (index = 0; (message[0] || message[1]); ++index) { unicode_text[index] = ((Uint8 *)message)[0]; unicode_text[index] <<= 8; unicode_text[index] |= ((Uint8 *)message)[1]; message += 2; } text = TTF_RenderUNICODE_Blended(font, unicode_text, *forecol); } break; } if (text == NULL) { fprintf(stderr, "Couldn't render text: %s\n", SDL_GetError()); TTF_CloseFont(font); cleanup(2); } x = (WIDTH - text->w)/2; y = (HEIGHT - text->h)/2; w = text->w; h = text->h; printf("Font is generally %d big, and string is %d big\n", TTF_FontHeight(font), text->h); /* Convert the text into an OpenGL texture */ glGetError(); texture = SDL_GL_LoadTexture(text, texcoord); if ((gl_error = glGetError()) != GL_NO_ERROR) { /* If this failed, the text may exceed texture size limits */ printf("Warning: Couldn't create texture: 0x%x\n", gl_error); } /* Make texture coordinates easy to understand */ texMinX = texcoord[0]; texMinY = texcoord[1]; texMaxX = texcoord[2]; texMaxY = texcoord[3]; /* We don't need the original text surface anymore */ SDL_FreeSurface(text); /* Initialize the GL state */ glViewport(0, 0, WIDTH, HEIGHT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-2.0, 2.0, -2.0, 2.0, -20.0, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glShadeModel(GL_SMOOTH); /* Wait for a keystroke, and blit text on mouse press */ done = 0; while (!done) { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_MOUSEMOTION: x = event.motion.x - w/2; y = event.motion.y - h/2; break; case SDL_KEYDOWN: case SDL_QUIT: done = 1; break; default: break; } } /* Clear the screen */ glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Draw the spinning cube */ glBegin(GL_QUADS); glColor3fv(color[0]); glVertex3fv(cube[0]); glColor3fv(color[1]); glVertex3fv(cube[1]); glColor3fv(color[2]); glVertex3fv(cube[2]); glColor3fv(color[3]); glVertex3fv(cube[3]); glColor3fv(color[3]); glVertex3fv(cube[3]); glColor3fv(color[4]); glVertex3fv(cube[4]); glColor3fv(color[7]); glVertex3fv(cube[7]); glColor3fv(color[2]); glVertex3fv(cube[2]); glColor3fv(color[0]); glVertex3fv(cube[0]); glColor3fv(color[5]); glVertex3fv(cube[5]); glColor3fv(color[6]); glVertex3fv(cube[6]); glColor3fv(color[1]); glVertex3fv(cube[1]); glColor3fv(color[5]); glVertex3fv(cube[5]); glColor3fv(color[4]); glVertex3fv(cube[4]); glColor3fv(color[7]); glVertex3fv(cube[7]); glColor3fv(color[6]); glVertex3fv(cube[6]); glColor3fv(color[5]); glVertex3fv(cube[5]); glColor3fv(color[0]); glVertex3fv(cube[0]); glColor3fv(color[3]); glVertex3fv(cube[3]); glColor3fv(color[4]); glVertex3fv(cube[4]); glColor3fv(color[6]); glVertex3fv(cube[6]); glColor3fv(color[1]); glVertex3fv(cube[1]); glColor3fv(color[2]); glVertex3fv(cube[2]); glColor3fv(color[7]); glVertex3fv(cube[7]); glEnd(); /* Rotate the cube */ glMatrixMode(GL_MODELVIEW); glRotatef(5.0, 1.0, 1.0, 1.0); /* Show the text on the screen */ SDL_GL_Enter2DMode(WIDTH, HEIGHT); glBindTexture(GL_TEXTURE_2D, texture); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(texMinX, texMinY); glVertex2i(x, y); glTexCoord2f(texMaxX, texMinY); glVertex2i(x+w, y); glTexCoord2f(texMinX, texMaxY); glVertex2i(x, y+h); glTexCoord2f(texMaxX, texMaxY); glVertex2i(x+w, y+h); glEnd(); SDL_GL_Leave2DMode(); /* Swap the buffers so everything is visible */ SDL_GL_SwapWindow(window); } SDL_GL_DeleteContext(context); TTF_CloseFont(font); cleanup(0); /* Not reached, but fixes compiler warnings */ return 0; } #else /* HAVE_OPENGL */ int main(int argc, char *argv[]) { printf("No OpenGL support on this system\n"); return 1; } #endif /* HAVE_OPENGL */ /* vi: set ts=4 sw=4 expandtab: */ SDL2_ttf-2.22.0/SDL_ttf.c0000644000076500000240000045125214551331661013637 0ustar valvestaff/* SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts Copyright (C) 2001-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #include "SDL.h" #include "SDL_cpuinfo.h" #include "SDL_endian.h" #include "SDL_ttf.h" #include #include FT_FREETYPE_H #include FT_OUTLINE_H #include FT_STROKER_H #include FT_GLYPH_H #include FT_TRUETYPE_IDS_H #include FT_IMAGE_H /* Enable rendering with color * Freetype may need to be compiled with FT_CONFIG_OPTION_USE_PNG */ #if defined(FT_HAS_COLOR) # define TTF_USE_COLOR 1 #else # define TTF_USE_COLOR 0 #endif /* Enable Signed Distance Field rendering (requires latest FreeType version) */ #if defined(FT_RASTER_FLAG_SDF) # define TTF_USE_SDF 1 #else # define TTF_USE_SDF 0 #endif #if TTF_USE_SDF #include FT_MODULE_H #endif /* Enable HarfBuzz for Complex text rendering * Freetype may need to be compiled with FT_CONFIG_OPTION_USE_HARFBUZZ */ #ifndef TTF_USE_HARFBUZZ # define TTF_USE_HARFBUZZ 0 #endif #if defined(SDL_BUILD_MAJOR_VERSION) && defined(SDL_COMPILE_TIME_ASSERT) SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MAJOR_VERSION, SDL_TTF_MAJOR_VERSION == SDL_BUILD_MAJOR_VERSION); SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MINOR_VERSION, SDL_TTF_MINOR_VERSION == SDL_BUILD_MINOR_VERSION); SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MICRO_VERSION, SDL_TTF_PATCHLEVEL == SDL_BUILD_MICRO_VERSION); #endif #if defined(SDL_COMPILE_TIME_ASSERT) SDL_COMPILE_TIME_ASSERT(SDL_TTF_MAJOR_VERSION_min, SDL_TTF_MAJOR_VERSION >= 0); /* Limited only by the need to fit in SDL_version */ SDL_COMPILE_TIME_ASSERT(SDL_TTF_MAJOR_VERSION_max, SDL_TTF_MAJOR_VERSION <= 255); SDL_COMPILE_TIME_ASSERT(SDL_TTF_MINOR_VERSION_min, SDL_TTF_MINOR_VERSION >= 0); /* Limited only by the need to fit in SDL_version */ SDL_COMPILE_TIME_ASSERT(SDL_TTF_MINOR_VERSION_max, SDL_TTF_MINOR_VERSION <= 255); SDL_COMPILE_TIME_ASSERT(SDL_TTF_PATCHLEVEL_min, SDL_TTF_PATCHLEVEL >= 0); /* Limited by its encoding in SDL_VERSIONNUM and in the ABI versions */ SDL_COMPILE_TIME_ASSERT(SDL_TTF_PATCHLEVEL_max, SDL_TTF_PATCHLEVEL <= 99); #endif #if TTF_USE_HARFBUZZ #include #include /* Default configuration */ static hb_direction_t g_hb_direction = HB_DIRECTION_LTR; static hb_script_t g_hb_script = HB_SCRIPT_UNKNOWN; #endif /* Harfbuzz */ int TTF_SetDirection(int direction) /* hb_direction_t */ { #if TTF_USE_HARFBUZZ g_hb_direction = direction; return 0; #else (void) direction; return -1; #endif } int TTF_SetScript(int script) /* hb_script_t */ { #if TTF_USE_HARFBUZZ g_hb_script = script; return 0; #else (void) script; return -1; #endif } /* Round glyph to 16 bytes width and use SSE2 instructions */ #if defined(__SSE2__) # define HAVE_SSE2_INTRINSICS 1 #endif /* Round glyph width to 16 bytes use NEON instructions */ #if 0 /*defined(__ARM_NEON)*/ # define HAVE_NEON_INTRINSICS 1 #endif /* Round glyph width to 8 bytes */ #define HAVE_BLIT_GLYPH_64 /* Android armeabi-v7a doesn't like int64 (Maybe all other __ARM_ARCH < 7 ?), * un-activate it, especially if NEON isn't detected */ #if defined(__ARM_ARCH) # if __ARM_ARCH < 8 # if defined(HAVE_BLIT_GLYPH_64) # undef HAVE_BLIT_GLYPH_64 # endif # endif #endif /* Default: round glyph width to 4 bytes to copy them faster */ #define HAVE_BLIT_GLYPH_32 /* Use Duff's device to unroll loops */ //#define USE_DUFFS_LOOP #if defined(HAVE_SSE2_INTRINSICS) static SDL_INLINE int hasSSE2(void) { static int val = -1; if (val != -1) { return val; } val = SDL_HasSSE2(); return val; } #endif #if defined(HAVE_NEON_INTRINSICS) static SDL_INLINE int hasNEON(void) { static int val = -1; if (val != -1) { return val; } val = SDL_HasNEON(); return val; } #endif /* FIXME: Right now we assume the gray-scale renderer Freetype is using supports 256 shades of gray, but we should instead key off of num_grays in the result FT_Bitmap after the FT_Render_Glyph() call. */ #define NUM_GRAYS 256 /* x offset = cos(((90.0-12)/360) * 2 * M_PI), or 12 degree angle */ /* same value as in FT_GlyphSlot_Oblique, fixed point 16.16 */ #define GLYPH_ITALICS 0x0366AL /* Handy routines for converting from fixed point 26.6 */ #define FT_FLOOR(X) (int)(((X) & -64) / 64) #define FT_CEIL(X) FT_FLOOR((X) + 63) /* Handy routine for converting to fixed point 26.6 */ #define F26Dot6(X) ((X) << 6) /* Faster divide by 255, with same result * in range [0; 255]: (x + 1 + (x >> 8)) >> 8 * in range [-255; 0]: (x + 255 + (x >> 8)) >> 8 */ #define DIVIDE_BY_255_SIGNED(x, sign_val) (((x) + (sign_val) + ((x)>>8)) >> 8) /* When x positive */ #define DIVIDE_BY_255(x) DIVIDE_BY_255_SIGNED(x, 1) #define CACHED_METRICS 0x20 #define CACHED_BITMAP 0x01 #define CACHED_PIXMAP 0x02 #define CACHED_COLOR 0x04 #define CACHED_LCD 0x08 #define CACHED_SUBPIX 0x10 typedef struct { unsigned char *buffer; /* aligned */ int left; int top; int width; int rows; int pitch; int is_color; } TTF_Image; /* Cached glyph information */ typedef struct cached_glyph { int stored; FT_UInt index; TTF_Image bitmap; TTF_Image pixmap; int sz_left; int sz_top; int sz_width; int sz_rows; int advance; union { /* TTF_HINTING_LIGHT_SUBPIXEL (only pixmap) */ struct { int lsb_minus_rsb; int translation; } subpixel; /* Other hinting */ struct { int rsb_delta; int lsb_delta; } kerning_smart; }; } c_glyph; /* Internal buffer to store positions computed by TTF_Size_Internal() * for rendered string by Render_Line() */ typedef struct PosBuf { FT_UInt index; int x; int y; } PosBuf_t; /* The structure used to hold internal font information */ struct _TTF_Font { /* Freetype2 maintains all sorts of useful info itself */ FT_Face face; /* We'll cache these ourselves */ int height; int ascent; int descent; int lineskip; /* The font style */ int style; int outline_val; /* Whether kerning is desired */ int allow_kerning; int use_kerning; /* Extra width in glyph bounds for text styles */ int glyph_overhang; /* Information in the font for underlining */ int line_thickness; int underline_top_row; int strikethrough_top_row; /* Cache for style-transformed glyphs */ c_glyph cache[256]; FT_UInt cache_index[128]; /* We are responsible for closing the font stream */ SDL_RWops *src; int freesrc; FT_Open_Args args; /* Internal buffer to store positions computed by TTF_Size_Internal() * for rendered string by Render_Line() */ PosBuf_t *pos_buf; Uint32 pos_len; Uint32 pos_max; /* Hinting modes */ int ft_load_target; int render_subpixel; #if TTF_USE_HARFBUZZ hb_font_t *hb_font; /* If HB_SCRIPT_INVALID, use global default script */ hb_script_t hb_script; /* If HB_DIRECTION_INVALID, use global default direction */ hb_direction_t hb_direction; #endif int render_sdf; /* Extra layout setting for wrapped text */ int horizontal_align; }; /* Tell if SDL_ttf has to handle the style */ #define TTF_HANDLE_STYLE_BOLD(font) ((font)->style & TTF_STYLE_BOLD) #define TTF_HANDLE_STYLE_ITALIC(font) ((font)->style & TTF_STYLE_ITALIC) #define TTF_HANDLE_STYLE_UNDERLINE(font) ((font)->style & TTF_STYLE_UNDERLINE) #define TTF_HANDLE_STYLE_STRIKETHROUGH(font) ((font)->style & TTF_STYLE_STRIKETHROUGH) /* Font styles that does not impact glyph drawing */ #define TTF_STYLE_NO_GLYPH_CHANGE (TTF_STYLE_UNDERLINE | TTF_STYLE_STRIKETHROUGH) /* The FreeType font engine/library */ static FT_Library library = NULL; static int TTF_initialized = 0; static SDL_bool TTF_byteswapped = SDL_FALSE; #define TTF_CHECK_INITIALIZED(errval) \ if (!TTF_initialized) { \ TTF_SetError("Library not initialized"); \ return errval; \ } #define TTF_CHECK_POINTER(p, errval) \ if (!(p)) { \ TTF_SetError("Passed a NULL pointer"); \ return errval; \ } typedef enum { RENDER_SOLID = 0, RENDER_SHADED, RENDER_BLENDED, RENDER_LCD } render_mode_t; typedef enum { STR_UTF8 = 0, STR_TEXT, STR_UNICODE } str_type_t; static int TTF_initFontMetrics(TTF_Font *font); static int TTF_Size_Internal(TTF_Font *font, const char *text, str_type_t str_type, int *w, int *h, int *xstart, int *ystart, int measure_width, int *extent, int *count); #define NO_MEASUREMENT \ 0, NULL, NULL static SDL_Surface* TTF_Render_Internal(TTF_Font *font, const char *text, str_type_t str_type, SDL_Color fg, SDL_Color bg, render_mode_t render_mode); static SDL_Surface* TTF_Render_Wrapped_Internal(TTF_Font *font, const char *text, str_type_t str_type, SDL_Color fg, SDL_Color bg, Uint32 wrapLength, render_mode_t render_mode); static SDL_INLINE int Find_GlyphByIndex(TTF_Font *font, FT_UInt idx, int want_bitmap, int want_pixmap, int want_color, int want_lcd, int want_subpixel, int translation, c_glyph **out_glyph, TTF_Image **out_image); static void Flush_Cache(TTF_Font *font); #if defined(USE_DUFFS_LOOP) /* 4-times unrolled loop */ #define DUFFS_LOOP4(pixel_copy_increment, width) \ { int n = (width+3)/4; \ switch (width & 3) { \ case 0: do { pixel_copy_increment; /* fallthrough */ \ case 3: pixel_copy_increment; /* fallthrough */ \ case 2: pixel_copy_increment; /* fallthrough */ \ case 1: pixel_copy_increment; /* fallthrough */ \ } while (--n > 0); \ } \ } #else /* Don't use Duff's device to unroll loops */ #define DUFFS_LOOP(pixel_copy_increment, width) \ { int n; \ for ( n=width; n > 0; --n ) { \ pixel_copy_increment; \ } \ } #define DUFFS_LOOP4(pixel_copy_increment, width) \ DUFFS_LOOP(pixel_copy_increment, width) #endif /* Blend colored glyphs */ static SDL_INLINE void BG_Blended_Color(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip, Uint8 fg_alpha) { const Uint32 *src = (Uint32 *)image->buffer; Uint32 *dst = destination; Uint32 width = image->width; Uint32 height = image->rows; if (fg_alpha == 0) { /* SDL_ALPHA_OPAQUE */ while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( *dst++ = *src++; , width); /* *INDENT-ON* */ src = (const Uint32 *)((const Uint8 *)src + srcskip); dst = (Uint32 *)((Uint8 *)dst + dstskip); } } else { Uint32 alpha; Uint32 tmp; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( /* prevent misaligned load: tmp = *src++; */ /* eventually, we can expect the compiler to replace the memcpy call with something optimized */ memcpy(&tmp, src++, sizeof(tmp)); /* This should NOT be SDL_memcpy */ alpha = tmp >> 24; tmp &= ~0xFF000000; alpha = fg_alpha * alpha; alpha = DIVIDE_BY_255(alpha) << 24; *dst++ = tmp | alpha , width); /* *INDENT-ON* */ src = (const Uint32 *)((const Uint8 *)src + srcskip); dst = (Uint32 *)((Uint8 *)dst + dstskip); } } } /* Blend with LCD rendering */ static SDL_INLINE void BG_Blended_LCD(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip, SDL_Color *fg) { const Uint32 *src = (Uint32 *)image->buffer; Uint32 *dst = destination; Uint32 width = image->width; Uint32 height = image->rows; Uint32 tmp, bg; Uint32 r, g, b; Uint8 fg_r, fg_g, fg_b; Uint8 bg_r, bg_g, bg_b; Uint32 bg_a; fg_r = fg->r; fg_g = fg->g; fg_b = fg->b; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( /* prevent misaligned load: tmp = *src++; */ memcpy(&tmp, src++, sizeof(tmp)); /* This should NOT be SDL_memcpy */ if (tmp) { bg = *dst; bg_a = bg & 0xff000000; bg_r = (bg >> 16) & 0xff; bg_g = (bg >> 8) & 0xff; bg_b = (bg >> 0) & 0xff; r = (tmp >> 16) & 0xff; g = (tmp >> 8) & 0xff; b = (tmp >> 0) & 0xff; r = fg_r * r + bg_r * (255 - r) + 127; r = DIVIDE_BY_255(r); g = fg_g * g + bg_g * (255 - g) + 127; g = DIVIDE_BY_255(g); b = fg_b * b + bg_b * (255 - b) + 127; b = DIVIDE_BY_255(b); r <<= 16; g <<= 8; b <<= 0; *dst = r | g | b | bg_a; } dst++; , width); /* *INDENT-ON* */ src = (const Uint32 *)((const Uint8 *)src + srcskip); dst = (Uint32 *)((Uint8 *)dst + dstskip); } } #if TTF_USE_SDF /* Blended Opaque SDF */ static SDL_INLINE void BG_Blended_Opaque_SDF(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip) { const Uint8 *src = image->buffer; Uint32 *dst = destination; Uint32 width = image->width; Uint32 height = image->rows; Uint32 s; Uint32 d; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( d = *dst; s = ((Uint32)*src++) << 24; if (s > d) { *dst = s; } dst++; , width); /* *INDENT-ON* */ src += srcskip; dst = (Uint32 *)((Uint8 *)dst + dstskip); } } /* Blended non-opaque SDF */ static SDL_INLINE void BG_Blended_SDF(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip, Uint8 fg_alpha) { const Uint8 *src = image->buffer; Uint32 *dst = destination; Uint32 width = image->width; Uint32 height = image->rows; Uint32 s; Uint32 d; Uint32 tmp; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( d = *dst; tmp = fg_alpha * (*src++); s = DIVIDE_BY_255(tmp) << 24; if (s > d) { *dst = s; } dst++; , width); /* *INDENT-ON* */ src += srcskip; dst = (Uint32 *)((Uint8 *)dst + dstskip); } } #endif /* TTF_USE_SDF */ /* Blended Opaque */ static SDL_INLINE void BG_Blended_Opaque(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip) { const Uint8 *src = image->buffer; Uint32 *dst = destination; Uint32 width = image->width; Uint32 height = image->rows; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( *dst++ |= ((Uint32)*src++) << 24; , width); /* *INDENT-ON* */ src += srcskip; dst = (Uint32 *)((Uint8 *)dst + dstskip); } } /* Blended non-opaque */ static SDL_INLINE void BG_Blended(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip, Uint8 fg_alpha) { const Uint8 *src = image->buffer; Uint32 *dst = destination; Uint32 width = image->width; Uint32 height = image->rows; Uint32 tmp; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( tmp = fg_alpha * (*src++); *dst++ |= DIVIDE_BY_255(tmp) << 24; , width); /* *INDENT-ON* */ src += srcskip; dst = (Uint32 *)((Uint8 *)dst + dstskip); } } #if defined(HAVE_BLIT_GLYPH_32) || defined(HAVE_BLIT_GLYPH_64) static SDL_INLINE void BG_Blended_Opaque_32(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip) { const Uint8 *src = image->buffer; Uint32 *dst = destination; Uint32 width = image->width / 4; Uint32 height = image->rows; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( *dst++ |= ((Uint32)*src++) << 24; *dst++ |= ((Uint32)*src++) << 24; *dst++ |= ((Uint32)*src++) << 24; *dst++ |= ((Uint32)*src++) << 24; , width); /* *INDENT-ON* */ src += srcskip; dst = (Uint32 *)((Uint8 *)dst + dstskip); } } static SDL_INLINE void BG_Blended_32(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip, Uint8 fg_alpha) { const Uint8 *src = image->buffer; Uint32 *dst = destination; Uint32 width = image->width / 4; Uint32 height = image->rows; Uint32 tmp0, tmp1, tmp2, tmp3; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( tmp0 = fg_alpha * (*src++); tmp1 = fg_alpha * (*src++); tmp2 = fg_alpha * (*src++); tmp3 = fg_alpha * (*src++); *dst++ |= DIVIDE_BY_255(tmp0) << 24; *dst++ |= DIVIDE_BY_255(tmp1) << 24; *dst++ |= DIVIDE_BY_255(tmp2) << 24; *dst++ |= DIVIDE_BY_255(tmp3) << 24; , width); /* *INDENT-ON* */ src += srcskip; dst = (Uint32 *)((Uint8 *)dst + dstskip); } } #endif #if defined(HAVE_SSE2_INTRINSICS) /* Apply: alpha_table[i] = i << 24; */ static SDL_INLINE void BG_Blended_Opaque_SSE(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip) { const __m128i *src = (__m128i *)image->buffer; __m128i *dst = (__m128i *)destination; Uint32 width = image->width / 16; Uint32 height = image->rows; __m128i s, s0, s1, s2, s3, d0, d1, d2, d3, r0, r1, r2, r3, L, H; const __m128i zero = _mm_setzero_si128(); while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( /* Read 16 Uint8 at once and put into 4 __m128i */ s = _mm_loadu_si128(src); // load unaligned d0 = _mm_load_si128(dst); // load d1 = _mm_load_si128(dst + 1); // load d2 = _mm_load_si128(dst + 2); // load d3 = _mm_load_si128(dst + 3); // load L = _mm_unpacklo_epi8(zero, s); H = _mm_unpackhi_epi8(zero, s); s0 = _mm_unpacklo_epi8(zero, L); s1 = _mm_unpackhi_epi8(zero, L); s2 = _mm_unpacklo_epi8(zero, H); s3 = _mm_unpackhi_epi8(zero, H); // already shifted by 24 r0 = _mm_or_si128(d0, s0); // or r1 = _mm_or_si128(d1, s1); // or r2 = _mm_or_si128(d2, s2); // or r3 = _mm_or_si128(d3, s3); // or _mm_store_si128(dst, r0); // store _mm_store_si128(dst + 1, r1); // store _mm_store_si128(dst + 2, r2); // store _mm_store_si128(dst + 3, r3); // store dst += 4; src += 1; , width); /* *INDENT-ON* */ src = (const __m128i *)((const Uint8 *)src + srcskip); dst = (__m128i *)((Uint8 *)dst + dstskip); } } static SDL_INLINE void BG_Blended_SSE(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip, Uint8 fg_alpha) { const __m128i *src = (__m128i *)image->buffer; __m128i *dst = (__m128i *)destination; Uint32 width = image->width / 16; Uint32 height = image->rows; const __m128i alpha = _mm_set1_epi16(fg_alpha); const __m128i one = _mm_set1_epi16(1); const __m128i zero = _mm_setzero_si128(); __m128i s, s0, s1, s2, s3, d0, d1, d2, d3, r0, r1, r2, r3, L, H, Ls8, Hs8; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( /* Read 16 Uint8 at once and put into 4 __m128i */ s = _mm_loadu_si128(src); // load unaligned d0 = _mm_load_si128(dst); // load d1 = _mm_load_si128(dst + 1); // load d2 = _mm_load_si128(dst + 2); // load d3 = _mm_load_si128(dst + 3); // load L = _mm_unpacklo_epi8(s, zero); // interleave, no shifting H = _mm_unpackhi_epi8(s, zero); // enough room to multiply /* Apply: alpha_table[i] = ((i * fg.a / 255) << 24; */ /* Divide by 255 is done as: (x + 1 + (x >> 8)) >> 8 */ L = _mm_mullo_epi16(L, alpha); // x := i * fg.a H = _mm_mullo_epi16(H, alpha); Ls8 = _mm_srli_epi16(L, 8); // x >> 8 Hs8 = _mm_srli_epi16(H, 8); L = _mm_add_epi16(L, one); // x + 1 H = _mm_add_epi16(H, one); L = _mm_add_epi16(L, Ls8); // x + 1 + (x >> 8) H = _mm_add_epi16(H, Hs8); L = _mm_srli_epi16(L, 8); // ((x + 1 + (x >> 8)) >> 8 H = _mm_srli_epi16(H, 8); L = _mm_slli_epi16(L, 8); // shift << 8, so we're prepared H = _mm_slli_epi16(H, 8); // to have final format << 24 s0 = _mm_unpacklo_epi8(zero, L); s1 = _mm_unpackhi_epi8(zero, L); s2 = _mm_unpacklo_epi8(zero, H); s3 = _mm_unpackhi_epi8(zero, H); // already shifted by 24 r0 = _mm_or_si128(d0, s0); // or r1 = _mm_or_si128(d1, s1); // or r2 = _mm_or_si128(d2, s2); // or r3 = _mm_or_si128(d3, s3); // or _mm_store_si128(dst, r0); // store _mm_store_si128(dst + 1, r1); // store _mm_store_si128(dst + 2, r2); // store _mm_store_si128(dst + 3, r3); // store dst += 4; src += 1; , width); /* *INDENT-ON* */ src = (const __m128i *)((const Uint8 *)src + srcskip); dst = (__m128i *)((Uint8 *)dst + dstskip); } } #endif #if defined(HAVE_NEON_INTRINSICS) /* Apply: alpha_table[i] = i << 24; */ static SDL_INLINE void BG_Blended_Opaque_NEON(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip) { const Uint32 *src = (Uint32 *)image->buffer; Uint32 *dst = destination; Uint32 width = image->width / 16; Uint32 height = image->rows; uint32x4_t s, d0, d1, d2, d3, r0, r1, r2, r3; uint8x16x2_t sx, sx01, sx23; uint32x4_t zero = vmovq_n_u32(0); while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( /* Read 4 Uint32 and put 16 Uint8 into uint32x4x2_t (uint8x16x2_t) * takes advantage of vzipq_u8 which produces two lanes */ s = vld1q_u32(src); // load d0 = vld1q_u32(dst); // load d1 = vld1q_u32(dst + 4); // load d2 = vld1q_u32(dst + 8); // load d3 = vld1q_u32(dst + 12); // load sx = vzipq_u8(zero, s); // interleave sx01 = vzipq_u8(zero, sx.val[0]); // interleave sx23 = vzipq_u8(zero, sx.val[1]); // interleave // already shifted by 24 r0 = vorrq_u32(d0, sx01.val[0]); // or r1 = vorrq_u32(d1, sx01.val[1]); // or r2 = vorrq_u32(d2, sx23.val[0]); // or r3 = vorrq_u32(d3, sx23.val[1]); // or vst1q_u32(dst, r0); // store vst1q_u32(dst + 4, r1); // store vst1q_u32(dst + 8, r2); // store vst1q_u32(dst + 12, r3); // store dst += 16; src += 4; , width); /* *INDENT-ON* */ src = (const Uint32 *)((const Uint8 *)src + srcskip); dst = (Uint32 *)((Uint8 *)dst + dstskip); } } /* Non-opaque, computes alpha blending on the fly */ static SDL_INLINE void BG_Blended_NEON(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip, Uint8 fg_alpha) { const Uint32 *src = (Uint32 *)image->buffer; Uint32 *dst = destination; Uint32 width = image->width / 16; Uint32 height = image->rows; uint32x4_t s, d0, d1, d2, d3, r0, r1, r2, r3; uint16x8_t Ls8, Hs8; uint8x16x2_t sx, sx01, sx23; const uint16x8_t alpha = vmovq_n_u16(fg_alpha); const uint16x8_t one = vmovq_n_u16(1); const uint32x4_t zero = vmovq_n_u32(0); while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( /* Read 4 Uint32 and put 16 Uint8 into uint32x4x2_t (uint8x16x2_t) * takes advantage of vzipq_u8 which produces two lanes */ s = vld1q_u32(src); // load d0 = vld1q_u32(dst); // load d1 = vld1q_u32(dst + 4); // load d2 = vld1q_u32(dst + 8); // load d3 = vld1q_u32(dst + 12); // load sx = vzipq_u8(s, zero); // interleave, no shifting // enough room to multiply /* Apply: alpha_table[i] = ((i * fg.a / 255) << 24; */ /* Divide by 255 is done as: (x + 1 + (x >> 8)) >> 8 */ sx.val[0] = vmulq_u16(sx.val[0], alpha); // x := i * fg.a sx.val[1] = vmulq_u16(sx.val[1], alpha); Ls8 = vshrq_n_u16(sx.val[0], 8); // x >> 8 Hs8 = vshrq_n_u16(sx.val[1], 8); sx.val[0] = vaddq_u16(sx.val[0], one); // x + 1 sx.val[1] = vaddq_u16(sx.val[1], one); sx.val[0] = vaddq_u16(sx.val[0], Ls8); // x + 1 + (x >> 8) sx.val[1] = vaddq_u16(sx.val[1], Hs8); sx.val[0] = vshrq_n_u16(sx.val[0], 8); // ((x + 1 + (x >> 8)) >> 8 sx.val[1] = vshrq_n_u16(sx.val[1], 8); sx.val[0] = vshlq_n_u16(sx.val[0], 8); // shift << 8, so we're prepared sx.val[1] = vshlq_n_u16(sx.val[1], 8); // to have final format << 24 sx01 = vzipq_u8(zero, sx.val[0]); // interleave sx23 = vzipq_u8(zero, sx.val[1]); // interleave // already shifted by 24 r0 = vorrq_u32(d0, sx01.val[0]); // or r1 = vorrq_u32(d1, sx01.val[1]); // or r2 = vorrq_u32(d2, sx23.val[0]); // or r3 = vorrq_u32(d3, sx23.val[1]); // or vst1q_u32(dst, r0); // store vst1q_u32(dst + 4, r1); // store vst1q_u32(dst + 8, r2); // store vst1q_u32(dst + 12, r3); // store dst += 16; src += 4; , width); /* *INDENT-ON* */ src = (const Uint32 *)((const Uint8 *)src + srcskip); dst = (Uint32 *)((Uint8 *)dst + dstskip); } } #endif static SDL_INLINE void BG(const TTF_Image *image, Uint8 *destination, Sint32 srcskip, Uint32 dstskip) { const Uint8 *src = image->buffer; Uint8 *dst = destination; Uint32 width = image->width; Uint32 height = image->rows; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( *dst++ |= *src++; , width); /* *INDENT-ON* */ src += srcskip; dst += dstskip; } } #if defined(HAVE_BLIT_GLYPH_64) static SDL_INLINE void BG_64(const TTF_Image *image, Uint8 *destination, Sint32 srcskip, Uint32 dstskip) { const Uint64 *src = (Uint64 *)image->buffer; Uint64 *dst = (Uint64 *)destination; Uint32 width = image->width / 8; Uint32 height = image->rows; Uint64 tmp; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( /* prevent misaligned load: *dst++ |= *src++; */ memcpy(&tmp, src++, sizeof(tmp)); /* This should NOT be SDL_memcpy */ *dst++ |= tmp; , width); /* *INDENT-ON* */ src = (const Uint64 *)((const Uint8 *)src + srcskip); dst = (Uint64 *)((Uint8 *)dst + dstskip); } } #elif defined(HAVE_BLIT_GLYPH_32) static SDL_INLINE void BG_32(const TTF_Image *image, Uint8 *destination, Sint32 srcskip, Uint32 dstskip) { const Uint32 *src = (Uint32 *)image->buffer; Uint32 *dst = (Uint32 *)destination; Uint32 width = image->width / 4; Uint32 height = image->rows; Uint32 tmp; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( /* prevent misaligned load: *dst++ |= *src++; */ memcpy(&tmp, src++, sizeof(tmp)); /* This should NOT be SDL_memcpy */ *dst++ |= tmp; , width); /* *INDENT-ON* */ src = (const Uint32 *)((const Uint8 *)src + srcskip); dst = (Uint32 *)((Uint8 *)dst + dstskip); } } #endif #if defined(HAVE_SSE2_INTRINSICS) static SDL_INLINE void BG_SSE(const TTF_Image *image, Uint8 *destination, Sint32 srcskip, Uint32 dstskip) { const __m128i *src = (__m128i *)image->buffer; __m128i *dst = (__m128i *)destination; Uint32 width = image->width / 16; Uint32 height = image->rows; __m128i s, d, r; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( s = _mm_loadu_si128(src); // load unaligned d = _mm_load_si128(dst); // load r = _mm_or_si128(d, s); // or _mm_store_si128(dst, r); // store src += 1; dst += 1; , width); /* *INDENT-ON* */ src = (const __m128i *)((const Uint8 *)src + srcskip); dst = (__m128i *)((Uint8 *)dst + dstskip); } } #endif #if defined(HAVE_NEON_INTRINSICS) static SDL_INLINE void BG_NEON(const TTF_Image *image, Uint8 *destination, Sint32 srcskip, Uint32 dstskip) { const Uint8 *src = image->buffer; Uint8 *dst = destination; Uint32 width = image->width / 16; Uint32 height = image->rows; uint8x16_t s, d, r; while (height--) { /* *INDENT-OFF* */ DUFFS_LOOP4( s = vld1q_u8(src); // load d = vld1q_u8(dst); // load r = vorrq_u8(d, s); // or vst1q_u8(dst, r); // store src += 16; dst += 16; , width); /* *INDENT-ON* */ src = (const Uint8 *)((const Uint8 *)src + srcskip); dst += dstskip; } } #endif /* Underline and Strikethrough style. Draw a line at the given row. */ static void Draw_Line(TTF_Font *font, const SDL_Surface *textbuf, int column, int row, int line_width, int line_thickness, Uint32 color, const render_mode_t render_mode) { int tmp = row + line_thickness - textbuf->h; int x_offset = column * textbuf->format->BytesPerPixel; Uint8 *dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch + x_offset; #if TTF_USE_HARFBUZZ hb_direction_t hb_direction = font->hb_direction; if (hb_direction == HB_DIRECTION_INVALID) { hb_direction = g_hb_direction; } /* No Underline/Strikethrough style if direction is vertical */ if (hb_direction == HB_DIRECTION_TTB || hb_direction == HB_DIRECTION_BTT) { return; } #else (void) font; #endif /* Not needed because of "font->height = SDL_max(font->height, bottom_row);". * But if you patch to render textshaping and break line in middle of a cluster, * (which is a bad usage and a corner case), you need this to prevent out of bounds. * You can get an "ystart" for the "whole line", which is different (and smaller) * than the ones of the "splitted lines". */ if (tmp > 0) { line_thickness -= tmp; } /* Previous case also happens with SDF (render_sdf) , because 'spread' property * requires to increase 'ystart' * Check for valid value anyway. */ if (line_thickness <= 0) { return; } /* Wrapped mode with an unbroken line: 'line_width' is greater that 'textbuf->w' */ line_width = SDL_min(line_width, textbuf->w); if (render_mode == RENDER_BLENDED || render_mode == RENDER_LCD) { while (line_thickness--) { SDL_memset4(dst, color, line_width); dst += textbuf->pitch; } } else { while (line_thickness--) { SDL_memset(dst, color, line_width); dst += textbuf->pitch; } } } static void clip_glyph(int *_x, int *_y, TTF_Image *image, const SDL_Surface *textbuf, int is_lcd) { int above_w; int above_h; int x = *_x; int y = *_y; int srcbpp = 1; if (image->is_color || is_lcd) { srcbpp = 4; } /* Don't go below x=0 */ if (x < 0) { int tmp = -x; x = 0; image->width -= tmp; image->buffer += srcbpp * tmp; } /* Don't go above textbuf->w */ above_w = x + image->width - textbuf->w; if (above_w > 0) { image->width -= above_w; } /* Don't go below y=0 */ if (y < 0) { int tmp = -y; y = 0; image->rows -= tmp; image->buffer += tmp * image->pitch; } /* Don't go above textbuf->h */ above_h = y + image->rows - textbuf->h; if (above_h > 0) { image->rows -= above_h; } /* Could be negative if (x > textbuf->w), or if (x + width < 0) */ image->width = SDL_max(0, image->width); image->rows = SDL_max(0, image->rows); /* After 'image->width' clipping: * Make sure 'rows' is also 0, so it doesn't break USE_DUFFS_LOOP */ if (image->width == 0) { image->rows = 0; } *_x = x; *_y = y; } /* Glyph width is rounded, dst addresses are aligned, src addresses are not aligned */ static int Get_Alignment(void) { #if defined(HAVE_NEON_INTRINSICS) if (hasNEON()) { return 16; } #endif #if defined(HAVE_SSE2_INTRINSICS) if (hasSSE2()) { return 16; } #endif #if defined(HAVE_BLIT_GLYPH_64) return 8; #elif defined(HAVE_BLIT_GLYPH_32) return 4; #else return 1; #endif } #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-value" #endif #define BUILD_RENDER_LINE(NAME, IS_BLENDED, IS_BLENDED_OPAQUE, IS_LCD, WB_WP_WC, WS, BLIT_GLYPH_BLENDED_OPAQUE_OPTIM, BLIT_GLYPH_BLENDED_OPTIM, BLIT_GLYPH_OPTIM) \ \ static SDL_INLINE \ int Render_Line_##NAME(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) \ { \ const int alignment = Get_Alignment() - 1; \ const int bpp = ((IS_BLENDED || IS_LCD) ? 4 : 1); \ unsigned int i; \ Uint8 fg_alpha = (fg ? fg->a : 0); \ for (i = 0; i < font->pos_len; i++) { \ FT_UInt idx = font->pos_buf[i].index; \ int x = font->pos_buf[i].x; \ int y = font->pos_buf[i].y; \ TTF_Image *image; \ \ if (Find_GlyphByIndex(font, idx, WB_WP_WC, WS, x & 63, NULL, &image) == 0) { \ int above_w, above_h; \ Uint32 dstskip; \ Sint32 srcskip; /* Can be negative */ \ Uint8 *dst; \ int remainder; \ Uint8 *saved_buffer = image->buffer; \ int saved_width = image->width; \ image->buffer += alignment; \ /* Position updated after glyph rendering */ \ x = xstart + FT_FLOOR(x) + image->left; \ y = ystart + FT_FLOOR(y) - image->top; \ \ /* Make sure glyph is inside textbuf */ \ above_w = x + image->width - textbuf->w; \ above_h = y + image->rows - textbuf->h; \ \ if (x >= 0 && y >= 0 && above_w <= 0 && above_h <= 0) { \ /* Most often, glyph is inside textbuf */ \ /* Compute dst */ \ dst = (Uint8 *)textbuf->pixels + y * textbuf->pitch + x * bpp; \ /* Align dst, get remainder, shift & align glyph width */ \ remainder = ((uintptr_t)dst & alignment) / bpp; \ dst = (Uint8 *)((uintptr_t)dst & ~alignment); \ image->buffer -= remainder; \ image->width = (image->width + remainder + alignment) & ~alignment; \ /* Compute srcskip, dstskip */ \ srcskip = image->pitch - image->width; \ dstskip = textbuf->pitch - image->width * bpp; \ /* Render glyph at (x, y) with optimized copy functions */ \ if (IS_LCD) { \ image->buffer = saved_buffer; \ image->buffer += alignment; \ image->width = saved_width; \ dst = (Uint8 *)textbuf->pixels + y * textbuf->pitch + x * bpp; \ /* Compute srcskip, dstskip */ \ srcskip = image->pitch - 4 * image->width; \ dstskip = textbuf->pitch - image->width * bpp; \ BG_Blended_LCD(image, (Uint32 *)dst, srcskip, dstskip, fg); \ } else if (!IS_BLENDED || image->is_color == 0) { \ if (IS_BLENDED_OPAQUE) { \ BLIT_GLYPH_BLENDED_OPAQUE_OPTIM(image, (Uint32 *)dst, srcskip, dstskip); \ } else if (IS_BLENDED) { \ BLIT_GLYPH_BLENDED_OPTIM(image, (Uint32 *)dst, srcskip, dstskip, fg_alpha); \ } else { \ BLIT_GLYPH_OPTIM(image, dst, srcskip, dstskip); \ } \ } else if (IS_BLENDED && image->is_color) { \ image->buffer = saved_buffer; \ image->buffer += alignment; \ image->width = saved_width; \ dst = (Uint8 *)textbuf->pixels + y * textbuf->pitch + x * bpp; \ /* Compute srcskip, dstskip */ \ srcskip = image->pitch - 4 * image->width; \ dstskip = textbuf->pitch - image->width * bpp; \ BG_Blended_Color(image, (Uint32 *)dst, srcskip, dstskip, fg_alpha); \ } \ /* restore modification */ \ image->width = saved_width; \ } else { \ /* Modify a copy, and clip it */ \ TTF_Image image_clipped = *image; \ /* Intersect image glyph at (x,y) with textbuf */ \ clip_glyph(&x, &y, &image_clipped, textbuf, IS_LCD); \ /* Compute dst */ \ dst = (Uint8 *)textbuf->pixels + y * textbuf->pitch + x * bpp; \ /* Compute srcskip, dstskip */ \ srcskip = image_clipped.pitch - image_clipped.width; \ dstskip = textbuf->pitch - image_clipped.width * bpp; \ /* Render glyph at (x, y) */ \ if (IS_LCD) { \ srcskip -= 3 * image_clipped.width; \ BG_Blended_LCD(&image_clipped, (Uint32 *)dst, srcskip, dstskip, fg); \ } else if (!IS_BLENDED || image->is_color == 0) { \ if (IS_BLENDED_OPAQUE) { \ BG_Blended_Opaque(&image_clipped, (Uint32 *)dst, srcskip, dstskip); \ } else if (IS_BLENDED) { \ BG_Blended(&image_clipped, (Uint32 *)dst, srcskip, dstskip, fg_alpha); \ } else { \ BG(&image_clipped, dst, srcskip, dstskip); \ } \ } else if (IS_BLENDED && image->is_color) { \ srcskip -= 3 * image_clipped.width; \ BG_Blended_Color(&image_clipped, (Uint32 *)dst, srcskip, dstskip, fg_alpha); \ } \ } \ image->buffer = saved_buffer; \ } else { \ return -1; \ } \ } \ \ return 0; \ } \ \ #define BITMAP CACHED_BITMAP, 0, 0, 0 #define PIXMAP 0, CACHED_PIXMAP, 0, 0 #define COLOR 0, 0, CACHED_COLOR, 0 #define LCD 0, 0, 0, CACHED_LCD #define SUBPIX CACHED_SUBPIX /* BUILD_RENDER_LINE(NAME, IS_BLENDED, IS_BLENDED_OPAQUE, WANT_BITMAP_PIXMAP_COLOR_LCD, WANT_SUBPIXEL, BLIT_GLYPH_BLENDED_OPAQUE_OPTIM, BLIT_GLYPH_BLENDED_OPTIM, BLIT_GLYPH_OPTIM) */ #if defined(HAVE_SSE2_INTRINSICS) BUILD_RENDER_LINE(SSE_Shaded , 0, 0, 0, PIXMAP, 0 , , , BG_SSE ) BUILD_RENDER_LINE(SSE_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended_SSE , ) BUILD_RENDER_LINE(SSE_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque_SSE , , ) BUILD_RENDER_LINE(SSE_Solid , 0, 0, 0, BITMAP, 0 , , , BG_SSE ) BUILD_RENDER_LINE(SSE_Shaded_SP , 0, 0, 0, PIXMAP, SUBPIX, , , BG_SSE ) BUILD_RENDER_LINE(SSE_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended_SSE , ) BUILD_RENDER_LINE(SSE_Blended_Opaque_SP , 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque_SSE , , ) BUILD_RENDER_LINE(SSE_LCD , 0, 0, 1, LCD, 0, , , ) BUILD_RENDER_LINE(SSE_LCD_SP , 0, 0, 1, LCD, SUBPIX, , , ) #endif #if defined(HAVE_NEON_INTRINSICS) BUILD_RENDER_LINE(NEON_Shaded , 0, 0, 0, PIXMAP, 0 , , , BG_NEON ) BUILD_RENDER_LINE(NEON_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended_NEON, ) BUILD_RENDER_LINE(NEON_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque_NEON, , ) BUILD_RENDER_LINE(NEON_Solid , 0, 0, 0, BITMAP, 0 , , , BG_NEON ) BUILD_RENDER_LINE(NEON_Shaded_SP , 0, 0, 0, PIXMAP, SUBPIX, , , BG_NEON ) BUILD_RENDER_LINE(NEON_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended_NEON, ) BUILD_RENDER_LINE(NEON_Blended_Opaque_SP, 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque_NEON, , ) BUILD_RENDER_LINE(NEON_LCD , 0, 0, 1, LCD, 0 , , , ) BUILD_RENDER_LINE(NEON_LCD_SP , 0, 0, 1, LCD, SUBPIX, , , ) #endif #if defined(HAVE_BLIT_GLYPH_64) BUILD_RENDER_LINE(64_Shaded , 0, 0, 0, PIXMAP, 0 , , , BG_64 ) BUILD_RENDER_LINE(64_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended_32 , ) BUILD_RENDER_LINE(64_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque_32 , , ) BUILD_RENDER_LINE(64_Solid , 0, 0, 0, BITMAP, 0 , , , BG_64 ) BUILD_RENDER_LINE(64_Shaded_SP , 0, 0, 0, PIXMAP, SUBPIX, , , BG_64 ) BUILD_RENDER_LINE(64_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended_32 , ) BUILD_RENDER_LINE(64_Blended_Opaque_SP , 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque_32 , , ) BUILD_RENDER_LINE(64_LCD , 0, 0, 1, LCD, 0 , , , ) BUILD_RENDER_LINE(64_LCD_SP , 0, 0, 1, LCD, SUBPIX, , , ) #elif defined(HAVE_BLIT_GLYPH_32) BUILD_RENDER_LINE(32_Shaded , 0, 0, 0, PIXMAP, 0 , , , BG_32 ) BUILD_RENDER_LINE(32_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended_32 , ) BUILD_RENDER_LINE(32_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque_32 , , ) BUILD_RENDER_LINE(32_Solid , 0, 0, 0, BITMAP, 0 , , , BG_32 ) BUILD_RENDER_LINE(32_Shaded_SP , 0, 0, 0, PIXMAP, SUBPIX, , , BG_32 ) BUILD_RENDER_LINE(32_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended_32 , ) BUILD_RENDER_LINE(32_Blended_Opaque_SP , 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque_32 , , ) BUILD_RENDER_LINE(32_LCD , 0, 0, 1, LCD, 0 , , , ) BUILD_RENDER_LINE(32_LCD_SP , 0, 0, 1, LCD, SUBPIX, , , ) #else BUILD_RENDER_LINE(8_Shaded , 0, 0, 0, PIXMAP, 0 , , , BG ) BUILD_RENDER_LINE(8_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended , ) BUILD_RENDER_LINE(8_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque , , ) BUILD_RENDER_LINE(8_Solid , 0, 0, 0, BITMAP, 0 , , , BG ) BUILD_RENDER_LINE(8_Shaded_SP , 0, 0, 0, PIXMAP, SUBPIX, , , BG ) BUILD_RENDER_LINE(8_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended , ) BUILD_RENDER_LINE(8_Blended_Opaque_SP , 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque , , ) BUILD_RENDER_LINE(8_LCD , 0, 0, 1, LCD, 0 , , , ) BUILD_RENDER_LINE(8_LCD_SP , 0, 0, 1, LCD, SUBPIX, , , ) #endif #if TTF_USE_SDF static int (*Render_Line_SDF_Shaded)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) = NULL; BUILD_RENDER_LINE(SDF_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended_SDF , ) BUILD_RENDER_LINE(SDF_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque_SDF , , ) static int (*Render_Line_SDF_Solid)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) = NULL; static int (*Render_Line_SDF_Shaded_SP)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) = NULL; BUILD_RENDER_LINE(SDF_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended_SDF , ) BUILD_RENDER_LINE(SDF_Blended_Opaque_SP , 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque_SDF , , ) static int (*Render_Line_SDF_LCD)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) = NULL; static int (*Render_Line_SDF_LCD_SP)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) = NULL; #endif #ifdef __GNUC__ #pragma GCC diagnostic pop #endif static SDL_INLINE int Render_Line(const render_mode_t render_mode, int subpixel, TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color fg) { /* Render line (pos_buf) to textbuf at (xstart, ystart) */ /* Subpixel with RENDER_SOLID doesn't make sense. */ /* (and 'cached->subpixel.translation' would need to distinguish bitmap/pixmap). */ int is_opaque = (fg.a == SDL_ALPHA_OPAQUE); #define Call_Specific_Render_Line(NAME) \ if (render_mode == RENDER_SHADED) { \ if (subpixel == 0) { \ return Render_Line_##NAME##_Shaded(font, textbuf, xstart, ystart, NULL); \ } else { \ return Render_Line_##NAME##_Shaded_SP(font, textbuf, xstart, ystart, NULL); \ } \ } else if (render_mode == RENDER_BLENDED) { \ if (is_opaque) { \ if (subpixel == 0) { \ return Render_Line_##NAME##_Blended_Opaque(font, textbuf, xstart, ystart, NULL); \ } else { \ return Render_Line_##NAME##_Blended_Opaque_SP(font, textbuf, xstart, ystart, NULL); \ } \ } else { \ if (subpixel == 0) { \ return Render_Line_##NAME##_Blended(font, textbuf, xstart, ystart, &fg); \ } else { \ return Render_Line_##NAME##_Blended_SP(font, textbuf, xstart, ystart, &fg); \ } \ } \ } else if (render_mode == RENDER_LCD) { \ if (subpixel == 0) { \ return Render_Line_##NAME##_LCD(font, textbuf, xstart, ystart, &fg); \ } else { \ return Render_Line_##NAME##_LCD_SP(font, textbuf, xstart, ystart, &fg); \ } \ } else { \ return Render_Line_##NAME##_Solid(font, textbuf, xstart, ystart, NULL); \ } #if TTF_USE_SDF if (font->render_sdf && render_mode == RENDER_BLENDED) { Call_Specific_Render_Line(SDF) } #endif #if defined(HAVE_NEON_INTRINSICS) if (hasNEON()) { Call_Specific_Render_Line(NEON) } #endif #if defined(HAVE_SSE2_INTRINSICS) if (hasSSE2()) { Call_Specific_Render_Line(SSE) } #endif #if defined(HAVE_BLIT_GLYPH_64) Call_Specific_Render_Line(64) #elif defined(HAVE_BLIT_GLYPH_32) Call_Specific_Render_Line(32) #else Call_Specific_Render_Line(8) #endif } #ifndef SIZE_MAX # define SIZE_MAX ((size_t)(-1)) #endif #if !SDL_VERSION_ATLEAST(2, 23, 1) SDL_FORCE_INLINE int compat_size_add_overflow (size_t a, size_t b, size_t *ret) { if (b > SIZE_MAX - a) { return -1; } *ret = a + b; return 0; } SDL_FORCE_INLINE int compat_size_mul_overflow (size_t a, size_t b, size_t *ret) { if (a != 0 && b > SIZE_MAX / a) { return -1; } *ret = a * b; return 0; } #define SDL_size_add_overflow(a, b, r) compat_size_add_overflow(a, b, r) #define SDL_size_mul_overflow(a, b, r) compat_size_mul_overflow(a, b, r) #endif /* SDL < 2.23.1 */ /* Create a surface with memory: * - pitch is rounded to alignment * - address is aligned * * If format is 4 bytes per pixel, bgcolor is used to initialize each * 4-byte word in the image data. * * Otherwise, the low byte of format is used to initialize each byte * in the image data. */ static SDL_Surface *AllocateAlignedPixels(size_t width, size_t height, SDL_PixelFormatEnum format, Uint32 bgcolor) { const size_t alignment = Get_Alignment() - 1; const size_t bytes_per_pixel = SDL_BYTESPERPIXEL(format); SDL_Surface *textbuf = NULL; size_t size; size_t data_bytes; void *pixels, *ptr; size_t pitch; /* Worst case at the end of line pulling 'alignment' extra blank pixels */ if (width > SDL_MAX_SINT32 || height > SDL_MAX_SINT32 || SDL_size_add_overflow(width, alignment, &pitch) || SDL_size_mul_overflow(pitch, bytes_per_pixel, &pitch) || SDL_size_add_overflow(pitch, alignment, &pitch) || pitch > SDL_MAX_SINT32) { return NULL; } pitch &= ~alignment; if (SDL_size_mul_overflow(height, pitch, &data_bytes) || SDL_size_add_overflow(data_bytes, sizeof (void *) + alignment, &size) || size > SDL_MAX_SINT32) { /* Overflow... */ return NULL; } ptr = SDL_malloc(size); if (ptr == NULL) { return NULL; } /* address is aligned */ pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment); ((void **)pixels)[-1] = ptr; textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, (int)width, (int)height, 0, (int)pitch, format); if (textbuf == NULL) { SDL_free(ptr); return NULL; } /* Let SDL handle the memory allocation */ textbuf->flags &= ~SDL_PREALLOC; textbuf->flags |= SDL_SIMD_ALIGNED; if (bytes_per_pixel == 4) { SDL_memset4(pixels, bgcolor, data_bytes / 4); } else { SDL_memset(pixels, (bgcolor & 0xff), data_bytes); } return textbuf; } static SDL_Surface* Create_Surface_Solid(int width, int height, SDL_Color fg, Uint32 *color) { SDL_Surface *textbuf = AllocateAlignedPixels(width, height, SDL_PIXELFORMAT_INDEX8, 0); if (textbuf == NULL) { return NULL; } /* Underline/Strikethrough color style */ *color = 1; /* Fill the palette: 1 is foreground */ { SDL_Palette *palette = textbuf->format->palette; palette->colors[0].r = 255 - fg.r; palette->colors[0].g = 255 - fg.g; palette->colors[0].b = 255 - fg.b; palette->colors[1].r = fg.r; palette->colors[1].g = fg.g; palette->colors[1].b = fg.b; palette->colors[1].a = fg.a; } SDL_SetColorKey(textbuf, SDL_TRUE, 0); return textbuf; } static SDL_Surface* Create_Surface_Shaded(int width, int height, SDL_Color fg, SDL_Color bg, Uint32 *color) { SDL_Surface *textbuf = AllocateAlignedPixels(width, height, SDL_PIXELFORMAT_INDEX8, 0); Uint8 bg_alpha = bg.a; if (textbuf == NULL) { return NULL; } /* Underline/Strikethrough color style */ *color = NUM_GRAYS - 1; /* Support alpha blending */ if (fg.a != SDL_ALPHA_OPAQUE || bg.a != SDL_ALPHA_OPAQUE) { SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND); /* Would disturb alpha palette */ if (bg.a == SDL_ALPHA_OPAQUE) { bg.a = 0; } } /* Fill the palette with NUM_GRAYS levels of shading from bg to fg */ { SDL_Palette *palette = textbuf->format->palette; int rdiff = fg.r - bg.r; int gdiff = fg.g - bg.g; int bdiff = fg.b - bg.b; int adiff = fg.a - bg.a; int sign_r = (rdiff >= 0) ? 1 : 255; int sign_g = (gdiff >= 0) ? 1 : 255; int sign_b = (bdiff >= 0) ? 1 : 255; int sign_a = (adiff >= 0) ? 1 : 255; int i; for (i = 0; i < NUM_GRAYS; ++i) { /* Compute color[i] = (i * color_diff / 255) */ int tmp_r = i * rdiff; int tmp_g = i * gdiff; int tmp_b = i * bdiff; int tmp_a = i * adiff; palette->colors[i].r = (Uint8)(bg.r + DIVIDE_BY_255_SIGNED(tmp_r, sign_r)); palette->colors[i].g = (Uint8)(bg.g + DIVIDE_BY_255_SIGNED(tmp_g, sign_g)); palette->colors[i].b = (Uint8)(bg.b + DIVIDE_BY_255_SIGNED(tmp_b, sign_b)); palette->colors[i].a = (Uint8)(bg.a + DIVIDE_BY_255_SIGNED(tmp_a, sign_a)); } /* Make sure background has the correct alpha value */ palette->colors[0].a = bg_alpha; } return textbuf; } static SDL_Surface *Create_Surface_Blended(int width, int height, SDL_Color fg, Uint32 *color) { SDL_Surface *textbuf = NULL; Uint32 bgcolor; /* Background color: initialize with fg and 0 alpha */ bgcolor = (fg.r << 16) | (fg.g << 8) | fg.b; /* Underline/Strikethrough color style */ *color = bgcolor | ((Uint32)fg.a << 24); /* Create the target surface if required */ if (width != 0) { textbuf = AllocateAlignedPixels(width, height, SDL_PIXELFORMAT_ARGB8888, bgcolor); if (textbuf == NULL) { return NULL; } /* Support alpha blending */ if (fg.a != SDL_ALPHA_OPAQUE) { SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND); } } return textbuf; } static SDL_Surface* Create_Surface_LCD(int width, int height, SDL_Color fg, SDL_Color bg, Uint32 *color) { SDL_Surface *textbuf = NULL; Uint32 bgcolor; /* Background color */ bgcolor = (((Uint32)bg.a) << 24) | (bg.r << 16) | (bg.g << 8) | bg.b; /* Underline/Strikethrough color style */ *color = (((Uint32)bg.a) << 24) | (fg.r << 16) | (fg.g << 8) | fg.b; /* Create the target surface if required */ if (width != 0) { textbuf = AllocateAlignedPixels(width, height, SDL_PIXELFORMAT_ARGB8888, bgcolor); if (textbuf == NULL) { return NULL; } /* Support alpha blending */ if (bg.a != SDL_ALPHA_OPAQUE) { SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND); } } return textbuf; } /* rcg06192001 get linked library's version. */ const SDL_version* TTF_Linked_Version(void) { static SDL_version linked_version; SDL_TTF_VERSION(&linked_version); return &linked_version; } /* This function tells the library whether UNICODE text is generally byteswapped. A UNICODE BOM character at the beginning of a string will override this setting for that string. */ void TTF_ByteSwappedUNICODE(SDL_bool swapped) { TTF_byteswapped = swapped; } #if defined(USE_FREETYPE_ERRORS) static void TTF_SetFTError(const char *msg, FT_Error error) { #undef FTERRORS_H_ #define FT_ERRORDEF(e, v, s) { e, s }, #define FT_ERROR_START_LIST { #define FT_ERROR_END_LIST { 0, NULL } }; const struct { int err_code; const char *err_msg; } ft_errors[] = #include FT_ERRORS_H unsigned int i; const char *err_msg = NULL; for (i = 0; i < sizeof (ft_errors) / sizeof (ft_errors[0]); ++i) { if (error == ft_errors[i].err_code) { err_msg = ft_errors[i].err_msg; break; } } if (!err_msg) { err_msg = "unknown FreeType error"; } TTF_SetError("%s: %s", msg, err_msg); } #else #define TTF_SetFTError(msg, error) TTF_SetError(msg) #endif /* USE_FREETYPE_ERRORS */ int TTF_Init(void) { int status = 0; /* Some debug to know how it gets compiled */ #if 0 int duffs = 0, sse2 = 0, neon = 0, compil_sse2 = 0, compil_neon = 0; # if defined(USE_DUFFS_LOOP) duffs = 1; # endif # if defined(HAVE_SSE2_INTRINSICS) sse2 = hasSSE2(); compil_sse2 = 1; # endif # if defined(HAVE_NEON_INTRINSICS) neon = hasNEON(); compil_neon = 1; # endif SDL_Log("SDL_ttf: hasSSE2=%d hasNEON=%d alignment=%d duffs_loop=%d compil_sse2=%d compil_neon=%d", sse2, neon, Get_Alignment(), duffs, compil_sse2, compil_neon); SDL_Log("Sizeof TTF_Image: %d c_glyph: %d TTF_Font: %d", sizeof (TTF_Image), sizeof (c_glyph), sizeof (TTF_Font)); #endif if (!TTF_initialized) { FT_Error error = FT_Init_FreeType(&library); if (error) { TTF_SetFTError("Couldn't init FreeType engine", error); status = -1; } } if (status == 0) { ++TTF_initialized; #if TTF_USE_SDF # if 0 /* Set various properties of the renderers. */ int spread = 4; int overlaps = 0; FT_Property_Set( library, "bsdf", "spread", &spread); FT_Property_Set( library, "sdf", "spread", &spread); FT_Property_Set( library, "sdf", "overlaps", &overlaps); # endif #endif } return status; } SDL_COMPILE_TIME_ASSERT(FT_Int, sizeof(int) == sizeof(FT_Int)); /* just in case. */ void TTF_GetFreeTypeVersion(int *major, int *minor, int *patch) { FT_Library_Version(library, major, minor, patch); } void TTF_GetHarfBuzzVersion(int *major, int *minor, int *patch) { unsigned int hb_major = 0; unsigned int hb_minor = 0; unsigned int hb_micro = 0; #if TTF_USE_HARFBUZZ hb_version(&hb_major, &hb_minor, &hb_micro); #endif if (major) { *major = (int)hb_major; } if (minor) { *minor = (int)hb_minor; } if (patch) { *patch = (int)hb_micro; } } static unsigned long RWread( FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count ) { SDL_RWops *src; src = (SDL_RWops *)stream->descriptor.pointer; SDL_RWseek(src, (int)offset, RW_SEEK_SET); if (count == 0) { return 0; } return (unsigned long)SDL_RWread(src, buffer, 1, (int)count); } TTF_Font* TTF_OpenFontIndexDPIRW(SDL_RWops *src, int freesrc, int ptsize, long index, unsigned int hdpi, unsigned int vdpi) { TTF_Font *font; FT_Error error; FT_Face face; FT_Stream stream; FT_CharMap found; Sint64 position; int i; if (!TTF_initialized) { TTF_SetError("Library not initialized"); if (src && freesrc) { SDL_RWclose(src); } return NULL; } if (!src) { TTF_SetError("Passed a NULL font source"); return NULL; } /* Check to make sure we can seek in this stream */ position = SDL_RWtell(src); if (position < 0) { TTF_SetError("Can't seek in stream"); if (freesrc) { SDL_RWclose(src); } return NULL; } font = (TTF_Font *)SDL_malloc(sizeof (*font)); if (font == NULL) { TTF_SetError("Out of memory"); if (freesrc) { SDL_RWclose(src); } return NULL; } SDL_memset(font, 0, sizeof (*font)); font->src = src; font->freesrc = freesrc; stream = (FT_Stream)SDL_malloc(sizeof (*stream)); if (stream == NULL) { TTF_SetError("Out of memory"); TTF_CloseFont(font); return NULL; } SDL_memset(stream, 0, sizeof (*stream)); stream->read = RWread; stream->descriptor.pointer = src; stream->pos = (unsigned long)position; stream->size = (unsigned long)(SDL_RWsize(src) - position); font->args.flags = FT_OPEN_STREAM; font->args.stream = stream; error = FT_Open_Face(library, &font->args, index, &font->face); if (error || font->face == NULL) { TTF_SetFTError("Couldn't load font file", error); TTF_CloseFont(font); return NULL; } face = font->face; /* Set charmap for loaded font */ found = 0; #if 0 /* Font debug code */ for (i = 0; i < face->num_charmaps; i++) { FT_CharMap charmap = face->charmaps[i]; SDL_Log("Found charmap: platform id %d, encoding id %d", charmap->platform_id, charmap->encoding_id); } #endif if (!found) { for (i = 0; i < face->num_charmaps; i++) { FT_CharMap charmap = face->charmaps[i]; if (charmap->platform_id == 3 && charmap->encoding_id == 10) { /* UCS-4 Unicode */ found = charmap; break; } } } if (!found) { for (i = 0; i < face->num_charmaps; i++) { FT_CharMap charmap = face->charmaps[i]; if ((charmap->platform_id == 3 && charmap->encoding_id == 1) /* Windows Unicode */ || (charmap->platform_id == 3 && charmap->encoding_id == 0) /* Windows Symbol */ || (charmap->platform_id == 2 && charmap->encoding_id == 1) /* ISO Unicode */ || (charmap->platform_id == 0)) { /* Apple Unicode */ found = charmap; break; } } } if (found) { /* If this fails, continue using the default charmap */ FT_Set_Charmap(face, found); } /* Set the default font style */ font->style = TTF_STYLE_NORMAL; font->outline_val = 0; font->ft_load_target = FT_LOAD_TARGET_NORMAL; TTF_SetFontKerning(font, 1); font->pos_len = 0; font->pos_max = 16; font->pos_buf = (PosBuf_t *)SDL_malloc(font->pos_max * sizeof (font->pos_buf[0])); if (! font->pos_buf) { TTF_SetError("Out of memory"); TTF_CloseFont(font); return NULL; } #if TTF_USE_HARFBUZZ font->hb_font = hb_ft_font_create(face, NULL); if (font->hb_font == NULL) { TTF_SetError("Cannot create harfbuzz font"); TTF_CloseFont(font); return NULL; } /* Default load-flags of hb_ft_font_create is no-hinting. * So unless you call hb_ft_font_set_load_flags to match what flags you use for rendering, * you will get mismatching advances and raster. */ hb_ft_font_set_load_flags(font->hb_font, FT_LOAD_DEFAULT | font->ft_load_target); /* By default the script / direction are inherited from global variables */ font->hb_script = HB_SCRIPT_INVALID; font->hb_direction = HB_DIRECTION_INVALID; #endif if (TTF_SetFontSizeDPI(font, ptsize, hdpi, vdpi) < 0) { TTF_SetFTError("Couldn't set font size", error); TTF_CloseFont(font); return NULL; } return font; } int TTF_SetFontSizeDPI(TTF_Font *font, int ptsize, unsigned int hdpi, unsigned int vdpi) { FT_Face face = font->face; FT_Error error; /* Make sure that our font face is scalable (global metrics) */ if (FT_IS_SCALABLE(face)) { /* Set the character size using the provided DPI. If a zero DPI * is provided, then the other DPI setting will be used. If both * are zero, then Freetype's default 72 DPI will be used. */ error = FT_Set_Char_Size(face, 0, ptsize * 64, hdpi, vdpi); if (error) { TTF_SetFTError("Couldn't set font size", error); return -1; } } else { /* Non-scalable font case. ptsize determines which family * or series of fonts to grab from the non-scalable format. * It is not the point size of the font. */ if (face->num_fixed_sizes <= 0) { TTF_SetError("Couldn't select size : no num_fixed_sizes"); return -1; } /* within [0; num_fixed_sizes - 1] */ ptsize = SDL_max(ptsize, 0); ptsize = SDL_min(ptsize, face->num_fixed_sizes - 1); error = FT_Select_Size(face, ptsize); if (error) { TTF_SetFTError("Couldn't select size", error); return -1; } } if (TTF_initFontMetrics(font) < 0) { TTF_SetError("Cannot initialize metrics"); return -1; } Flush_Cache(font); #if TTF_USE_HARFBUZZ /* Call when size or variations settings on underlying FT_Face change. */ hb_ft_font_changed(font->hb_font); #endif return 0; } int TTF_SetFontSize(TTF_Font *font, int ptsize) { return TTF_SetFontSizeDPI(font, ptsize, 0, 0); } /* Update font parameter depending on a style change */ static int TTF_initFontMetrics(TTF_Font *font) { FT_Face face = font->face; int underline_offset; /* Make sure that our font face is scalable (global metrics) */ if (FT_IS_SCALABLE(face)) { /* Get the scalable font metrics for this font */ FT_Fixed scale = face->size->metrics.y_scale; font->ascent = FT_CEIL(FT_MulFix(face->ascender, scale)); font->descent = FT_CEIL(FT_MulFix(face->descender, scale)); font->height = FT_CEIL(FT_MulFix(face->ascender - face->descender, scale)); font->lineskip = FT_CEIL(FT_MulFix(face->height, scale)); underline_offset = FT_FLOOR(FT_MulFix(face->underline_position, scale)); font->line_thickness = FT_FLOOR(FT_MulFix(face->underline_thickness, scale)); } else { /* Get the font metrics for this font, for the selected size */ font->ascent = FT_CEIL(face->size->metrics.ascender); font->descent = FT_CEIL(face->size->metrics.descender); font->height = FT_CEIL(face->size->metrics.height); font->lineskip = FT_CEIL(face->size->metrics.height); /* face->underline_position and face->underline_height are only * relevant for scalable formats (see freetype.h FT_FaceRec) */ underline_offset = font->descent / 2; font->line_thickness = 1; } if (font->line_thickness < 1) { font->line_thickness = 1; } font->underline_top_row = font->ascent - underline_offset - 1; font->strikethrough_top_row = font->height / 2; /* Adjust OutlineStyle, only for scalable fonts */ /* TTF_Size(): increase w and h by 2 * outline_val, translate positionning by 1 * outline_val */ if (font->outline_val > 0) { int fo = font->outline_val; font->line_thickness += 2 * fo; font->underline_top_row -= fo; font->strikethrough_top_row -= fo; } /* Robustness: no negative values allowed */ font->underline_top_row = SDL_max(0, font->underline_top_row); font->strikethrough_top_row = SDL_max(0, font->strikethrough_top_row); /* Update height according to the needs of the underline style */ if (TTF_HANDLE_STYLE_UNDERLINE(font)) { int bottom_row = font->underline_top_row + font->line_thickness; font->height = SDL_max(font->height, bottom_row); } /* Update height according to the needs of the strikethrough style */ if (TTF_HANDLE_STYLE_STRIKETHROUGH(font)) { int bottom_row = font->strikethrough_top_row + font->line_thickness; font->height = SDL_max(font->height, bottom_row); } #if defined(DEBUG_FONTS) SDL_Log("Font metrics:"); SDL_Log("ascent = %d, descent = %d", font->ascent, font->descent); SDL_Log("height = %d, lineskip = %d", font->height, font->lineskip); SDL_Log("underline_offset = %d, line_thickness = %d", underline_offset, font->line_thickness); SDL_Log("underline_top_row = %d, strikethrough_top_row = %d", font->underline_top_row, font->strikethrough_top_row); SDL_Log("scalable=%d fixed_sizes=%d", FT_IS_SCALABLE(face), FT_HAS_FIXED_SIZES(face)); #endif font->glyph_overhang = face->size->metrics.y_ppem / 10; return 0; } TTF_Font* TTF_OpenFontDPIRW( SDL_RWops *src, int freesrc, int ptsize, unsigned int hdpi, unsigned int vdpi ) { return TTF_OpenFontIndexDPIRW(src, freesrc, ptsize, 0, hdpi, vdpi); } TTF_Font* TTF_OpenFontIndexRW( SDL_RWops *src, int freesrc, int ptsize, long index ) { return TTF_OpenFontIndexDPIRW(src, freesrc, ptsize, index, 0, 0); } TTF_Font* TTF_OpenFontIndexDPI( const char *file, int ptsize, long index, unsigned int hdpi, unsigned int vdpi ) { SDL_RWops *rw = SDL_RWFromFile(file, "rb"); if ( rw == NULL ) { return NULL; } return TTF_OpenFontIndexDPIRW(rw, 1, ptsize, index, hdpi, vdpi); } TTF_Font* TTF_OpenFontRW(SDL_RWops *src, int freesrc, int ptsize) { return TTF_OpenFontIndexRW(src, freesrc, ptsize, 0); } TTF_Font* TTF_OpenFontDPI(const char *file, int ptsize, unsigned int hdpi, unsigned int vdpi) { return TTF_OpenFontIndexDPI(file, ptsize, 0, hdpi, vdpi); } TTF_Font* TTF_OpenFontIndex(const char *file, int ptsize, long index) { return TTF_OpenFontIndexDPI(file, ptsize, index, 0, 0); } TTF_Font* TTF_OpenFont(const char *file, int ptsize) { return TTF_OpenFontIndex(file, ptsize, 0); } static void Flush_Glyph_Image(TTF_Image *image) { if (image->buffer) { SDL_free(image->buffer); image->buffer = NULL; } } static void Flush_Glyph(c_glyph *glyph) { glyph->stored = 0; glyph->index = 0; Flush_Glyph_Image(&glyph->pixmap); Flush_Glyph_Image(&glyph->bitmap); } static void Flush_Cache(TTF_Font *font) { int i; int size = sizeof (font->cache) / sizeof (font->cache[0]); for (i = 0; i < size; ++i) { if (font->cache[i].stored) { Flush_Glyph(&font->cache[i]); } } } static FT_Error Load_Glyph(TTF_Font *font, c_glyph *cached, int want, int translation) { const int alignment = Get_Alignment() - 1; FT_GlyphSlot slot; FT_Error error; int ft_load = FT_LOAD_DEFAULT | font->ft_load_target; #if TTF_USE_COLOR if (want & CACHED_COLOR) { ft_load |= FT_LOAD_COLOR; } #endif error = FT_Load_Glyph(font->face, cached->index, ft_load); if (error) { goto ft_failure; } /* Get our glyph shortcut */ slot = font->face->glyph; if (want & CACHED_LCD) { if (slot->format == FT_GLYPH_FORMAT_BITMAP) { TTF_SetError("LCD mode not possible with bitmap font"); return -1; } } /* Get the glyph metrics, always needed */ if (cached->stored == 0) { cached->sz_left = slot->bitmap_left; cached->sz_top = slot->bitmap_top; cached->sz_rows = slot->bitmap.rows; cached->sz_width = slot->bitmap.width; /* Current version of freetype is 2.9.1, but on older freetype (2.8.1) this can be 0. * Try to get them from 'FT_Glyph_Metrics' */ if (cached->sz_left == 0 && cached->sz_top == 0 && cached->sz_rows == 0 && cached->sz_width == 0) { FT_Glyph_Metrics *metrics = &slot->metrics; if (metrics) { int minx = FT_FLOOR(metrics->horiBearingX); int maxx = FT_CEIL(metrics->horiBearingX + metrics->width); int maxy = FT_FLOOR(metrics->horiBearingY); int miny = maxy - FT_CEIL(metrics->height); cached->sz_left = minx; cached->sz_top = maxy; cached->sz_rows = maxy - miny; cached->sz_width = maxx - minx; } } /* All FP 26.6 are 'long' but 'int' should be engouh */ cached->advance = (int)slot->metrics.horiAdvance; /* FP 26.6 */ if (font->render_subpixel == 0) { /* FT KERNING_MODE_SMART */ cached->kerning_smart.rsb_delta = (int)slot->rsb_delta; /* FP 26.6 */ cached->kerning_smart.lsb_delta = (int)slot->lsb_delta; /* FP 26.6 */ } else { /* FT LCD_MODE_LIGHT_SUBPIXEL */ cached->subpixel.lsb_minus_rsb = (int)(slot->lsb_delta - slot->rsb_delta); /* FP 26.6 */ cached->subpixel.translation = 0; /* FP 26.6 */ } #if defined(DEBUG_FONTS) SDL_Log("Index=%d sz_left=%d sz_top=%d sz_width=%d sz_rows=%d advance=%d is_outline=%d is_bitmap=%d", cached->index, cached->sz_left, cached->sz_top, cached->sz_width, cached->sz_rows, cached->advance, slot->format == FT_GLYPH_FORMAT_OUTLINE, slot->format == FT_GLYPH_FORMAT_BITMAP); #endif /* Adjust for bold text */ if (TTF_HANDLE_STYLE_BOLD(font)) { cached->sz_width += font->glyph_overhang; cached->advance += F26Dot6(font->glyph_overhang); } /* Adjust for italic text */ if (TTF_HANDLE_STYLE_ITALIC(font) && slot->format == FT_GLYPH_FORMAT_OUTLINE) { cached->sz_width += (GLYPH_ITALICS * font->height) >> 16; } /* Adjust for subpixel */ if (font->render_subpixel) { cached->sz_width += 1; } /* Adjust for SDF */ if (font->render_sdf) { /* Default 'spread' property */ cached->sz_width += 2 * 8; cached->sz_rows += 2 * 8; } cached->stored |= CACHED_METRICS; } if (((want & CACHED_BITMAP) && !(cached->stored & CACHED_BITMAP)) || ((want & CACHED_PIXMAP) && !(cached->stored & CACHED_PIXMAP)) || ((want & CACHED_COLOR) && !(cached->stored & CACHED_COLOR)) || ((want & CACHED_LCD) && !(cached->stored & CACHED_LCD)) || (want & CACHED_SUBPIX) ) { const int mono = (want & CACHED_BITMAP); TTF_Image *dst = (mono ? &cached->bitmap : &cached->pixmap); FT_Glyph glyph = NULL; FT_Bitmap *src; FT_Render_Mode ft_render_mode; if (mono) { ft_render_mode = FT_RENDER_MODE_MONO; } else { ft_render_mode = FT_RENDER_MODE_NORMAL; #if TTF_USE_SDF if ((want & CACHED_COLOR) && font->render_sdf) { ft_render_mode = FT_RENDER_MODE_SDF; } #endif if ((want & CACHED_LCD)) { ft_render_mode = FT_RENDER_MODE_LCD; } } /* Subpixel translation, flush previous datas */ if (want & CACHED_SUBPIX) { Flush_Glyph_Image(&cached->pixmap); FT_Outline_Translate(&slot->outline, translation, 0 ); cached->subpixel.translation = translation; } /* Handle the italic style, only for scalable fonts */ if (TTF_HANDLE_STYLE_ITALIC(font) && slot->format == FT_GLYPH_FORMAT_OUTLINE) { FT_Matrix shear; shear.xx = 1 << 16; shear.xy = GLYPH_ITALICS; shear.yx = 0; shear.yy = 1 << 16; FT_Outline_Transform(&slot->outline, &shear); } /* Render as outline */ if ((font->outline_val > 0 && slot->format == FT_GLYPH_FORMAT_OUTLINE) || slot->format == FT_GLYPH_FORMAT_BITMAP) { FT_BitmapGlyph bitmap_glyph; error = FT_Get_Glyph(slot, &glyph); if (error) { goto ft_failure; } if (font->outline_val > 0) { FT_Stroker stroker; error = FT_Stroker_New(library, &stroker); if (error) { goto ft_failure; } FT_Stroker_Set(stroker, font->outline_val * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); FT_Glyph_Stroke(&glyph, stroker, 1 /* delete the original glyph */); FT_Stroker_Done(stroker); } /* Render the glyph */ error = FT_Glyph_To_Bitmap(&glyph, ft_render_mode, 0, 1); if (error) { FT_Done_Glyph(glyph); goto ft_failure; } /* Access bitmap content by typecasting */ bitmap_glyph = (FT_BitmapGlyph) glyph; src = &bitmap_glyph->bitmap; /* Get new metrics, from bitmap */ dst->left = bitmap_glyph->left; dst->top = bitmap_glyph->top; } else { /* Render the glyph */ error = FT_Render_Glyph(slot, ft_render_mode); if (error) { goto ft_failure; } /* Access bitmap from slot */ src = &slot->bitmap; /* Get new metrics, from slot */ dst->left = slot->bitmap_left; dst->top = slot->bitmap_top; } /* Common metrics */ dst->width = src->width; dst->rows = src->rows; dst->buffer = NULL; /* FT can make small size glyph of 'width == 0', and 'rows != 0'. * Make sure 'rows' is also 0, so it doesn't break USE_DUFFS_LOOP */ if (dst->width == 0) { dst->rows = 0; } /* Adjust for bold text */ if (TTF_HANDLE_STYLE_BOLD(font)) { dst->width += font->glyph_overhang; } /* Compute pitch: glyph is padded right to be able to read an 'aligned' size expanding on the right */ dst->pitch = dst->width + alignment; #if TTF_USE_COLOR if (src->pixel_mode == FT_PIXEL_MODE_BGRA) { dst->pitch += 3 * dst->width; } #endif if (src->pixel_mode == FT_PIXEL_MODE_LCD) { dst->pitch += 3 * dst->width; } if (dst->rows != 0) { unsigned int i; /* Glyph buffer is NOT aligned, * Extra width so it can read an 'aligned' size expanding on the left */ dst->buffer = (unsigned char *)SDL_malloc(alignment + dst->pitch * dst->rows); if (!dst->buffer) { error = FT_Err_Out_Of_Memory; goto ft_failure; } /* Memset */ SDL_memset(dst->buffer, 0, alignment + dst->pitch * dst->rows); /* Shift, so that the glyph is decoded centered */ dst->buffer += alignment; /* FT_Render_Glyph() and .fon fonts always generate a two-color (black and white) * glyphslot surface, even when rendered in FT_RENDER_MODE_NORMAL. */ /* FT_IS_SCALABLE() means that the face contains outline glyphs, but does not imply * that outline is rendered as 8-bit grayscale, because embedded bitmap/graymap is * preferred (see FT_LOAD_DEFAULT section of FreeType2 API Reference). * FT_Render_Glyph() canreturn two-color bitmap or 4/16/256 color graymap * according to the format of embedded bitmap/graymap. */ for (i = 0; i < (unsigned int)src->rows; i++) { unsigned char *srcp = src->buffer + i * src->pitch; unsigned char *dstp = dst->buffer + i * dst->pitch; unsigned int k, quotient, remainder; /* Decode exactly the needed size from src->width */ if (src->pixel_mode == FT_PIXEL_MODE_MONO) { quotient = src->width / 8; remainder = src->width & 0x7; } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY2) { quotient = src->width / 4; remainder = src->width & 0x3; } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY4) { quotient = src->width / 2; remainder = src->width & 0x1; #if TTF_USE_COLOR } else if (src->pixel_mode == FT_PIXEL_MODE_BGRA) { quotient = src->width; remainder = 0; #endif } else if (src->pixel_mode == FT_PIXEL_MODE_LCD) { quotient = src->width / 3; remainder = 0; } else { quotient = src->width; remainder = 0; } /* FT_RENDER_MODE_MONO and src->pixel_mode MONO */ #ifdef _MSC_VER #pragma warning(push, 1) #pragma warning(disable:4127) #endif #define MONO_MONO(K_MAX) \ if ((K_MAX)) { \ unsigned char c = *srcp++; \ for (k = 0; k < (K_MAX); ++k) { \ *dstp++ = (c & 0x80) >> 7; \ c <<= 1; \ } \ } /* FT_RENDER_MODE_MONO and src->pixel_mode GRAY2 */ #define MONO_GRAY2(K_MAX) \ if ((K_MAX)) { \ unsigned char c = *srcp++; \ for (k = 0; k < (K_MAX); ++k) { \ *dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0; \ c <<= 2; \ } \ } /* FT_RENDER_MODE_MONO and src->pixel_mode GRAY4 */ #define MONO_GRAY4(K_MAX) \ if ((K_MAX)) { \ unsigned char c = *srcp++; \ for (k = 0; k < (K_MAX); ++k) { \ *dstp++ = (((c&0xF0) >> 4) >= 0x8) ? 1 : 0; \ c <<= 4; \ } \ } /* FT_RENDER_MODE_NORMAL and src->pixel_mode MONO */ #define NORMAL_MONO(K_MAX) \ if ((K_MAX)) { \ unsigned char c = *srcp++; \ for (k = 0; k < (K_MAX); ++k) { \ if ((c&0x80) >> 7) { \ *dstp++ = NUM_GRAYS - 1; \ } else { \ *dstp++ = 0x00; \ } \ c <<= 1; \ } \ } /* FT_RENDER_MODE_NORMAL and src->pixel_mode GRAY2 */ #define NORMAL_GRAY2(K_MAX) \ if ((K_MAX)) { \ unsigned char c = *srcp++; \ for (k = 0; k < (K_MAX); ++k) { \ if ((c&0xA0) >> 6) { \ *dstp++ = NUM_GRAYS * ((c&0xA0) >> 6) / 3 - 1; \ } else { \ *dstp++ = 0x00; \ } \ c <<= 2; \ } \ } /* FT_RENDER_MODE_NORMAL and src->pixel_mode GRAY4 */ #define NORMAL_GRAY4(K_MAX) \ if ((K_MAX)) { \ unsigned char c = *srcp++; \ for (k = 0; k < (K_MAX); ++k) { \ if ((c&0xF0) >> 4) { \ *dstp++ = NUM_GRAYS * ((c&0xF0) >> 4) / 15 - 1; \ } else { \ *dstp++ = 0x00; \ } \ c <<= 4; \ } \ } if (mono) { if (src->pixel_mode == FT_PIXEL_MODE_MONO) { while (quotient--) { MONO_MONO(8); } MONO_MONO(remainder); } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY2) { while (quotient--) { MONO_GRAY2(4); } MONO_GRAY2(remainder); } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY4) { while (quotient--) { MONO_GRAY4(2); } MONO_GRAY4(remainder); } else { while (quotient--) { unsigned char c = *srcp++; *dstp++ = (c >= 0x80) ? 1 : 0; } } } else if (src->pixel_mode == FT_PIXEL_MODE_MONO) { /* This special case wouldn't be here if the FT_Render_Glyph() * function wasn't buggy when it tried to render a .fon font with 256 * shades of gray. Instead, it returns a black and white surface * and we have to translate it back to a 256 gray shaded surface. */ while (quotient--) { NORMAL_MONO(8); } NORMAL_MONO(remainder); } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY2) { while (quotient--) { NORMAL_GRAY2(4); } NORMAL_GRAY2(remainder); } else if (src->pixel_mode == FT_PIXEL_MODE_GRAY4) { while (quotient--) { NORMAL_GRAY4(2); } NORMAL_GRAY4(remainder); #if TTF_USE_COLOR } else if (src->pixel_mode == FT_PIXEL_MODE_BGRA) { SDL_memcpy(dstp, srcp, 4 * src->width); #endif } else if (src->pixel_mode == FT_PIXEL_MODE_LCD) { while (quotient--) { Uint8 alpha = 0; Uint8 r, g, b; r = *srcp++; g = *srcp++; b = *srcp++; *dstp++ = b; *dstp++ = g; *dstp++ = r; *dstp++ = alpha; } } else { #if TTF_USE_SDF if (ft_render_mode != FT_RENDER_MODE_SDF) { SDL_memcpy(dstp, srcp, src->width); } else { int x; for (x = 0; x < src->width; x++) { Uint8 s = srcp[x]; Uint8 d; if (s < 128) { d = 256 - (128 - s) * 2; } else { d = 255; /* some glitch ? if (s == 255) { d = 0; }*/ } dstp[x] = d; } } #else SDL_memcpy(dstp, srcp, src->width); #endif } } } #ifdef _MSC_VER #pragma warning(pop) #endif /* Handle the bold style */ if (TTF_HANDLE_STYLE_BOLD(font)) { int row; /* The pixmap is a little hard, we have to add and clamp */ for (row = dst->rows - 1; row >= 0; --row) { Uint8 *pixmap = dst->buffer + row * dst->pitch; int col, offset; /* Minimal memset */ /* SDL_memset(pixmap + dst->width - font->glyph_overhang, 0, font->glyph_overhang); */ for (offset = 1; offset <= font->glyph_overhang; ++offset) { for (col = dst->width - 1; col > 0; --col) { if (mono) { pixmap[col] |= pixmap[col-1]; } else { int pixel = (pixmap[col] + pixmap[col-1]); if (pixel > NUM_GRAYS - 1) { pixel = NUM_GRAYS - 1; } pixmap[col] = (Uint8) pixel; } } } } } /* Shift back */ if (dst->buffer) { dst->buffer -= alignment; } #if TTF_USE_COLOR if (src->pixel_mode == FT_PIXEL_MODE_BGRA) { dst->is_color = 1; } else { dst->is_color = 0; } #else dst->is_color = 0; #endif /* Mark that we rendered this format */ if (mono) { cached->stored |= CACHED_BITMAP; } else if (src->pixel_mode == FT_PIXEL_MODE_LCD) { cached->stored |= CACHED_LCD; } else { #if TTF_USE_COLOR if (want & CACHED_COLOR) { cached->stored |= CACHED_COLOR; /* Most of the time, glyphs loaded with FT_LOAD_COLOR are non colored, so the cache is also suitable for Shaded rendering (eg, loaded without FT_LOAD_COLOR) */ if (dst->is_color == 0) { cached->stored |= CACHED_PIXMAP; } } else { cached->stored |= CACHED_PIXMAP; /* If font has no color information, Shaded/Pixmap cache is also suitable for Blend/Color */ if (!FT_HAS_COLOR(font->face)) { cached->stored |= CACHED_COLOR; } } #else cached->stored |= CACHED_COLOR | CACHED_PIXMAP; #endif } /* Free outlined glyph */ if (glyph) { FT_Done_Glyph(glyph); } } /* We're done, this glyph is cached since 'stored' is not 0 */ return 0; ft_failure: TTF_SetFTError("Couldn't find glyph", error); return -1; } static SDL_INLINE int Find_GlyphByIndex(TTF_Font *font, FT_UInt idx, int want_bitmap, int want_pixmap, int want_color, int want_lcd, int want_subpixel, int translation, c_glyph **out_glyph, TTF_Image **out_image) { /* cache size is 256, get key by masking */ c_glyph *glyph = &font->cache[idx & 0xff]; if (out_glyph) { *out_glyph = glyph; } if (want_pixmap || want_color || want_lcd) { *out_image = &glyph->pixmap; } if (want_bitmap) { *out_image = &glyph->bitmap; } if (want_subpixel) { /* No a real cache, but if it always advances by integer pixels (eg translation 0 or same as previous), * this allows to render as fast as normal mode. */ int retval; int want = CACHED_METRICS | want_bitmap | want_pixmap | want_color | want_lcd | want_subpixel; if (glyph->stored && glyph->index != idx) { Flush_Glyph(glyph); } if (glyph->subpixel.translation == translation) { want &= ~CACHED_SUBPIX; } if ((glyph->stored & want) == want) { return 0; } if (want_color || want_pixmap || want_lcd) { if (glyph->stored & (CACHED_COLOR|CACHED_PIXMAP|CACHED_LCD)) { Flush_Glyph(glyph); } } glyph->index = idx; retval = Load_Glyph(font, glyph, want, translation); if (retval == 0) { return 0; } else { return -1; } } else { int retval; const int want = CACHED_METRICS | want_bitmap | want_pixmap | want_color | want_lcd; /* Faster check as it gets inlined */ if (want_pixmap) { if ((glyph->stored & CACHED_PIXMAP) && glyph->index == idx) { return 0; } } else if (want_bitmap) { if ((glyph->stored & CACHED_BITMAP) && glyph->index == idx) { return 0; } } else if (want_color) { if ((glyph->stored & CACHED_COLOR) && glyph->index == idx) { return 0; } } else if (want_lcd) { if ((glyph->stored & CACHED_LCD) && glyph->index == idx) { return 0; } } else { /* Get metrics */ if (glyph->stored && glyph->index == idx) { return 0; } } /* Cache cannot contain both PIXMAP and COLOR (unless COLOR is actually not colored) and LCD So, if it's already used, clear it */ if (want_color || want_pixmap || want_lcd) { if (glyph->stored & (CACHED_COLOR|CACHED_PIXMAP|CACHED_LCD)) { Flush_Glyph(glyph); } } if (glyph->stored && glyph->index != idx) { Flush_Glyph(glyph); } glyph->index = idx; retval = Load_Glyph(font, glyph, want, 0); if (retval == 0) { return 0; } else { return -1; } } } static SDL_INLINE FT_UInt get_char_index(TTF_Font *font, Uint32 ch) { Uint32 cache_index_size = sizeof (font->cache_index) / sizeof (font->cache_index[0]); if (ch < cache_index_size) { FT_UInt idx = font->cache_index[ch]; if (idx) { return idx; } idx = FT_Get_Char_Index(font->face, ch); font->cache_index[ch] = idx; return idx; } return FT_Get_Char_Index(font->face, ch); } static SDL_INLINE int Find_GlyphMetrics(TTF_Font *font, Uint32 ch, c_glyph **out_glyph) { FT_UInt idx = get_char_index(font, ch); return Find_GlyphByIndex(font, idx, 0, 0, 0, 0, 0, 0, out_glyph, NULL); } void TTF_CloseFont(TTF_Font *font) { if (font) { #if TTF_USE_HARFBUZZ hb_font_destroy(font->hb_font); #endif Flush_Cache(font); if (font->face) { FT_Done_Face(font->face); } if (font->args.stream) { SDL_free(font->args.stream); } if (font->freesrc) { SDL_RWclose(font->src); } if (font->pos_buf) { SDL_free(font->pos_buf); } SDL_free(font); } } /* Gets the number of bytes needed to convert a Latin-1 string to UTF-8 */ static size_t LATIN1_to_UTF8_len(const char *text) { size_t bytes = 1; while (*text) { Uint8 ch = *(const Uint8 *)text++; if (ch <= 0x7F) { bytes += 1; } else { bytes += 2; } } return bytes; } /* Gets the number of bytes needed to convert a UCS2 string to UTF-8 */ static size_t UCS2_to_UTF8_len(const Uint16 *text) { SDL_bool swapped = TTF_byteswapped; size_t bytes = 1; while (*text) { Uint16 ch = *text++; if (ch == UNICODE_BOM_NATIVE) { swapped = SDL_FALSE; continue; } if (ch == UNICODE_BOM_SWAPPED) { swapped = SDL_TRUE; continue; } if (swapped) { ch = SDL_Swap16(ch); } if (ch <= 0x7F) { bytes += 1; } else if (ch <= 0x7FF) { bytes += 2; } else { bytes += 3; } } return bytes; } /* Convert a Latin-1 string to a UTF-8 string */ static void LATIN1_to_UTF8(const char *src, Uint8 *dst) { while (*src) { Uint8 ch = *(const Uint8 *)src++; if (ch <= 0x7F) { *dst++ = ch; } else { *dst++ = 0xC0 | ((ch >> 6) & 0x1F); *dst++ = 0x80 | (ch & 0x3F); } } *dst = '\0'; } /* Convert a UCS-2 string to a UTF-8 string */ static void UCS2_to_UTF8(const Uint16 *src, Uint8 *dst) { SDL_bool swapped = TTF_byteswapped; while (*src) { Uint16 ch = *src++; if (ch == UNICODE_BOM_NATIVE) { swapped = SDL_FALSE; continue; } if (ch == UNICODE_BOM_SWAPPED) { swapped = SDL_TRUE; continue; } if (swapped) { ch = SDL_Swap16(ch); } if (ch <= 0x7F) { *dst++ = (Uint8) ch; } else if (ch <= 0x7FF) { *dst++ = 0xC0 | (Uint8) ((ch >> 6) & 0x1F); *dst++ = 0x80 | (Uint8) (ch & 0x3F); } else { *dst++ = 0xE0 | (Uint8) ((ch >> 12) & 0x0F); *dst++ = 0x80 | (Uint8) ((ch >> 6) & 0x3F); *dst++ = 0x80 | (Uint8) (ch & 0x3F); } } *dst = '\0'; } /* Convert a unicode char to a UTF-8 string */ static SDL_bool Char_to_UTF8(Uint32 ch, Uint8 *dst) { if (ch <= 0x7F) { *dst++ = (Uint8) ch; } else if (ch <= 0x7FF) { *dst++ = 0xC0 | (Uint8) ((ch >> 6) & 0x1F); *dst++ = 0x80 | (Uint8) (ch & 0x3F); } else if (ch <= 0xFFFF) { *dst++ = 0xE0 | (Uint8) ((ch >> 12) & 0x0F); *dst++ = 0x80 | (Uint8) ((ch >> 6) & 0x3F); *dst++ = 0x80 | (Uint8) (ch & 0x3F); } else if (ch <= 0x1FFFFF) { *dst++ = 0xF0 | (Uint8) ((ch >> 18) & 0x07); *dst++ = 0x80 | (Uint8) ((ch >> 12) & 0x3F); *dst++ = 0x80 | (Uint8) ((ch >> 6) & 0x3F); *dst++ = 0x80 | (Uint8) (ch & 0x3F); } else if (ch <= 0x3FFFFFF) { *dst++ = 0xF8 | (Uint8) ((ch >> 24) & 0x03); *dst++ = 0x80 | (Uint8) ((ch >> 18) & 0x3F); *dst++ = 0x80 | (Uint8) ((ch >> 12) & 0x3F); *dst++ = 0x80 | (Uint8) ((ch >> 6) & 0x3F); *dst++ = 0x80 | (Uint8) (ch & 0x3F); } else if (ch < 0x7FFFFFFF) { *dst++ = 0xFC | (Uint8) ((ch >> 30) & 0x01); *dst++ = 0x80 | (Uint8) ((ch >> 24) & 0x3F); *dst++ = 0x80 | (Uint8) ((ch >> 18) & 0x3F); *dst++ = 0x80 | (Uint8) ((ch >> 12) & 0x3F); *dst++ = 0x80 | (Uint8) ((ch >> 6) & 0x3F); *dst++ = 0x80 | (Uint8) (ch & 0x3F); } else { TTF_SetError("Invalid character"); return SDL_FALSE; } *dst = '\0'; return SDL_TRUE; } /* Gets a unicode value from a UTF-8 encoded string * Ouputs increment to advance the string */ #define UNKNOWN_UNICODE 0xFFFD static Uint32 UTF8_getch(const char *src, size_t srclen, int *inc) { const Uint8 *p = (const Uint8 *)src; size_t left = 0; size_t save_srclen = srclen; SDL_bool overlong = SDL_FALSE; SDL_bool underflow = SDL_FALSE; Uint32 ch = UNKNOWN_UNICODE; if (srclen == 0) { return UNKNOWN_UNICODE; } if (p[0] >= 0xFC) { if ((p[0] & 0xFE) == 0xFC) { if (p[0] == 0xFC && (p[1] & 0xFC) == 0x80) { overlong = SDL_TRUE; } ch = (Uint32) (p[0] & 0x01); left = 5; } } else if (p[0] >= 0xF8) { if ((p[0] & 0xFC) == 0xF8) { if (p[0] == 0xF8 && (p[1] & 0xF8) == 0x80) { overlong = SDL_TRUE; } ch = (Uint32) (p[0] & 0x03); left = 4; } } else if (p[0] >= 0xF0) { if ((p[0] & 0xF8) == 0xF0) { if (p[0] == 0xF0 && (p[1] & 0xF0) == 0x80) { overlong = SDL_TRUE; } ch = (Uint32) (p[0] & 0x07); left = 3; } } else if (p[0] >= 0xE0) { if ((p[0] & 0xF0) == 0xE0) { if (p[0] == 0xE0 && (p[1] & 0xE0) == 0x80) { overlong = SDL_TRUE; } ch = (Uint32) (p[0] & 0x0F); left = 2; } } else if (p[0] >= 0xC0) { if ((p[0] & 0xE0) == 0xC0) { if ((p[0] & 0xDE) == 0xC0) { overlong = SDL_TRUE; } ch = (Uint32) (p[0] & 0x1F); left = 1; } } else { if ((p[0] & 0x80) == 0x00) { ch = (Uint32) p[0]; } } --srclen; while (left > 0 && srclen > 0) { ++p; if ((p[0] & 0xC0) != 0x80) { ch = UNKNOWN_UNICODE; break; } ch <<= 6; ch |= (p[0] & 0x3F); --srclen; --left; } if (left > 0) { underflow = SDL_TRUE; } /* Technically overlong sequences are invalid and should not be interpreted. However, it doesn't cause a security risk here and I don't see any harm in displaying them. The application is responsible for any other side effects of allowing overlong sequences (e.g. string compares failing, etc.) See bug 1931 for sample input that triggers this. */ /* if (overlong) return UNKNOWN_UNICODE; */ (void) overlong; if (underflow || (ch >= 0xD800 && ch <= 0xDFFF) || (ch == 0xFFFE || ch == 0xFFFF) || ch > 0x10FFFF) { ch = UNKNOWN_UNICODE; } *inc = (int)(save_srclen - srclen); return ch; } int TTF_FontHeight(const TTF_Font *font) { return font->height; } int TTF_FontAscent(const TTF_Font *font) { return font->ascent + 2 * font->outline_val; } int TTF_FontDescent(const TTF_Font *font) { return font->descent; } int TTF_FontLineSkip(const TTF_Font *font) { return font->lineskip; } int TTF_GetFontKerning(const TTF_Font *font) { return font->allow_kerning; } void TTF_SetFontKerning(TTF_Font *font, int allowed) { font->allow_kerning = allowed; font->use_kerning = allowed && FT_HAS_KERNING(font->face); } long TTF_FontFaces(const TTF_Font *font) { return font->face->num_faces; } int TTF_FontFaceIsFixedWidth(const TTF_Font *font) { return FT_IS_FIXED_WIDTH(font->face); } const char * TTF_FontFaceFamilyName(const TTF_Font *font) { return font->face->family_name; } const char * TTF_FontFaceStyleName(const TTF_Font *font) { return font->face->style_name; } int TTF_GlyphIsProvided(TTF_Font *font, Uint16 ch) { return (int)get_char_index(font, ch); } int TTF_GlyphIsProvided32(TTF_Font *font, Uint32 ch) { return (int)get_char_index(font, ch); } int TTF_GlyphMetrics(TTF_Font *font, Uint16 ch, int *minx, int *maxx, int *miny, int *maxy, int *advance) { return TTF_GlyphMetrics32(font, ch, minx, maxx, miny, maxy, advance); } int TTF_GlyphMetrics32(TTF_Font *font, Uint32 ch, int *minx, int *maxx, int *miny, int *maxy, int *advance) { c_glyph *glyph; TTF_CHECK_POINTER(font, -1); if (Find_GlyphMetrics(font, ch, &glyph) < 0) { return -1; } if (minx) { *minx = glyph->sz_left; } if (maxx) { *maxx = glyph->sz_left + glyph->sz_width; *maxx += 2 * font->outline_val; } if (miny) { *miny = glyph->sz_top - glyph->sz_rows; } if (maxy) { *maxy = glyph->sz_top; *maxy += 2 * font->outline_val; } if (advance) { *advance = FT_CEIL(glyph->advance); } return 0; } int TTF_SetFontDirection(TTF_Font *font, TTF_Direction direction) { #if TTF_USE_HARFBUZZ hb_direction_t dir; if (direction == TTF_DIRECTION_LTR) { dir = HB_DIRECTION_LTR; } else if (direction == TTF_DIRECTION_RTL) { dir = HB_DIRECTION_RTL; } else if (direction == TTF_DIRECTION_TTB) { dir = HB_DIRECTION_BTT; } else if (direction == TTF_DIRECTION_BTT) { dir = HB_DIRECTION_TTB; } else { return -1; } font->hb_direction = dir; return 0; #else (void) font; (void) direction; return -1; #endif } int TTF_SetFontScriptName(TTF_Font *font, const char *script) { #if TTF_USE_HARFBUZZ Uint8 a, b, c, d; hb_script_t scr; if (script == NULL || SDL_strlen(script) != 4) { return -1; } a = script[0]; b = script[1]; c = script[2]; d = script[3]; scr = HB_TAG(a, b, c, d); font->hb_script = scr; return 0; #else (void) font; (void) script; return -1; #endif } static int TTF_Size_Internal(TTF_Font *font, const char *text, const str_type_t str_type, int *w, int *h, int *xstart, int *ystart, int measure_width, int *extent, int *count) { int x = 0; int pos_x, pos_y; int minx = 0, maxx = 0; int miny = 0, maxy = 0; Uint8 *utf8_alloc = NULL; c_glyph *glyph; #if TTF_USE_HARFBUZZ hb_direction_t hb_direction; hb_script_t hb_script; hb_buffer_t *hb_buffer = NULL; unsigned int g; unsigned int glyph_count; hb_glyph_info_t *hb_glyph_info; hb_glyph_position_t *hb_glyph_position; int y = 0; int advance_if_bold = 0; #else size_t textlen; int skip_first = 1; FT_UInt prev_index = 0; FT_Pos prev_delta = 0; #endif int prev_advance = 0; /* Measurement mode */ int char_count = 0; int current_width = 0; TTF_CHECK_INITIALIZED(-1); TTF_CHECK_POINTER(font, -1); TTF_CHECK_POINTER(text, -1); /* Convert input string to default encoding UTF-8 */ if (str_type == STR_TEXT) { utf8_alloc = SDL_stack_alloc(Uint8, LATIN1_to_UTF8_len(text)); if (utf8_alloc == NULL) { SDL_OutOfMemory(); goto failure; } LATIN1_to_UTF8(text, utf8_alloc); text = (const char *)utf8_alloc; } else if (str_type == STR_UNICODE) { const Uint16 *text16 = (const Uint16 *) text; utf8_alloc = SDL_stack_alloc(Uint8, UCS2_to_UTF8_len(text16)); if (utf8_alloc == NULL) { SDL_OutOfMemory(); goto failure; } UCS2_to_UTF8(text16, utf8_alloc); text = (const char *)utf8_alloc; } maxy = font->height; /* Reset buffer */ font->pos_len = 0; #if TTF_USE_HARFBUZZ /* Adjust for bold text */ if (TTF_HANDLE_STYLE_BOLD(font)) { advance_if_bold = F26Dot6(font->glyph_overhang); } /* Create a buffer for harfbuzz to use */ hb_buffer = hb_buffer_create(); if (hb_buffer == NULL) { TTF_SetError("Cannot create harfbuzz buffer"); goto failure; } hb_direction = font->hb_direction; hb_script = font->hb_script; if (hb_script == HB_SCRIPT_INVALID) { hb_script = g_hb_script; } if (hb_direction == HB_DIRECTION_INVALID) { hb_direction = g_hb_direction; } /* Set global configuration */ hb_buffer_set_direction(hb_buffer, hb_direction); hb_buffer_set_script(hb_buffer, hb_script); /* Layout the text */ hb_buffer_add_utf8(hb_buffer, text, -1, 0, -1); hb_shape(font->hb_font, hb_buffer, NULL, 0); /* Get the result */ hb_glyph_info = hb_buffer_get_glyph_infos(hb_buffer, &glyph_count); hb_glyph_position = hb_buffer_get_glyph_positions(hb_buffer, &glyph_count); /* Load and render each character */ for (g = 0; g < glyph_count; g++) { FT_UInt idx = hb_glyph_info[g].codepoint; int x_advance = hb_glyph_position[g].x_advance; int y_advance = hb_glyph_position[g].y_advance; int x_offset = hb_glyph_position[g].x_offset; int y_offset = hb_glyph_position[g].y_offset; #else /* Load each character and sum it's bounding box */ textlen = SDL_strlen(text); while (textlen > 0) { int inc = 0; Uint32 c = UTF8_getch(text, textlen, &inc); FT_UInt idx = get_char_index(font, c); text += inc; textlen -= inc; if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) { continue; } #endif if (Find_GlyphByIndex(font, idx, 0, 0, 0, 0, 0, 0, &glyph, NULL) < 0) { goto failure; } /* Realloc, if needed */ if (font->pos_len >= font->pos_max) { PosBuf_t *saved = font->pos_buf; font->pos_max *= 2; font->pos_buf = (PosBuf_t *)SDL_realloc(font->pos_buf, font->pos_max * sizeof (font->pos_buf[0])); if (font->pos_buf == NULL) { font->pos_max /= 2; font->pos_buf = saved; TTF_SetError("Out of memory"); goto failure; } } #if TTF_USE_HARFBUZZ /* Compute positions */ pos_x = x + x_offset; pos_y = y + F26Dot6(font->ascent) - y_offset; x += x_advance + advance_if_bold; y += y_advance; #else /* Compute positions */ x += prev_advance; prev_advance = glyph->advance; if (font->use_kerning) { if (prev_index && glyph->index) { FT_Vector delta; FT_Get_Kerning(font->face, prev_index, glyph->index, FT_KERNING_UNFITTED, &delta); x += delta.x; } prev_index = glyph->index; } /* FT SUBPIXEL : LCD_MODE_LIGHT_SUBPIXEL */ if (font->render_subpixel) { x += prev_delta; /* Increment by prev_glyph->lsb_delta - prev_glyph->rsb_delta; */ prev_delta = glyph->subpixel.lsb_minus_rsb; } else { /* FT KERNING_MODE_SMART: Use `lsb_delta' and `rsb_delta' to improve integer positioning of glyphs */ if (skip_first) { skip_first = 0; } else { if (prev_delta - glyph->kerning_smart.lsb_delta > 32 ) { x -= 64; } else if (prev_delta - glyph->kerning_smart.lsb_delta < -31 ) { x += 64; } } prev_delta = glyph->kerning_smart.rsb_delta; x = ((x + 32) & -64); /* ROUND() */ } /* Compute positions where to copy the glyph bitmap */ pos_x = x; pos_y = F26Dot6(font->ascent); #endif /* Store things for Render_Line() */ font->pos_buf[font->pos_len].x = pos_x; font->pos_buf[font->pos_len].y = pos_y; font->pos_buf[font->pos_len].index = idx; font->pos_len += 1; /* Compute previsionnal global bounding box */ pos_x = FT_FLOOR(pos_x) + glyph->sz_left; pos_y = FT_FLOOR(pos_y) - glyph->sz_top; minx = SDL_min(minx, pos_x); maxx = SDL_max(maxx, pos_x + glyph->sz_width); miny = SDL_min(miny, pos_y); maxy = SDL_max(maxy, pos_y + glyph->sz_rows); /* Measurement mode */ if (measure_width) { int cw = SDL_max(maxx, FT_FLOOR(x + prev_advance)) - minx; cw += 2 * font->outline_val; if (cw <= measure_width) { current_width = cw; char_count += 1; } if (cw >= measure_width) { break; } } } /* Allows to render a string with only one space (bug 4344). */ maxx = SDL_max(maxx, FT_FLOOR(x + prev_advance)); /* Initial x start position: often 0, except when a glyph would be written at * a negative position. In this case an offset is needed for the whole line. */ if (xstart) { *xstart = (minx < 0)? -minx : 0; *xstart += font->outline_val; if (font->render_sdf) { *xstart += 8; /* Default 'spread' property */ } } /* Initial y start: compensation for a negative y offset */ if (ystart) { *ystart = (miny < 0)? -miny : 0; *ystart += font->outline_val; if (font->render_sdf) { *ystart += 8; /* Default 'spread' property */ } } /* Fill the bounds rectangle */ if (w) { *w = (maxx - minx); if (*w != 0) { *w += 2 * font->outline_val; } } if (h) { *h = (maxy - miny); *h += 2 * font->outline_val; } /* Measurement mode */ if (measure_width) { if (extent) { *extent = current_width; } if (count) { #if TTF_USE_HARFBUZZ if (char_count == glyph_count) { /* The higher level code doesn't know about ligatures, * so if we've covered all the glyphs, report the full * string length. * * If we have to line wrap somewhere in the middle, we * might be off by the number of ligatures, but there * isn't an easy way around that without using hb_buffer * at that level instead. */ *count = (int)SDL_utf8strlen(text); } else #endif *count = char_count; } } #if TTF_USE_HARFBUZZ if (hb_buffer) { hb_buffer_destroy(hb_buffer); } #endif if (utf8_alloc) { SDL_stack_free(utf8_alloc); } return 0; failure: #if TTF_USE_HARFBUZZ if (hb_buffer) { hb_buffer_destroy(hb_buffer); } #endif if (utf8_alloc) { SDL_stack_free(utf8_alloc); } return -1; } int TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h) { return TTF_Size_Internal(font, text, STR_TEXT, w, h, NULL, NULL, NO_MEASUREMENT); } int TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h) { return TTF_Size_Internal(font, text, STR_UTF8, w, h, NULL, NULL, NO_MEASUREMENT); } int TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h) { return TTF_Size_Internal(font, (const char *)text, STR_UNICODE, w, h, NULL, NULL, NO_MEASUREMENT); } int TTF_MeasureText(TTF_Font *font, const char *text, int width, int *extent, int *count) { return TTF_Size_Internal(font, text, STR_TEXT, NULL, NULL, NULL, NULL, width, extent, count); } int TTF_MeasureUTF8(TTF_Font *font, const char *text, int width, int *extent, int *count) { return TTF_Size_Internal(font, text, STR_UTF8, NULL, NULL, NULL, NULL, width, extent, count); } int TTF_MeasureUNICODE(TTF_Font *font, const Uint16 *text, int width, int *extent, int *count) { return TTF_Size_Internal(font, (const char *)text, STR_UNICODE, NULL, NULL, NULL, NULL, width, extent, count); } static SDL_Surface* TTF_Render_Internal(TTF_Font *font, const char *text, const str_type_t str_type, SDL_Color fg, SDL_Color bg, const render_mode_t render_mode) { Uint32 color; int xstart, ystart, width, height; SDL_Surface *textbuf = NULL; Uint8 *utf8_alloc = NULL; TTF_CHECK_INITIALIZED(NULL); TTF_CHECK_POINTER(font, NULL); TTF_CHECK_POINTER(text, NULL); if (render_mode == RENDER_LCD && !FT_IS_SCALABLE(font->face)) { TTF_SetError("LCD rendering is not available for non-scalable font"); goto failure; } /* Convert input string to default encoding UTF-8 */ if (str_type == STR_TEXT) { utf8_alloc = SDL_stack_alloc(Uint8, LATIN1_to_UTF8_len(text)); if (utf8_alloc == NULL) { SDL_OutOfMemory(); goto failure; } LATIN1_to_UTF8(text, utf8_alloc); text = (const char *)utf8_alloc; } else if (str_type == STR_UNICODE) { const Uint16 *text16 = (const Uint16 *) text; utf8_alloc = SDL_stack_alloc(Uint8, UCS2_to_UTF8_len(text16)); if (utf8_alloc == NULL) { SDL_OutOfMemory(); goto failure; } UCS2_to_UTF8(text16, utf8_alloc); text = (const char *)utf8_alloc; } #if TTF_USE_SDF /* Invalid cache if we were using SDF */ if (render_mode != RENDER_BLENDED) { if (font->render_sdf) { font->render_sdf = 0; Flush_Cache(font); } } #endif /* Get the dimensions of the text surface */ if ((TTF_Size_Internal(font, text, STR_UTF8, &width, &height, &xstart, &ystart, NO_MEASUREMENT) < 0) || !width) { TTF_SetError("Text has zero width"); goto failure; } /* Support alpha blending */ fg.a = fg.a ? fg.a : SDL_ALPHA_OPAQUE; bg.a = bg.a ? bg.a : SDL_ALPHA_OPAQUE; /* Create surface for rendering */ if (render_mode == RENDER_SOLID) { textbuf = Create_Surface_Solid(width, height, fg, &color); } else if (render_mode == RENDER_SHADED) { textbuf = Create_Surface_Shaded(width, height, fg, bg, &color); } else if (render_mode == RENDER_BLENDED) { textbuf = Create_Surface_Blended(width, height, fg, &color); } else { /* render_mode == RENDER_LCD */ textbuf = Create_Surface_LCD(width, height, fg, bg, &color); } if (textbuf == NULL) { goto failure; } /* Render one text line to textbuf at (xstart, ystart) */ if (Render_Line(render_mode, font->render_subpixel, font, textbuf, xstart, ystart, fg) < 0) { goto failure; } /* Apply underline or strikethrough style, if needed */ if (TTF_HANDLE_STYLE_UNDERLINE(font)) { Draw_Line(font, textbuf, 0, ystart + font->underline_top_row, width, font->line_thickness, color, render_mode); } if (TTF_HANDLE_STYLE_STRIKETHROUGH(font)) { Draw_Line(font, textbuf, 0, ystart + font->strikethrough_top_row, width, font->line_thickness, color, render_mode); } if (utf8_alloc) { SDL_stack_free(utf8_alloc); } return textbuf; failure: if (textbuf) { SDL_FreeSurface(textbuf); } if (utf8_alloc) { SDL_stack_free(utf8_alloc); } return NULL; } SDL_Surface* TTF_RenderText_Solid(TTF_Font *font, const char *text, SDL_Color fg) { return TTF_Render_Internal(font, text, STR_TEXT, fg, fg /* unused */, RENDER_SOLID); } SDL_Surface* TTF_RenderUTF8_Solid(TTF_Font *font, const char *text, SDL_Color fg) { return TTF_Render_Internal(font, text, STR_UTF8, fg, fg /* unused */, RENDER_SOLID); } SDL_Surface* TTF_RenderUNICODE_Solid(TTF_Font *font, const Uint16 *text, SDL_Color fg) { return TTF_Render_Internal(font, (const char *)text, STR_UNICODE, fg, fg /* unused */, RENDER_SOLID); } SDL_Surface* TTF_RenderGlyph_Solid(TTF_Font *font, Uint16 ch, SDL_Color fg) { return TTF_RenderGlyph32_Solid(font, ch, fg); } SDL_Surface* TTF_RenderGlyph32_Solid(TTF_Font *font, Uint32 ch, SDL_Color fg) { Uint8 utf8[7]; TTF_CHECK_POINTER(font, NULL); if (!Char_to_UTF8(ch, utf8)) { return NULL; } return TTF_RenderUTF8_Solid(font, (char *)utf8, fg); } SDL_Surface* TTF_RenderText_Shaded(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg) { return TTF_Render_Internal(font, text, STR_TEXT, fg, bg, RENDER_SHADED); } SDL_Surface* TTF_RenderUTF8_Shaded(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg) { return TTF_Render_Internal(font, text, STR_UTF8, fg, bg, RENDER_SHADED); } SDL_Surface* TTF_RenderUNICODE_Shaded(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg) { return TTF_Render_Internal(font, (const char *)text, STR_UNICODE, fg, bg, RENDER_SHADED); } SDL_Surface* TTF_RenderGlyph_Shaded(TTF_Font *font, Uint16 ch, SDL_Color fg, SDL_Color bg) { return TTF_RenderGlyph32_Shaded(font, ch, fg, bg); } SDL_Surface* TTF_RenderGlyph32_Shaded(TTF_Font *font, Uint32 ch, SDL_Color fg, SDL_Color bg) { Uint8 utf8[7]; TTF_CHECK_POINTER(font, NULL); if (!Char_to_UTF8(ch, utf8)) { return NULL; } return TTF_RenderUTF8_Shaded(font, (char *)utf8, fg, bg); } SDL_Surface* TTF_RenderText_Blended(TTF_Font *font, const char *text, SDL_Color fg) { return TTF_Render_Internal(font, text, STR_TEXT, fg, fg /* unused */, RENDER_BLENDED); } SDL_Surface* TTF_RenderUTF8_Blended(TTF_Font *font, const char *text, SDL_Color fg) { return TTF_Render_Internal(font, text, STR_UTF8, fg, fg /* unused */, RENDER_BLENDED); } SDL_Surface* TTF_RenderUNICODE_Blended(TTF_Font *font, const Uint16 *text, SDL_Color fg) { return TTF_Render_Internal(font, (const char *)text, STR_UNICODE, fg, fg /* unused */, RENDER_BLENDED); } SDL_Surface* TTF_RenderText_LCD(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg) { return TTF_Render_Internal(font, text, STR_TEXT, fg, bg, RENDER_LCD); } SDL_Surface* TTF_RenderUTF8_LCD(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg) { return TTF_Render_Internal(font, text, STR_UTF8, fg, bg, RENDER_LCD); } SDL_Surface* TTF_RenderUNICODE_LCD(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg) { return TTF_Render_Internal(font, (const char *)text, STR_UNICODE, fg, bg, RENDER_LCD); } SDL_Surface* TTF_RenderGlyph_LCD(TTF_Font *font, Uint16 ch, SDL_Color fg, SDL_Color bg) { return TTF_RenderGlyph32_LCD(font, ch, fg, bg); } SDL_Surface* TTF_RenderGlyph32_LCD(TTF_Font *font, Uint32 ch, SDL_Color fg, SDL_Color bg) { Uint8 utf8[7]; TTF_CHECK_POINTER(font, NULL); if (!Char_to_UTF8(ch, utf8)) { return NULL; } return TTF_RenderUTF8_LCD(font, (char *)utf8, fg, bg); } static SDL_bool CharacterIsDelimiter(Uint32 c) { if (c == ' ' || c == '\t' || c == '\r' || c == '\n') { return SDL_TRUE; } return SDL_FALSE; } static SDL_bool CharacterIsNewLine(Uint32 c) { if (c == '\n') { return SDL_TRUE; } return SDL_FALSE; } static SDL_Surface* TTF_Render_Wrapped_Internal(TTF_Font *font, const char *text, const str_type_t str_type, SDL_Color fg, SDL_Color bg, Uint32 wrapLength, const render_mode_t render_mode) { Uint32 color; int width, height; SDL_Surface *textbuf = NULL; Uint8 *utf8_alloc = NULL; int i, numLines, rowHeight, lineskip; char **strLines = NULL, *text_cpy; TTF_CHECK_INITIALIZED(NULL); TTF_CHECK_POINTER(font, NULL); TTF_CHECK_POINTER(text, NULL); if (render_mode == RENDER_LCD && !FT_IS_SCALABLE(font->face)) { TTF_SetError("LCD rendering is not available for non-scalable font"); goto failure; } /* Convert input string to default encoding UTF-8 */ if (str_type == STR_TEXT) { utf8_alloc = SDL_stack_alloc(Uint8, LATIN1_to_UTF8_len(text)); if (utf8_alloc == NULL) { SDL_OutOfMemory(); goto failure; } LATIN1_to_UTF8(text, utf8_alloc); text_cpy = (char *)utf8_alloc; } else if (str_type == STR_UNICODE) { const Uint16 *text16 = (const Uint16 *) text; utf8_alloc = SDL_stack_alloc(Uint8, UCS2_to_UTF8_len(text16)); if (utf8_alloc == NULL) { SDL_OutOfMemory(); goto failure; } UCS2_to_UTF8(text16, utf8_alloc); text_cpy = (char *)utf8_alloc; } else { /* Use a copy anyway */ size_t str_len = SDL_strlen(text); utf8_alloc = SDL_stack_alloc(Uint8, str_len + 1); if (utf8_alloc == NULL) { SDL_OutOfMemory(); goto failure; } SDL_memcpy(utf8_alloc, text, str_len + 1); text_cpy = (char *)utf8_alloc; } #if TTF_USE_SDF /* Invalid cache if we were using SDF */ if (render_mode != RENDER_BLENDED) { if (font->render_sdf) { font->render_sdf = 0; Flush_Cache(font); } } #endif /* Get the dimensions of the text surface */ if ((TTF_SizeUTF8(font, text_cpy, &width, &height) < 0) || !width) { TTF_SetError("Text has zero width"); goto failure; } /* wrapLength is unsigned, but don't allow negative values */ if ((int)wrapLength < 0) { TTF_SetError("Invalid parameter 'wrapLength'"); goto failure; } numLines = 1; if (*text_cpy) { int maxNumLines = 0; size_t textlen = SDL_strlen(text_cpy); numLines = 0; do { int extent = 0, max_count = 0, char_count = 0; size_t save_textlen = (size_t)(-1); char *save_text = NULL; if (numLines >= maxNumLines) { char **saved = strLines; if (wrapLength == 0) { maxNumLines += 32; } else { maxNumLines += (width / wrapLength) + 1; } strLines = (char **)SDL_realloc(strLines, maxNumLines * sizeof (*strLines)); if (strLines == NULL) { strLines = saved; SDL_OutOfMemory(); goto failure; } } strLines[numLines++] = text_cpy; if (TTF_MeasureUTF8(font, text_cpy, wrapLength, &extent, &max_count) < 0) { TTF_SetError("Error measure text"); goto failure; } if (wrapLength != 0) { if (max_count == 0) { max_count = 1; } } while (textlen > 0) { int inc = 0; int is_delim; Uint32 c = UTF8_getch(text_cpy, textlen, &inc); text_cpy += inc; textlen -= inc; if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) { continue; } char_count += 1; /* With wrapLength == 0, normal text rendering but newline aware */ is_delim = (wrapLength > 0) ? CharacterIsDelimiter(c) : CharacterIsNewLine(c); /* Record last delimiter position */ if (is_delim) { save_textlen = textlen; save_text = text_cpy; /* Break, if new line */ if (c == '\n' || c == '\r') { *(text_cpy - 1) = '\0'; break; } } /* Break, if reach the limit */ if (char_count == max_count) { break; } } /* Cut at last delimiter/new lines, otherwise in the middle of the word */ if (save_text && textlen) { text_cpy = save_text; textlen = save_textlen; } } while (textlen > 0); } lineskip = TTF_FontLineSkip(font); rowHeight = SDL_max(height, lineskip); if (wrapLength == 0) { /* Find the max of all line lengths */ if (numLines > 1) { width = 0; for (i = 0; i < numLines; i++) { char save_c = 0; int w, h; /* Add end-of-line */ if (strLines) { text = strLines[i]; if (i + 1 < numLines) { save_c = strLines[i + 1][0]; strLines[i + 1][0] = '\0'; } } if (TTF_SizeUTF8(font, text, &w, &h) == 0) { width = SDL_max(w, width); } /* Remove end-of-line */ if (strLines) { if (i + 1 < numLines) { strLines[i + 1][0] = save_c; } } } /* In case there are all newlines */ width = SDL_max(width, 1); } } else { if (numLines <= 1 && font->horizontal_align == TTF_WRAPPED_ALIGN_LEFT) { /* Don't go above wrapLength if you have only 1 line which hasn't been cut */ width = SDL_min((int)wrapLength, width); } else { width = wrapLength; } } height = rowHeight + lineskip * (numLines - 1); /* Support alpha blending */ fg.a = fg.a ? fg.a : SDL_ALPHA_OPAQUE; bg.a = bg.a ? bg.a : SDL_ALPHA_OPAQUE; /* Create surface for rendering */ if (render_mode == RENDER_SOLID) { textbuf = Create_Surface_Solid(width, height, fg, &color); } else if (render_mode == RENDER_SHADED) { textbuf = Create_Surface_Shaded(width, height, fg, bg, &color); } else if (render_mode == RENDER_BLENDED) { textbuf = Create_Surface_Blended(width, height, fg, &color); } else { /* render_mode == RENDER_LCD */ textbuf = Create_Surface_LCD(width, height, fg, bg, &color); } if (textbuf == NULL) { goto failure; } /* Render each line */ for (i = 0; i < numLines; i++) { int xstart, ystart, line_width, xoffset; char save_c = 0; /* Add end-of-line */ if (strLines) { text = strLines[i]; if (i + 1 < numLines) { save_c = strLines[i + 1][0]; strLines[i + 1][0] = '\0'; } } /* Initialize xstart, ystart and compute positions */ if (TTF_Size_Internal(font, text, STR_UTF8, &line_width, NULL, &xstart, &ystart, NO_MEASUREMENT) < 0) { goto failure; } /* Move to i-th line */ ystart += i * lineskip; /* Control left/right/center align of each bit of text */ if (font->horizontal_align == TTF_WRAPPED_ALIGN_RIGHT) { xoffset = width - line_width; } else if (font->horizontal_align == TTF_WRAPPED_ALIGN_CENTER) { xoffset = width / 2 - line_width / 2; } else { xoffset = 0; } xoffset = SDL_max(0, xoffset); /* Render one text line to textbuf at (xstart, ystart) */ if (Render_Line(render_mode, font->render_subpixel, font, textbuf, xstart + xoffset, ystart, fg) < 0) { goto failure; } /* Apply underline or strikethrough style, if needed */ if (TTF_HANDLE_STYLE_UNDERLINE(font)) { Draw_Line(font, textbuf, xoffset, ystart + font->underline_top_row, line_width, font->line_thickness, color, render_mode); } if (TTF_HANDLE_STYLE_STRIKETHROUGH(font)) { Draw_Line(font, textbuf, xoffset, ystart + font->strikethrough_top_row, line_width, font->line_thickness, color, render_mode); } /* Remove end-of-line */ if (strLines) { if (i + 1 < numLines) { strLines[i + 1][0] = save_c; } } } if (strLines) { SDL_free(strLines); } if (utf8_alloc) { SDL_stack_free(utf8_alloc); } return textbuf; failure: if (textbuf) { SDL_FreeSurface(textbuf); } if (strLines) { SDL_free(strLines); } if (utf8_alloc) { SDL_stack_free(utf8_alloc); } return NULL; } SDL_Surface* TTF_RenderText_Solid_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, text, STR_TEXT, fg, fg /* unused */, wrapLength, RENDER_SOLID); } SDL_Surface* TTF_RenderUTF8_Solid_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, text, STR_UTF8, fg, fg /* unused */, wrapLength, RENDER_SOLID); } SDL_Surface* TTF_RenderUNICODE_Solid_Wrapped(TTF_Font *font, const Uint16 *text, SDL_Color fg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, (const char *)text, STR_UNICODE, fg, fg /* unused */, wrapLength, RENDER_SOLID); } SDL_Surface* TTF_RenderText_Shaded_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, text, STR_TEXT, fg, bg, wrapLength, RENDER_SHADED); } SDL_Surface* TTF_RenderUTF8_Shaded_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, text, STR_UTF8, fg, bg, wrapLength, RENDER_SHADED); } SDL_Surface* TTF_RenderUNICODE_Shaded_Wrapped(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, (const char *)text, STR_UNICODE, fg, bg, wrapLength, RENDER_SHADED); } SDL_Surface* TTF_RenderText_Blended_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, text, STR_TEXT, fg, fg /* unused */, wrapLength, RENDER_BLENDED); } SDL_Surface* TTF_RenderUTF8_Blended_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, text, STR_UTF8, fg, fg /* unused */, wrapLength, RENDER_BLENDED); } SDL_Surface* TTF_RenderUNICODE_Blended_Wrapped(TTF_Font *font, const Uint16 *text, SDL_Color fg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, (const char *)text, STR_UNICODE, fg, fg /* unused */, wrapLength, RENDER_BLENDED); } SDL_Surface* TTF_RenderText_LCD_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, text, STR_TEXT, fg, bg, wrapLength, RENDER_LCD); } SDL_Surface* TTF_RenderUTF8_LCD_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, text, STR_UTF8, fg, bg, wrapLength, RENDER_LCD); } SDL_Surface* TTF_RenderUNICODE_LCD_Wrapped(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength) { return TTF_Render_Wrapped_Internal(font, (const char *)text, STR_UNICODE, fg, bg, wrapLength, RENDER_LCD); } SDL_Surface* TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg) { return TTF_RenderGlyph32_Blended(font, ch, fg); } SDL_Surface* TTF_RenderGlyph32_Blended(TTF_Font *font, Uint32 ch, SDL_Color fg) { Uint8 utf8[7]; TTF_CHECK_POINTER(font, NULL); if (!Char_to_UTF8(ch, utf8)) { return NULL; } return TTF_RenderUTF8_Blended(font, (char *)utf8, fg); } void TTF_SetFontStyle(TTF_Font *font, int style) { int prev_style; long face_style; TTF_CHECK_POINTER(font,); prev_style = font->style; face_style = font->face->style_flags; /* Don't add a style if already in the font, SDL_ttf doesn't need to handle them */ if (face_style & FT_STYLE_FLAG_BOLD) { style &= ~TTF_STYLE_BOLD; } if (face_style & FT_STYLE_FLAG_ITALIC) { style &= ~TTF_STYLE_ITALIC; } font->style = style; TTF_initFontMetrics(font); /* Flush the cache if the style has changed. * Ignore styles which do not impact glyph drawning. */ if ((font->style | TTF_STYLE_NO_GLYPH_CHANGE) != (prev_style | TTF_STYLE_NO_GLYPH_CHANGE)) { Flush_Cache(font); } } int TTF_GetFontStyle(const TTF_Font *font) { int style; long face_style; TTF_CHECK_POINTER(font, -1); style = font->style; face_style = font->face->style_flags; /* Add the style already in the font */ if (face_style & FT_STYLE_FLAG_BOLD) { style |= TTF_STYLE_BOLD; } if (face_style & FT_STYLE_FLAG_ITALIC) { style |= TTF_STYLE_ITALIC; } return style; } void TTF_SetFontOutline(TTF_Font *font, int outline) { TTF_CHECK_POINTER(font,); font->outline_val = SDL_max(0, outline); TTF_initFontMetrics(font); Flush_Cache(font); } int TTF_GetFontOutline(const TTF_Font *font) { TTF_CHECK_POINTER(font, -1); return font->outline_val; } void TTF_SetFontHinting(TTF_Font *font, int hinting) { TTF_CHECK_POINTER(font,); if (hinting == TTF_HINTING_LIGHT || hinting == TTF_HINTING_LIGHT_SUBPIXEL) { font->ft_load_target = FT_LOAD_TARGET_LIGHT; } else if (hinting == TTF_HINTING_MONO) { font->ft_load_target = FT_LOAD_TARGET_MONO; } else if (hinting == TTF_HINTING_NONE) { font->ft_load_target = FT_LOAD_NO_HINTING; } else { font->ft_load_target = FT_LOAD_TARGET_NORMAL; } font->render_subpixel = (hinting == TTF_HINTING_LIGHT_SUBPIXEL) ? 1 : 0; #if TTF_USE_HARFBUZZ /* update flag for HB */ hb_ft_font_set_load_flags(font->hb_font, FT_LOAD_DEFAULT | font->ft_load_target); #endif Flush_Cache(font); } int TTF_GetFontHinting(const TTF_Font *font) { TTF_CHECK_POINTER(font, -1); if (font->ft_load_target == FT_LOAD_TARGET_LIGHT) { if (font->render_subpixel == 0) { return TTF_HINTING_LIGHT; } else { return TTF_HINTING_LIGHT_SUBPIXEL; } } else if (font->ft_load_target == FT_LOAD_TARGET_MONO) { return TTF_HINTING_MONO; } else if (font->ft_load_target == FT_LOAD_NO_HINTING) { return TTF_HINTING_NONE; } return TTF_HINTING_NORMAL; } int TTF_SetFontSDF(TTF_Font *font, SDL_bool on_off) { TTF_CHECK_POINTER(font, -1); #if TTF_USE_SDF font->render_sdf = on_off; Flush_Cache(font); return 0; #else TTF_SetError("SDL_ttf compiled without SDF support"); return -1; #endif } SDL_bool TTF_GetFontSDF(const TTF_Font *font) { TTF_CHECK_POINTER(font, SDL_FALSE); return font->render_sdf; } void TTF_SetFontWrappedAlign(TTF_Font *font, int align) { TTF_CHECK_POINTER(font,); /* input not checked, unknown values assumed to be TTF_WRAPPED_ALIGN_LEFT */ if (align == TTF_WRAPPED_ALIGN_CENTER) { font->horizontal_align = TTF_WRAPPED_ALIGN_CENTER; } else if (align == TTF_WRAPPED_ALIGN_RIGHT) { font->horizontal_align = TTF_WRAPPED_ALIGN_RIGHT; } else { font->horizontal_align = TTF_WRAPPED_ALIGN_LEFT; } } int TTF_GetFontWrappedAlign(const TTF_Font *font) { TTF_CHECK_POINTER(font,-1); return font->horizontal_align; } void TTF_Quit(void) { if (TTF_initialized) { if (--TTF_initialized == 0) { FT_Done_FreeType(library); library = NULL; } } } int TTF_WasInit(void) { return TTF_initialized; } /* don't use this function. It's just here for binary compatibility. */ int TTF_GetFontKerningSize(TTF_Font *font, int prev_index, int index) { FT_Vector delta; TTF_CHECK_POINTER(font, -1); FT_Get_Kerning(font->face, (FT_UInt)prev_index, (FT_UInt)index, FT_KERNING_DEFAULT, &delta); return (int)(delta.x >> 6); } int TTF_GetFontKerningSizeGlyphs(TTF_Font *font, Uint16 previous_ch, Uint16 ch) { return TTF_GetFontKerningSizeGlyphs32(font, previous_ch, ch); } int TTF_GetFontKerningSizeGlyphs32(TTF_Font *font, Uint32 previous_ch, Uint32 ch) { FT_Error error; c_glyph *prev_glyph, *glyph; FT_Vector delta; TTF_CHECK_POINTER(font, -1); if (ch == UNICODE_BOM_NATIVE || ch == UNICODE_BOM_SWAPPED) { return 0; } if (previous_ch == UNICODE_BOM_NATIVE || previous_ch == UNICODE_BOM_SWAPPED) { return 0; } if (Find_GlyphMetrics(font, ch, &glyph) < 0) { return -1; } if (Find_GlyphMetrics(font, previous_ch, &prev_glyph) < 0) { return -1; } error = FT_Get_Kerning(font->face, prev_glyph->index, glyph->index, FT_KERNING_DEFAULT, &delta); if (error) { TTF_SetFTError("Couldn't get glyph kerning", error); return -1; } return (int)(delta.x >> 6); } /* vi: set ts=4 sw=4 expandtab: */ SDL2_ttf-2.22.0/autogen.sh0000755000076500000240000000030114551277723014166 0ustar valvestaff#!/bin/sh set -e "${ACLOCAL:-aclocal}" -I acinclude "${AUTOMAKE:-automake}" --foreign --include-deps --add-missing --copy "${AUTOCONF:-autoconf}" echo "Now you are ready to run ./configure"