Huw Davies : gdi32:
Extract the constituent TrueType files from Mac suitcase fonts into the
user 's caches directory
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Dec 21 10:36:40 CST 2006
Module: wine
Branch: master
Commit: 4e6860433e72714ed1e500eb523710656e71ba02
URL: http://source.winehq.org/git/wine.git/?a=commit;h=4e6860433e72714ed1e500eb523710656e71ba02
Author: Huw Davies <huw at codeweavers.com>
Date: Thu Dec 21 15:21:13 2006 +0000
gdi32: Extract the constituent TrueType files from Mac suitcase fonts into the user's caches directory
and use these instead of the original suitcase.
---
configure | 6 +-
configure.ac | 1 +
dlls/gdi32/Makefile.in | 2 +-
dlls/gdi32/freetype.c | 257 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 264 insertions(+), 2 deletions(-)
diff --git a/configure b/configure
index 6779121..3e9b56e 100755
--- a/configure
+++ b/configure
@@ -759,6 +759,7 @@ IOKITLIB
LDEXECFLAGS
DISKARBITRATIONLIB
COREAUDIO
+CARBONLIB
CROSSTEST
CROSSCC
CROSSWINDRES
@@ -13462,6 +13463,8 @@ fi
esac
if test "$ac_cv_header_Carbon_Carbon_h" = "yes"
then
+ CARBONLIB="-framework Carbon"
+
QUARTZFILES='$(QUARTZFILES)'
fi
;;
@@ -21426,6 +21429,7 @@ IOKITLIB!$IOKITLIB$ac_delim
LDEXECFLAGS!$LDEXECFLAGS$ac_delim
DISKARBITRATIONLIB!$DISKARBITRATIONLIB$ac_delim
COREAUDIO!$COREAUDIO$ac_delim
+CARBONLIB!$CARBONLIB$ac_delim
CROSSTEST!$CROSSTEST$ac_delim
CROSSCC!$CROSSCC$ac_delim
CROSSWINDRES!$CROSSWINDRES$ac_delim
@@ -21442,7 +21446,7 @@ LIBOBJS!$LIBOBJS$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 76; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 77; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/configure.ac b/configure.ac
index efbf32d..9fc757b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1023,6 +1023,7 @@ case $host_os in
dnl Enable quartz driver on Mac OS X
if test "$ac_cv_header_Carbon_Carbon_h" = "yes"
then
+ AC_SUBST(CARBONLIB,"-framework Carbon")
QUARTZFILES='$(QUARTZFILES)'
fi
;;
diff --git a/dlls/gdi32/Makefile.in b/dlls/gdi32/Makefile.in
index df6f89b..e3b2d67 100644
--- a/dlls/gdi32/Makefile.in
+++ b/dlls/gdi32/Makefile.in
@@ -7,7 +7,7 @@ MODULE = gdi32.dll
IMPORTLIB = libgdi32.$(IMPLIBEXT)
IMPORTS = advapi32 kernel32 ntdll
EXTRAINCL = @FREETYPEINCL@
-EXTRALIBS = @ICULIBS@
+EXTRALIBS = @ICULIBS@ @CARBONLIB@
SPEC_SRCS16 = \
dispdib.spec \
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 84daf4f..b9a46bc 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -37,6 +37,44 @@
#include <stdio.h>
#include <assert.h>
+#ifdef HAVE_CARBON_CARBON_H
+#define LoadResource __carbon_LoadResource
+#define CompareString __carbon_CompareString
+#define GetCurrentThread __carbon_GetCurrentThread
+#define GetCurrentProcess __carbon_GetCurrentProcess
+#define AnimatePalette __carbon_AnimatePalette
+#define EqualRgn __carbon_EqualRgn
+#define FillRgn __carbon_FillRgn
+#define FrameRgn __carbon_FrameRgn
+#define GetPixel __carbon_GetPixel
+#define InvertRgn __carbon_InvertRgn
+#define LineTo __carbon_LineTo
+#define OffsetRgn __carbon_OffsetRgn
+#define PaintRgn __carbon_PaintRgn
+#define Polygon __carbon_Polygon
+#define ResizePalette __carbon_ResizePalette
+#define SetRectRgn __carbon_SetRectRgn
+#include <Carbon/Carbon.h>
+#undef LoadResource
+#undef CompareString
+#undef GetCurrentThread
+#undef _CDECL
+#undef DPRINTF
+#undef GetCurrentProcess
+#undef AnimatePalette
+#undef EqualRgn
+#undef FillRgn
+#undef FrameRgn
+#undef GetPixel
+#undef InvertRgn
+#undef LineTo
+#undef OffsetRgn
+#undef PaintRgn
+#undef Polygon
+#undef ResizePalette
+#undef SetRectRgn
+#endif /* HAVE_CARBON_CARBON_H */
+
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
@@ -438,6 +476,204 @@ static const WCHAR font_mutex_nameW[] =
* cga40woa.fon=cga40850.fon
*/
+#ifdef HAVE_CARBON_CARBON_H
+static char *find_cache_dir(void)
+{
+ FSRef ref;
+ OSErr err;
+ static char cached_path[MAX_PATH];
+ 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;
+ SInt16 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 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 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;
+
+ fond = Get1IndResource('FOND', 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;
+ 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', font_id);
+ if(!sfnt)
+ {
+ TRACE("can't get sfnt resource %04x\n", font_id);
+ continue;
+ }
+
+ output = HeapAlloc(GetProcessHeap(), 0, output_len);
+ if(output)
+ {
+ int fd;
+
+ sprintf(output, "%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.max_size *= 2;
+ ret.array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ret.array, ret.max_size * sizeof(*ret.array));
+ }
+ ret.array[ret.size++] = output;
+ }
+ else
+ {
+ WARN("unable to create %s\n", output);
+ HeapFree(GetProcessHeap(), 0, output);
+ }
+ }
+ ReleaseResource(sfnt);
+ }
+ HUnlock(fond);
+ ReleaseResource(fond);
+ idx++;
+ }
+ CloseResFile(res_ref);
+
+ return ret.array;
+}
+
+#endif /* HAVE_CARBON_CARBON_H */
static inline BOOL is_win9x(void)
{
@@ -722,6 +958,27 @@ static BOOL AddFontFileToList(const char
int i, bitmap_num, internal_leading;
FONTSIGNATURE fs;
+#ifdef HAVE_CARBON_CARBON_H
+ if(!fake_family)
+ {
+ char **mac_list = expand_mac_font(file);
+ if(mac_list)
+ {
+ BOOL had_one = FALSE;
+ char **cursor;
+ for(cursor = mac_list; *cursor; cursor++)
+ {
+ had_one = TRUE;
+ AddFontFileToList(*cursor, NULL, flags);
+ HeapFree(GetProcessHeap(), 0, *cursor);
+ }
+ HeapFree(GetProcessHeap(), 0, mac_list);
+ if(had_one)
+ return TRUE;
+ }
+ }
+#endif /* HAVE_CARBON_CARBON_H */
+
do {
char *family_name = fake_family;
More information about the wine-cvs
mailing list