Guesstimate Windows font metrics for Type 1 fonts

Ian Pilcher ian.pilcher at home.com
Sat May 12 00:38:50 CDT 2001


I still can't figure out how the Windows PostScript driver calculates
line spacings for built-in fonts; they don't seem to be based on any
metrics that are in AFM files.  (I'm beginning to believe that they're
simply hardcoded into the driver.)  This sets it to 115% of the em
square, which at least matches up for a couple of fonts.

Modified files:
    dlls/wineps: afm.c psdrv.h

Log message:
    Ian Pilcher
    Guesstimate Windows font metrics for Type 1 fonts
-- 
========================================================================
Ian Pilcher                                         ian.pilcher at home.com
========================================================================
-------------- next part --------------
diff -urN ../wine-20010511cvs/dlls/wineps/afm.c ./dlls/wineps/afm.c
--- ../wine-20010511cvs/dlls/wineps/afm.c	Fri May 11 14:54:24 2001
+++ ./dlls/wineps/afm.c	Fri May 11 23:00:09 2001
@@ -29,6 +29,38 @@
 typedef int (*compar_callback_fn) (const void *, const void *);
 
 /*******************************************************************************
+ *  IsWinANSI
+ *
+ *  Checks whether Unicode value is part of Microsoft code page 1252
+ *
+ */
+static const INT ansiChars[21] =
+{
+    0x0152, 0x0153, 0x0160, 0x0161, 0x0178, 0x017d, 0x017e, 0x0192, 0x02c6,
+    0x02c9, 0x02dc, 0x03bc, 0x2013, 0x2014, 0x2026, 0x2030, 0x2039, 0x203a,
+    0x20ac, 0x2122, 0x2219
+};
+
+static int cmpUV(const INT *a, const INT *b)
+{
+    return *a - *b;
+}
+ 
+inline static BOOL IsWinANSI(INT uv)
+{
+    if ((0x0020 <= uv && uv <= 0x007e) || (0x00a0 <= uv && uv <= 0x00ff) ||
+    	    (0x2018 <= uv && uv <= 0x201a) || (0x201c <= uv && uv <= 0x201e) ||
+	    (0x2020 <= uv && uv <= 2022))
+    	return TRUE;
+	
+    if (bsearch(&uv, ansiChars, 21, sizeof(INT),
+    	    (compar_callback_fn)cmpUV) != NULL)
+    	return TRUE;
+	
+    return FALSE;
+}
+
+/*******************************************************************************
  *  	CheckMetrics
  *
  *  Check an AFMMETRICS structure to make sure all elements have been properly
@@ -751,6 +783,98 @@
     return TRUE;
 }
 
+/*******************************************************************************
+ *  CalcWindowsMetrics
+ *
+ *  Calculates several Windows-specific font metrics for each font.  Relies on
+ *  the fact that AFMs are allocated with HEAP_ZERO_MEMORY to distinguish
+ *  TrueType fonts (when implemented), which already have these filled in.
+ *
+ */
+static VOID CalcWindowsMetrics()
+{
+    FONTFAMILY	*family = PSDRV_AFMFontList;
+    
+    while (family != NULL)
+    {
+    	AFMLISTENTRY	*afmle = family->afmlist;
+	
+	while (afmle != NULL)
+	{
+	    WINMETRICS	wm;
+	    AFM     	*afm = afmle->afm;  	/* should always be valid */
+	    INT     	i;
+	    
+	    if (afm->WinMetrics.usUnitsPerEm != 0)
+	    	continue;   	    	    	    /* TrueType font */
+		
+	    wm.usUnitsPerEm = 1000;         	    /* for PostScript fonts */
+	    wm.sTypoAscender = (SHORT)(afm->Ascender + 0.5);
+	    wm.sTypoDescender = (SHORT)(afm->Descender + 0.5);
+	    
+	    wm.sTypoLineGap = 1200 - (wm.sTypoAscender - wm.sTypoDescender);
+	    if (wm.sTypoLineGap < 0)
+	    	wm.sTypoLineGap = 0;
+		
+	    wm.usWinAscent = 0;
+	    wm.usWinDescent = 0;
+	    
+	    for (i = 0; i < afm->NumofMetrics; ++i)
+	    {
+	    	if (IsWinANSI(afm->Metrics[i].UV) == FALSE)
+		    continue;
+		    
+		if (afm->Metrics[i].B.ury > 0)
+		{
+		    USHORT ascent = (USHORT)(afm->Metrics[i].B.ury + 0.5);
+						
+		    if (ascent > wm.usWinAscent)
+		    	wm.usWinAscent = ascent;
+		}
+		
+		if (afm->Metrics[i].B.lly < 0)    
+		{
+		    USHORT descent = (USHORT)(-(afm->Metrics[i].B.lly) + 0.5);
+		    
+		    if (descent > wm.usWinDescent)
+		    	wm.usWinDescent = descent;
+		}
+	    }
+	    
+	    if (wm.usWinAscent == 0 && afm->FontBBox.ury > 0)
+	    	wm.usWinAscent = (USHORT)(afm->FontBBox.ury + 0.5);
+		
+	    if (wm.usWinDescent == 0 && afm->FontBBox.lly < 0)
+	    	wm.usWinDescent = (USHORT)(-(afm->FontBBox.lly) + 0.5);
+		
+	    wm.sAscender = wm.usWinAscent;
+	    wm.sDescender = -(wm.usWinDescent);
+	    
+	    wm.sLineGap = 1150 - (wm.sAscender - wm.sDescender);
+	    if (wm.sLineGap < 0)
+	    	wm.sLineGap = 0;
+						
+	    TRACE("Windows metrics for '%s':\n", afm->FullName);
+	    TRACE("\tsAscender = %i\n", wm.sAscender);
+	    TRACE("\tsDescender = %i\n", wm.sDescender);
+	    TRACE("\tsLineGap = %i\n", wm.sLineGap);
+	    TRACE("\tusUnitsPerEm = %u\n", wm.usUnitsPerEm);
+	    TRACE("\tsTypoAscender = %i\n", wm.sTypoAscender);
+	    TRACE("\tsTypoDescender = %i\n", wm.sTypoDescender);
+	    TRACE("\tsTypoLineGap = %i\n", wm.sTypoLineGap);
+	    TRACE("\tusWinAscent = %u\n", wm.usWinAscent);
+	    TRACE("\tusWinDescent = %u\n", wm.usWinDescent);
+	    
+	    afm->WinMetrics = wm;
+	    
+	    afmle = afmle->next;
+	}
+	
+	family = family ->next;
+    }
+}
+
+
 /***********************************************************
  *
  *	PSDRV_GetFontMetrics
@@ -845,6 +969,7 @@
     PSDRV_IndexGlyphList();
     if (SortFontMetrics() == FALSE)
     	return FALSE;
+    CalcWindowsMetrics();
     PSDRV_DumpFontList();
     return TRUE;
 }
diff -urN ../wine-20010511cvs/dlls/wineps/psdrv.h ./dlls/wineps/psdrv.h
--- ../wine-20010511cvs/dlls/wineps/psdrv.h	Wed May  9 12:11:59 2001
+++ ./dlls/wineps/psdrv.h	Fri May 11 22:58:08 2001
@@ -53,12 +53,15 @@
 } AFMMETRICS;
 
 typedef struct {
-    USHORT    	    	usUnitsPerEm; 	    	/* 1000 for Type 1 fonts */
-    SHORT   	    	sTypoAscender;	    	/* AFM Ascender */
-    SHORT   	    	sTypoDescender;     	/* AFM Descender */
-    SHORT   	    	sTypoLineGap;	    	/* guess for Type 1 fonts */
-    USHORT  	    	usWinAscent;
-    USHORT  	    	usWinDescent;
+    USHORT    	    	usUnitsPerEm; 	    	/* head:unitsPerEm */
+    SHORT   	    	sAscender;  	    	/* hhea:Ascender */
+    SHORT   	    	sDescender; 	    	/* hhea:Descender */
+    SHORT   	    	sLineGap;   	    	/* hhea:LineGap */
+    SHORT   	    	sTypoAscender;	    	/* OS/2:sTypoAscender */
+    SHORT   	    	sTypoDescender;     	/* OS/2:sTypoDescender */
+    SHORT   	    	sTypoLineGap;	    	/* OS/2:sTypeLineGap */
+    USHORT  	    	usWinAscent;	    	/* OS/2:usWinAscent */
+    USHORT  	    	usWinDescent;	    	/* OS/2:usWinDescent */
 } WINMETRICS;
 
 typedef struct _tagAFM {


More information about the wine-patches mailing list