|
|
/******************************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
|