Hi, I saw a small discussion in fontconfig mail list, asking for a method getting a pathname from FT_Face.
http://lists.freedesktop.org/archives/fontconfig/2010-January/003349.html Although the original requester didn't describe why such incomplete de-abstraction is needed (ANSI C provides no function getting a pathname from FILE handle), I think it could be presumable request. In the cases of Mac OS (both of classic and X) and Microsoft Windows, the operating system provide an authorized font management system that provides official font identifiers to application programmers (e.g. familyID of QuickDraw, ATSFontRef of AppleTypeService, HFONT of Win32, etc), and some of them provide the method to obtain the pathnames of source font file(s) providing the face. # I don't know Win32 has such, but post-Vista Windows # has such, IDWriteFontFace::GetFiles method. However, on modern Unix platforms, there is no such authorized system providing font identifier. Each applications should manage the font resource with their own font identifier. When an application developer writes his software from scratch, or check whole of the source carefully, he will find the best font resource identifier for his application, and it won't be FT_Face. But, when he has quite small scope (or, he is not permitted to modify the source to pass the font identifier from the font managing part to his part), he may fall to a sad situation that all he can access is FT_Face object only. -- In fontconfig mail list, Behdad commented as one can get the pathname if he digs the internal/private data of FT_Face record: http://lists.freedesktop.org/archives/fontconfig/2010-January/003356.html It is correct. FT_Face->stream->pathname would be the possible place to be checked. This location can be dermined without internal header files (although FT_Face->stream is commented as private). However, there is no guarantee that the stream is opened from a file and the content of pathname is valid. In addition, FT_Face->stream->pathname won't point source pathname of LZW or GZIP stream. More detailed work is required for comprehensive functionality. I wrote an experimental patch to provide FT_Get_Path_From_{Stream,Face}. I attached the detailed description in the end of this post. Although I wrote the request to get a pathname from FT_Face object as "presumable" in above, but I'm not sure it is "frequent". So I won't commit this patch soon. When we receive so many requests for such functionalities, let's start the discussion. However, I want to make stream drivers more modularized styles, for easier insertion of new (or external) stream drivers. Regards, mpsuzuki == New functions to retrieve pathnames from FT_Face or FT_Stream object. I'm not sure if FT_Get_Path_From_Stream is required for public API. diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index e74f319..5c25b5c 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -3866,6 +3866,20 @@ FT_BEGIN_HEADER FT_Face_SetUnpatentedHinting( FT_Face face, FT_Bool value ); + + FT_EXPORT( FT_Error ) + FT_Get_Path_From_Stream( FT_Library library, + FT_Stream stream, + FT_Byte* buff, + FT_Offset buffsize ); + + + FT_EXPORT( FT_Error ) + FT_Get_Path_From_Face( FT_Face face, + FT_Byte* buff, + FT_Offset buffsize ); + + /* */ >From the internal of FreeType2, FT_Get_Path_From_Face() is a thin wrapper of FT_Get_Path_From_Stream(). However, if we care the attached files (e.g. AFM attached to PFA), more detailed work is needed. diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 46bcd3b..60432ef 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -4497,4 +4497,15 @@ } + FT_EXPORT_DEF( FT_Error ) + FT_Get_Path_From_Face( FT_Face face, + FT_Byte* buff, + FT_Offset buffsize ) + { + return FT_Get_Path_From_Stream( face->driver->root.library, + face->stream, + buff, buffsize ); + } + + /* END */ The internal part of There are 2 fundamental streams in FreeType2 are, file & memory image. For file-based stream, src/base/ftsystem.c provides FILE handle based stream with ANSI C file I/O functions. For the systems with the functions accessing files faster than ANSI C file I/O, like mmap(), system-specific ftsystem.c are provided (Unix, Amiga, VMS). To access the pathname info from these fundamental streams, FT_Get_Path_From_Stream_System() is used. diff --git a/include/freetype/internal/ftstream.h b/include/freetype/internal/ftstream.h index a91eb72..fcfaf69 100644 --- a/include/freetype/internal/ftstream.h +++ b/include/freetype/internal/ftstream.h @@ -531,6 +531,15 @@ FT_BEGIN_HEADER (FT_Byte**)&(bytes) ) ) + /* Get a pathname from a stream, */ + /* if it is a stream opened by system file i/o function. */ + FT_BASE( FT_Error ) + FT_Get_Path_From_Stream_System( FT_Library library, + FT_Stream stream, + FT_Byte* buff, + FT_Offset buffsize ); + + FT_END_HEADER #endif /* __FTSTREAM_H__ */ The implementation of FT_Get_Path_From_Stream_System() is written in all ftsystem.c. The scheme is exactly same: if comparing stream->{read,close} are pointing to file I/O functions, and stream->pathname.pointer is not NULL, the content is copied to the buffer passed by the caller. diff --git a/src/base/ftsystem.c b/src/base/ftsystem.c index 4d06d6d..6e91905 100644 --- a/src/base/ftsystem.c +++ b/src/base/ftsystem.c @@ -252,6 +252,31 @@ } + FT_BASE_DEF( FT_Error ) + FT_Get_Path_From_Stream_System( FT_Library library, + FT_Stream stream, + FT_Byte* buff, + FT_Offset buffsize ) + { + FT_UNUSED( library ); + + + if ( !stream || + stream->read != ft_ansi_stream_io || + stream->close != ft_ansi_stream_close || + !stream->pathname.pointer ) + return FT_Err_Invalid_Stream_Handle; + + if ( ft_strlen( stream->pathname.pointer ) + 1 > buffsize ) + return FT_Err_Out_Of_Memory; + + ft_strncpy( buff, stream->pathname.pointer, + ft_strlen( stream->pathname.pointer ) + 1 ); + + return FT_Err_Ok; + } + + #ifdef FT_DEBUG_MEMORY extern FT_Int diff --git a/builds/amiga/src/base/ftsystem.c b/builds/amiga/src/base/ftsystem.c index 016f1e2..e908f37 100644 --- a/builds/amiga/src/base/ftsystem.c +++ b/builds/amiga/src/base/ftsystem.c @@ -450,6 +450,31 @@ Free_VecPooled( APTR poolHeader, } + FT_BASE_DEF( FT_Error ) + FT_Get_Path_From_Stream_System( FT_Library library, + FT_Stream stream, + FT_Byte* buff, + FT_Offset buffsize ) + { + FT_UNUSED( library ); + + + if ( !stream || + stream->read != ft_amiga_stream_io || + stream->close != ft_amiga_stream_close || + !stream->pathname.pointer ) + return FT_Err_Invalid_Stream_Handle; + + if ( ft_strlen( stream->pathname.pointer ) + 1 > buffsize ) + return FT_Err_Out_Of_Memory; + + ft_strncpy( buff, stream->pathname.pointer, + ft_strlen( stream->pathname.pointer ) + 1 ); + + return FT_Err_Ok; + } + + #ifdef FT_DEBUG_MEMORY extern FT_Int diff --git a/builds/unix/ftsystem.c b/builds/unix/ftsystem.c index 95f8271..eee020b 100644 --- a/builds/unix/ftsystem.c +++ b/builds/unix/ftsystem.c @@ -369,6 +369,32 @@ } + FT_BASE_DEF( FT_Error ) + FT_Get_Path_From_Stream_System( FT_Library library, + FT_Stream stream, + FT_Byte* buff, + FT_Offset buffsize ) + { + FT_UNUSED( library ); + + + if ( !stream || + stream->read != 0 || + ( stream->close != ft_close_stream_by_munmap && + stream->close != ft_close_stream_by_free ) || + !stream->pathname.pointer ) + return FT_Err_Invalid_Stream_Handle; + + if ( ft_strlen( stream->pathname.pointer ) + 1 > buffsize ) + return FT_Err_Out_Of_Memory; + + ft_strncpy( buff, stream->pathname.pointer, + ft_strlen( stream->pathname.pointer ) + 1 ); + + return FT_Err_Ok; + } + + #ifdef FT_DEBUG_MEMORY extern FT_Int diff --git a/builds/vms/ftsystem.c b/builds/vms/ftsystem.c index 76bfae9..69de2ec 100644 --- a/builds/vms/ftsystem.c +++ b/builds/vms/ftsystem.c @@ -271,6 +271,31 @@ } + FT_BASE_DEF( FT_Error ) + FT_Get_Path_From_Stream_System( FT_Library library, + FT_Stream stream, + FT_Byte* buff, + FT_Offset buffsize ) + { + FT_UNUSED( library ); + + + if ( !stream || + stream->read != 0 || + stream->close != ft_close_stream || + !stream->pathname.pointer ) + return FT_Err_Invalid_Stream_Handle; + + if ( ft_strlen( stream->pathname.pointer ) + 1 > buffsize ) + return FT_Err_Out_Of_Memory; + + ft_strncpy( buff, stream->pathname.pointer, + ft_strlen( stream->pathname.pointer ) + 1 ); + + return FT_Err_Ok; + } + + #ifdef FT_DEBUG_MEMORY extern FT_Int Except of the fundamental streams (file, memory), FreeType2 has 2 optional streams for compressed data: LZW and GZIP. We cannot apply the scheme used for fundamental streams to retrieve the pathname. Why? The function pointers like ft_ansi_stream_{io,close} are available when base module of FreeType2 is being built, but ft_lzw_stream_{io,close} are closed in LZW module. The base module cannot check given FT_Stream is driven by LZW or GZIP stream driver. If so, LZW module should provide FT_Get_Path_From_Stream_LZW()? It is not so good idea. We don't want to expose this function to public, but it is difficult to define an internal function which is interchanged between only 2 modules (e.g. visible for based & lzw module). As FT_BASE() exists but FT_SFNT() nor FT_PSAUX() don't, the internal headers include/freetype/internal/XXX.h are mainly used to define the internal data structure, not to define internal functions. Such requirements are implemented as the services in the modules. So I followed this decision: LZW & GZIP stream drivers provide new module to provide a service checking the stream driver and retrieving pathname info. I introduced "stream-identifier" service that have 2 interfaces: driven_by_this() and get_pathname(). The former is a function comparing the function pointers, the latter is retrieve stream pathname. diff --git a/include/freetype/internal/ftserv.h b/include/freetype/internal/ftserv.h index 569b9f7..cab54c7 100644 --- a/include/freetype/internal/ftserv.h +++ b/include/freetype/internal/ftserv.h @@ -604,6 +604,7 @@ FT_BEGIN_HEADER #define FT_SERVICE_POSTSCRIPT_INFO_H <freetype/internal/services/svpsinfo.h> #define FT_SERVICE_POSTSCRIPT_NAME_H <freetype/internal/services/svpostnm.h> #define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h> +#define FT_SERVICE_STREAM_ID_H <freetype/internal/services/svstrmid.h> #define FT_SERVICE_TRUETYPE_ENGINE_H <freetype/internal/services/svtteng.h> #define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h> #define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h> diff --git a/include/freetype/internal/services/svstrmid.h b/include/freetype/internal/services/svstrmid.h new file mode 100644 index 0000000..be2c366 --- /dev/null +++ b/include/freetype/internal/services/svstrmid.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* svstrmid.h */ +/* */ +/* FreeType API for Stream Identifier (specification). */ +/* */ +/* Copyright 2010 by suzuki toshiya */ +/* */ +/* 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. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVSTRMID_H__ +#define __SVSTRMID_H__ + +FT_BEGIN_HEADER + + +#define FT_SERVICE_ID_STREAM_IDENTIFIER "stream-identifier" + + typedef FT_Error + (*DrivenByThis_Func)( FT_Stream stream ); + + typedef FT_Error + (*GetPathName_Func)( FT_Library library, + FT_Stream stream, + FT_Byte* buff, + FT_Offset buffsize ); + + + + FT_DEFINE_SERVICE( StreamID ) + { + DrivenByThis_Func driven_by_this; + GetPathName_Func get_pathname; + }; + + /* */ + + +FT_END_HEADER + + +#endif /* __SVSTRMID_H__ */ + + +/* END */ Following is a stream-identifier for GZIP stream driver. driven_by_gzip() compares stream->{read,close} and ft_gzip_stream_{io,close} and assure the stream is driven by this driver. get_pathname_from_gzip_stream() retrieves the parent stream of GZIP stream and try to resolve the stream recursively. diff --git a/src/gzip/ftgzip.c b/src/gzip/ftgzip.c index 6f0c515..501e1d7 100644 --- a/src/gzip/ftgzip.c +++ b/src/gzip/ftgzip.c @@ -29,6 +29,7 @@ #include FT_MODULE_ERRORS_H +#include FT_SERVICE_STREAM_ID_H #undef __FTERRORS_H__ @@ -44,6 +45,7 @@ #error "gzip code does not support PIC yet" #endif +#include "ftgzmod.h" #ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB #include <zlib.h> @@ -670,6 +672,43 @@ return error; } + + static FT_Error + driven_by_gzip( FT_Stream stream ) + { + if ( stream && + stream->read == ft_gzip_stream_io && + stream->close == ft_gzip_stream_close ) + return Gzip_Err_Ok; + else + return Gzip_Err_Invalid_Stream_Handle; + } + + + static FT_Error + get_pathname_from_gzip_stream( FT_Library library, + FT_Stream stream, + FT_Byte* buff, + FT_Offset buffsize ) + { + FT_GZipFile zip; + + + if ( !stream ) + return Gzip_Err_Invalid_Stream_Handle; + + zip = (FT_GZipFile)(stream->descriptor.pointer); + return FT_Get_Path_From_Stream( library, zip->source, buff, buffsize ); + } + + + static const FT_Service_StreamIDRec gzip_stream_identifier = + { + (DrivenByThis_Func)driven_by_gzip, + (GetPathName_Func)get_pathname_from_gzip_stream + }; + + #else /* !FT_CONFIG_OPTION_USE_ZLIB */ FT_EXPORT_DEF( FT_Error ) @@ -685,4 +724,36 @@ #endif /* !FT_CONFIG_OPTION_USE_ZLIB */ + static const FT_ServiceDescRec gzip_services[] = + { +#ifdef FT_CONFIG_OPTION_USE_ZLIB + { FT_SERVICE_ID_STREAM_IDENTIFIER, &gzip_stream_identifier }, +#endif + { NULL, NULL } + }; + + + static FT_Module_Interface + gzip_get_interface( FT_Driver driver, + const FT_String* gzip_interface ) + { + FT_UNUSED( driver ); + + return ft_service_list_lookup( gzip_services, gzip_interface ); + } + + + FT_DEFINE_MODULE( gzip_module_class, + 0, /* not a font driver or renderer */ + sizeof( FT_ModuleRec ), + "gzip-stream", /* driver name */ + 0x10000L, /* driver version 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or higher */ + NULL, /* XXX: not ported to PIC yet */ + (FT_Module_Constructor) NULL, + (FT_Module_Destructor) NULL, + (FT_Module_Requester) gzip_get_interface + ) + + /* END */ Current GZIP stream driver is not built as a FT_Module, so I added src/gzip/ftgzmod.h (to define FT_Module interface) and src/gzip/modules.mk (to make gzip module listed in ftmodules.h). diff --git a/src/gzip/ftgzmod.h b/src/gzip/ftgzmod.h new file mode 100644 index 0000000..b6754e0 --- /dev/null +++ b/src/gzip/ftgzmod.h @@ -0,0 +1,35 @@ +/***************************************************************************/ +/* */ +/* ftgzmod.h */ +/* */ +/* FreeType's module for GZIP stream (specification). */ +/* */ +/* Copyright 2010 by suzuki toshiya */ +/* */ +/* 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. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTGZMOD_H__ +#define __FTGZMOD_H__ + + +#include <ft2build.h> +#include FT_MODULE_H + + +FT_BEGIN_HEADER + + + FT_DECLARE_MODULE( gzip_module_class ) + + +FT_END_HEADER + +#endif /* __FTLZWMOD_H__ */ + diff --git a/src/gzip/module.mk b/src/gzip/module.mk new file mode 100644 index 0000000..f85325f --- /dev/null +++ b/src/gzip/module.mk @@ -0,0 +1,22 @@ +# +# FreeType 2 GZIP module definition +# + + +# Copyright 2010 by suzuki toshiya +# +# 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. + + +FTMODULE_H_COMMANDS += GZIP_MODULE + +define GZIP_MODULE +$(OPEN_DRIVER) FT_Module_Class, gzip_module_class $(CLOSE_DRIVER) +$(ECHO_DRIVER)gzip $(ECHO_DRIVER_DESC)helper module for GZIP stream$(ECHO_DRIVER_DONE) +endef + +# EOF For LZW driver, ditto. diff --git a/src/lzw/ftlzw.c b/src/lzw/ftlzw.c index 6e57ded..59edf0b 100644 --- a/src/lzw/ftlzw.c +++ b/src/lzw/ftlzw.c @@ -31,6 +31,7 @@ #include FT_MODULE_ERRORS_H +#include FT_SERVICE_STREAM_ID_H #undef __FTERRORS_H__ @@ -47,6 +48,7 @@ #endif #include "ftzopen.h" +#include "ftlzwmod.h" /***************************************************************************/ @@ -389,6 +391,41 @@ } + static FT_Error + driven_by_lzw( FT_Stream stream ) + { + if ( stream && + stream->read == ft_lzw_stream_io && + stream->close == ft_lzw_stream_close ) + return LZW_Err_Ok; + else + return LZW_Err_Invalid_Stream_Handle; + } + + + static FT_Error + get_pathname_from_lzw_stream( FT_Library library, + FT_Stream stream, + FT_Byte* buff, + FT_Offset buffsize ) + { + FT_LZWFile zip; + + + if ( !stream ) + return LZW_Err_Invalid_Stream_Handle; + + zip = (FT_LZWFile)(stream->descriptor.pointer); + return FT_Get_Path_From_Stream( library, zip->source, buff, buffsize ); + } + + static const FT_Service_StreamIDRec lzw_stream_identifier = + { + (DrivenByThis_Func)driven_by_lzw, + (GetPathName_Func)get_pathname_from_lzw_stream + }; + + #include "ftzopen.c" @@ -409,4 +446,36 @@ #endif /* !FT_CONFIG_OPTION_USE_LZW */ + static const FT_ServiceDescRec lzw_services[] = + { +#ifdef FT_CONFIG_OPTION_USE_LZW + { FT_SERVICE_ID_STREAM_IDENTIFIER, &lzw_stream_identifier }, +#endif + { NULL, NULL } + }; + + + static FT_Module_Interface + lzw_get_interface( FT_Driver driver, + const FT_String* lzw_interface ) + { + FT_UNUSED( driver ); + + return ft_service_list_lookup( lzw_services, lzw_interface ); + } + + + FT_DEFINE_MODULE( lzw_module_class, + 0, /* not a font driver or renderer */ + sizeof( FT_ModuleRec ), + "lzw-stream", /* driver name */ + 0x10000L, /* driver version 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or higher */ + NULL, /* XXX: not ported to PIC yet */ + (FT_Module_Constructor) NULL, + (FT_Module_Destructor) NULL, + (FT_Module_Requester) lzw_get_interface + ) + + /* END */ diff --git a/src/lzw/ftlzwmod.h b/src/lzw/ftlzwmod.h new file mode 100644 index 0000000..ab977a9 --- /dev/null +++ b/src/lzw/ftlzwmod.h @@ -0,0 +1,35 @@ +/***************************************************************************/ +/* */ +/* ftlzwmod.h */ +/* */ +/* FreeType's module for LZW stream (specification). */ +/* */ +/* Copyright 2010 by suzuki toshiya */ +/* */ +/* 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. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTLZWMOD_H__ +#define __FTLZWMOD_H__ + + +#include <ft2build.h> +#include FT_MODULE_H + + +FT_BEGIN_HEADER + + + FT_DECLARE_MODULE( lzw_module_class ) + + +FT_END_HEADER + +#endif /* __FTLZWMOD_H__ */ + diff --git a/src/lzw/module.mk b/src/lzw/module.mk new file mode 100644 index 0000000..5d5e760 --- /dev/null +++ b/src/lzw/module.mk @@ -0,0 +1,22 @@ +# +# FreeType 2 LZW module definition +# + + +# Copyright 2010 by suzuki toshiya +# +# 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. + + +FTMODULE_H_COMMANDS += LZW_MODULE + +define LZW_MODULE +$(OPEN_DRIVER) FT_Module_Class, lzw_module_class $(CLOSE_DRIVER) +$(ECHO_DRIVER)lzw $(ECHO_DRIVER_DESC)helper module for LZW stream$(ECHO_DRIVER_DONE) +endef + +# EOF Finally, we can implement FT_Get_Path_From_Stream(). Scanning all modules including stream-identifier service, and if the stream is driven by the module, we try to retrieve the pathname by its service. If no module is driving the stream, the fundamental stream is tried. diff --git a/src/base/ftstream.c b/src/base/ftstream.c index b638599..ac33c9a 100644 --- a/src/base/ftstream.c +++ b/src/base/ftstream.c @@ -19,6 +19,8 @@ #include <ft2build.h> #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_SERVICE_H +#include FT_SERVICE_STREAM_ID_H /*************************************************************************/ @@ -849,4 +851,41 @@ } + FT_EXPORT( FT_Error ) + FT_Get_Path_From_Stream( FT_Library library, + FT_Stream stream, + FT_Byte* buff, + FT_Offset buffsize ) + { + FT_Module* cur; + FT_Module* limit; + + + /* check non-base stream drivers */ + cur = library->modules; + limit = cur + library->num_modules; + for ( ; cur < limit ; cur ++ ) + { + FT_Service_StreamID streamid_svc; + + /* We care only stream driver, module_flags must not be font driver, renderer, hinter, styler */ + if ( !cur[0] || !cur[0]->clazz || cur[0]->clazz->module_flags || !cur[0]->clazz->get_interface ) + continue; + + streamid_svc = (FT_Service_StreamID) cur[0]->clazz->get_interface( NULL, FT_SERVICE_ID_STREAM_IDENTIFIER ); + if ( !streamid_svc || !streamid_svc->driven_by_this || !streamid_svc->get_pathname ) + continue; + + if ( streamid_svc->driven_by_this( stream ) ) + continue; + + return streamid_svc->get_pathname( library, stream, buff, buffsize ); + } + + /* check system-specific file stream driver(s) */ + + return FT_Get_Path_From_Stream_System( library, stream, buff, buffsize ); + } + + /* END */ BTW, in most case, we lookup a font-format-specific service in the internal of FreeType2. We can have a valid font driver handle taken from a face (by FT_Face->driver), we can pass a valid driver to get_interface( driver, service_id ) function of the module. But in this case, FT_Get_Path_From_Stream() takes no face object, so we don't have valid driver. Some get_interface() implementations in font drivers don't check NULL driver, these modules can be crashed by passing NULL drivers. Following is a patch to check the driver argument to avoid NULL pointer dereference, or to remove the dereference of unused driver handle. diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c index 217adf2..dad0b65 100644 --- a/src/cff/cffdrivr.c +++ b/src/cff/cffdrivr.c @@ -621,14 +621,15 @@ { FT_Module sfnt; FT_Module_Interface result; - FT_Library library = driver->library; - FT_UNUSED(library); result = ft_service_list_lookup( FT_CFF_SERVICES_GET, module_interface ); if ( result != NULL ) return result; + if ( !driver ) + return NULL; + /* we pass our request to the `sfnt' module */ sfnt = FT_Get_Module( driver->library, "sfnt" ); diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c index 3518850..00b363f 100644 --- a/src/psnames/psmodule.c +++ b/src/psnames/psmodule.c @@ -561,8 +561,7 @@ psnames_get_service( FT_Module module, const char* service_id ) { - FT_Library library = module->library; - FT_UNUSED(library); + FT_UNUSED( module ); return ft_service_list_lookup( FT_PSCMAPS_SERVICES_GET, service_id ); } diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index 1d157b7..1097efb 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -417,8 +417,6 @@ sfnt_get_interface( FT_Module module, const char* module_interface ) { - FT_Library library = module->library; - FT_UNUSED(library); FT_UNUSED( module ); return ft_service_list_lookup( FT_SFNT_SERVICES_GET, module_interface ); diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c index d4978a9..d723b57 100644 --- a/src/truetype/ttdriver.c +++ b/src/truetype/ttdriver.c @@ -402,16 +402,17 @@ tt_get_interface( FT_Module driver, /* TT_Driver */ const char* tt_interface ) { - FT_Library library = driver->library; FT_Module_Interface result; FT_Module sfntd; SFNT_Service sfnt; - FT_UNUSED(library); result = ft_service_list_lookup( FT_TT_SERVICES_GET, tt_interface ); if ( result != NULL ) return result; + if ( !driver ) + return NULL; + /* only return the default interface from the SFNT module */ sfntd = FT_Get_Module( driver->library, "sfnt" ); if ( sfntd ) _______________________________________________ Freetype-devel mailing list Freetype-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/freetype-devel