Classic (pre-2001) Mac OS used "suitcase" font files, where TrueType font data was stored in the file's resource fork instead of the data fork. Wine has support for converting suitcases into individual .ttf files that Windows apps could directly open, possibly driven by Mac OS X 10.4 shipping the Microsoft core web fonts as suitcases. Remove this support, it uses very deprecated APIs and suitcase font files are largely history (although macOS can still use them).
CrossOver has disabled this functionality since 2018 (because of an FSRef-related bug in macOS 10.13), without any customer complains that I'm aware of.
From: Brendan Shanks bshanks@codeweavers.com
--- configure.ac | 2 +- dlls/win32u/Makefile.in | 2 +- dlls/win32u/freetype.c | 256 +--------------------------------------- 3 files changed, 3 insertions(+), 257 deletions(-)
diff --git a/configure.ac b/configure.ac index c408e3788d6..f78fe6f0ab4 100644 --- a/configure.ac +++ b/configure.ac @@ -922,7 +922,7 @@ case $host_os in LDDLLFLAGS="-fPIC" enable_winemac_drv=${enable_winemac_drv:-yes} dnl declare needed frameworks - AC_SUBST(CARBON_LIBS,"-framework Carbon") + AC_SUBST(CORETEXT_LIBS,"-framework CoreText") AC_SUBST(COREFOUNDATION_LIBS,"-framework CoreFoundation") AC_SUBST(DISKARBITRATION_LIBS,"-framework DiskArbitration -framework CoreFoundation") AC_SUBST(IOKIT_LIBS,"-framework IOKit -framework CoreFoundation") diff --git a/dlls/win32u/Makefile.in b/dlls/win32u/Makefile.in index 5c51e7d7275..454fb2555bc 100644 --- a/dlls/win32u/Makefile.in +++ b/dlls/win32u/Makefile.in @@ -4,7 +4,7 @@ UNIXLIB = win32u.so IMPORTLIB = win32u IMPORTS = ntdll UNIX_CFLAGS = $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) -UNIX_LIBS = $(CARBON_LIBS) $(APPKIT_LIBS) $(PTHREAD_LIBS) -lm +UNIX_LIBS = $(CORETEXT_LIBS) $(APPKIT_LIBS) $(PTHREAD_LIBS) -lm
EXTRADLLFLAGS = -nodefaultlibs
diff --git a/dlls/win32u/freetype.c b/dlls/win32u/freetype.c index c749e076c65..587e577505c 100644 --- a/dlls/win32u/freetype.c +++ b/dlls/win32u/freetype.c @@ -41,38 +41,7 @@ #include <unistd.h>
#ifdef __APPLE__ -#define LoadResource __carbon_LoadResource -#define CheckMenuItem __carbon_CheckMenuItem -#define CompareString __carbon_CompareString -#define GetCurrentThread __carbon_GetCurrentThread -#define GetCurrentProcess __carbon_GetCurrentProcess -#define GetProcessInformation __carbon_GetProcessInformation -#define DeleteMenu __carbon_DeleteMenu -#define DrawMenu __carbon_DrawMenu -#define DrawMenuBar __carbon_DrawMenuBar -#define EnableMenuItem __carbon_EnableMenuItem -#define GetMenu __carbon_GetMenu -#define IsWindowVisible __carbon_IsWindowVisible -#define MoveWindow __carbon_MoveWindow -#define Polygon __carbon_Polygon -#define ShowWindow __carbon_ShowWindow -#include <Carbon/Carbon.h> -#undef LoadResource -#undef CompareString -#undef GetCurrentThread -#undef _CDECL -#undef GetCurrentProcess -#undef GetProcessInformation -#undef CheckMenuItem -#undef DeleteMenu -#undef DrawMenu -#undef DrawMenuBar -#undef EnableMenuItem -#undef GetMenu -#undef IsWindowVisible -#undef MoveWindow -#undef Polygon -#undef ShowWindow +#include <CoreText/CoreText.h> #endif /* __APPLE__ */
#ifdef HAVE_FT2BUILD_H @@ -305,208 +274,6 @@ static BOOL freetype_set_bitmap_text_metrics( struct gdi_font *font ); * cga40woa.fon=cga40850.fon */
-#ifdef __APPLE__ -static char *find_cache_dir(void) -{ - FSRef ref; - OSErr err; - static char cached_path[PATH_MAX]; - static const char *wine = "/Wine", *fonts = "/Fonts"; - - if(*cached_path) return cached_path; - - err = FSFindFolder(kUserDomain, kCachedDataFolderType, kCreateFolder, &ref); - if(err != noErr) - { - WARN("can't create cached data folder\n"); - return NULL; - } - err = FSRefMakePath(&ref, (unsigned char*)cached_path, sizeof(cached_path)); - if(err != noErr) - { - WARN("can't create cached data path\n"); - *cached_path = '\0'; - return NULL; - } - if(strlen(cached_path) + strlen(wine) + strlen(fonts) + 1 > sizeof(cached_path)) - { - ERR("Could not create full path\n"); - *cached_path = '\0'; - return NULL; - } - strcat(cached_path, wine); - - if(mkdir(cached_path, 0700) == -1 && errno != EEXIST) - { - WARN("Couldn't mkdir %s\n", cached_path); - *cached_path = '\0'; - return NULL; - } - strcat(cached_path, fonts); - if(mkdir(cached_path, 0700) == -1 && errno != EEXIST) - { - WARN("Couldn't mkdir %s\n", cached_path); - *cached_path = '\0'; - return NULL; - } - return cached_path; -} - -/****************************************************************** - * expand_mac_font - * - * Extracts individual TrueType font files from a Mac suitcase font - * and saves them into the user's caches directory (see - * find_cache_dir()). - * Returns a NULL terminated array of filenames. - * - * We do this because they are apps that try to read ttf files - * themselves and they don't like Mac suitcase files. - */ -static char **expand_mac_font(const char *path) -{ - FSRef ref; - ResFileRefNum res_ref; - OSStatus s; - unsigned int idx; - const char *out_dir; - const char *filename; - int output_len; - struct { - char **array; - unsigned int size, max_size; - } ret; - - TRACE("path %s\n", path); - - s = FSPathMakeRef((unsigned char*)path, &ref, FALSE); - if(s != noErr) - { - WARN("failed to get ref\n"); - return NULL; - } - - s = FSOpenResourceFile(&ref, 0, NULL, fsRdPerm, &res_ref); - if(s != noErr) - { - TRACE("no data fork, so trying resource fork\n"); - res_ref = FSOpenResFile(&ref, fsRdPerm); - if(res_ref == -1) - { - TRACE("unable to open resource fork\n"); - return NULL; - } - } - - ret.size = 0; - ret.max_size = 10; - ret.array = calloc( ret.max_size, sizeof(*ret.array) ); - if(!ret.array) - { - CloseResFile(res_ref); - return NULL; - } - - out_dir = find_cache_dir(); - - filename = strrchr(path, '/'); - if(!filename) filename = path; - else filename++; - - /* output filename has the form out_dir/filename_%04x.ttf */ - output_len = strlen(out_dir) + 1 + strlen(filename) + 5 + 5; - - UseResFile(res_ref); - idx = 1; - while(1) - { - FamRec *fam_rec; - unsigned short *num_faces_ptr, num_faces, face; - AsscEntry *assoc; - Handle fond; - ResType fond_res = FT_MAKE_TAG('F','O','N','D'); - - fond = Get1IndResource(fond_res, idx); - if(!fond) break; - TRACE("got fond resource %d\n", idx); - HLock(fond); - - fam_rec = *(FamRec**)fond; - num_faces_ptr = (unsigned short *)(fam_rec + 1); - num_faces = GET_BE_WORD(*num_faces_ptr); - num_faces++; - assoc = (AsscEntry*)(num_faces_ptr + 1); - TRACE("num faces %04x\n", num_faces); - for(face = 0; face < num_faces; face++, assoc++) - { - Handle sfnt; - ResType sfnt_res = FT_MAKE_TAG('s','f','n','t'); - unsigned short size, font_id; - char *output; - - size = GET_BE_WORD(assoc->fontSize); - font_id = GET_BE_WORD(assoc->fontID); - if(size != 0) - { - TRACE("skipping id %04x because it's not scalable (fixed size %d)\n", font_id, size); - continue; - } - - TRACE("trying to load sfnt id %04x\n", font_id); - sfnt = GetResource(sfnt_res, font_id); - if(!sfnt) - { - TRACE("can't get sfnt resource %04x\n", font_id); - continue; - } - - output = malloc( output_len); - if(output) - { - int fd; - - snprintf(output, output_len, "%s/%s_%04x.ttf", out_dir, filename, font_id); - - fd = open(output, O_CREAT | O_EXCL | O_WRONLY, 0600); - if(fd != -1 || errno == EEXIST) - { - if(fd != -1) - { - unsigned char *sfnt_data; - - HLock(sfnt); - sfnt_data = *(unsigned char**)sfnt; - write(fd, sfnt_data, GetHandleSize(sfnt)); - HUnlock(sfnt); - close(fd); - } - if(ret.size >= ret.max_size - 1) /* Always want the last element to be NULL */ - { - ret.array = realloc( ret.array, ret.max_size * sizeof(*ret.array) * 2 ); - memset( ret.array + ret.max_size, 0, ret.max_size * sizeof(*ret.array) ); - ret.max_size *= 2; - } - ret.array[ret.size++] = output; - } - else - { - WARN("unable to create %s\n", output); - free( output ); - } - } - ReleaseResource(sfnt); - } - HUnlock(fond); - ReleaseResource(fond); - idx++; - } - CloseResFile(res_ref); - - return ret.array; -} - -#endif /* __APPLE__ */ - /* This function builds an FT_Fixed from a double. It fails if the absolute value of the float number is greater than 32768. @@ -1348,27 +1115,6 @@ static INT AddFontToList(const WCHAR *dos_name, const char *unix_name, void *fon /* we always load external fonts from files - otherwise we would get a crash in update_reg_entries */ assert(unix_name || !(flags & ADDFONT_EXTERNAL_FONT));
-#ifdef __APPLE__ - if(unix_name) - { - char **mac_list = expand_mac_font(unix_name); - if(mac_list) - { - BOOL had_one = FALSE; - char **cursor; - for(cursor = mac_list; *cursor; cursor++) - { - had_one = TRUE; - AddFontToList(NULL, *cursor, NULL, 0, flags); - free( *cursor ); - } - free( mac_list ); - if(had_one) - return 1; - } - } -#endif /* __APPLE__ */ - if (!dos_name && unix_name && !ntdll_get_dos_file_name( unix_name, &filename, FILE_OPEN )) dos_name = filename;
As I recall, file structure was relatively simple. Could we instead parse it ourselves? My point is that lack of API should not prevent support this.
On Mon Jun 30 21:56:12 2025 +0000, Nikolay Sivov wrote:
As I recall, file structure was relatively simple. Could we instead parse it ourselves? My point is that lack of API should not prevent support this.
We could parse the resource fork ourselves, I just don't know that it's worth the trouble. These fonts haven't been common in years, and there are other tools that can convert them permanently to .ttf.
This merge request was approved by Huw Davies.