Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2235 lines
67 KiB

/******************************Module*Header*******************************\
* Module Name: fdcvt.c
*
* ifi interface calls, file loading and file conversions.
*
* Created: 22-Oct-1990 13:33:55
* Author: Bodin Dresevic [BodinD]
*
* Copyright (c) 1990 Microsoft Corporation
\**************************************************************************/
#include "fd.h"
#include "ctype.h"
#include "exehdr.h"
#include <string.h>
#if DBG
unsigned gflBmfdDebug = 0;
#define BMFD_DEBUG_DUMP_HEADER 1
typedef VOID (*VPRINT) (char*,...);
VOID vDumpFontHeader(PRES_ELEM, VPRINT);
#endif
// This points to the base of our list of FD_GLYPHSETS
CP_GLYPHSET *gpcpGlyphsets = NULL;
/******************************Public*Routine******************************\
* BmfdQueryFontCaps
*
* Effects: returns the capabilities of this driver.
* Only mono bitmaps are supported.
*
* History:
* 27-Nov-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
LONG BmfdQueryFontCaps(ULONG culCaps, PULONG pulCaps)
{
ASSERTGDI(culCaps == 2, "ERROR why would the engine call us like this");
if (culCaps < 2)
return(0L);
pulCaps[0] = 2L;
//
// 1 bit per pel bitmaps only are supported
//
pulCaps[1] = QC_1BIT;
return(2L);
}
/******************************Public*Routine******************************\
* BmfdUnloadFontFile(HFF hff)
*
* Frees the resources that have been loced allocated by BmfdLoadFontFile
* BmfdLoadFontResData
*
* History:
* 15-Nov-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL
BmfdUnloadFontFile(
HFF hff
)
{
FACEINFO *pfai, *pfaiTooFar;
ASSERTGDI(hff, "BmfdUnloadFontFile, hff\n");
// check the reference count, if not 0 (font file is still
// selected into a font context) we have a problem
ASSERTGDI(PFF(hff)->cRef == 0L, "cRef: did not update links properly\n");
// free the memory associated with all converted files
pfai = PFF(hff)->afai;
pfaiTooFar = pfai + PFF(hff)->cFntRes;
EngAcquireSemaphore(ghsemBMFD);
while (pfai < pfaiTooFar)
{
vUnloadGlyphset(&gpcpGlyphsets, pfai->pcp);
pfai += 1;
}
EngReleaseSemaphore(ghsemBMFD);
// free memory associated with this FONTFILE object,
VFREEMEM(hff);
return(TRUE);
}
/******************************Public*Routine******************************\
*
* FSHORT fsSelectionFlags(PBYTE ajHdr)
*
* Effects: compute fsSelection field of the ifimetrics
*
* History:
* 13-May-1991 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
FSHORT
fsSelectionFlags(
PBYTE ajHdr
)
{
FSHORT fsSelection = 0;
if (ajHdr[OFF_Italic])
fsSelection |= FM_SEL_ITALIC;
if (ajHdr[OFF_Underline])
fsSelection |= FM_SEL_UNDERSCORE;
if (ajHdr[OFF_StrikeOut])
fsSelection |= FM_SEL_STRIKEOUT;
#ifdef DEBUG_ITALIC
DbgPrint("It = %ld, Str = %ld, Und = %ld, Asc = %ld\n",
(ULONG)ajHdr[OFF_Italic],
(ULONG)ajHdr[OFF_StrikeOut],
(ULONG)ajHdr[OFF_Underline],
(ULONG)sMakeSHORT((PBYTE)&ajHdr[OFF_Ascent])
);
#endif // DEBUG_ITALIC
// the following line is somewhat arbitrary, we set the FM_SEL_BOLD
// flag iff weight is > FW_NORMAL (400). we will not allow emboldening
// simulation on the font that has this flag set
if (usMakeUSHORT((PBYTE)&ajHdr[OFF_Weight]) > FW_NORMAL)
fsSelection |= FM_SEL_BOLD;
return(fsSelection);
}
/******************************Public*Routine******************************\
*
* vAlignHdrData
*
* Effects: packs header data into dword alligned structure
*
* History:
* 29-Oct-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
VOID
vAlignHdrData(
PCVTFILEHDR pcvtfh,
PRES_ELEM pre
)
{
PBYTE ajHdr = (PBYTE)pre->pvResData;
#ifdef DUMPCALL
DbgPrint("\nvAlignHdrData(" );
DbgPrint("\n PCVTFILEHDR pcvtfh = %-#8lx", pcvtfh );
DbgPrint("\n PRES_ELEM pre = %-#8lx", pre );
DbgPrint("\n )\n" );
#endif
/******************************************************/
/**/ #if DBG /**/
/**/ if (gflBmfdDebug & BMFD_DEBUG_DUMP_HEADER) /**/
/**/ vDumpFontHeader(pre, (VPRINT) DbgPrint); /**/
/**/ #endif /**/
/******************************************************/
// zero out the whole structure before doing anything
RtlZeroMemory(pcvtfh, sizeof(CVTFILEHDR));
// The iVersion only had length of 2 bytes in the original struct
pcvtfh->iVersion = usMakeUSHORT((PBYTE)&ajHdr[OFF_Version]);
pcvtfh->chFirstChar = ajHdr[OFF_FirstChar ];
pcvtfh->chLastChar = ajHdr[OFF_LastChar ];
pcvtfh->chDefaultChar = ajHdr[OFF_DefaultChar];
pcvtfh->chBreakChar = ajHdr[OFF_BreakChar ];
pcvtfh->cy = usMakeUSHORT((PBYTE)&ajHdr[OFF_PixHeight]);
#ifdef FE_SB // vAlignHdrData():Get DBCS character's width
pcvtfh->usCharSet = (USHORT) ajHdr[OFF_CharSet];
if( !IS_ANY_DBCS_CHARSET( pcvtfh->usCharSet ) )
#endif // FE_SB
{
// Fri 29-Apr-1994 07:11:06 by Kirk Olynyk [kirko]
//
// There are some buggy font files that are fixed pitch but
// have a MaxWidth greater than the fixed pitch width
// e.g. "Crosstalk IBMPC Fonts v2.0". We check for the
// disparity here. If the font is fixed pitch, as indicated
// by a non zero value of PixWidth, and the average width
// is equal to the fixed pitch width, then the maximum
// pixel width (MaxWidth) is set equal to the PixWidth.
// If the MaxWidth value was correct, then this piece
// of code puts in a bad value for the maxiumum width.
// But this will be fixed! The calling sequences of
// interest are:
//
// bConverFontRes() calls bVerifyFNT() calls vAlignHdrData()
//
// then later in bConvertFontRes()
//
// bConverFontRes() calls vCheckOffsetTable()
//
// It is vCheckOffsetTabl() that would correct
// the maximum pixel if it was incorrectly set here
USHORT usPixWidth = usMakeUSHORT(ajHdr + OFF_PixWidth);
USHORT usAvgWidth = usMakeUSHORT(ajHdr + OFF_AvgWidth);
USHORT usMaxWidth = usMakeUSHORT(ajHdr + OFF_MaxWidth);
if (usPixWidth && usPixWidth == usAvgWidth)
usMaxWidth = usPixWidth;
pcvtfh->usMaxWidth = usMaxWidth;
#ifdef FE_SB // vAlignHdrData():Init DBCS width 0 for non DBCS font.
pcvtfh->usDBCSWidth = 0;
#endif // FE_SB
}
#ifdef FE_SB // vAlignHdrData():Get DBCS character's width
else
{
// usMaxWidth specifies DBCS width in 3.0J and 3.1J font width of double byte
// character let keep this value, because pcvtfh->usMaxWidth might be change in
// vCheckOffsetTable()
pcvtfh->usDBCSWidth = usMakeUSHORT(ajHdr + OFF_MaxWidth);
pcvtfh->usMaxWidth = usMakeUSHORT(ajHdr + OFF_MaxWidth);
}
#endif // FE_SB
if (pcvtfh->iVersion == 0x00000200)
pcvtfh->dpOffsetTable = OFF_OffTable20;
else if (pcvtfh->iVersion == 0x00000300)
pcvtfh->dpOffsetTable = OFF_OffTable30;
else
pcvtfh->dpOffsetTable = -1; // will generate error
}
/******************************Public*Routine******************************\
* BOOL bDbgPrintAndFail(PSZ psz)
*
* History:
* 06-Dec-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
#if DBG
BOOL
bDbgPrintAndFail(
PSZ psz
)
{
DONTUSE(psz);
//#ifdef DEBUGFF
DbgPrint(psz);
//#endif
return(FALSE);
}
#else
#define bDbgPrintAndFail(psz) FALSE
#endif
BOOL
bVerifyFNTQuick(
PRES_ELEM pre
)
{
#ifdef DUMPCALL
DbgPrint("\nbVerifyResource(" );
DbgPrint("\n PCVTFILEHDR pcvtfh = %-#8lx", pcvtfh);
DbgPrint("\n PRES_ELEM pre = %-#8lx", pre );
DbgPrint("\n )\n" );
#endif
PBYTE ajHdr = (PBYTE)pre->pvResData;
USHORT usVersion;
if (pre->cjResData < OFF_OffTable20)
return(bDbgPrintAndFail("BMFD! resource size too small for OFF_OffTable20\n")); // supported.
if ((READ_WORD(&ajHdr[OFF_Type]) & TYPE_VECTOR)) // Vector bit has to
return(FALSE); // we expect to hit this line on vector fonts
usVersion = READ_WORD(&ajHdr[OFF_Version]);
if ((usVersion != 0x0200) && // The only version
(usVersion != 0x0300) ) // The only version
return(FALSE); // we hit that one too on vector fonts
if ((usVersion == 0x0300) && (pre->cjResData < OFF_OffTable30))
return(bDbgPrintAndFail("BMFD! resource size too small for OFF_OffTable30\n")); // supported.
return TRUE;
}
/******************************Public*Routine******************************\
* bVerifyResource
*
* Effects: CHECK whether header contains file info which corresponds to
* the raster font requirements, go into the file and check
* the consistency of the header data
*
* History:
* 30-Oct-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL
bVerifyResource(
PCVTFILEHDR pcvtfh,
PRES_ELEM pre
)
{
#ifdef DUMPCALL
DbgPrint("\nbVerifyResource(" );
DbgPrint("\n PCVTFILEHDR pcvtfh = %-#8lx", pcvtfh);
DbgPrint("\n PRES_ELEM pre = %-#8lx", pre );
DbgPrint("\n )\n" );
#endif
PBYTE ajHdr = (PBYTE)pre->pvResData;
ULONG cjSize;
LONG dpBits = lMakeLONG((PBYTE)&ajHdr[OFF_BitsOffset]);
SHORT sAscent;
ASSERTGDI(
((READ_WORD(&ajHdr[OFF_Version]) == 0x0200) || (READ_WORD(&ajHdr[OFF_Version]) == 0x0300)),
"BMFD!wrong iVersion for bitmap font\n"
);
if (pcvtfh->iVersion == 0x00000200)
if (dpBits > SEGMENT_SIZE)
return(bDbgPrintAndFail("BMFD!dpBits \n")); // Bits Offset Not Ok
// file size must be <= than the size of the view
cjSize = ulMakeULONG(ajHdr + OFF_Size);
if (cjSize > pre->cjResData)
{
cjSize = pre->cjResData; // no offset can be bigger than this
}
sAscent = sMakeSHORT((PBYTE)&ajHdr[OFF_Ascent]);
if (abs(sAscent) > (SHORT)pcvtfh->cy)
return(bDbgPrintAndFail("BMFD!sAscent \n")); // Ascent Too Big
if (sMakeSHORT((PBYTE)&ajHdr[OFF_ExtLeading]) < 0)
return(bDbgPrintAndFail("BMFD!ExtLeading \n")); // Ext Lead Not Ok;
#if DBG
// CHECK fsType field, if vector type, this would have been caught by
// bVerifyFNTQuick
ASSERTGDI(
(READ_WORD(&ajHdr[OFF_Type]) & TYPE_VECTOR) == 0,
"bmfd!this mustn't have been a vector font\n"
);
if (sMakeSHORT((PBYTE)&ajHdr[OFF_IntLeading]) < 0)
DbgPrint(
"bmfd warning: possibly bad font file - sIntLeading = %ld\n\n",
(LONG)sMakeSHORT((PBYTE)&ajHdr[OFF_IntLeading])
);
#endif
if (sMakeSHORT((PBYTE)&ajHdr[OFF_IntLeading]) > sAscent)
return(bDbgPrintAndFail("BMFD!IntLeading too big\n")); // Int Lead Too Big;
// check consistency of character ranges
if (pcvtfh->chFirstChar > pcvtfh->chLastChar)
return(bDbgPrintAndFail("BMFD!FirstChar\n")); // this can't be
// default and break character are given relative to the FirstChar,
// so that the actual default (break) character is given as
// chFirst + chDefault(Break)
if ((UCHAR)(pcvtfh->chDefaultChar + pcvtfh->chFirstChar) > pcvtfh->chLastChar)
{
// here we will do something which never should have been done if
// win 3.0 did any parameter validation on loading fonts .
// This is done in order not to reject fonts that have only Def and Break
// chars messed up, but everything else is ok. Example of such shipped
// fonts are some samna corp. fonts that come with AmiPro application.
// Their Def char is the absolute value rather than value relative to
// the first char in the font. This is of course the bug in the font
// files, but since win30 does not reject these files, we must not do that
// either.
#if DBG
DbgPrint("bmfd!_bVerifyResource: warning -- bogus Default char = %ld\n", (ULONG)pcvtfh->chDefaultChar);
#endif
if ((pcvtfh->chDefaultChar >= pcvtfh->chFirstChar) && (pcvtfh->chDefaultChar <= pcvtfh->chLastChar))
{
// attempt to fix the problem stemming from the bug in the font file
pcvtfh->chDefaultChar -= pcvtfh->chFirstChar;
}
else
{
// this definitely is not a sensible font file, but samna provided us
// withone such font as well
pcvtfh->chDefaultChar = 0;
}
}
if ((UCHAR)(pcvtfh->chBreakChar + pcvtfh->chFirstChar) > pcvtfh->chLastChar)
{
// here we will do something which never should have been done if
// win 3.0 did any parameter validation on loading fonts .
// This is done in order not to reject fonts that have only Def and Break
// chars messed up, but everything else is ok. Example of such shipped
// fonts are some samna corp. fonts that come with AmiPro application.
// Their Break char is the absolute value rather than value relative to
// the first char in the font. This is of course the bug in the font
// files, but since win30 does not reject these files, we must not do that
// either.
#if DBG
DbgPrint("bmfd!_bVerifyResource: warning bogus Break char = %ld\n", (ULONG)pcvtfh->chBreakChar);
#endif
if ((pcvtfh->chBreakChar >= pcvtfh->chFirstChar) && (pcvtfh->chBreakChar <= pcvtfh->chLastChar))
{
// attempt to fix the problem stemming from the bug in the font file
pcvtfh->chBreakChar -= pcvtfh->chFirstChar;
}
else
{
// this definitely is not a sensible font file, but samna provided us
// with one such font as well
pcvtfh->chBreakChar = 0;
}
}
// offset to the offset table
ASSERTGDI((pcvtfh->dpOffsetTable & 1) == 0, "dpOffsetTable is not even\n");
if ((pcvtfh->dpOffsetTable != OFF_OffTable20) &&
(pcvtfh->dpOffsetTable != OFF_OffTable30))
return(bDbgPrintAndFail("BMFD!dpOffsetTable \n"));
// make sure that the first offset in the offset table is equal to dpBits,
// this is an internal consistency check of the font, also verify that
// all offsets are smaller than cjSize
{
PBYTE pjFirstOffset = (PBYTE)pre->pvResData + pcvtfh->dpOffsetTable + 2;
UINT cGlyphs = pcvtfh->chLastChar - pcvtfh->chFirstChar + 1;
PBYTE pjOffsetEnd;
if (pcvtfh->iVersion == 0x00000200)
{
// in 2.0 offsets are 16 bit
if (dpBits != (PTRDIFF)(*((PUSHORT)pjFirstOffset)))
return(bDbgPrintAndFail("BMFD!2.0 pjFirstOffset \n"));
if (pcvtfh->dpOffsetTable + 2 + (cGlyphs * 4) > pre->cjResData)
return(bDbgPrintAndFail("BMFD!2.0 OffsetTable out of file \n"));
// 4 is sizeof(TYPE2TABLE) as defined and used in fdquery.c
pjOffsetEnd = pjFirstOffset + cGlyphs * 4;
for ( ; pjFirstOffset < pjOffsetEnd; pjFirstOffset += 4)
{
if ((ULONG)READ_WORD(pjFirstOffset) > cjSize)
return bDbgPrintAndFail("BMFD!invalid offset in 2.0 bm font\n");
}
}
else // 3.0 guarantedd by the very first check
{
// in 3.0 offsets are 32 bit
if (dpBits != (PTRDIFF)ulMakeULONG(pjFirstOffset))
return(bDbgPrintAndFail("BMFD!3.0 pjFirstOffset \n"));
if (pcvtfh->dpOffsetTable + 2 + (cGlyphs * 6) > pre->cjResData)
return(bDbgPrintAndFail("BMFD!3.0 OffsetTable out of file \n"));
// 6 is sizeof(TYPE3TABLE) as defined and used in fdquery.c
pjOffsetEnd = pjFirstOffset + cGlyphs * 6;
for ( ; pjFirstOffset < pjOffsetEnd; pjFirstOffset += 6)
{
if (READ_DWORD(pjFirstOffset) > cjSize)
return bDbgPrintAndFail("BMFD!invalid offset in 3.0 bm font\n");
}
}
}
// check 3.0 fields if necessary
if (pcvtfh->iVersion == 0x00000300)
{
FSHORT fsFlags = usMakeUSHORT ((PBYTE)&ajHdr[OFF_Flags]);
if (fsFlags & (DFF_16COLOR | DFF_256COLOR | DFF_RGBCOLOR))
return(bDbgPrintAndFail("BMFD!Flags: Do not support color fonts\n"));
if (lMakeLONG((PBYTE)pre->pvResData + OFF_ColorPointer))
return(bDbgPrintAndFail("BMFD!dpColor: Do not support color fonts\n"));
}
return(TRUE);
}
/******************************Public*Routine******************************\
* bVerifyFNT
*
* Combine the two routines into a single one
*
* History:
* 27-Jan-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL
bVerifyFNT(
PCVTFILEHDR pcvtfh,
PRES_ELEM pre
)
{
#ifdef DUMPCALL
DbgPrint("\nbVerifyFNT(" );
DbgPrint("\n PCVTFILEHDR pcvtfh = %-#8lx", pcvtfh );
DbgPrint("\n PRES_ELEM pre = %-#8lx", pre );
DbgPrint("\n )\n" );
#endif
// read nonalligned header data at the top of the view into an alligned structure
vAlignHdrData(pcvtfh,pre);
// make sure that the data matches requirements of a windows bitmap font
return(bVerifyResource(pcvtfh,pre));
}
/******************************Public*Routine******************************\
*
* BOOL bBmfdLoadFont // forward declaration
*
* Loads an *.fon or an *.fnt file,
* returns handle to a fonfile object if successfull
*
* History:
* 27-Jan-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL bBmfdLoadFont // forward declaration
(
HFF iFile,
PBYTE pvView,
ULONG cjView,
ULONG iType,
HFF *phff
)
{
PFONTFILE pff;
ULONG cjff;
WINRESDATA wrd;
RES_ELEM re;
ULONG ifnt;
ULONG cjDescription; // size of the desctiption string (in bytes)
PTRDIFF dpwszDescription; // offset to the description string
CHAR achDescription[256]; // this is the max length of string
// in the 16-bit EXE format.
ULONG cjBMFDIFIMETRICS;
#ifdef FE_SB // hffLoadFont()
ULONG cFontResIncludeVert;
#endif // FE_SB
ULONG dpIFI;
IFIMETRICS *pifi;
*phff = (HFF)NULL;
#ifdef DUMPCALL
DbgPrint("\nbBmfdLoadFont(" );
DbgPrint("\n ULONG iType = %-#8lx" );
DbgPrint("\n )\n" );
#endif
ASSERTGDI((iType == TYPE_DLL16) || (iType == TYPE_FNT) || ((iType == TYPE_EXE)),
"bmfd!bBmfdLoadFont(): unknown iType\n");
// If .FON format, there are possibly multiple font resources. Handle it.
if (iType == TYPE_DLL16)
{
if (!bInitWinResData(pvView,cjView,&wrd))
{
return FALSE;
}
}
// Otherwise, if .FNT format, the current file view may be used.
else // fnt
{
re.pvResData = pvView;
re.dpResData = 0;
re.cjResData = cjView;
re.pjFaceName = NULL; // get the face name from the FNT resource
wrd.cFntRes = 1;
}
// If .FON format, retrieve the description string (because we won't have
// the mapped file view later and therefore cannot search for it later).
#ifdef FE_SB // hffLoadFont()
// We assume font all font resource is SHIFT_JIS font. We prepare room for Vertical font
cjff = offsetof(FONTFILE,afai) + ( wrd.cFntRes * 2 ) * sizeof(FACEINFO);
#else
cjff = offsetof(FONTFILE,afai) + wrd.cFntRes * sizeof(FACEINFO);
#endif
dpwszDescription = 0; // no description string, use Facename later
cjDescription = 0;
if ((iType == TYPE_DLL16) && bDescStr(pvView, cjView, achDescription))
{
dpwszDescription = cjff;
cjDescription = (strlen(achDescription) + 1) * sizeof(WCHAR);
cjff += cjDescription;
}
// remember where the first ifimetrics goes
dpIFI = cjff = ALIGN_UP( cjff, PVOID );
// compute the total amount of memory needed for the ifimetrics and everything
// else:
for (ifnt = 0L; ifnt < wrd.cFntRes; ifnt++)
{
if (iType == TYPE_DLL16)
{
if (!bGetFntResource(&wrd,ifnt,&re))
return FALSE;
}
// do a preliminary check on the resource, before doing a thorough one
if (!bVerifyFNTQuick(&re))
return FALSE;
if (!bBMFDIFIMETRICS(pvView, cjView, NULL, &re, &cjBMFDIFIMETRICS))
return FALSE;
#ifdef FE_SB
cjff += ( cjBMFDIFIMETRICS * 2 );
#else
cjff += cjBMFDIFIMETRICS;
#endif
}
// Allocate a FONTFILE of the appropriate size from the handle manager.
if ((*phff = hffAlloc(cjff)) == HFF_INVALID)
{
SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
RETURN("bmfd!bBmfdLoadFont(): memory allocation error\n", FALSE);
}
pff = PFF(*phff);
// Init fields of pff structure
pff->ident = ID_FONTFILE;
pff->fl = 0;
pff->iType = iType;
pff->iFile = iFile; // will be needed at unload time
pff->cFntRes = wrd.cFntRes;
pff->cjDescription = cjDescription;
pff->dpwszDescription = dpwszDescription;
// Convert each of the font resources (RES_ELEM) to a CVTRESDATA and a
// (set of) FACEDATA.
pifi = (IFIMETRICS *)((PBYTE)pff + dpIFI);
#ifdef FE_SB // bBmfdLoadFont()
// We have to compute strict font face count include simulated @face
// ifnt = Physical font counter
// cFontResIncludeVert = FACEINFO structure counter
cFontResIncludeVert = 0;
for (ifnt = 0L; ifnt < wrd.cFntRes; ifnt++)
{
// At first We process for nomal face font
if (iType == TYPE_DLL16)
{
if (!bGetFntResource(&wrd,ifnt,&re))
{
VFREEMEM(*phff);
*phff = (HFF)NULL;
return FALSE;
}
}
pff->afai[cFontResIncludeVert].re = re; // remember this for easier access later
pff->afai[cFontResIncludeVert].bVertical = FALSE;
pff->afai[cFontResIncludeVert].pifi = pifi;
if (!bConvertFontRes(pvView, cjView, &re, &pff->afai[cFontResIncludeVert]))
{
#ifdef DBG_NTRES
WARNING("bmfd!hffLoadFont(): file format conversion failed\n");
#endif // DBG_NTRES
VFREEMEM(*phff);
*phff = (HFF)NULL;
return FALSE;
}
// Count Nomal face font
cFontResIncludeVert ++;
// Point it to next room
pifi = (IFIMETRICS *)((PBYTE)pifi + pifi->cjThis);
//
// Check this font resource's Charset is some DBCS charset. If it is so , Set up
// Vertical font stuff. Or not so. Increment counter.
//
// if the font is for DBCS font, usDBCSWidth is not be zero, the value is setted
// above bConvertFontRes().
//
if( (pff->afai[cFontResIncludeVert - 1].cvtfh.usDBCSWidth) != 0 )
{
// Vertical Writting use the same font at SBCS CodeArea
pff->afai[cFontResIncludeVert].re = re;
// Vertical Writting use the different font at DBCS CoreArea
pff->afai[cFontResIncludeVert].bVertical = TRUE;
pff->afai[cFontResIncludeVert].pifi = pifi;
// Convert font resource and setup CVTFILEHDR and IFIMETRICS
if ( !bConvertFontRes(pvView, cjView, &re, &pff->afai[cFontResIncludeVert]))
{
#ifdef DBG_NTRES
WARNING("bmfd!hffLoadFont(): file format conversion failed at Vertical font\n");
#endif // DBG_NTRES
VFREEMEM(*phff);
*phff = (HFF)NULL;
return FALSE;
}
// Count Vertical face font
cFontResIncludeVert ++;
// Point it to next room
pifi = (IFIMETRICS *)((PBYTE)pifi + pifi->cjThis);
}
}
// We have strictly font resource count include simulated Vertical font now
// Reset font resource count in FONTFILE structure
pff->cFntRes = cFontResIncludeVert;
#else
for (ifnt = 0L; ifnt < wrd.cFntRes; ifnt++)
{
if (iType == TYPE_DLL16)
{
if (!bGetFntResource(&wrd,ifnt,&re))
{
VFREEMEM(*phff);
*phff = (HFF)NULL;
return FALSE;
}
}
pff->afai[ifnt].re = re; // remember this for easier access later
pff->afai[ifnt].pifi = pifi; // remember this for easier access later
if (!bConvertFontRes(pvView, cjView, &re, &pff->afai[ifnt]))
{
#ifdef DBG_NTRES
WARNING("bmfd!bBmfdLoadFont(): file format conversion failed\n");
#endif // DBG_NTRES
VFREEMEM(*phff);
*phff = (HFF)NULL;
return FALSE;
}
pifi = (IFIMETRICS *)((PBYTE)pifi + pifi->cjThis);
}
#endif
// If we found a description string, store it in the FONTFILE.
if (cjDescription != 0)
vToUNICODEN((PWSZ) ((PBYTE) pff + dpwszDescription), cjDescription/sizeof(WCHAR), achDescription, cjDescription/sizeof(WCHAR));
// Initialize the rest.
pff->cRef = 0;
return TRUE;
}
/******************************Public*Routine******************************\
* jFamilyType(FSHORT fsPitchAndFamily)
*
* computes jFamilyType field of the panose structure
*
* History:
* 19-Dec-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BYTE
jFamilyType(
FSHORT fsPitchAndFamily
)
{
BYTE j;
if (fsPitchAndFamily & FF_DONTCARE)
j = PAN_ANY;
else if (fsPitchAndFamily & FF_SCRIPT)
j = PAN_FAMILY_SCRIPT;
else if (fsPitchAndFamily & FF_DECORATIVE)
j = PAN_FAMILY_DECORATIVE;
else
{
j = PAN_FAMILY_TEXT_DISPLAY;
}
return(j);
}
/******************************Public*Routine******************************\
* bConvertFontRes
*
* format of the converted file:
*
* converted header on the top, followed by array of IFIMETRICS structures,
* followed by the table of offsets to GLYPHDATA structures for individual
* glyphs, followed by an array of GLYPHDATA structures themselves
*
* Warnings:
*
* History:
* January 2002 -by- Jay Krell [JayKrell]
* range check memory mapped i/o
* 13-Nov-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL
bConvertFontRes(
PVOID pvView,
SIZE_T cjView,
PRES_ELEM pre, // IN
FACEINFO *pfai // OUT
)
{
BOOL bResult;
bResult = FALSE;
#ifdef DUMPCALL
DbgPrint("\nbConverFontRes(\n" );
DbgPrint(" PRES_ELEM pre = %-#8lx\n",pre );
DbgPrint(" FACEINFO *pfai = %-#8lx\n",pfai);
DbgPrint(" );\n\n" );
#endif
// make sure that the data matches requirements of a windows bitmap font
// Note: bVerifyFNT() does more than just look at the font -- it does
// part of the conversion by copying the data to the CVFILEHDR
// "converted file header"
//
if(!bVerifyFNT(&pfai->cvtfh,pre))
{
goto Exit;
}
ASSERTGDI(pfai->cvtfh.dpOffsetTable != -1L, "BMFD!bConvertFontRes(): could not align header\n");
// compute the size of the IFIMETRICS structure that is followed by
// FamilyName, FaceName and UniqueName UNICODE strings and simulations
if (!bBMFDIFIMETRICS(pvView, cjView, &pfai->cvtfh, pre, NULL))
{
goto Exit;
}
// compute the size of the converted file to be created, fix bugs in file header
vCheckOffsetTable(&pfai->cvtfh, pre);
// calucate pfai->iDefFace
vDefFace(pfai,pre);
// compute glyph set that corresponds to this resource:
EngAcquireSemaphore(ghsemBMFD);
pfai->pcp = pcpComputeGlyphset(&gpcpGlyphsets,
(UINT) pfai->cvtfh.chFirstChar,
(UINT) pfai->cvtfh.chLastChar,
((PBYTE)pre->pvResData)[OFF_CharSet]);
EngReleaseSemaphore(ghsemBMFD);
if (pfai->pcp == NULL)
{
// If we fail it should be because of we are out of memory.
SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
WARNING("BMFD!bConvertFontRes(): memory allocation error\n");
goto Exit;
}
// fill the ifimetrics
vBmfdFill_IFIMETRICS(pfai,pre);
bResult = TRUE;
Exit:
#if DBG
if (!bResult)
{
NotifyBadFont("WIN32K: %s failing\n", __FUNCTION__);
}
#endif
return bResult;
}
/******************************Public*Routine******************************\
* bBMFDIFIMETRICS
*
* Effects: returns the size cjIFI of IFIMETRICS struct, with appended strings
* caches the lengths of these strings,pszFamilyName, and cjIFI
* for later use by vBmfdFill_IFIMETRICS
* Warnings:
*
* History:
* January 2002 -by- Jay Krell [JayKrell]
* range check memory mapped i/o
* 20-Oct-1992 -by- Kirk Olynyk [kirko]
* The IFIMETRICS structure has changed. The effect of the change upon
* this procedure is to allocate room for the new simulation structure
* FONTDIFF which informs GDI of the available simulations.
* 20-Nov-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL
bBMFDIFIMETRICS(
PVOID pvView,
SIZE_T cjView,
PCVTFILEHDR pcvtfh OPTIONAL,
PRES_ELEM pre,
OUT PULONG pcjIFIOut OPTIONAL
)
{
// face name lives in the original file
ULONG cSims;
ULONG cjIFI;
ULONG cjFaceName;
PSZ pszFaceName;
BOOL bResult;
SIZE_T pszFaceNameLength;
bResult = FALSE;
if (pcjIFIOut != NULL)
{
*pcjIFIOut = 0;
}
if( pre->pjFaceName == NULL )
{
// get facename from FNT resource for non 16bit resource files
pszFaceName = (PSZ)((PBYTE)pre->pvResData +
lMakeLONG((PBYTE)pre->pvResData + OFF_Face));
}
else
{
// otherwise get facename from the FONTDIR resource for win 3.1
// compatibility reasons
pszFaceName = pre->pjFaceName;
}
if (!bMappedViewStrlen(pvView, cjView, pszFaceName, &pszFaceNameLength))
{
goto Exit;
}
// 1 is added to the length of a string in WCHAR's
// so as to allow for the terminating zero character, the number of
// WCHAR's is then multiplied by 2 to get the corresponding number of bytes,
// which is then rounded up to a DWORD boundary for faster access
#ifdef FE_SB // VERTICAL:cjIFIMETRICS(): make room for '@'
cjFaceName = ALIGN4(sizeof(WCHAR) * (pszFaceNameLength + 1 + 1));
#else
cjFaceName = ALIGN4(sizeof(WCHAR) * (pszFaceNameLength + 1));
#endif
// the full size of IFIMETRICS is the size of the structure itself followed by
// the appended strings AND the 3 FONTDIFF structures corresponding to the
// BOLD, ITALIC, and BOLD_ITALIC simulations.
cjIFI = sizeof(IFIMETRICS) + cjFaceName;
if (cSims = (cFacesRes(pre) - 1))
{
cjIFI += sizeof(FONTSIM) + cSims * sizeof(FONTDIFF);
}
cjIFI = ALIGN_UP( cjIFI, PVOID );
if (pcvtfh)
{
// cache the lengths of these strings for later use
pcvtfh->cjFaceName = cjFaceName;
pcvtfh->cjIFI = cjIFI;
}
// make sure that the result is a multiple of ULONG size, otherwise we may
// have a problem when making arrays of IFIMETRICS structures
ASSERTGDI((cjIFI & 3L) == 0L, "ifi is not DWORD alligned\n");
if (pcjIFIOut != NULL)
{
*pcjIFIOut = cjIFI;
}
bResult = TRUE;
Exit:
#if DBG
if (!bResult)
{
NotifyBadFont("WIN32K: %s failing\n", __FUNCTION__);
}
#endif
return bResult;
}
/******************************Public*Routine******************************\
* bNonZeroRow
*
* History:
* 21-Jun-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL
bNonZeroRow(
PBYTE pjRow,
ULONG cy,
ULONG cjWidth
)
{
ULONG ij; // index into a byte
for (ij = 0; ij < cjWidth; ij++, pjRow += cy)
{
if (*pjRow)
{
return(TRUE);
}
}
return(FALSE); // zero scan
}
/******************************Public*Routine******************************\
* vFindTAndB
*
* computes top and bottom of the ink using the bits in the raw fnt format
*
* History:
* 21-Jun-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
VOID
vFindTAndB(
PBYTE pjBitmap, // pointer to the bitmap in *.fnt column format
ULONG cx,
ULONG cy,
ULONG *pyTopIncMin,
ULONG *pyBottomExcMax
)
{
ULONG cjWidth = CJ_SCAN(cx); // # of bytes in row of the bitmap in the *.fnt format
PBYTE pjRow;
PBYTE pjRowEnd;
#ifdef DUMPCALL
DbgPrint("\nvFindTAndB(\n" );
DbgPrint(" PBYTE pjBitmap = %-#8lx\n",pjBitmap );
DbgPrint(" ULONG cx = %d\n",cx );
DbgPrint(" ULONG cy = %d\n",cy );
DbgPrint(" ULONG *pyTopIncMin = %-#8lx\n",pyTopIncMin );
DbgPrint(" ULONG *pyBottomExcMax = %-#8lx\n",pyBottomExcMax );
DbgPrint(" );\n\n" );
#endif
/* default them to null in every case to prevent accessing unitialized data
in the case the bitmap is null, or all it's row are filled with zero */
*pyTopIncMin = *pyBottomExcMax = 0;
// case of zero width glyphs
if (!pjBitmap)
{
// no ink at all, out of here
ASSERTGDI(cx == 0, "bmfd, vFindTAndB, cx != 0\n");
return;
}
// real glyphs
for
(
pjRow = pjBitmap, pjRowEnd = pjRow + cy;
pjRow < pjRowEnd;
pjRow++
)
{
if (bNonZeroRow(pjRow, cy, cjWidth))
{
*pyTopIncMin = (ULONG)(pjRow - pjBitmap);
break;
}
}
if (pjRow == pjRowEnd)
{
// no ink at all, out of here
return;
}
// start searhing backwards for the bottom
for
(
pjRow = pjBitmap + (cy - 1);
pjRow >= pjBitmap;
pjRow--
)
{
if (bNonZeroRow(pjRow, cy, cjWidth))
{
*pyBottomExcMax = (ULONG)((pjRow - pjBitmap) + 1); // + 1 for exclusiveness
break;
}
}
ASSERTGDI(*pyTopIncMin <= *pyBottomExcMax, "BMFD!top>bottom\n");
}
/******************************Public*Routine******************************\
* vComputeSpecialChars
*
* Effects:
* compute special characters taking into account character set
* Not quite sure what to do when char set is not ansi. It is really
* to figure out what to do for a "font" where glyph bitmaps
* are pushbuttons etc.
* This routine will clearly blow up when a char set is catacana
* This is char set == 37 (amisym)
*
* History:
* 28-Nov-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
VOID
vComputeSpecialChars(
PCVTFILEHDR pcvtfh,
PWCHAR pwcDefaultChar,
PWCHAR pwcBreakChar
)
{
UCHAR chDefault = pcvtfh->chDefaultChar + pcvtfh->chFirstChar;
UCHAR chBreak = pcvtfh->chBreakChar + pcvtfh->chFirstChar;
// Default and Break chars are given relative to the first chaR
RtlMultiByteToUnicodeN(pwcDefaultChar, sizeof(WCHAR), NULL, &chDefault, 1);
RtlMultiByteToUnicodeN(pwcBreakChar, sizeof(WCHAR), NULL, &chBreak, 1);
}
/******************************Public*Routine******************************\
* vBmfdFill_IFIMETRICS
*
* Effects:
* fills the fields of the IFIMETRICS structure using the info from
* the converted and the original font file and converted file header
*
*
* History:
* Fri 24-Jun-1994 20:30:41 by Kirk Olynyk [kirko]
* Changed the test for pitch to look at PixWidth.
* 20-Oct-92 by Kirk Olynyk [kirko]
* Made changes to be compatible with the new and improved IFIMETRICS
* structure.
* Fri 24-Jan-1992 07:56:16 by Kirk Olynyk [kirko]
* Changed the way EmHeight is calculated.
* Fri 18-Oct-1991 10:36:43 by Kirk Olynyk [kirko]
* Changed the InlineDir, CharRot, CharSlope, and WidthClass
* to be expressed as POINTL's.
* 23-Jul-1991 Gilman Wong [gilmanw]
* Fixed PANOSE numbers for jFamily and jSerifStyle.
* 12-Nov-1990 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
VOID
vBmfdFill_IFIMETRICS(
FACEINFO *pfai,
PRES_ELEM pre
)
{
FWORD fwdHeight;
FONTSIM *pFontSim;
FONTDIFF *pfdiffBold = 0, *pfdiffItalic = 0, *pfdiffBoldItalic = 0;
PANOSE *ppanose;
ULONG cchFaceName;
PBYTE ajHdr = (PBYTE)pre->pvResData;
FWORD sAscent,sIntLeading;
#ifdef FE_SB // vBmfdFill_IFIMETRICS()
BOOL bDBCSFont = (pfai->cvtfh.usDBCSWidth != 0 ? TRUE : FALSE);
#endif // FE_SB
// compute pointers to the various sections of the converted file
PCVTFILEHDR pcvtfh = &pfai->cvtfh;
PIFIMETRICS pifi = pfai->pifi;
// face name lives in the original file, this is the only place pvView is used
PSZ pszFaceName;
// Either grab the facename from the FONTDIR or the FNT resources depending
// on wether or not this is a 16bit font resource.
if( pre->pjFaceName == NULL )
{
pszFaceName = (PSZ)(ajHdr + lMakeLONG((PBYTE)&ajHdr[OFF_Face]));
}
else
{
pszFaceName = pre->pjFaceName;
}
#ifdef DUMPCALL
DbgPrint("\nvBmfdFill_IFIMETRICS(\n" );
DbgPrint(" FACEINFO *pfai = %-#8lx\n", pfai );
DbgPrint(" PRES_ELEM pre = %-#8lx\n", pre );
DbgPrint(" );\n\n" );
#endif
pifi->cjIfiExtra = 0;
//
// the string begins on a DWORD aligned address.
//
pifi->dpwszFaceName = OFFSET_OF_NEXT(DWORD,sizeof(IFIMETRICS));
// face name == family name for bitmap fonts [Win3.0 compatibility]
pifi->dpwszFamilyName = pifi->dpwszFaceName;
//
// these names don't exist, so point to the NULL char [Win3.1 compatibility]
// Note: lstrlen() does not count the terminating NULL.
//
cchFaceName = strlen(pszFaceName);
pifi->dpwszStyleName =
pifi->dpwszFaceName + sizeof(WCHAR) * cchFaceName;
pifi->dpwszUniqueName = pifi->dpwszStyleName;
// copy the strings to their new location. Here we assume that the sufficient
// memory has been allocated
#ifdef FE_SB // vBmfdFill_IFIMETRICS():Add @ to face name
if( pfai->bVertical )
{
vToUNICODEN((PWSZ)((PBYTE)pifi + pifi->dpwszFaceName + sizeof(WCHAR)),
cchFaceName+1, pszFaceName, cchFaceName+1);
// Insert @
*(PWCHAR)((PBYTE)pifi + pifi->dpwszFaceName) = L'@';
}
else
{
#endif // FE_SB
vToUNICODEN((PWSZ)((PBYTE)pifi + pifi->dpwszFaceName), cchFaceName+1, pszFaceName, cchFaceName+1);
#ifdef FE_SB
}
#endif // DBCS_VERT
pifi->cjThis = pcvtfh->cjIFI;
//
// Check to see if simulations are necessary and if they are, fill
// in the offsets to the various simulation fields and update cjThis
// field of the IFIMETRICS structure
//
switch (pfai->iDefFace)
{
case FF_FACE_NORMAL:
case FF_FACE_BOLD:
case FF_FACE_ITALIC:
pifi->dpFontSim =
OFFSET_OF_NEXT(
DWORD,
sizeof(IFIMETRICS) + pcvtfh->cjFaceName
);
pFontSim = (FONTSIM*) ((BYTE*)pifi + pifi->dpFontSim);
switch (pfai->iDefFace)
{
case FF_FACE_NORMAL:
//
// simulations are needed for bold, italic, and bold-italic
//
pFontSim->dpBold =
OFFSET_OF_NEXT(DWORD,sizeof(FONTSIM));
pFontSim->dpItalic =
OFFSET_OF_NEXT(DWORD,pFontSim->dpBold + sizeof(FONTDIFF));
pFontSim->dpBoldItalic =
OFFSET_OF_NEXT(DWORD,pFontSim->dpItalic + sizeof(FONTDIFF));
pfdiffBold =
(FONTDIFF*) ((BYTE*) pFontSim + pFontSim->dpBold);
pfdiffItalic =
(FONTDIFF*) ((BYTE*) pFontSim + pFontSim->dpItalic);
pfdiffBoldItalic =
(FONTDIFF*) ((BYTE*) pFontSim + pFontSim->dpBoldItalic);
break;
case FF_FACE_BOLD:
case FF_FACE_ITALIC:
//
// a simulation is needed for bold-italic only
//
pFontSim->dpBold = 0;
pFontSim->dpItalic = 0;
pFontSim->dpBoldItalic = OFFSET_OF_NEXT(DWORD,sizeof(FONTSIM));
pfdiffBoldItalic =
(FONTDIFF*) ((BYTE*) pFontSim + pFontSim->dpBoldItalic);
break;
default:
RIP("BMFD -- bad iDefFace\n");
}
break;
case FF_FACE_BOLDITALIC:
pifi->dpFontSim = 0;
break;
default:
RIP("vBmfdFill_IFIMETRICS -- bad iDefFace");
}
pifi->jWinCharSet = ajHdr[OFF_CharSet];
// There are two way to determine the pitch of a font.
//
// a) If the low nibble of ajHdr[OFF_Family] is not zero then
// the font is variable pitch otherwise it is fixed
// b) if ajHdr[OFF_PixWidth] is non zero then the font is
// fixed pitch and this is the character width otherwise
// the font is varialble pitch
//
// Under Windows, method b) is used to determine the pitch of
// a font. There exist buggy fonts in which methods a) and
// b) give different answers. An example is found in Issac
// Asimov's "The Ultimate Robot". For the font face "URPalatI"
// method a) indicates that the font is fixed pitch while
// method b) indicates that it is variable. The truth is that
// this font is varialbe pitch. So, we choose method b).
// Of course, if another font gives the correct answer for method
// a) and the incorrect answer for method b) then we will
// look bad.
// Mon 27-Jun-1994 06:58:46 by Kirk Olynyk [kirko]
pifi->jWinPitchAndFamily = ajHdr[OFF_Family] & 0xf0;
pifi->jWinPitchAndFamily |= ajHdr[OFF_PixWidth] ? FIXED_PITCH : VARIABLE_PITCH;
#ifdef MAYBE_NEEDED_FOR_MET
if (ajHdr[OFF_Family] & MONO_FONT)
{
// Have no idea what MONO_FONT is, some new win95 invetion
pifi->jWinPitchAndFamily |= MONO_FONT;
}
#endif
// weight, we have seen files where the weight has been 0 or some other junk
// we replace 400, our mapper would have done it anyway [bodind]
pifi->usWinWeight = usMakeUSHORT((PBYTE)&ajHdr[OFF_Weight]);
if ((pifi->usWinWeight > MAX_WEIGHT) || (pifi->usWinWeight < MIN_WEIGHT))
pifi->usWinWeight = 400;
pifi->flInfo = ( FM_INFO_TECH_BITMAP
| FM_INFO_RETURNS_BITMAPS
| FM_INFO_1BPP
| FM_INFO_INTEGER_WIDTH
| FM_INFO_RIGHT_HANDED
| FM_INFO_INTEGRAL_SCALING
| FM_INFO_NONNEGATIVE_AC
#ifdef FE_SB // vBmfdFill_IFIMETRICS():set FM_INFO_90DEGREE_ROTATIONS flag
| FM_INFO_90DEGREE_ROTATIONS
#endif
);
// we have set it correctly above, we want to make sure that somebody
// is not going to alter that code so as to break the code here
ASSERTGDI(
((pifi->jWinPitchAndFamily & 0xf) == FIXED_PITCH) || ((pifi->jWinPitchAndFamily & 0xf) == VARIABLE_PITCH),
"BMFD!WRONG PITCH \n"
);
#ifdef FE_SB // vBmfdFill_IFIMETRICS():remove FM_INFO_CONSTANT_WIDTH flag
if ((pifi->jWinPitchAndFamily & 0xf) == FIXED_PITCH)
{
if( !bDBCSFont )
pifi->flInfo |= FM_INFO_CONSTANT_WIDTH;
pifi->flInfo |= FM_INFO_OPTICALLY_FIXED_PITCH;
}
// Bmfd treat only FIXED pitch font in full width character, We report this infomation to GRE
// for optimaization
if( bDBCSFont )
{
pifi->flInfo |= FM_INFO_DBCS_FIXED_PITCH;
}
#else
if ((pifi->jWinPitchAndFamily & 0xf) == FIXED_PITCH)
{
pifi->flInfo |= FM_INFO_CONSTANT_WIDTH;
pifi->flInfo |= FM_INFO_OPTICALLY_FIXED_PITCH;
}
#endif
pifi->lEmbedId = 0;
pifi->fsSelection = fsSelectionFlags(ajHdr);
//
// The choices for fsType are FM_TYPE_LICENSED and FM_READONLY_EMBED
// These are TrueType things and do not apply to old fashioned bitmap
// fonts.
//
pifi->fsType = 0;
sIntLeading = sMakeSHORT((PBYTE)&ajHdr[OFF_IntLeading]);
pifi->fwdUnitsPerEm = (sIntLeading > 0) ?
(FWORD)pcvtfh->cy - sIntLeading : (FWORD)pcvtfh->cy;
pifi->fwdLowestPPEm = 0;
sAscent = (FWORD)sMakeSHORT((PBYTE)&ajHdr[OFF_Ascent]);
pifi->fwdWinAscender = sAscent;
pifi->fwdWinDescender = (FWORD)pcvtfh->cy - sAscent;
pifi->fwdMacAscender = sAscent;
pifi->fwdMacDescender = -pifi->fwdWinDescender;
pifi->fwdMacLineGap = (FWORD)sMakeSHORT((PBYTE)&ajHdr[OFF_ExtLeading]);
pifi->fwdTypoAscender = pifi->fwdMacAscender;
pifi->fwdTypoDescender = pifi->fwdMacDescender;
pifi->fwdTypoLineGap = pifi->fwdMacLineGap;
pifi->fwdMaxCharInc = (FWORD)pcvtfh->usMaxWidth;
pifi->fwdAveCharWidth = (FWORD)usMakeUSHORT((PBYTE)&ajHdr[OFF_AvgWidth]);
if (pifi->fwdAveCharWidth > pcvtfh->usMaxWidth)
{
// fix the bug in the header if there is one
pifi->fwdAveCharWidth = pcvtfh->usMaxWidth;
}
// don't know much about SuperScripts
pifi->fwdSubscriptXSize = 0;
pifi->fwdSubscriptYSize = 0;
pifi->fwdSubscriptXOffset = 0;
pifi->fwdSubscriptYOffset = 0;
//
// don't know much about SubScripts
//
pifi->fwdSuperscriptXSize = 0;
pifi->fwdSuperscriptYSize = 0;
pifi->fwdSuperscriptXOffset = 0;
pifi->fwdSuperscriptYOffset = 0;
//
// win 30 magic. see the code in textsims.c in the Win 3.1 sources
//
fwdHeight = pifi->fwdWinAscender + pifi->fwdWinDescender;
pifi->fwdUnderscoreSize = (fwdHeight > 12) ? (fwdHeight / 12) : 1;
pifi->fwdUnderscorePosition = -(FWORD)(pifi->fwdUnderscoreSize / 2 + 1);
pifi->fwdStrikeoutSize = pifi->fwdUnderscoreSize;
{
// We are further adjusting underscore position if underline
// hangs below char stems.
// The only font where this effect is noticed to
// be important is an ex pm font sys08cga.fnt, presently used in console
FWORD yUnderlineBottom = -pifi->fwdUnderscorePosition
+ ((pifi->fwdUnderscoreSize + (FWORD)1) >> 1);
FWORD dy = yUnderlineBottom - pifi->fwdWinDescender;
if (dy > 0)
{
#ifdef CHECK_CRAZY_DESC
DbgPrint("bmfd: Crazy descender: old = %ld, adjusted = %ld\n\n",
(ULONG)pifi->fwdMaxDescender,
(ULONG)yUnderlineBottom);
#endif // CHECK_CRAZY_DESC
pifi->fwdUnderscorePosition += dy;
}
}
//
// Win 3.1 method
//
// LineOffset = ((((Ascent-IntLeading)*2)/3) + IntLeading)
//
// [remember that they measure the offset from the top of the cell,
// where as NT measures offsets from the baseline]
//
pifi->fwdStrikeoutPosition =
(FWORD) ((sAscent - sIntLeading + 2)/3);
pifi->chFirstChar = pcvtfh->chFirstChar;
pifi->chLastChar = pcvtfh->chLastChar;
pifi->chBreakChar = pcvtfh->chBreakChar + pcvtfh->chFirstChar;
// chDefault: here we are just putting the junk from the header, which we
// know may be wrong but this is what win31 is reporting.
// E.g. for SmallFonts (shipped with win31) they report
// 128 as default even though it is not even supported in a font.
// In NT however, we must report an existent char as default char to
// the engine. So for buggy fonts we break the relationship
// wcDefault == AnsiToUnicode(chDefault);
pifi->chDefaultChar = ((PBYTE)pre->pvResData)[OFF_DefaultChar] +
((PBYTE)pre->pvResData)[OFF_FirstChar] ;
// wcDefaultChar
// wcBreakChar
vComputeSpecialChars(
pcvtfh,
&(pifi->wcDefaultChar),
&(pifi->wcBreakChar)
);
// These should be taken from the glyph set
{
FD_GLYPHSET * pgset = &pfai->pcp->gset;
WCRUN *pwcrunLast = &(pgset->awcrun[pgset->cRuns - 1]);
pifi->wcFirstChar = pgset->awcrun[0].wcLow;
pifi->wcLastChar = pwcrunLast->wcLow + pwcrunLast->cGlyphs - 1;
}
// This is what Win 3.1 returns for CapHeight and XHeight
// for TrueType fonts ... we will do the same here.
//
pifi->fwdCapHeight = pifi->fwdUnitsPerEm/2;
pifi->fwdXHeight = pifi->fwdUnitsPerEm/4;
pifi->dpCharSets = 0; // no multiple charsets in bm fonts
// All the fonts that this font driver will see are to be rendered left
// to right
pifi->ptlBaseline.x = 1;
pifi->ptlBaseline.y = 0;
pifi->ptlAspect.y = (LONG) usMakeUSHORT((PBYTE)&ajHdr[OFF_VertRes ]);
pifi->ptlAspect.x = (LONG) usMakeUSHORT((PBYTE)&ajHdr[OFF_HorizRes]);
if (pifi->ptlAspect.y == 0)
{
pifi->ptlAspect.y = 1;
WARNING("bmfd!vBmfdFill_IFIMETRICS():ptlAspect.y == 0\n");
}
if (pifi->ptlAspect.x == 0)
{
pifi->ptlAspect.x = 1;
WARNING("bmfd!vBmfdFill_IFIMETRICS():ptlAspect.x == 0\n");
}
if (!(pifi->fsSelection & FM_SEL_ITALIC))
{
// The base class of font is not italicized,
pifi->ptlCaret.x = 0;
pifi->ptlCaret.y = 1;
}
else
{
// somewhat arbitrary
pifi->ptlCaret.x = 1;
pifi->ptlCaret.y = 2;
}
//
// The font box reflects the fact that a-spacing and c-spacing are zero
//
pifi->rclFontBox.left = 0;
pifi->rclFontBox.top = (LONG) pifi->fwdTypoAscender;
pifi->rclFontBox.right = (LONG) pifi->fwdMaxCharInc;
pifi->rclFontBox.bottom = (LONG) pifi->fwdTypoDescender;
//
// achVendorId, unknown, don't bother figure it out from copyright msg
//
pifi->achVendId[0] = 'U';
pifi->achVendId[1] = 'n';
pifi->achVendId[2] = 'k';
pifi->achVendId[3] = 'n';
pifi->cKerningPairs = 0;
//
// Panose
//
pifi->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN;
ppanose = &(pifi->panose);
ppanose->bFamilyType = jFamilyType((USHORT)pifi->jWinPitchAndFamily);
ppanose->bSerifStyle =
((pifi->jWinPitchAndFamily & 0xf0) == FF_SWISS) ?
PAN_SERIF_NORMAL_SANS : PAN_ANY;
ppanose->bWeight = (BYTE) WINWT_TO_PANWT(pifi->usWinWeight);
ppanose->bProportion = (usMakeUSHORT((PBYTE)&ajHdr[OFF_PixWidth]) == 0) ? PAN_ANY : PAN_PROP_MONOSPACED;
ppanose->bContrast = PAN_ANY;
ppanose->bStrokeVariation = PAN_ANY;
ppanose->bArmStyle = PAN_ANY;
ppanose->bLetterform = PAN_ANY;
ppanose->bMidline = PAN_ANY;
ppanose->bXHeight = PAN_ANY;
//
// Now fill in the fields for the simulated fonts
//
if (pifi->dpFontSim)
{
//
// Create a FONTDIFF template reflecting the base font
//
FONTDIFF FontDiff;
FontDiff.jReserved1 = 0;
FontDiff.jReserved2 = 0;
FontDiff.jReserved3 = 0;
FontDiff.bWeight = pifi->panose.bWeight;
FontDiff.usWinWeight = pifi->usWinWeight;
FontDiff.fsSelection = pifi->fsSelection;
FontDiff.fwdAveCharWidth = pifi->fwdAveCharWidth;
FontDiff.fwdMaxCharInc = pifi->fwdMaxCharInc;
FontDiff.ptlCaret = pifi->ptlCaret;
if (pfdiffBold)
{
*pfdiffBold = FontDiff;
pfdiffBoldItalic->bWeight = PAN_WEIGHT_BOLD;
pfdiffBold->fsSelection |= FM_SEL_BOLD;
pfdiffBold->usWinWeight = FW_BOLD;
pfdiffBold->fwdAveCharWidth += 1;
pfdiffBold->fwdMaxCharInc += 1;
}
if (pfdiffItalic)
{
*pfdiffItalic = FontDiff;
pfdiffItalic->fsSelection |= FM_SEL_ITALIC;
pfdiffItalic->ptlCaret.x = 1;
pfdiffItalic->ptlCaret.y = 2;
}
if (pfdiffBoldItalic)
{
*pfdiffBoldItalic = FontDiff;
pfdiffBoldItalic->bWeight = PAN_WEIGHT_BOLD;
pfdiffBoldItalic->fsSelection |= (FM_SEL_BOLD | FM_SEL_ITALIC);
pfdiffBoldItalic->usWinWeight = FW_BOLD;
pfdiffBoldItalic->fwdAveCharWidth += 1;
pfdiffBoldItalic->fwdMaxCharInc += 1;
pfdiffBoldItalic->ptlCaret.x = 1;
pfdiffBoldItalic->ptlCaret.y = 2;
}
}
}
#if defined(_X86_)
extern VOID vLToE(FLOATL *pe, LONG l);
/*
VOID vLToE(FLOATL *pe, LONG l)
{
PULONG pul = (PULONG)pe;
ASSERTGDI(sizeof(FLOAT) == sizeof(LONG),
"vLtoE : sizeof(FLOAT) != sizeof(LONG)\n");
*pul = ulLToE(l);
}
*/
/*
//!!! an assembly routine should be provided here instead
//!!! Now we comment out all lines where this function should be
//!!! used. Fortunately, this info is not used by the Engine yet
//!!! This is done per request of mikehar (BodinD)
VOID vDivE(FLOAT *pe, LONG l1, LONG l2) // *pe = l1/l2
{
//!!! this is a hack, it must be fixed to avoid
// 387 instructions in assembled code. This does not work
// on a machine without 387 or a system without math emulator
*pe = ((FLOAT)l1) / ((FLOAT)l2);
}
*/
#endif
/******************************Public*Routine******************************\
* bDescStr
*
* Grunge around in the EXE header to retrieve the description string. Copy
* the string (if found) to the return string buffer. This buffer should
* be at least 256 characters. The EXE format limits the string to 255
* characters (not including a terminating NULL).
*
* Returns:
* TRUE if successful, FALSE otherwise.
*
* History:
* 09-Mar-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
// !!! [GilmanW] 09-Mar-1992
// !!! This only supports the 16-bit .FON file format (which corresponds to
// !!! the 16-bit NEWEXE format defined in exehdr.h).
// !!!
// !!! We need to add support for the 32-bit .FON format, whatever that is.
// !!!
// !!! Effect this has on 32-bit files: facename will be used as descr string.
BOOL
bDescStr(
PVOID pvView,
SIZE_T cjView,
PSZ pszString
)
{
PTRDIFF dpNewExe; // offset to NEWEXE header
PTRDIFF dpNRSTOffset; // offset to non-resident names table
ULONG cch; // count of characters in string resource
PSZ psz; // pointer to characters in string resource
PSZ pszTmp;
PBYTE pj = (PBYTE) pvView; // PBYTE pointer into file view
#ifdef DUMPCALL
DbgPrint("\nbDescStr(\n" );
DbgPrint(" PSZ pszString = %-#8lx\n", pszString );
DbgPrint(" );\n\n" );
#endif
// Validation. Check EXE_HDR magic number.
if (OFF_e_magic + sizeof(WORD) > cjView)
{
WARNING("bmfd!bDescStr(): header too short\n");
return (FALSE);
}
if (READ_WORD(pj + OFF_e_magic) != EMAGIC)
{
WARNING("bmfd!bDescStr(): not a 16-bit .FON file (bad EMAGIC number)!\n");
return(FALSE);
}
// More validation. Check NEWEXE magic number.
dpNewExe = READ_DWORD(pj + OFF_e_lfanew);
if ((dpNewExe < 0) || (dpNewExe + sizeof(USHORT) > cjView))
{
WARNING("bmfd!bDescStr(): bad dpNewExe\n");
return (FALSE);
}
if (READ_WORD(pj + dpNewExe) != NEMAGIC )
{
WARNING("bmfd!bDescStr(): not a 16-bit .FON file (bad NEMAGIC number)!\n");
return(FALSE);
}
// Get description string out of the non-resident strings table of the
// NEWEXE header. Resource strings are counted strings: the first byte
// is the count of characters, and the string follows. A NULL is not
// guaranteed. However, we know the string is < 256 characters.
dpNRSTOffset = READ_DWORD(pj + dpNewExe + OFF_ne_nrestab);
if ( (DWORD)(dpNRSTOffset) > cjView - 1) // one byte the Pascal style string length
{
WARNING("bmfd!bDescStr(): bad dpNRSTOffset\n");
return (FALSE);
}
// If zero length string, then there is none.
if ( (cch = (ULONG)(*(pj + dpNRSTOffset))) == 0 )
{
WARNING("bmfd!bDescStr(): bad description string\n");
return (FALSE);
}
if ((dpNRSTOffset + 2 + cch > cjView) || (*(pj + dpNRSTOffset + cch + 1) != 0))
// length of the string + one character for the pascal size + one character for the null terminator
{
WARNING("bmfd!bDescStr(): bad string\n");
return (FALSE);
}
// Pointer to the actual string.
psz = pj + dpNRSTOffset + 1;
// Parse out the "FONTRES xxx, yyy, zzz : " header if it exists.
if ( (pszTmp = strchr(psz, ':')) != (PSZ) NULL )
{
// Skip over the ':'.
pszTmp++;
cch -= (ULONG)(pszTmp - psz);
// Skip spaces.
while ( *pszTmp == ' ' && cch > 0)
{
pszTmp++;
cch--;
}
// If not at end of string, then we're at the string.
if ( *pszTmp != '\0' && cch > 0)
{
psz = pszTmp;
}
// Otherwise, this is a bad string (contains only a header).
else
{
WARNING("bmfd!bDescStr(): bad description string (only string header)\n");
return (FALSE);
}
}
// Copy the string.
strncpy(pszString, psz, cch);
pszString[cch] = '\0'; // add terminating NULL
// Success.
return(TRUE);
}
/******************************Public*Routine******************************\
*
* PBYTE pjRawBitmap
*
* gets the pointer to the raw bitmap data in the resource file
*
* History:
* 23-Mar-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
PBYTE
pjRawBitmap(
HGLYPH hg, // IN
PCVTFILEHDR pcvtfh, // IN
PRES_ELEM pre, // IN
PULONG pcx // OUT place cx here
)
{
// size of table entry in USHORT's
ULONG cusTableEntry = ((pcvtfh->iVersion == 0x00000200) ? 2 : 3);
// get the pointer to the beginning of the offset table in
// the original *.fnt file
PUSHORT pusOffTable = (PUSHORT)((PBYTE)pre->pvResData + pcvtfh->dpOffsetTable);
PUSHORT pus_cx;
DWORD dwOffset;
#ifdef DUMPCALL
DbgPrint("\npjRawBitmap(\n");
DbgPrint(" HGLYPH hg = %-#8lx\n", hg );
DbgPrint(" PCVTFILEHDR pcvtfh = %-#8lx\n", pcvtfh);
DbgPrint(" PRES_ELEM pre = %-#8lx\n", pre );
DbgPrint(" PULONG pcx = %-#8lx\n", pcx );
DbgPrint(" );\n\n" );
#endif
// hg is equal to the ansi value of the glyph - chFirstChar:
if (hg > (HGLYPH)(pcvtfh->chLastChar - pcvtfh->chFirstChar))
{
// DbgPrint ( "hg 0x %lx, chFirst 0x %x, chLastChar 0x %x \n",
// hg, (WCHAR)pcvtfh->chFirstChar, (WCHAR)pcvtfh->chLastChar);
hg = pcvtfh->chDefaultChar;
}
// points to the table entry for this character
pus_cx = pusOffTable + hg * cusTableEntry;
// If cx is non-zero, then the character exists, else use default char
*pcx = *pus_cx;
if (*pus_cx == 0)
{
// no bits, will have to return fake bitmap
return NULL;
}
// increment pus_cx to point to the offset to the bitmap in the resource file
pus_cx++;
if (pcvtfh->iVersion == 0x00000200)
{
dwOffset = READ_WORD(pus_cx);
}
else // long offset, win 3.0 format
{
dwOffset = READ_DWORD(pus_cx);
}
if (dwOffset > (CJ_SCAN(*pcx) * pcvtfh->cy) + dwOffset ||
(CJ_SCAN(*pcx) * pcvtfh->cy) + dwOffset > pre->cjResData)
{
// bitmap is out of font file, will have to return fake bitmap
WARNING("bmfd!pjRawBitmap(): bitmap is out of font file\n");
*pcx = 0;
return NULL;
}
return ((PBYTE)pre->pvResData + dwOffset);
}
/******************************Public*Routine******************************\
*
* vCheckOffsetTable: fixes the possible problems in the file header
*
* History:
* 23-Mar-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
VOID
vCheckOffsetTable(
PCVTFILEHDR pcvtfh,
PRES_ELEM pre
)
{
ULONG cusTableEntry; // size of table entry in USHORT's
ULONG i; // loop index
USHORT cxMax; // has to be computed since there are bugs in files
ULONG cCodePoints = pcvtfh->chLastChar + 1 - pcvtfh->chFirstChar;
PUSHORT pus_cx; // pointer to the beginning of the offset table
#ifdef DUMPCALL
DbgPrint("\nvCheckOffsetTable(\n" );
DbgPrint(" PCVTFILEHDR pcvtfh = %-#8lx\n", pcvtfh);
DbgPrint(" PRES_ELEM pre = %-#8lx\n", pre );
DbgPrint(" );\n\n" );
#endif
pus_cx = (PUSHORT)((PBYTE)pre->pvResData + pcvtfh->dpOffsetTable);
ASSERTGDI (
((ULONG_PTR)pus_cx & 1L) == 0,
"offset table begins at odd address\n"
);
// initialize the max so far
cxMax = 0;
if (pcvtfh->iVersion == 0x00000200) // 2.0 font file
cusTableEntry = 2; // 2 bytes for cx + 2 bytes for offset
else // 3.0 font file
{
ASSERTGDI(pcvtfh->iVersion == 0x00000300, "must be 0x00000300 font\n");
cusTableEntry = 3; // 2 bytes for cx + 4 bytes for offset
}
// check offset table for all codepoints. It is important to find the
// real cxMax and not to trust the value in the header since as we have
// seen it may be wrong, which could cause a crash. This in fact is the
// case with one of the faces in aldfonte.fon, where they report avg. width
// to be 0x14 and max width to be 0x13, i.e. smaller than the avg!!!!.
// However, cxMax for that font, found in the loop below, turns out to be
// 0x14, i.e. >= avg width, as it should be. [bodind]
pcvtfh->fsFlags = 0;
for (i = 0; i < cCodePoints; i++, pus_cx += cusTableEntry)
{
if ((*pus_cx) > cxMax)
cxMax = (*pus_cx);
// See if this font file contains zero width glyphs,
// if so we have to turn off usual DEVICEMETRICS accelerator
// flags for this font. We shall have to be providing
// the fake 1x1 bitmap for this font.
if ((*pus_cx) == 0)
{
pcvtfh->fsFlags |= FS_ZERO_WIDTH_GLYPHS;
}
}
#ifdef FOOGOO
if (pcvtfh->fsFlags & FS_ZERO_WIDTH_GLYPHS)
{
KdPrint(("\n %s: .fnt font resource with zero width glyphs\n", pre->pjFaceName));
}
#endif
// cache the values
pcvtfh->cjGlyphMax = CJ_GLYPHDATA(cxMax,pcvtfh->cy);
pcvtfh->usMaxWidth = max(pcvtfh->usMaxWidth, cxMax);
}
#if DBG
/******************************Public*Routine******************************\
* vDumpFontHeader *
* *
* History: *
* Mon 27-Jun-1994 07:00:29 by Kirk Olynyk [kirko] *
* Wrote it. *
\**************************************************************************/
#define GETBYTE(XXX) ajHdr[OFF_##XXX]
#define GETWORD(XXX) READ_WORD(&ajHdr[OFF_##XXX])
#define GETDWORD(XXX) READ_DWORD(&ajHdr[OFF_##XXX])
VOID vDumpFontHeader(
PRES_ELEM pre
, VPRINT vPrint
)
{
PBYTE ajHdr = (PBYTE)pre->pvResData;
vPrint("\n\nvDumpFontHeader\n\n");
vPrint("Version = %-#x\n", GETWORD(Version));
vPrint("Size = %-#x\n", GETDWORD(Size));
vPrint("Copyright = \"%s\"\n",ajHdr + OFF_Copyright);
vPrint("Type = %-#x\n", GETWORD(Type));
vPrint("Points = %-#x\n", GETWORD(Points));
vPrint("VertRes = %-#x\n", GETWORD(VertRes));
vPrint("HorizRes = %-#x\n", GETWORD(HorizRes));
vPrint("Ascent = %-#x\n", GETWORD(Ascent));
vPrint("IntLeading = %-#x\n", GETWORD(IntLeading));
vPrint("ExtLeading = %-#x\n", GETWORD(ExtLeading));
vPrint("Italic = %-#x\n", GETBYTE(Italic));
vPrint("Underline = %-#x\n", GETBYTE(Underline));
vPrint("StrikeOut = %-#x\n", GETBYTE(StrikeOut));
vPrint("Weight = %-#x\n", GETWORD(Weight));
vPrint("CharSet = %-#x\n", GETBYTE(CharSet));
vPrint("PixWidth = %-#x\n", GETWORD(PixWidth));
vPrint("PixHeight = %-#x\n", GETWORD(PixHeight));
vPrint("Family = %-#x\n", GETBYTE(Family));
vPrint("AvgWidth = %-#x\n", GETWORD(AvgWidth));
vPrint("MaxWidth = %-#x\n", GETWORD(MaxWidth));
vPrint("FirstChar = %-#x\n", GETBYTE(FirstChar));
vPrint("LastChar = %-#x\n", GETBYTE(LastChar));
vPrint("DefaultChar = %-#x\n", GETBYTE(DefaultChar));
vPrint("BreakChar = %-#x\n", GETBYTE(BreakChar));
vPrint("WidthBytes = %-#x\n", GETWORD(WidthBytes));
vPrint("Device = %-#x\n", GETDWORD(Device));
vPrint("Face = %-#x\n", GETDWORD(Face));
vPrint(" = \"%s\"\n",
(PSZ)(pre->pjFaceName == 0 ? ajHdr + GETWORD(Face) : pre->pjFaceName));
vPrint("BitsPointer = %-#x\n", GETDWORD(BitsPointer));
vPrint("BitsOffset = %-#x\n", GETDWORD(BitsOffset));
vPrint("jUnused20 = %-#x\n", GETBYTE(jUnused20));
vPrint("OffTable20 = %-#x\n", GETWORD(OffTable20));
vPrint("\n\n");
{
// consistency checks go here
char *pszBad = "Inconsistency detected:";
if ((GETWORD(PixWidth)) && (GETWORD(PixWidth) != GETWORD(MaxWidth)))
DbgPrint("%s PixWidth != MaxWidth\n",pszBad);
if ((ajHdr[OFF_Family] & 0xf) && ajHdr[OFF_PixWidth])
DbgPrint("%s Family indicates variable pitch and PixWidth indicates fixed\n",pszBad);
else if (!(ajHdr[OFF_Family] & 0xf) && !ajHdr[OFF_PixWidth])
DbgPrint("%s Family indicates fixed pitch and PixWidth indicates variable\n",pszBad);
vPrint("\n\n");
}
}
#endif