[autofit] Enable dynamic loading of HarfBuzz. (1/2)

This commit activates the mini-HarfBuzz header files and provides the
necessary infrastructure for dynamically loading HarfBuzz if
`FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC` is defined (this macro gets set up
in a follow-up commit).

* src/autofit/ft-hb.c: New file, providing `ft_hb_funcs_init` and
  `ft_hb_funcs_done` for loading HarfBuzz dynamically.  The name of the
  library is hold in the macro `FT_LIBHARFBUZZ`, which can be overridden.

* src/autofit/ft-hb.h: Don't include `hb.h` but `ft-hb-types.h`.
  (hb): Modified to handle both standard linking and dynamically
  loading of HarfBuzz.
  (HB_EXTERN): New macro to load `ft-hb-decls.h`.

* src/autofit/afadjust.c [FT_CONFIG_OPTION_USE_HARFBUZZ]: For the sake of
  dynamically loading the HarfBuzz library, replace the compile-time macro
  `HB_VERSION_ATLEAST` with a call to the run-time function
  `hb_version_atleast` where necessary – a follow-up commit will set the
  minimum version of HarfBuzz to 2.6.8, which provides all necessary
  functions needed by FreeType.

* src/autofit/afmodule.h: Include `ft-hb.h`.
  (AF_ModuleRec) [FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC]: Add `hb_funcs`
  structure to hold pointers to the dynamically loaded HarfBuzz functions.

* src/autofit/afmodule.c (af_autofitter_init, af_autofitter_done)
  [FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC]: Call `ft_hb_funcs_init` and
  `ft_hb_funcs_done`.

* src/autofit/afshaper.h: Updated.
* src/autofit/autofit.c: Include `ft-hb.c`.

* src/autofit/rules.mk (AUTOF_DRV_SRC, AUTOF_DRV_H): Updated.
This commit is contained in:
Behdad Esfahbod (بهداد اسفهبد)
2025-04-27 18:44:49 +02:00
committed by Werner Lemberg
parent b512ce3ec7
commit 7651fe00be
8 changed files with 233 additions and 28 deletions

View File

@@ -987,7 +987,6 @@
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
# if HB_VERSION_ATLEAST( 7, 2, 0 )
/*
Find all glyphs that a code point could turn into from the OpenType
@@ -1124,7 +1123,6 @@
hb( set_destroy )( helper_result );
}
# endif /* HB_VERSION_ATLEAST */
#endif /* FT_CONFIG_OPTION_USE_HARFBUZZ */
@@ -1166,8 +1164,8 @@
goto Exit;
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
# if HB_VERSION_ATLEAST( 7, 2, 0 )
if ( hb( version_atleast )( 7, 2, 0 ) )
{
/* No need to check whether HarfBuzz has allocation issues; */
/* it continues to work in such cases and simply returns */
@@ -1277,10 +1275,9 @@
codepoint = FT_Get_Next_Char( face, codepoint, &glyph_index );
}
}
else
# endif /* HB_VERSION_ATLEAST */
#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
#endif /* FT_CONFIG_OPTION_USE_HARFBUZZ */
{
FT_UInt i;
@@ -1313,8 +1310,6 @@
af_reverse_character_map_entry_compare );
}
#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
FT_TRACE4(( " reverse character map built successfully"
" with %ld entries\n", ( *map )->length ));

View File

@@ -412,6 +412,11 @@
module->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
module->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \
defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC )
ft_hb_funcs_init( module );
#endif
return FT_Err_Ok;
}
@@ -421,6 +426,11 @@
{
FT_UNUSED( ft_module );
#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \
defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC )
ft_hb_funcs_done( (AF_Module)ft_module );
#endif
#ifdef FT_DEBUG_AUTOFIT
if ( af_debug_hints_rec_->memory )
af_glyph_hints_done( af_debug_hints_rec_ );

View File

@@ -22,6 +22,7 @@
#include <freetype/internal/ftobjs.h>
#include <freetype/ftmodapi.h>
#include "ft-hb.h"
FT_BEGIN_HEADER
@@ -40,6 +41,11 @@ 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 )
ft_hb_funcs_t* hb_funcs;
#endif
} AF_ModuleRec, *AF_Module;

View File

@@ -23,15 +23,6 @@
#include <freetype/freetype.h>
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
#include <hb.h>
#include <hb-ot.h>
#include "ft-hb-ft.h"
#endif
FT_BEGIN_HEADER
FT_Error

View File

@@ -18,6 +18,7 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include "ft-hb.c"
#include "ft-hb-ft.c"
#include "afadjust.c"
#include "afblue.c"

165
src/autofit/ft-hb.c Normal file
View File

@@ -0,0 +1,165 @@
/****************************************************************************
*
* ft-hb.c
*
* FreeType-HarfBuzz bridge (body).
*
* Copyright (C) 2025 by
* Behdad Esfahbod.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/freetype.h>
#include <freetype/internal/ftmemory.h>
#include "afglobal.h"
#include "ft-hb.h"
#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \
defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC )
#ifndef FT_LIBHARFBUZZ
# ifdef _WIN32
# define FT_LIBHARFBUZZ "libharfbuzz-0.dll"
# else
# ifdef __APPLE__
# define FT_LIBHARFBUZZ "libharfbuzz.0.dylib"
# else
# define FT_LIBHARFBUZZ "libharfbuzz.so.0"
# endif
# endif
#endif
#ifdef _WIN32
# include <windows.h>
#else /* !_WIN32 */
# include <dlfcn.h>
/* The GCC pragma suppresses the warning "ISO C forbids */
/* assignment between function pointer and 'void *'", which */
/* inevitably gets emitted with `-Wpedantic`; see the man */
/* page of function `dlsym` for more information. */
# if defined( __GNUC__ )
# pragma GCC diagnostic push
# ifndef __cplusplus
# pragma GCC diagnostic ignored "-Wpedantic"
# endif
# endif
#endif /* !_WIN32 */
FT_LOCAL_DEF( void )
ft_hb_funcs_init( struct AF_ModuleRec_ *af_module )
{
FT_Memory memory = af_module->root.memory;
FT_Error error;
ft_hb_funcs_t *funcs = NULL;
ft_hb_version_atleast_func_t version_atleast = NULL;
#ifdef _WIN32
HANDLE lib;
# define DLSYM( lib, name ) \
(ft_ ## name ## _func_t)GetProcAddress( lib, #name )
#else
void *lib;
# define DLSYM( lib, name ) \
(ft_ ## name ## _func_t)dlsym( lib, #name )
#endif
af_module->hb_funcs = NULL;
if ( FT_NEW( funcs ) )
return;
FT_ZERO( funcs );
#ifdef _WIN32
lib = LoadLibraryA( FT_LIBHARFBUZZ );
if ( !lib )
goto Fail;
version_atleast = DLSYM( lib, hb_version_atleast );
#else /* !_WIN32 */
lib = RTLD_DEFAULT;
version_atleast = DLSYM( lib, hb_version_atleast );
if ( !version_atleast )
{
/* Load the HarfBuzz library.
*
* We never close the library, since we opened it with RTLD_GLOBAL.
* This is important for the case where we are using HarfBuzz as a
* shared library, and we want to use the symbols from the library in
* other shared libraries or clients. HarfBuzz holds onto global
* variables, and closing the library will cause them to be
* invalidated.
*/
lib = dlopen( FT_LIBHARFBUZZ, RTLD_LAZY | RTLD_GLOBAL );
if ( !lib )
goto Fail;
version_atleast = DLSYM( lib, hb_version_atleast );
if ( !version_atleast )
goto Fail;
}
#endif /* !_WIN32 */
/* Load all symbols we use. */
#define HB_EXTERN( ret, name, args ) \
{ \
funcs->name = DLSYM( lib, name ); \
if ( !funcs->name ) \
goto Fail; \
}
#include "ft-hb-decls.h"
#undef HB_EXTERN
#undef DLSYM
af_module->hb_funcs = funcs;
return;
Fail:
if ( funcs )
FT_FREE( funcs );
}
FT_LOCAL_DEF( void )
ft_hb_funcs_done( struct AF_ModuleRec_ *af_module )
{
FT_Memory memory = af_module->root.memory;
if ( af_module->hb_funcs )
{
FT_FREE( af_module->hb_funcs );
af_module->hb_funcs = NULL;
}
}
#ifndef _WIN32
# if defined( __GNUC__ )
# pragma GCC diagnostic pop
# endif
#endif
#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */
/* END */

View File

@@ -19,8 +19,6 @@
#ifndef FT_HB_H
#define FT_HB_H
#include <hb.h>
#include <freetype/internal/compiler-macros.h>
#include <freetype/freetype.h>
@@ -29,10 +27,47 @@ FT_BEGIN_HEADER
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
#define hb( x ) hb_ ## x
# include "ft-hb-types.h"
# ifdef FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC
# define HB_EXTERN( ret, name, args ) \
typedef ret (*ft_ ## name ## _func_t) args;
# include "ft-hb-decls.h"
# undef HB_EXTERN
typedef struct ft_hb_funcs_t
{
# define HB_EXTERN( ret, name, args ) \
ft_ ## name ## _func_t name;
# include "ft-hb-decls.h"
# undef HB_EXTERN
} ft_hb_funcs_t;
struct AF_ModuleRec_;
FT_LOCAL( void )
ft_hb_funcs_init( struct AF_ModuleRec_ *af_module );
FT_LOCAL( void )
ft_hb_funcs_done( struct AF_ModuleRec_ *af_module );
# define hb( x ) globals->module->hb_funcs->hb_ ## x
# else /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */
# define HB_EXTERN( ret, name, args ) \
ret name args;
# include "ft-hb-decls.h"
# undef HB_EXTERN
# define hb( x ) hb_ ## x
# endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */
#endif /* FT_CONFIG_OPTION_USE_HARFBUZZ */
FT_END_HEADER
#endif /* FT_HB_H */

View File

@@ -40,18 +40,20 @@ AUTOF_DRV_SRC := $(AUTOF_DIR)/afadjust.c \
$(AUTOF_DIR)/afmodule.c \
$(AUTOF_DIR)/afranges.c \
$(AUTOF_DIR)/afshaper.c \
$(AUTOF_DIR)/ft-hb.c \
$(AUTOF_DIR)/ft-hb-ft.c
# AUTOF driver headers
#
AUTOF_DRV_H := $(AUTOF_DRV_SRC:%c=%h) \
$(AUTOF_DIR)/afcover.h \
$(AUTOF_DIR)/aferrors.h \
$(AUTOF_DIR)/afscript.h \
$(AUTOF_DIR)/afstyles.h \
$(AUTOF_DIR)/aftypes.h \
$(AUTOF_DIR)/afws-decl.h \
$(AUTOF_DIR)/afws-iter.h
AUTOF_DRV_H := $(AUTOF_DRV_SRC:%c=%h) \
$(AUTOF_DIR)/afcover.h \
$(AUTOF_DIR)/aferrors.h \
$(AUTOF_DIR)/afscript.h \
$(AUTOF_DIR)/afstyles.h \
$(AUTOF_DIR)/aftypes.h \
$(AUTOF_DIR)/afws-decl.h \
$(AUTOF_DIR)/afws-iter.h \
$(AUTOF_DIR)/ft-hb-decls.h
# AUTOF driver object(s)