Let HarfBuzz inject its function pointers into FreeType

This commit is contained in:
6ziv 2025-10-29 02:22:52 +08:00
parent ae63cc0d13
commit fa4fc2901a
9 changed files with 96 additions and 10 deletions

View file

@ -205,6 +205,9 @@ option(FT_DISABLE_HARFBUZZ
cmake_dependent_option(FT_DYNAMIC_HARFBUZZ
"Load HarfBuzz library dynamically at runtime, if possible." ON
"NOT FT_DISABLE_HARFBUZZ" OFF)
cmake_dependent_option(FT_USE_HARFBUZZ_CALLBACKS
"Let HarfBuzz library inject callback methods at runtime." OFF
"NOT FT_DISABLE_HARFBUZZ;NOT FT_DYNAMIC_HARFBUZZ" OFF)
cmake_dependent_option(FT_REQUIRE_HARFBUZZ
"Require HarfBuzz for improving auto-hinting of OpenType fonts." OFF
"NOT FT_DISABLE_HARFBUZZ" OFF)
@ -272,10 +275,14 @@ if (NOT FT_DISABLE_HARFBUZZ)
endif()
endif()
endif()
elseif(FT_USE_HARFBUZZ_CALLBACKS)
set(FT_HARFBUZZ_CALLBACKS_ENABLED TRUE)
endif()
if (FT_DYNAMIC_HARFBUZZ_ENABLED)
message(STATUS "Enabled dynamic loading of HarfBuzz library at runtime.")
elseif (FT_HARFBUZZ_CALLBACKS_ENABLED)
message(STATUS "Enable HarfBuzz to inject callbacks into FreeType.")
elseif (FT_REQUIRE_HARFBUZZ)
find_package(HarfBuzz ${HARFBUZZ_MIN_VERSION} REQUIRED)
else ()
@ -373,7 +380,7 @@ if (PNG_FOUND)
"/\\* +(#define +FT_CONFIG_OPTION_USE_PNG) +\\*/" "\\1"
FTOPTION_H "${FTOPTION_H}")
endif ()
if (HARFBUZZ_FOUND OR FT_DYNAMIC_HARFBUZZ_ENABLED)
if (HARFBUZZ_FOUND OR FT_DYNAMIC_HARFBUZZ_ENABLED OR FT_HARFBUZZ_CALLBACKS_ENABLED)
string(REGEX REPLACE
"/\\* +(#define +FT_CONFIG_OPTION_USE_HARFBUZZ) +\\*/" "\\1"
FTOPTION_H "${FTOPTION_H}")
@ -381,6 +388,10 @@ if (HARFBUZZ_FOUND OR FT_DYNAMIC_HARFBUZZ_ENABLED)
string(REGEX REPLACE
"/\\* +(#define +FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC) +\\*/" "\\1"
FTOPTION_H "${FTOPTION_H}")
elseif (FT_HARFBUZZ_CALLBACKS_ENABLED)
string(REGEX REPLACE
"/\\* +(#define +FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS) +\\*/" "\\1"
FTOPTION_H "${FTOPTION_H}")
endif ()
endif ()
if (BROTLIDEC_FOUND)
@ -572,7 +583,7 @@ if (FT_DYNAMIC_HARFBUZZ_ENABLED AND FT_NEED_LIBDL)
target_link_libraries(freetype PRIVATE dl)
list(APPEND PKGCONFIG_LIBS_PRIVATE " -ldl")
endif ()
if (HarfBuzz_FOUND AND (NOT FT_DYNAMIC_HARFBUZZ_ENABLED))
if (HarfBuzz_FOUND AND (NOT FT_DYNAMIC_HARFBUZZ_ENABLED) AND (NOT FT_HARFBUZZ_CALLBACKS_ENABLED))
target_link_libraries(freetype PRIVATE HarfBuzz::HarfBuzz)
list(APPEND PKGCONFIG_REQUIRES_PRIVATE "harfbuzz >= ${HARFBUZZ_MIN_VERSION}")
endif ()

View file

@ -441,7 +441,7 @@ fi
# check for system libharfbuzz
AC_ARG_WITH([harfbuzz],
[AS_HELP_STRING([--with-harfbuzz=@<:@yes|dynamic|no|auto@:>@],
[AS_HELP_STRING([--with-harfbuzz=@<:@yes|dynamic|no|callbacks|auto@:>@],
[improve auto-hinting of OpenType fonts @<:@default=auto@:>@])],
[], [with_harfbuzz=auto])
@ -505,6 +505,14 @@ if test x"$have_harfbuzz" = xno; then
;;
esac
fi
have_harfbuzz_callbacks=no
if test x"$have_harfbuzz" = xno; then
if test x"$with_harfbuzz" = xcallbacks; then
have_harfbuzz_callbacks=yes
have_harfbuzz="yes (callbacks)"
fi
fi
if test x"$have_harfbuzz" = xno; then
@ -1165,6 +1173,11 @@ if test "$have_harfbuzz_dynamic" != no; then
else
ftoption_unset FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC
fi
if test "$have_harfbuzz_callbacks" != no; then
ftoption_set FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS
else
ftoption_unset FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS
fi
if test "$have_brotli" != no; then
CFLAGS="$CFLAGS $BROTLI_CFLAGS"
LDFLAGS="$LDFLAGS $BROTLI_LIBS"

View file

@ -317,6 +317,26 @@ FT_BEGIN_HEADER
*/
/* #define FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */
/**************************************************************************
*
* HarfBuzz callbacks support.
*
* Define this macro if you want the HarfBuzz library to inject callback
* functions to FreeType
*
* This option has no effect if `FT_CONFIG_OPTION_USE_HARFBUZZ` is not
* defined.
*
* When this option is enabled, FreeType will not load or link to the
* HarfBuzz library. Instead, the HarfBuzz library is expected to set
* use property 'harfbuzz-callbacks' to pass callback functions into
* FreeType.
*
* If you use a build system like cmake or the `configure` script,
* options set by those programs have precedence, overwriting the value
* here with the configured one.
*/
/* #define FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS */
/**************************************************************************
*

View file

@ -388,6 +388,13 @@ if not harfbuzz_dep.found() and \
endif
endif
if harfbuzz_opt == 'callbacks'
ftoption_command += [
'--enable=FT_CONFIG_OPTION_USE_HARFBUZZ',
'--enable=FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS',
]
endif
if harfbuzz_opt == 'disabled' or harfbuzz_opt == 'auto'
harfbuzz_opt = 'NO'
endif

View file

@ -24,7 +24,7 @@ option('bzip2',
option('harfbuzz',
type: 'combo',
choices: ['auto', 'enabled', 'dynamic', 'disabled'],
choices: ['auto', 'enabled', 'dynamic', 'disabled', 'callbacks'],
value: 'auto',
description: 'Use Harfbuzz library to improve auto-hinting;'
+ ' if available, many glyphs not directly addressable'

View file

@ -275,7 +275,16 @@
return error;
}
#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \
defined( FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS )
#if defined ( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC )
#error "Can not set both dynamic harfbuzz and injected harfbuzz callbacks"
#endif
else if ( !ft_strcmp( property_name, "harfbuzz-callbacks" ) )
{
module->hb_funcs = (ft_hb_funcs_t*)value;
}
#endif
FT_TRACE2(( "af_property_set: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
@ -362,7 +371,17 @@
return error;
}
#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \
defined( FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS )
#if defined ( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC )
#error "Can not set both dynamic harfbuzz and injected harfbuzz callbacks"
#endif
else if ( !ft_strcmp( property_name, "harfbuzz-callbacks" ) )
{
ft_hb_funcs_t **val = (ft_hb_funcs_t **)value;
*val = module->hb_funcs;
}
#endif
FT_TRACE2(( "af_property_get: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );

View file

@ -41,8 +41,9 @@ FT_BEGIN_HEADER
FT_Bool no_stem_darkening;
FT_Int darken_params[8];
#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \
defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC )
#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \
( defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC ) || \
defined( FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS ) )
ft_hb_funcs_t* hb_funcs;
#endif

View file

@ -179,6 +179,14 @@
#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */
#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \
defined( FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS )
FT_LOCAL_DEF( FT_Bool )
ft_hb_enabled( struct AF_FaceGlobalsRec_ *globals )
{
return globals->module->hb_funcs != NULL;
}
#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS*/
FT_LOCAL_DEF( FT_Bool )
ft_hb_enabled( struct AF_FaceGlobalsRec_ *globals )
{
@ -191,6 +199,8 @@
#endif
}
#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS */
#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */

View file

@ -29,7 +29,8 @@ FT_BEGIN_HEADER
# include "ft-hb-types.h"
# ifdef FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC
# if defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC ) || \
defined( FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS )
# define HB_EXTERN( ret, name, args ) \
typedef ret (*ft_ ## name ## _func_t) args;
@ -44,6 +45,8 @@ FT_BEGIN_HEADER
# undef HB_EXTERN
} ft_hb_funcs_t;
# ifdef FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC
struct AF_ModuleRec_;
FT_LOCAL( void )
@ -52,9 +55,11 @@ FT_BEGIN_HEADER
FT_LOCAL( void )
ft_hb_funcs_done( struct AF_ModuleRec_ *af_module );
# endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */
# define hb( x ) globals->module->hb_funcs->hb_ ## x
# else /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */
# else /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC && !FT_CONFIG_OPTION_USE_HARFBUZZ_CALLBACKS*/
# define HB_EXTERN( ret, name, args ) \
ret name args;