ft-hb.c (4487B)
1 /**************************************************************************** 2 * 3 * ft-hb.c 4 * 5 * FreeType-HarfBuzz bridge (body). 6 * 7 * Copyright (C) 2025 by 8 * Behdad Esfahbod. 9 * 10 * This file is part of the FreeType project, and may only be used, 11 * modified, and distributed under the terms of the FreeType project 12 * license, LICENSE.TXT. By continuing to use, modify, or distribute 13 * this file you indicate that you have read the license and 14 * understand and accept it fully. 15 * 16 */ 17 18 19 #if !defined( _WIN32 ) && !defined( _GNU_SOURCE ) 20 # define _GNU_SOURCE 1 /* for RTLD_DEFAULT */ 21 #endif 22 23 #include <freetype/freetype.h> 24 #include <freetype/internal/ftmemory.h> 25 26 #include "afglobal.h" 27 28 #include "ft-hb.h" 29 30 31 #if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \ 32 defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC ) 33 34 #ifndef FT_LIBHARFBUZZ 35 # ifdef _WIN32 36 # define FT_LIBHARFBUZZ "libharfbuzz-0.dll" 37 # else 38 # ifdef __APPLE__ 39 # define FT_LIBHARFBUZZ "libharfbuzz.0.dylib" 40 # else 41 # define FT_LIBHARFBUZZ "libharfbuzz.so.0" 42 # endif 43 # endif 44 #endif 45 46 #ifdef _WIN32 47 48 # include <windows.h> 49 50 #else /* !_WIN32 */ 51 52 # include <dlfcn.h> 53 54 /* The GCC pragma suppresses the warning "ISO C forbids */ 55 /* assignment between function pointer and 'void *'", which */ 56 /* inevitably gets emitted with `-Wpedantic`; see the man */ 57 /* page of function `dlsym` for more information. */ 58 # if defined( __GNUC__ ) 59 # pragma GCC diagnostic push 60 # ifndef __cplusplus 61 # pragma GCC diagnostic ignored "-Wpedantic" 62 # endif 63 # endif 64 65 #endif /* !_WIN32 */ 66 67 68 FT_LOCAL_DEF( void ) 69 ft_hb_funcs_init( struct AF_ModuleRec_ *af_module ) 70 { 71 FT_Memory memory = af_module->root.memory; 72 FT_Error error; 73 74 ft_hb_funcs_t *funcs = NULL; 75 ft_hb_version_atleast_func_t version_atleast = NULL; 76 77 #ifdef _WIN32 78 HANDLE lib; 79 # define DLSYM( lib, name ) \ 80 (ft_ ## name ## _func_t)GetProcAddress( lib, #name ) 81 #else 82 void *lib; 83 # define DLSYM( lib, name ) \ 84 (ft_ ## name ## _func_t)dlsym( lib, #name ) 85 #endif 86 87 88 af_module->hb_funcs = NULL; 89 90 if ( FT_NEW( funcs ) ) 91 return; 92 FT_ZERO( funcs ); 93 94 #ifdef _WIN32 95 96 lib = LoadLibraryA( FT_LIBHARFBUZZ ); 97 if ( !lib ) 98 goto Fail; 99 version_atleast = DLSYM( lib, hb_version_atleast ); 100 101 #else /* !_WIN32 */ 102 103 # ifdef RTLD_DEFAULT 104 # define FT_RTLD_FLAGS RTLD_LAZY | RTLD_GLOBAL 105 lib = RTLD_DEFAULT; 106 version_atleast = DLSYM( lib, hb_version_atleast ); 107 # else 108 # define FT_RTLD_FLAGS RTLD_LAZY 109 # endif 110 111 if ( !version_atleast ) 112 { 113 /* Load the HarfBuzz library. 114 * 115 * We never close the library, since we opened it with RTLD_GLOBAL. 116 * This is important for the case where we are using HarfBuzz as a 117 * shared library, and we want to use the symbols from the library in 118 * other shared libraries or clients. HarfBuzz holds onto global 119 * variables, and closing the library will cause them to be 120 * invalidated. 121 */ 122 lib = dlopen( FT_LIBHARFBUZZ, FT_RTLD_FLAGS ); 123 if ( !lib ) 124 goto Fail; 125 version_atleast = DLSYM( lib, hb_version_atleast ); 126 } 127 128 #endif /* !_WIN32 */ 129 130 if ( !version_atleast ) 131 goto Fail; 132 133 /* Load all symbols we use. */ 134 #define HB_EXTERN( ret, name, args ) \ 135 { \ 136 funcs->name = DLSYM( lib, name ); \ 137 if ( !funcs->name ) \ 138 goto Fail; \ 139 } 140 #include "ft-hb-decls.h" 141 #undef HB_EXTERN 142 143 #undef DLSYM 144 145 af_module->hb_funcs = funcs; 146 return; 147 148 Fail: 149 if ( funcs ) 150 FT_FREE( funcs ); 151 } 152 153 154 FT_LOCAL_DEF( void ) 155 ft_hb_funcs_done( struct AF_ModuleRec_ *af_module ) 156 { 157 FT_Memory memory = af_module->root.memory; 158 159 160 if ( af_module->hb_funcs ) 161 { 162 FT_FREE( af_module->hb_funcs ); 163 af_module->hb_funcs = NULL; 164 } 165 } 166 167 168 FT_LOCAL_DEF( FT_Bool ) 169 ft_hb_enabled( struct AF_FaceGlobalsRec_ *globals ) 170 { 171 return globals->module->hb_funcs != NULL; 172 } 173 174 #ifndef _WIN32 175 # if defined( __GNUC__ ) 176 # pragma GCC diagnostic pop 177 # endif 178 #endif 179 180 #else /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */ 181 182 FT_LOCAL_DEF( FT_Bool ) 183 ft_hb_enabled( struct AF_FaceGlobalsRec_ *globals ) 184 { 185 FT_UNUSED( globals ); 186 187 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ 188 return TRUE; 189 #else 190 return FALSE; 191 #endif 192 } 193 194 #endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */ 195 196 197 /* END */