WINEPS: Read metrics from TrueType fonts

Ian Pilcher ian.pilcher at home.com
Sun May 13 13:18:23 CDT 2001


This patch enables the PostScript driver to read font metrics directly
from TrueType font files with FreeType 2.  It looks for font files in
directories listed in the [TrueType Font Directories] section of the
wine config file.  For example:

    [TrueType Font Directories]
    "dir0" = "/usr/X11R6/lib/X11/fonts/TrueType"
    "dir1" = "/usr/share/fonts/default/TrueType"
    etc.

It does not embed the fonts into its output.  Ghostscript users can
install their TrueType fonts in Ghostscript (with their Fontmap file or
the GS_FONTPATH environment variable); users printing to PostScript
printers will have to convert their fonts to Type 1 or Type 42 format
and
use an external program to add them to the print jobs.

At present, the driver also requires that every font be listed in the
target printer's PPD file.  I will change this shortly.

New files:
    dlls/wineps: truetype.c

Modified files:
    configure.in
    dlls/wineps: Makefile.in afm.c psdrv.h
    include: acconfig.h

Log message:
    Ian Pilcher
    WINEPS: Read metrics from TrueType fonts
-- 
========================================================================
Ian Pilcher                                         ian.pilcher at home.com
========================================================================
-------------- next part --------------
diff -urN ../wine-20010511cvs/configure.in ./configure.in
--- ../wine-20010511cvs/configure.in	Sat May 12 14:44:40 2001
+++ ./configure.in	Sat May 12 14:37:53 2001
@@ -378,6 +378,30 @@
 )
 AC_SUBST(CUPSLIBS)
 
+dnl **** Check for FreeType 2 ****
+AC_CHECK_LIB(freetype,FT_Init_FreeType,ft_lib=yes,ft_lib=no)
+if test "$ft_lib" = "no"
+then
+    FREETYPELIBS=""
+    FREETYPEINCL=""
+    wine_cv_msg_freetype=no
+else
+    AC_CHECK_PROG(ft_devel,freetype-config,yes,no)
+    if test "$ft_devel" = "no"
+    then
+    	FREETYPELIBS=""
+	FREETYPEINCL=""
+	wine_cv_msg_freetype=yes
+    else
+    	AC_DEFINE(HAVE_FREETYPE)
+	FREETYPELIBS=`freetype-config --libs`
+	FREETYPEINCL=`freetype-config --cflags`
+	wine_cv_msg_freetype=no
+    fi
+fi
+AC_SUBST(FREETYPELIBS)
+AC_SUBST(FREETYPEINCL)
+
 dnl **** Check for IPX (currently Linux only) ****
 AC_CACHE_CHECK("for GNU style IPX support", ac_cv_c_ipx_gnu,
  AC_TRY_COMPILE(
@@ -1318,6 +1342,15 @@
   echo "*** Note: You have cups runtime libraries, but no development"
   echo "*** libraries. Install the cups-devel package or whichever package"
   echo "*** contains cups.h to enable CUPS support in WINE."
+fi
+
+if test "$wine_cv_msg_freetype" = "yes"
+then
+  echo
+  echo "*** Note: Your system appears to have the FreeType 2 runtime libraries"
+  echo "*** installed, but 'freetype-config' is not in your PATH. Install the"
+  echo "*** freetype-devel package (or its equivalent on your distribution) to"
+  echo "*** enable Wine to use TrueType fonts."
 fi
 
 echo
diff -urN ../wine-20010511cvs/dlls/wineps/Makefile.in ./dlls/wineps/Makefile.in
--- ../wine-20010511cvs/dlls/wineps/Makefile.in	Sat May 12 14:44:40 2001
+++ ./dlls/wineps/Makefile.in	Sat May 12 14:37:53 2001
@@ -6,7 +6,8 @@
 SOVERSION = 1.0
 ALTNAMES  = wineps16
 IMPORTS   = user32 gdi32 winspool.drv kernel32 ntdll
-EXTRALIBS = @CUPSLIBS@
+EXTRALIBS = @CUPSLIBS@ @FREETYPELIBS@
+EXTRAINCL = @FREETYPEINCL@
 
 C_SRCS = \
 	afm.c \
@@ -26,7 +27,8 @@
 	pen.c \
 	ppd.c \
 	ps.c \
-	text.c
+	text.c \
+	truetype.c
 
 RC_SRCS= \
 	rsrc.rc
diff -urN ../wine-20010511cvs/dlls/wineps/afm.c ./dlls/wineps/afm.c
--- ../wine-20010511cvs/dlls/wineps/afm.c	Sat May 12 14:44:40 2001
+++ ./dlls/wineps/afm.c	Sat May 12 14:42:41 2001
@@ -655,8 +655,9 @@
 	{
 	    INT i;
 	    
-	    TRACE("\tFontName '%s' (%i glyphs):\n", afmle->afm->FontName,
-	    	    afmle->afm->NumofMetrics);
+	    TRACE("\tFontName '%s' (%i glyphs) - '%s' encoding:\n",
+	    	    afmle->afm->FontName, afmle->afm->NumofMetrics,
+		    afmle->afm->EncodingScheme);
 	    
 	    for (i = 0; i < afmle->afm->NumofMetrics; ++i)
 	    {
@@ -672,7 +673,10 @@
  *  SortFontMetrics
  *
  *  Initializes the UV member of each glyph's AFMMETRICS and sorts each font's
- *  Metrics by Unicode Value.
+ *  Metrics by Unicode Value.  If the font has a standard encoding (i.e. it is
+ *  using the Adobe Glyph List encoding vector), look up each glyph's Unicode
+ *  Value based on it's glyph name.  If the font has a font-specific encoding,
+ *  map the default PostScript encodings into the Unicode private use area.
  *
  */
 static int UnicodeGlyphByNameIndex(const UNICODEGLYPH *a, const UNICODEGLYPH *b)
@@ -966,10 +970,17 @@
 	if (PSDRV_ReadAFMDir (value) == FALSE)
 	    return FALSE;
 
-    PSDRV_IndexGlyphList();
+    PSDRV_IndexGlyphList(); 	    	/* So SortFontMetrics will work */
     if (SortFontMetrics() == FALSE)
     	return FALSE;
     CalcWindowsMetrics();
+
+#ifdef HAVE_FREETYPE   
+    if (PSDRV_GetTrueTypeMetrics() == FALSE)
+    	return FALSE;
+    PSDRV_IndexGlyphList();
+#endif
+
     PSDRV_DumpFontList();
     return TRUE;
 }
diff -urN ../wine-20010511cvs/dlls/wineps/psdrv.h ./dlls/wineps/psdrv.h
--- ../wine-20010511cvs/dlls/wineps/psdrv.h	Sat May 12 14:44:40 2001
+++ ./dlls/wineps/psdrv.h	Sat May 12 14:37:53 2001
@@ -418,6 +418,7 @@
 INT PSDRV_GlyphListInit();
 GLYPHNAME *PSDRV_GlyphName(LPCSTR szName);
 VOID PSDRV_IndexGlyphList();
+BOOL PSDRV_GetTrueTypeMetrics();
 
 #endif
 
diff -urN ../wine-20010511cvs/dlls/wineps/truetype.c ./dlls/wineps/truetype.c
--- ../wine-20010511cvs/dlls/wineps/truetype.c	Sat May 12 14:44:40 2001
+++ ./dlls/wineps/truetype.c	Sat May 12 14:42:41 2001
@@ -0,0 +1,609 @@
+/*******************************************************************************
+ *  truetype.c
+ *
+ *  TrueType font-related functions for Wine PostScript driver.  Currently just
+ *  uses FreeType to read font metrics.
+ *
+ *  Copyright 2001  Ian Pilcher
+ *
+ */
+#include <freetype/freetype.h>
+#include <freetype/ftnames.h>
+#include <freetype/ttnameid.h>
+#include <freetype/tttables.h>
+#include <freetype/ftglyph.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "winnt.h"
+#include "options.h"
+#include "psdrv.h"
+#include "debugtools.h"
+#include "heap.h"
+
+DEFAULT_DEBUG_CHANNEL(psdrv);
+
+#ifdef HAVE_FREETYPE
+
+#define REQUIRED_FACE_FLAGS 	(   FT_FACE_FLAG_SCALABLE   |	\
+    	    	    	    	    FT_FACE_FLAG_HORIZONTAL |	\
+				    FT_FACE_FLAG_SFNT	    |	\
+				    FT_FACE_FLAG_GLYPH_NAMES	)
+
+static FT_Library   	library;
+static FT_Face	    	face;
+static FT_CharMap   	charmap;
+static TT_Header    	*head;
+static TT_Postscript	*post;
+static TT_OS2	    	*os2;
+static TT_HoriHeader	*hhea;
+
+/*******************************************************************************
+ *
+ *  FindCharMap
+ *
+ *  Sets charmap and points afm->EncodingScheme to encoding name (in driver
+ *  heap).  Leaves both uninitialized if font contains no Windows encoding.
+ *
+ *  Returns FALSE to indicate memory allocation error.
+ *
+ */
+static const char *encoding_names[7] =
+{
+    "WindowsSymbol",	    /* TT_MS_ID_SYMBOL_CS */
+    "WindowsUnicode",	    /* TT_MS_ID_UNICODE_CS */
+    "WindowsShiftJIS",	    /* TT_MS_ID_SJIS */
+    "WindowsPRC",  	    /* TT_MS_ID_GB2312 */
+    "WindowsBig5",  	    /* TT_MS_ID_BIG_5 */
+    "WindowsWansung",	    /* TT_MS_ID_WANSUNG */
+    "WindowsJohab"  	    /* TT_MS_ID_JOHAB */
+};
+ 
+static BOOL FindCharMap(AFM *afm)
+{
+    FT_Int  	i;
+    FT_Error	error;
+    
+    charmap = NULL;
+    
+    for (i = 0; i < face->num_charmaps; ++i)
+    {
+    	if (face->charmaps[i]->platform_id != TT_PLATFORM_MICROSOFT)
+	    continue;
+	    
+	if (face->charmaps[i]->encoding_id == TT_MS_ID_UNICODE_CS)
+    	{
+	    charmap = face->charmaps[i];
+	    break;
+	}
+	    
+	if (charmap == NULL)
+	    charmap = face->charmaps[i];
+    }
+    
+    if (charmap == NULL)
+    	return TRUE;
+	
+    error = FT_Set_Charmap(face, charmap);
+    if (error != FT_Err_Ok)
+    {
+    	ERR("%s returned %i\n", "FT_Set_CharMap", error);
+	return FALSE;
+    }
+	
+    if (charmap->encoding_id < 7)
+    {
+    	afm->EncodingScheme = HEAP_strdupA(PSDRV_Heap, 0,
+	    	encoding_names[charmap->encoding_id]);
+	if (afm->EncodingScheme == NULL)
+	    return FALSE;
+    }
+    else
+    {
+    	afm->EncodingScheme = HeapAlloc(PSDRV_Heap, 0,
+	    	sizeof("WindowsUnknown") + 1 + charmap->encoding_id / 10);
+	if (afm->EncodingScheme == NULL)
+	    return FALSE;
+	    
+	sprintf(afm->EncodingScheme, "%s%u", "WindowsUnknown",
+	    	charmap->encoding_id);
+    }
+    
+    return TRUE;
+}
+
+/*******************************************************************************
+ *  NameTableString
+ *
+ *  Converts a name table string to a null-terminated character string.  The
+ *  space for the character string is allocated from the driver heap.
+ *
+ *  This function handles only platform_id = 3 (TT_PLATFORM_MICROSOFT) -- 16-bit
+ *  big-endian strings.  It also only handles ASCII character codes (< 128).
+ *
+ *  This function will set *sz to NULL if it cannot parse the string, but it
+ *  will only return FALSE in the event of an unexpected error (memory
+ *  allocation failure).
+ *
+ */
+static BOOL NameTableString(LPSTR *sz, const FT_SfntName *name)
+{    
+    FT_UShort 	i, len, *ws;
+    LPSTR   	s;
+    
+    if (name->platform_id != TT_PLATFORM_MICROSOFT)
+    {
+    	ERR("Unsupported encoding %i\n", name->platform_id);
+	return FALSE;	    /* should never get here */
+    }
+    
+    len = name->string_len / 2;
+    s = *sz = HeapAlloc(PSDRV_Heap, 0, len + 1);
+    if (s == NULL)
+    	return FALSE;
+    ws = (FT_UShort *)(name->string);
+	
+    for (i = 0; i < len; ++i, ++s, ++ws)
+    {
+    	FT_UShort   wc = *ws;
+	
+#ifndef WORDS_BIGENDIAN
+    	wc = (wc >> 8) | (wc << 8);
+#endif
+
+    	if (wc > 127)
+	{
+	    WARN("Non-ASCII character 0x%.4x\n", wc);
+	    HeapFree(PSDRV_Heap, 0, *sz);
+	    *sz = NULL;
+	    return TRUE;
+	}
+	
+	*s = (CHAR)wc;
+    }
+    
+    *s = '\0';
+    return TRUE;
+}
+
+/*******************************************************************************
+ *  ReadNameTable
+ *
+ *  Reads various font names from the TrueType 'NAME' table.  Currently looks
+ *  for U.S. English names only,
+ *
+ *  May leave a pointer uninitialized if the desired string is not present;
+ *  returns FALSE only in the event of an unexpected error.
+ *
+ */
+static BOOL ReadNameTable(AFM *afm)
+{
+    FT_UInt 	numStrings, stringIndex;
+    FT_SfntName name;
+    FT_Error	error;
+
+    numStrings = FT_Get_Sfnt_Name_Count(face);
+    
+    for (stringIndex = 0; stringIndex < numStrings; ++stringIndex)
+    {
+	error = FT_Get_Sfnt_Name(face, stringIndex, &name);
+	if (error != FT_Err_Ok)
+	{
+	    ERR("%s returned %i\n", "FT_Get_Sfnt_Name", error);
+	    return FALSE;
+	}
+	
+	/* FIXME - Handle other languages? */
+	
+	if (name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES ||
+	    	name.platform_id != charmap->platform_id ||
+	    	name.encoding_id != charmap->encoding_id)
+	    continue;
+	
+    	switch (name.name_id)
+	{
+	    case TT_NAME_ID_FONT_FAMILY:
+	    
+	    	if (NameTableString(&(afm->FamilyName), &name) == FALSE)
+		    return FALSE;
+		break;
+	    
+	    case TT_NAME_ID_FULL_NAME:
+	    
+	    	if (NameTableString(&(afm->FullName), &name) == FALSE)
+		    return FALSE;
+		break;
+	    
+	    case TT_NAME_ID_PS_NAME:
+	    
+	    	if (NameTableString(&(afm->FontName), &name) == FALSE)
+		    return FALSE;
+		break;
+	}
+    }
+    
+    return TRUE;
+}
+
+/*******************************************************************************
+ *  FreeAFM
+ *
+ *  Frees an AFM and all subsidiary objects.  For this function to work
+ *  properly, the AFM must have been allocated with HEAP_ZERO_MEMORY, and the
+ *  UNICODEVECTOR and it's associated array of UNICODEGLYPHs must have been
+ *  allocated as a single object.
+ */
+static void FreeAFM(AFM *afm)
+{
+    if (afm->FontName != NULL)
+    	HeapFree(PSDRV_Heap, 0, afm->FontName);
+    if (afm->FullName != NULL)
+    	HeapFree(PSDRV_Heap, 0, afm->FullName);
+    if (afm->FamilyName != NULL)
+    	HeapFree(PSDRV_Heap, 0, afm->FamilyName);
+    if (afm->EncodingScheme != NULL)
+    	HeapFree(PSDRV_Heap, 0, afm->EncodingScheme);
+    if (afm->Metrics != NULL)
+    	HeapFree(PSDRV_Heap, 0, afm->Metrics);
+    if (afm->Encoding != NULL)
+    	HeapFree(PSDRV_Heap, 0, afm->Encoding);
+	
+    HeapFree(PSDRV_Heap, 0, afm);
+}
+
+/*******************************************************************************
+ *  PSUnits
+ *
+ *  Convert TrueType font units (relative to font em square) to PostScript
+ *  units.  This is defined as a macro, so it can handle different TrueType
+ *  data types as inputs.
+ *
+ */
+#define PSUnits(x)  (((float)(x)) * 1000.0 / ((float)(head->Units_Per_EM)))
+
+/*******************************************************************************
+ *  ReadMetricsTables
+ *
+ *  Reads basic font metrics from the 'head', 'post', and 'OS/2' tables.
+ *  Returns FALSE if any table is missing.
+ *
+ */ 
+static BOOL ReadMetricsTables(AFM *afm)
+{
+    head = FT_Get_Sfnt_Table(face, ft_sfnt_head);
+    post = FT_Get_Sfnt_Table(face, ft_sfnt_post);
+    hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
+    os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
+    
+    if (head == NULL || post == NULL || hhea == NULL || os2 == NULL)
+	return FALSE;
+    
+    if (os2->version == 0xffff)     	    /* Old Macintosh font */
+	return FALSE;
+    
+    afm->Weight = os2->usWeightClass;
+    afm->ItalicAngle = ((float)(post->italicAngle)) / 65536.0;
+    afm->IsFixedPitch = (post->isFixedPitch == 0) ? FALSE : TRUE;
+    afm->UnderlinePosition = PSUnits(post->underlinePosition);
+    afm->UnderlineThickness = PSUnits(post->underlineThickness);
+	    
+    afm->FontBBox.llx = PSUnits(head->xMin);
+    afm->FontBBox.lly = PSUnits(head->yMin);
+    afm->FontBBox.urx = PSUnits(head->xMax);
+    afm->FontBBox.ury = PSUnits(head->yMax);
+    
+    /* CapHeight & XHeight set by ReadCharMetrics */
+    
+    afm->Ascender = PSUnits(os2->sTypoAscender);
+    afm->Descender = PSUnits(os2->sTypoDescender);
+    afm->FullAscender = afm->FontBBox.ury;  	    /* get rid of this */
+    
+    afm->WinMetrics.usUnitsPerEm = head->Units_Per_EM;
+    afm->WinMetrics.sAscender = hhea->Ascender;
+    afm->WinMetrics.sDescender = hhea->Descender;
+    afm->WinMetrics.sLineGap = hhea->Line_Gap;
+    afm->WinMetrics.sTypoAscender = os2->sTypoAscender;
+    afm->WinMetrics.sTypoDescender = os2->sTypoDescender;
+    afm->WinMetrics.sTypoLineGap = os2->sTypoLineGap;
+    afm->WinMetrics.usWinAscent = os2->usWinAscent;
+    afm->WinMetrics.usWinDescent = os2->usWinDescent;
+    
+    return TRUE;
+}
+
+/*******************************************************************************
+ *  ReadCharMetrics
+ *
+ *  Reads metrics for each glyph in a TrueType font.  Since FreeAFM will try to
+ *  free afm->Metrics and afm->Encoding if they are non-NULL, don't free them
+ *  in the event of an error.  (FreeAFM depends on the fact that afm->Encoding
+ *  and its associated array of UNICODEGLYPHs are allocated as a single object.)
+ *
+ */
+static BOOL ReadCharMetrics(AFM *afm)
+{
+    FT_ULong	    charcode, index;
+    UNICODEGLYPH    *glyphs;
+    
+    /*
+     *	There does not seem to be an easy way to get the number of characters
+     *	in an encoding out of a TrueType font.
+     */
+    for (charcode = 0, index = 0; charcode < 65536; ++charcode)
+    {
+    	if (FT_Get_Char_Index(face, charcode) != 0)
+	    ++index;
+    }
+    
+    afm->NumofMetrics = index;
+    
+    afm->Metrics = HeapAlloc(PSDRV_Heap, 0, index * sizeof(AFMMETRICS));
+    afm->Encoding = HeapAlloc(PSDRV_Heap, 0, sizeof(UNICODEVECTOR) +
+    	    index * sizeof(UNICODEGLYPH));
+    if (afm->Metrics == NULL || afm->Encoding == NULL)
+    	return FALSE;
+	
+    glyphs = (UNICODEGLYPH *)(afm->Encoding + 1);
+    afm->Encoding->size = index;
+    afm->Encoding->glyphs = glyphs;
+    
+    for (charcode = 0, index = 0; charcode <= 65536; ++charcode)
+    {
+    	FT_UInt     glyph_index = FT_Get_Char_Index(face, charcode);
+	FT_Error    error;
+	FT_Glyph    glyph;
+	FT_BBox     bbox;
+	char	    buffer[256];
+	
+	if (glyph_index == 0)
+	    continue;
+	    
+	error = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE |
+	    	FT_LOAD_IGNORE_TRANSFORM | FT_LOAD_LINEAR_DESIGN);
+	if (error != FT_Err_Ok)
+	{
+	    ERR("%s returned %i\n", "FT_Load_Glyph", error);
+	    return FALSE;
+	}
+	
+	error = FT_Get_Glyph(face->glyph, &glyph);
+	if (error != FT_Err_Ok)
+	{
+	    ERR("%s returned %i\n", "FT_Get_Glyph", error);
+	    return FALSE;
+	}
+	
+	FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &bbox);
+	
+	error = FT_Get_Glyph_Name(face, glyph_index, buffer, 255);
+	if (error != FT_Err_Ok)
+	{
+	    ERR("%s returned %i\n", "FT_Get_Glyph_Name", error);
+	    return FALSE;
+	}
+	
+	afm->Metrics[index].N = PSDRV_GlyphName(buffer);
+	if (afm->Metrics[index].N == NULL)
+	    return FALSE;
+	
+	afm->Metrics[index].C = charcode;
+	afm->Metrics[index].UV = charcode;
+	afm->Metrics[index].WX = PSUnits(face->glyph->metrics.horiAdvance);
+	afm->Metrics[index].B.llx = PSUnits(bbox.xMin);
+	afm->Metrics[index].B.lly = PSUnits(bbox.yMin);
+	afm->Metrics[index].B.urx = PSUnits(bbox.xMax);
+	afm->Metrics[index].B.ury = PSUnits(bbox.yMax);
+	afm->Metrics[index].L = NULL;
+	
+	TRACE("Metrics for '%s' WX = %f B = %f,%f - %f,%f\n",
+	    	afm->Metrics[index].N->sz, afm->Metrics[index].WX,
+		afm->Metrics[index].B.llx, afm->Metrics[index].B.lly,
+	      	afm->Metrics[index].B.urx, afm->Metrics[index].B.ury);
+	
+	glyphs[index].UV = charcode;
+	glyphs[index].name = afm->Metrics[index].N;
+	
+	if (charcode == 0x0048)     	    	    /* 'H' */
+	    afm->CapHeight = PSUnits(bbox.yMax);
+	if (charcode == 0x0078)     	    	    /* 'x' */
+	    afm->XHeight = PSUnits(bbox.yMax);
+		
+	++index;
+    }
+    
+    return TRUE;
+}
+
+/*******************************************************************************
+ *  ReadTrueTypeAFM
+ *
+ *  Fills in AFM structure for opened TrueType font file.  Returns FALSE only on
+ *  an unexpected error (memory allocation failure or FreeType error); otherwise
+ *  returns TRUE.  Leaves it to the caller (ReadTrueTypeFile) to clean up.
+ *
+ */
+static BOOL ReadTrueTypeAFM(AFM *afm)
+{
+
+    if ((face->face_flags & REQUIRED_FACE_FLAGS) != REQUIRED_FACE_FLAGS)
+    {
+    	WARN("Font flags do not match requirements\n");
+	return TRUE;
+    }
+    
+    if (FindCharMap(afm) == FALSE)
+    	return FALSE;
+	
+    if (charmap == NULL)
+    {
+    	WARN("No Windows encodings in font\n");
+	return TRUE;
+    }
+    
+    TRACE("Using encoding '%s'\n", afm->EncodingScheme);
+
+    if (ReadNameTable(afm) == FALSE)
+    	return FALSE;
+   
+    if (afm->FamilyName == NULL || afm->FullName == NULL ||
+    	    afm->FontName == NULL)
+    {
+    	WARN("Required strings missing from font\n");
+	return TRUE;
+    }
+
+    if (ReadMetricsTables(afm) == FALSE)    /* Non-fatal */
+    {
+    	WARN("Required metrics tables missing from font\n");
+	return TRUE;
+    }
+    
+    if (ReadCharMetrics(afm) == FALSE)
+    	return FALSE;
+
+    return TRUE;
+}
+
+/*******************************************************************************
+ *  ReadTrueTypeFile
+ *
+ *  Reads PostScript-style font metrics from a TrueType font file.  Only returns
+ *  FALSE for unexpected errors (memory allocation, etc.); returns TRUE if it's
+ *  just a bad font file.
+ *
+ */
+static BOOL ReadTrueTypeFile(LPCSTR filename)
+{
+    FT_Error	error;
+    AFM     	*afm;
+    
+    TRACE("'%s'\n", filename);
+
+    afm = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY, sizeof(AFM));
+    if (afm == NULL)
+    	return FALSE;
+
+    error = FT_New_Face(library, filename, 0, &face);
+
+    if (error != FT_Err_Ok)
+    {
+    	WARN("FreeType error %i opening '%s'\n", error, filename);
+	HeapFree(PSDRV_Heap, 0, afm);
+	return TRUE;
+    }
+    
+    if (ReadTrueTypeAFM(afm) == FALSE)
+    {
+    	FreeAFM(afm);
+	FT_Done_Face(face);
+	return FALSE;
+    }    
+
+    error = FT_Done_Face(face);
+    if (error != FT_Err_Ok)
+    {
+    	ERR("%s returned %i\n", "FT_Done_Face", error);
+	FreeAFM(afm);
+	return FALSE;
+    }
+    
+    if (afm->Encoding == NULL)	    /* last element to be set */
+    {
+    	FreeAFM(afm);
+	return TRUE;
+    }
+    
+    if (PSDRV_AddAFMtoList(&PSDRV_AFMFontList, afm) == FALSE)
+    {
+    	FreeAFM(afm);
+	return FALSE;
+    }
+    
+    return TRUE;
+}
+    
+
+
+/*******************************************************************************
+ *  PSDRV_GetTrueTypeMetrics
+ *
+ *  Reads PostScript-stype font metrics from TrueType font files in directories
+ *  listed in the [TrueType Font Directories] section of the Wine configuration
+ *  file.
+ *
+ *  If this function fails, the driver will fail to initialize and the driver
+ *  heap will be destroyed, so it's not necessary to HeapFree everything in
+ *  that event.
+ *
+ */
+BOOL PSDRV_GetTrueTypeMetrics()
+{
+    CHAR    	keybuf[256], namebuf[256];
+    INT     	i = 0;
+    FT_Error	error;
+
+    error = FT_Init_FreeType(&library);
+    if (error != FT_Err_Ok)
+    {
+    	ERR("%s returned %i\n", "FT_Init_FreeType", error);
+	return FALSE;
+    }
+
+    while (PROFILE_EnumWineIniString("TrueType Font Directories", i++, keybuf,
+    	    sizeof(keybuf), namebuf, sizeof(namebuf)))
+    {
+    	struct dirent	*dent;
+    	DIR 	    	*dir;
+	INT 	    	dnlen;	    /* directory name length */
+
+    	namebuf[sizeof(namebuf) - 1] = '\0';
+    	dir = opendir(namebuf);
+	if (dir == NULL)
+	{
+	    WARN("Error opening directory '%s'\n", namebuf);
+	    continue;
+	}
+	
+	dnlen = strlen(namebuf);
+	namebuf[dnlen] = '/';	    	/* 2 slashes is OK, 0 is not */
+	++dnlen;
+	
+	while ((dent = readdir(dir)) != NULL)
+	{
+	    INT fnlen;	    /* file name length */
+	    
+	    fnlen = strlen(dent->d_name);
+	    
+	    if (fnlen < 5 || strcasecmp(dent->d_name + fnlen - 4, ".ttf") != 0)
+	    {
+	    	TRACE("Skipping filename '%s'\n", dent->d_name);
+		continue;
+	    }
+	    
+	    if (dnlen + fnlen + 1 > sizeof(namebuf))	/* allow for '\0' */
+	    {
+	    	WARN("Path '%s/%s' is too long\n", namebuf, dent->d_name);
+		continue;
+	    }
+	    
+	    memcpy(namebuf + dnlen, dent->d_name, fnlen + 1);
+	    
+	    if (ReadTrueTypeFile(namebuf) == FALSE)
+	    {
+	    	ERR("Error reading '%s'\n", namebuf);
+	    	closedir(dir);
+		FT_Done_FreeType(library);
+		return FALSE;
+	    }
+	}
+	
+	closedir(dir);
+    }
+   
+    FT_Done_FreeType(library);
+    return TRUE;
+}
+
+#endif
diff -urN ../wine-20010511cvs/include/acconfig.h ./include/acconfig.h
--- ../wine-20010511cvs/include/acconfig.h	Sat May 12 14:44:40 2001
+++ ./include/acconfig.h	Sat May 12 14:37:53 2001
@@ -122,3 +122,6 @@
 
 /* Define if we have CUPS */
 #undef HAVE_CUPS
+
+/* Define if FreeType 2 is installed */
+#undef HAVE_FREETYPE


More information about the wine-patches mailing list