| /**************************************************************************** |
| * |
| * 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. |
| * |
| */ |
| |
| |
| #if !defined( _WIN32 ) && !defined( _GNU_SOURCE ) |
| # define _GNU_SOURCE 1 /* for RTLD_DEFAULT */ |
| #endif |
| |
| #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 */ |
| |
| # ifdef RTLD_DEFAULT |
| # define FT_RTLD_FLAGS RTLD_LAZY | RTLD_GLOBAL |
| lib = RTLD_DEFAULT; |
| version_atleast = DLSYM( lib, hb_version_atleast ); |
| # else |
| # define FT_RTLD_FLAGS RTLD_LAZY |
| # endif |
| |
| 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, FT_RTLD_FLAGS ); |
| if ( !lib ) |
| goto Fail; |
| version_atleast = DLSYM( lib, hb_version_atleast ); |
| } |
| |
| #endif /* !_WIN32 */ |
| |
| if ( !version_atleast ) |
| goto Fail; |
| |
| /* 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; |
| } |
| } |
| |
| |
| FT_LOCAL_DEF( FT_Bool ) |
| ft_hb_enabled( struct AF_FaceGlobalsRec_ *globals ) |
| { |
| return globals->module->hb_funcs != NULL; |
| } |
| |
| #ifndef _WIN32 |
| # if defined( __GNUC__ ) |
| # pragma GCC diagnostic pop |
| # endif |
| #endif |
| |
| #else /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */ |
| |
| FT_LOCAL_DEF( FT_Bool ) |
| ft_hb_enabled( struct AF_FaceGlobalsRec_ *globals ) |
| { |
| FT_UNUSED( globals ); |
| |
| #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ |
| return TRUE; |
| #else |
| return FALSE; |
| #endif |
| } |
| |
| #endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */ |
| |
| |
| /* END */ |