freetype-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ft-devel] Hide Carbon-dependency of ftmac.c ([ft] cannot open some font


From: mpsuzuki
Subject: [ft-devel] Hide Carbon-dependency of ftmac.c ([ft] cannot open some fonts on mac and linux)
Date: Sat, 22 Sep 2007 18:32:54 +0900

Hi,

Recently David Turner proposed to use dlsym()-type features for
ftmac.c to solve the incompatibilities of libfreetype.dylib
with ftmac.c and without ftmac.c, in freetype mailing list.

As a proof of his idea, I wrote a sample header file "ftmacdyn.h"
to replace Carbon-derived functions in ftmac.c by the function
pointers. By including ftmacdyn.h, ftmac.c is changed to resolve
the Carbon functions in runtime, without writing the code but
insersion a few initialization routines. libfreetype.dylib has
no explicit symbol reference to Carbon frameworks.

I want to discuss with developers importing Unix applications
to Mac OS X, about the idea using such hook to remove the
explicit symbol reference of Mac OS specific frameworks.

--

I think it's sufficient as a draft for further discussion,
but attached ftmacdyn.h is NOT finished work, there are several
issues:

* CPP feature: Current ftmacdyn.h uses C99 preprocessor macros
  (to handle variadic arguments). They are incompatible with
  "-ansi" option. The legacy C compiler of Mac OS X 10.0 (using
  precompiled header by default) cannot process it by default.

* Softening of compiler's inspection: The types of function
  pointers are declared by ftmacdyn.h, not by the system.
  The mismatching between ftmacdyn.h and system cannot be
  checked. Either the deprecated functions cannot be found.

* Maintainancability: If a developer inserts ftmac.c new Carbon
  functions, he has to update ftmacdyn.h: declaration of function
  pointer types, allocation of function pointer, and initialization
  of function pointer. It's troublesome. If he slipped to update
  ftmacdyn.h, he will receive unexpected error in both phases of
  compilation of libfreetype.dylib and linking built libfreetype
  with other applications.

I think these issues must be solved by auto generation of
ftmacdyn.h. It's not difficult to generate ftmacdyn.h if we
have the list of required Carbon functions. The compilation
of ftmac.c (without ftmacdyn.h) is convenient to obtain the
list and check type mismatching issues, but repeating
compile ftmac.c, generate ftmacdyn.h, recompile ftmac.c is
not smart, even if it's automatic.

Regards,
mpsuzuki

On Fri, 21 Sep 2007 17:31:35 +0900
address@hidden wrote:
>On Fri, 21 Sep 2007 00:32:35 +0200
>"David Turner" <address@hidden> wrote:
>>the traditional, and painful, way to deal with this sort of problems
>>in a seamless way (at least for the user) is to use dlopen()-style dynamic
>>linking to access the "missing" Carbon functions.
>
>>do you think it'd be possible to add this to FreeType, to get rid of the
>>--with-old-mac-fonts and related issues ?
>
>I think it's possible.
>
>>I know it's non trivial work, but that would be the right thing to do.
>
>Although I've proposed a replacement by Carbon-free MacOS
>font support, I have to agree this pointing out. ftmac.c
>provides a few functions that cannot be implemented without
>QuickDraw or ATS (getting a font file from QuickDraw/ATS
>font name), runtime resolving of Carbon dependency is required
>to provide these functions safely.
>
>The expected procedure would be:
>
>step 1: check whether runtime linker has already loaded
>        Carbon framework (even if the application developer
>        doesn't care Carbon-dependent feature of FreeType,
>        some applications load Carbon framework for other
>        purpose, e.g. to use native GUI library etc).
>
>step 2: if Carbon framework is not loaded, try to load it.
>        if could not load, returniappropriate error.
>
>step 3: if Carbon framework is loaded, try to resolve
>        required Carbon-dependent symbols. If could not
>        resolve, return appropriate error.
>
>In last year, I've written testing code for step 3 during
>the discussion about how to deprecate the legacy Carbon
>functions.
>
>The headache is, step 1 + 2 are expected to be implemented
>without non-standard frameworks, to avoid unexpected dependency.
>If the softwares are built only with POSIX APIs, the binaries
>are linked with libSystem.B.dylib only. The external libraries
>(e.g. libdl.dylib or CoreFoundation framework) should not be
>used even if they provide convenient functions.
>
>The latest libSystem.B.dylib on Mac OS X 10.4 includes dlsym(),
>but older libSystem.B.dylib on Mac OS X 10.{0, 1} doesn't.
>In such old systems, NSIsSymbolNameDefined() may be used for,
>but they are deprecated :-( I have to think over smart
>implementation after the investigation of function availabilities
>on each Mac OS X revisions. Anyway, I will write small code
>to demonstrate on specific platform within 1 month, please wait.
>
>Regards,
>mpsuzuki


Index: src/base/ftmac.c
===================================================================
RCS file: /sources/freetype/freetype2/src/base/ftmac.c,v
retrieving revision 1.59
diff -u -r1.59 ftmac.c
--- src/base/ftmac.c    29 Aug 2007 06:08:59 -0000      1.59
+++ src/base/ftmac.c    22 Sep 2007 08:30:21 -0000
@@ -91,6 +95,8 @@
 #undef FT_GetFile_From_Mac_ATS_Name( a, b, c )
 #undef FT_New_Face_From_FSSpec( a, b, c, d )
 
+#define FT_InitCarbonFuncPtrs()        do ; while ( 0 )
+#include <ftmacdyn.h>
 
   /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
      TrueType in case *both* are available (this is not common,
@@ -133,6 +139,8 @@
     FSSpec    spec;
 
 
+    FT_InitCarbonFuncPtrs();
+
     err = ATSFontGetFileSpecification( ats_font_id, &spec );
     if ( noErr == err )
       err = FSpMakeFSRef( &spec, ats_font_ref );
@@ -198,6 +206,8 @@
     FT_Error  err;
 
 
+    FT_InitCarbonFuncPtrs();
+
     err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
     if ( FT_Err_Ok != err )
       return err;
@@ -226,6 +236,8 @@
     FT_Error  err;
 
 
+    FT_InitCarbonFuncPtrs();
+
     err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
     if ( FT_Err_Ok != err )
       return err;
@@ -895,6 +907,8 @@
     FT_Error  error = FT_Err_Ok;
 
 
+    FT_InitCarbonFuncPtrs();
+
     GetResInfo( fond, &fond_id, &fond_type, fond_name );
     if ( ResError() != noErr || fond_type != 'FOND' )
       return FT_Err_Invalid_File_Format;
@@ -1009,6 +1023,8 @@
     error  = FT_Err_Ok;
     *aface = NULL;
 
+    FT_InitCarbonFuncPtrs();
+
     /* try resourcefork based font: LWFN, FFIL */
     error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
                                        face_index, aface );
@@ -1046,6 +1062,7 @@
     if ( !ref )
       return FT_Err_Invalid_Argument;
 
+    FT_InitCarbonFuncPtrs();
     err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
     if ( err )
       error = FT_Err_Cannot_Open_Resource;
@@ -1088,6 +1105,7 @@
     FSRef  ref;
 
 
+    FT_InitCarbonFuncPtrs();
     if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
       return FT_Err_Invalid_Argument;
     else
--- /dev/null   2007-09-18 12:46:17.498542285 +0900
+++ src/base/ftmacdyn.h 2007-09-22 05:44:36.000000000 +0900
@@ -0,0 +1,140 @@
+#include <mach-o/dyld.h>
+#undef FT_InitCarbonFuncPtrs()
+
+/* symbols in CoreFoundation framework */
+#define        CFRelease(...)                          
(*dyn_CFRelease)(__VA_ARGS__)
+#define        CFStringCreateWithCString(...)          
(*dyn_CFStringCreateWithCString)(__VA_ARGS__)
+
+/* symbols in FileManager framework */
+#define        FSCompareFSRefs(...)    (*dyn_FSCompareFSRefs)(__VA_ARGS__)
+#define        FSGetCatalogInfo(...)   (*dyn_FSGetCatalogInfo)(__VA_ARGS__)
+#define        FSGetForkCBInfo(...)    (*dyn_FSGetForkCBInfo)(__VA_ARGS__)
+#define        FSOpenResFile(...)      (*dyn_FSOpenResFile)(__VA_ARGS__)
+#define        FSOpenResourceFile(...) (*dyn_FSOpenResourceFile)(__VA_ARGS__)
+#define        FSPathMakeRef(...)      (*dyn_FSPathMakeRef)(__VA_ARGS__)
+#define        FSRefMakePath(...)      (*dyn_FSRefMakePath)(__VA_ARGS__)
+#define        FSpMakeFSRef(...)       (*dyn_FSpMakeFSRef)(__VA_ARGS__)
+#define        CloseResFile(...)       (*dyn_CloseResFile)(__VA_ARGS__)
+#define        Get1IndResource(...)    (*dyn_Get1IndResource)(__VA_ARGS__)
+#define        Get1Resource(...)       (*dyn_Get1Resource)(__VA_ARGS__)
+#define        GetHandleSize(...)      (*dyn_GetHandleSize)(__VA_ARGS__)
+#define        GetResInfo(...)         (*dyn_GetResInfo)(__VA_ARGS__)
+#define        GetResource(...)        (*dyn_GetResource)(__VA_ARGS__)
+#define        HomeResFile(...)        (*dyn_HomeResFile)(__VA_ARGS__)
+#define        ReleaseResource(...)    (*dyn_ReleaseResource)(__VA_ARGS__)
+#define        ResError(...)           (*dyn_ResError)(__VA_ARGS__)
+#define        UseResFile(...)         (*dyn_UseResFile)(__VA_ARGS__)
+
+
+/* symbols in ATS framework */
+#define        ATSFontFindFromName(...)                
(*dyn_ATSFontFindFromName)(__VA_ARGS__)
+#define        ATSFontGetFileSpecification(...)        
(*dyn_ATSFontGetFileSpecification)(__VA_ARGS__)
+
+#define ALLOC_CARBON_FUNC_PTR( func_name ) \
+       dyn##func_name##_t dyn##func_name
+
+#define INIT_CARBON_FUNC_PTR( func_name ) \
+       *(void **)(&(dyn##func_name)) = ( NSIsSymbolNameDefined( #func_name ) 
&& NSLookupAndBindSymbol( #func_name ) ? \
+                                          NSAddressOfSymbol( 
NSLookupAndBindSymbol( #func_name ) ) : NULL )
+
+#define DEFAULT_CORESERVICES_OBJ       
"/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices"
+#define DEFAULT_APPLICATIONSERVICES_OBJ        
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices"
+
+typedef void ( *dyn_CFRelease_t )( CFTypeRef );
+typedef CFStringRef ( *dyn_CFStringCreateWithCString_t )( CFAllocatorRef, 
const char*, CFStringEncoding );
+typedef Size ( *dyn_GetHandleSize_t )( Handle ) ;
+typedef OSErr ( *dyn_FSpMakeFSRef_t )( const FSSpec*, FSRef* ) ;
+typedef OSErr ( *dyn_FSCompareFSRefs_t )( const FSRef*, const FSRef* ) ;
+typedef OSErr ( *dyn_FSGetCatalogInfo_t )( const FSRef*, FSCatalogInfoBitmap, 
FSCatalogInfo*, HFSUniStr255*, FSSpec*, FSRef* ) ;
+typedef OSErr ( *dyn_FSGetForkCBInfo_t )( SInt16, FSVolumeRefNum, SInt16*, 
SInt16*, FSForkInfo*, FSRef*, HFSUniStr255* ) ;
+typedef OSStatus ( *dyn_FSRefMakePath_t )( const FSRef*, UInt8*, UInt32 ) ;
+typedef OSStatus ( *dyn_FSPathMakeRef_t )( const UInt8*, FSRef*, Boolean* ) ;
+typedef void ( *dyn_CloseResFile_t )( short ) ;
+typedef OSErr ( *dyn_ResError_t )( void ) ;
+typedef short ( *dyn_HomeResFile_t )( Handle ) ;
+typedef void ( *dyn_UseResFile_t )( short ) ;
+typedef Handle ( *dyn_Get1IndResource_t )( ResType, short ) ;
+typedef Handle ( *dyn_GetResource_t )( ResType, short ) ;
+typedef Handle ( *dyn_Get1Resource_t )( ResType, short ) ;
+typedef void ( *dyn_ReleaseResource_t )( Handle ) ;
+typedef void ( *dyn_GetResInfo_t )( Handle, short*, ResType*, Str255 ) ;
+typedef short ( *dyn_FSOpenResFile_t )( const FSRef*, SInt8 ) ;
+typedef OSErr ( *dyn_FSOpenResourceFile_t )( const FSRef*, UniCharCount, const 
UniChar*, SInt8, SInt16* ) ;
+typedef ATSFontRef ( *dyn_ATSFontFindFromName_t )( CFStringRef, ATSOptionFlags 
) ;
+typedef OSStatus ( *dyn_ATSFontGetFileSpecification_t )( ATSFontRef, FSSpec* ) 
;
+
+ALLOC_CARBON_FUNC_PTR( _CFRelease );
+ALLOC_CARBON_FUNC_PTR( _CFStringCreateWithCString );
+
+ALLOC_CARBON_FUNC_PTR( _CloseResFile );
+ALLOC_CARBON_FUNC_PTR( _Get1IndResource );
+ALLOC_CARBON_FUNC_PTR( _Get1Resource );
+ALLOC_CARBON_FUNC_PTR( _GetHandleSize );
+ALLOC_CARBON_FUNC_PTR( _GetResInfo );
+ALLOC_CARBON_FUNC_PTR( _GetResource );
+ALLOC_CARBON_FUNC_PTR( _HomeResFile );
+ALLOC_CARBON_FUNC_PTR( _ReleaseResource );
+ALLOC_CARBON_FUNC_PTR( _ResError );
+ALLOC_CARBON_FUNC_PTR( _UseResFile );
+
+ALLOC_CARBON_FUNC_PTR( _FSCompareFSRefs );
+ALLOC_CARBON_FUNC_PTR( _FSGetCatalogInfo );
+ALLOC_CARBON_FUNC_PTR( _FSGetForkCBInfo );
+ALLOC_CARBON_FUNC_PTR( _FSOpenResFile );
+ALLOC_CARBON_FUNC_PTR( _FSOpenResourceFile );
+ALLOC_CARBON_FUNC_PTR( _FSPathMakeRef );
+ALLOC_CARBON_FUNC_PTR( _FSRefMakePath );
+ALLOC_CARBON_FUNC_PTR( _FSpMakeFSRef );
+
+ALLOC_CARBON_FUNC_PTR( _ATSFontFindFromName ) ;
+ALLOC_CARBON_FUNC_PTR( _ATSFontGetFileSpecification ) ;
+
+FT_Bool ft_carbon_func_ptr_initialized = 0;
+
+int
+FT_InitCarbonFuncPtrs()
+{
+    if ( ft_carbon_func_ptr_initialized )
+        return 0;
+
+    if ( !NSIsSymbolNameDefined( "_CoreServicesVersionNumber" ) )
+    {
+        if ( !NSAddLibraryWithSearching( DEFAULT_CORESERVICES_OBJ ) )
+            return -1;
+    }
+
+    INIT_CARBON_FUNC_PTR( _CFRelease );
+    INIT_CARBON_FUNC_PTR( _CFStringCreateWithCString );
+
+    INIT_CARBON_FUNC_PTR( _CloseResFile );
+    INIT_CARBON_FUNC_PTR( _Get1IndResource );
+    INIT_CARBON_FUNC_PTR( _Get1Resource );
+    INIT_CARBON_FUNC_PTR( _GetHandleSize );
+    INIT_CARBON_FUNC_PTR( _GetResInfo );
+    INIT_CARBON_FUNC_PTR( _GetResource );
+    INIT_CARBON_FUNC_PTR( _HomeResFile );
+    INIT_CARBON_FUNC_PTR( _ReleaseResource );
+    INIT_CARBON_FUNC_PTR( _ResError );
+    INIT_CARBON_FUNC_PTR( _UseResFile );
+
+    INIT_CARBON_FUNC_PTR( _FSCompareFSRefs );
+    INIT_CARBON_FUNC_PTR( _FSGetCatalogInfo );
+    INIT_CARBON_FUNC_PTR( _FSGetForkCBInfo );
+    INIT_CARBON_FUNC_PTR( _FSOpenResFile );
+    INIT_CARBON_FUNC_PTR( _FSOpenResourceFile );
+    INIT_CARBON_FUNC_PTR( _FSPathMakeRef );
+    INIT_CARBON_FUNC_PTR( _FSRefMakePath );
+    INIT_CARBON_FUNC_PTR( _FSpMakeFSRef );
+
+    if ( !NSIsSymbolNameDefined( "_ApplicationServicesVersionNumber" ) )
+    {
+        if ( !NSAddLibraryWithSearching( DEFAULT_APPLICATIONSERVICES_OBJ ) )
+            return -2;
+    }
+
+    INIT_CARBON_FUNC_PTR( _ATSFontFindFromName ) ;
+    INIT_CARBON_FUNC_PTR( _ATSFontGetFileSpecification ) ;
+
+    ft_carbon_func_ptr_initialized = 1;
+    return 0;
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]