Read metrics from TrueType fonts.
This commit is contained in:
parent
31eaee4539
commit
563598d45d
33
configure.in
33
configure.in
|
@ -378,6 +378,30 @@ AC_CHECK_LIB(cups,cupsGetPPD,
|
||||||
)
|
)
|
||||||
AC_SUBST(CUPSLIBS)
|
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) ****
|
dnl **** Check for IPX (currently Linux only) ****
|
||||||
AC_CACHE_CHECK("for GNU style IPX support", ac_cv_c_ipx_gnu,
|
AC_CACHE_CHECK("for GNU style IPX support", ac_cv_c_ipx_gnu,
|
||||||
AC_TRY_COMPILE(
|
AC_TRY_COMPILE(
|
||||||
|
@ -1362,6 +1386,15 @@ then
|
||||||
echo "*** contains cups.h to enable CUPS support in WINE."
|
echo "*** contains cups.h to enable CUPS support in WINE."
|
||||||
fi
|
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
|
echo
|
||||||
echo "Configure finished. Do 'make depend && make' to compile Wine."
|
echo "Configure finished. Do 'make depend && make' to compile Wine."
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -6,7 +6,8 @@ MODULE = wineps
|
||||||
SOVERSION = 1.0
|
SOVERSION = 1.0
|
||||||
ALTNAMES = wineps16
|
ALTNAMES = wineps16
|
||||||
IMPORTS = user32 gdi32 winspool.drv kernel32 ntdll
|
IMPORTS = user32 gdi32 winspool.drv kernel32 ntdll
|
||||||
EXTRALIBS = @CUPSLIBS@
|
EXTRALIBS = @CUPSLIBS@ @FREETYPELIBS@
|
||||||
|
EXTRAINCL = @FREETYPEINCL@
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
afm.c \
|
afm.c \
|
||||||
|
@ -26,7 +27,8 @@ C_SRCS = \
|
||||||
pen.c \
|
pen.c \
|
||||||
ppd.c \
|
ppd.c \
|
||||||
ps.c \
|
ps.c \
|
||||||
text.c
|
text.c \
|
||||||
|
truetype.c
|
||||||
|
|
||||||
RC_SRCS= \
|
RC_SRCS= \
|
||||||
rsrc.rc
|
rsrc.rc
|
||||||
|
|
|
@ -654,8 +654,9 @@ static void PSDRV_DumpFontList(void)
|
||||||
{
|
{
|
||||||
INT i;
|
INT i;
|
||||||
|
|
||||||
TRACE("\tFontName '%s' (%i glyphs):\n", afmle->afm->FontName,
|
TRACE("\tFontName '%s' (%i glyphs) - '%s' encoding:\n",
|
||||||
afmle->afm->NumofMetrics);
|
afmle->afm->FontName, afmle->afm->NumofMetrics,
|
||||||
|
afmle->afm->EncodingScheme);
|
||||||
|
|
||||||
for (i = 0; i < afmle->afm->NumofMetrics; ++i)
|
for (i = 0; i < afmle->afm->NumofMetrics; ++i)
|
||||||
{
|
{
|
||||||
|
@ -671,7 +672,10 @@ static void PSDRV_DumpFontList(void)
|
||||||
* SortFontMetrics
|
* SortFontMetrics
|
||||||
*
|
*
|
||||||
* Initializes the UV member of each glyph's AFMMETRICS and sorts each font's
|
* 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)
|
static int UnicodeGlyphByNameIndex(const UNICODEGLYPH *a, const UNICODEGLYPH *b)
|
||||||
|
@ -965,10 +969,17 @@ BOOL PSDRV_GetFontMetrics(void)
|
||||||
if (PSDRV_ReadAFMDir (value) == FALSE)
|
if (PSDRV_ReadAFMDir (value) == FALSE)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
PSDRV_IndexGlyphList();
|
PSDRV_IndexGlyphList(); /* So SortFontMetrics will work */
|
||||||
if (SortFontMetrics() == FALSE)
|
if (SortFontMetrics() == FALSE)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
CalcWindowsMetrics();
|
CalcWindowsMetrics();
|
||||||
|
|
||||||
|
#ifdef HAVE_FREETYPE
|
||||||
|
if (PSDRV_GetTrueTypeMetrics() == FALSE)
|
||||||
|
return FALSE;
|
||||||
|
PSDRV_IndexGlyphList();
|
||||||
|
#endif
|
||||||
|
|
||||||
PSDRV_DumpFontList();
|
PSDRV_DumpFontList();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -418,6 +418,7 @@ VOID PSDRV_DrawLine( DC *dc );
|
||||||
INT PSDRV_GlyphListInit();
|
INT PSDRV_GlyphListInit();
|
||||||
GLYPHNAME *PSDRV_GlyphName(LPCSTR szName);
|
GLYPHNAME *PSDRV_GlyphName(LPCSTR szName);
|
||||||
VOID PSDRV_IndexGlyphList();
|
VOID PSDRV_IndexGlyphList();
|
||||||
|
BOOL PSDRV_GetTrueTypeMetrics();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,610 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* TrueType font-related functions for Wine PostScript driver. Currently just
|
||||||
|
* uses FreeType to read font metrics.
|
||||||
|
*
|
||||||
|
* Copyright 2001 Ian Pilcher
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_FREETYPE
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
|
||||||
|
#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 /* HAVE_FREETYPE */
|
|
@ -123,6 +123,9 @@
|
||||||
/* Define if we have CUPS */
|
/* Define if we have CUPS */
|
||||||
#undef HAVE_CUPS
|
#undef HAVE_CUPS
|
||||||
|
|
||||||
|
/* Define if FreeType 2 is installed */
|
||||||
|
#undef HAVE_FREETYPE
|
||||||
|
|
||||||
/* Define if we have 64 bit file offsets */
|
/* Define if we have 64 bit file offsets */
|
||||||
#undef HAVE_OFF64_T
|
#undef HAVE_OFF64_T
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,9 @@
|
||||||
/* Define if we have CUPS */
|
/* Define if we have CUPS */
|
||||||
#undef HAVE_CUPS
|
#undef HAVE_CUPS
|
||||||
|
|
||||||
|
/* Define if FreeType 2 is installed */
|
||||||
|
#undef HAVE_FREETYPE
|
||||||
|
|
||||||
/* Define if we have 64 bit file offsets */
|
/* Define if we have 64 bit file offsets */
|
||||||
#undef HAVE_OFF64_T
|
#undef HAVE_OFF64_T
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue