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

Reply via email to