Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1385 lines
38 KiB

/******************************Module*Header*******************************\
* Module Name: pfeobj.cxx
*
* Non-inline methods for physical font entry objects.
*
* Created: 30-Oct-1990 09:32:48
* Author: Gilman Wong [gilmanw]
*
* Copyright (c) 1990-1995 Microsoft Corporation
\**************************************************************************/
// #pragma warning (disable: 4509)
#include "precomp.hxx"
#include "flhack.hxx"
#ifdef FE_SB
INT
_CRTAPI1 CompareRoutine(WCHAR *pwc1, WCHAR *pwc2)
{
return(*pwc1-*pwc2);
}
#endif
/******************************Public*Routine******************************\
*
* ULONG cComputeGISET
*
* similar to cComputeGlyphSet in mapfile.c, computes the number of
* distinct glyph handles in a font and the number of runs, ie. number of
* contiguous ranges of glyph handles
*
*
* History:
* 03-Aug-1995 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
ULONG cComputeGISET (
USHORT * pgi,
ULONG cgi,
GISET * pgiset,
ULONG cGiRuns
)
{
ULONG iRun, iFirst, iFirstNext;
ULONG cgiTotal = 0, cgiRun;
// now compute cRuns if pgiset == 0 and fill the glyphset if pgiset != 0
for (iFirst = 0, iRun = 0; iFirst < cgi; iRun++, iFirst = iFirstNext)
{
// find iFirst corresponding to the next range.
for (iFirstNext = iFirst + 1; iFirstNext < cgi; iFirstNext++)
{
if ((pgi[iFirstNext] - pgi[iFirstNext - 1]) > 1)
break;
}
// note that this line here covers the case when there are repetitions
// in the pgi array.
cgiRun = pgi[iFirstNext-1] - pgi[iFirst] + 1;
cgiTotal += cgiRun;
if (pgiset != NULL)
{
pgiset->agirun[iRun].giLow = pgi[iFirst];
pgiset->agirun[iRun].cgi = (USHORT) cgiRun;
}
}
// store results if need be
if (pgiset != NULL)
{
ASSERTGDI(iRun == cGiRuns, "gdisrv! iRun != cRun\n");
pgiset->cGiRuns = cGiRuns;
// init the sum before entering the loop
pgiset->cgiTotal = cgiTotal;
}
return iRun;
}
/******************************Public*Routine******************************\
*
* bComputeGISET, similar to ComputeGlyphSet, only for gi's
*
* History:
* 03-Aug-1995 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
#include "stdlib.h"
VOID vSortPlacebo
(
USHORT *pwc,
ULONG cChar
)
{
ULONG i;
for (i = 1; i < cChar; i++)
{
// upon every entry to this loop the array 0,1,..., (i-1) will be sorted
INT j;
WCHAR wcTmp = pwc[i];
for (j = i - 1; (j >= 0) && (pwc[j] > wcTmp); j--)
{
pwc[j+1] = pwc[j];
}
pwc[j+1] = wcTmp;
}
}
BOOL bComputeGISET(IFIMETRICS * pifi, FD_GLYPHSET *pfdg, GISET **ppgiset)
{
BOOL bRet = TRUE;
*ppgiset = NULL;
GISET *pgiset;
if (pfdg->flAccel & (GS_16BIT_HANDLES | GS_8BIT_HANDLES))
{
// first check if this is an accelerated case where handles are the same
// as glyph indicies
ULONG cig = 0;
if (pifi->cjIfiExtra > offsetof(IFIEXTRA, cig))
{
cig = ((IFIEXTRA *)(pifi + 1))->cig;
}
if (cig)
{
// one run only from zero to (cig-1);
if (pgiset = (GISET*)PALLOCMEM(offsetof(GISET,agirun) + 1 * sizeof(GIRUN),'slgG'))
{
// now fill in the array of runs
pgiset->cgiTotal = cig;
pgiset->cGiRuns = 1;
pgiset->agirun[0].giLow = 0;
pgiset->agirun[0].cgi = (USHORT)cig;
// we are done now
*ppgiset = pgiset;
}
else
{
bRet = FALSE;
}
}
else
{
// one of the goofy fonts, we will do as before
USHORT *pgi, *pgiBegin;
// aloc tmp buffer to contain glyph handles of all glyphs in the font
if (pgiBegin = (USHORT*)PALLOCMEM(pfdg->cGlyphsSupported * sizeof(USHORT),'slgG'))
{
pgi = pgiBegin;
for (ULONG iRun = 0; iRun < pfdg->cRuns; iRun++)
{
HGLYPH *phg, *phgEnd;
phg = pfdg->awcrun[iRun].phg;
if (phg) // non unicode handles
{
phgEnd = phg + pfdg->awcrun[iRun].cGlyphs;
for ( ; phg < phgEnd; pgi++, phg++)
*pgi = (USHORT)(*phg);
}
else // unicode handles
{
USHORT wcLo = pfdg->awcrun[iRun].wcLow;
USHORT wcHi = wcLo + pfdg->awcrun[iRun].cGlyphs - 1;
for ( ; wcLo <= wcHi; wcLo++, phg++)
*pgi = wcLo;
}
}
// now sort the array of glyph indicies. This array will be mostly
// sorted so that our algorithm is efficient
#ifdef FE_SB
qsort((void*)pgiBegin, pfdg->cGlyphsSupported, sizeof(WORD),
(int (__cdecl *)(const void *, const void *))CompareRoutine);
#else
//qsort((void*)pgiBegin, sizeof(USHORT), sizeof(USHORT), NULL);
vSortPlacebo(pgiBegin,pfdg->cGlyphsSupported);
#endif
// once the array is sorted we can easily compute the number of giRuns
ULONG cGiRun = cComputeGISET(pgiBegin, pfdg->cGlyphsSupported, NULL, 0);
if (pgiset = (GISET*)PALLOCMEM(offsetof(GISET,agirun) + cGiRun * sizeof(GIRUN),'slgG'))
{
// now fill in the array of runs
cComputeGISET(pgiBegin, pfdg->cGlyphsSupported, pgiset, cGiRun);
*ppgiset = pgiset;
}
else
{
bRet = FALSE;
}
VFREEMEM(pgiBegin);
}
else
{
bRet = FALSE;
}
}
}
return bRet;
}
//
// This is used to give ppfe->pkp something to point to if a driver
// error occurs. That way, we won't waste time calling the driver
// again.
//
FD_KERNINGPAIR gkpNothing = { 0, 0, 0 };
static ULONG ulTimerPFE = 0;
/******************************Public*Routine******************************\
* PFEMEMOBJ::PFEMEMOBJ() *
* *
* Constructor for physical font entry memory object. *
* *
* History: *
* 30-Oct-1990 -by- Gilman Wong [gilmanw] *
* Wrote it. *
\**************************************************************************/
void PFEMEMOBJ::ctHelper()
{
fs = 0;
ppfe = (PFE *) HmgAlloc(
offsetof(PFE,aiFamilyName) + gcfsCharSetTable * sizeof(BYTE),
PFE_TYPE, HMGR_ALLOC_ALT_LOCK | HMGR_MAKE_PUBLIC);
}
/******************************Public*Routine******************************\
* PFEMEMOBJ::~PFEMEMOBJ() *
* *
* Destructor for physical font entry memory object. *
* *
* History: *
* 30-Oct-1990 -by- Gilman Wong [gilmanw] *
* Wrote it. *
\**************************************************************************/
void PFEMEMOBJ::dtHelper()
{
if ((ppfe != PPFENULL) && !(fs & PFEMO_KEEPIT))
{
if (ppfe->pgiset)
VFREEMEM(ppfe->pgiset); // fix this, do mem alloc in one attempt
HmgFree((HOBJ) ppfe->hGet());
}
}
/******************************Public*Routine******************************\
* VOID PFEOBJ::vDelete() *
* *
* Destroy the PFE physical font entry object. *
* *
* History: *
* 30-Oct-1990 -by- Gilman Wong [gilmanw] *
* Wrote it. *
\**************************************************************************/
VOID PFEOBJ::vDelete(PFECLEANUP *ppfec)
{
// Save driver allocated resources in PFECLEANUP so that we can later
// call the driver to free them.
ppfec->pfdg = ppfe->pfdg;
ppfec->idfdg = ppfe->idfdg;
ppfec->pifi = ppfe->pifi;
ppfec->idifi = ppfe->idifi;
ppfec->pkp = ppfe->pkp;
ppfec->idkp = ppfe->idkp;
if (ppfe->pgiset)
{
VFREEMEM(ppfe->pgiset);
ppfe->pgiset = NULL;
}
// Free object memory and invalidate pointer.
HmgFree((HOBJ) ppfe->hGet());
ppfe = PPFENULL;
}
/******************************Public*Routine******************************\
* PFEOBJ::flFontType()
*
* Computes the flags defining the type of this font. Allowed flags are
* identical to the flType flags returned in font enumeration.
*
* Return:
* The flags.
*
* History:
* 04-Mar-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
FLONG PFEOBJ::flFontType()
{
FLONG flRet;
IFIOBJ ifio(pifi());
// Compute the FontType flags, simulations are irrelevant
flRet =
ifio.bTrueType() ?
TRUETYPE_FONTTYPE : (ifio.bBitmap() ? RASTER_FONTTYPE : 0);
// Add the device flag if this is also a device specific font.
flRet |= (bDeviceFont()) ? DEVICE_FONTTYPE : 0;
return (flRet);
}
/******************************Public*Routine******************************\
* PFEOBJ::efstyCompute()
*
* Compute the ENUMFONTSTYLE from the IFIMETRICS.
*
* Returns:
* The ENUMFONTSTYLE of font. Note that EFSTYLE_SKIP and EFSTYLE_OTHER are
* not legal return values for this function. These values are used only
* to mark fonts for which another font already exists that fills our
* category for a given enumeration of a family.
*
* History:
* 04-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
ENUMFONTSTYLE PFEOBJ::efstyCompute()
{
IFIOBJ ifio(pifi());
switch (ifio.fsSelection() & (FM_SEL_ITALIC | FM_SEL_BOLD) )
{
case FM_SEL_ITALIC:
return EFSTYLE_ITALIC;
case FM_SEL_BOLD:
return EFSTYLE_BOLD;
case FM_SEL_ITALIC | FM_SEL_BOLD:
return EFSTYLE_BOLDITALIC;
default:
return EFSTYLE_REGULAR;
}
}
/******************************Public*Routine******************************\
* COUNT PFEOBJ::cKernPairs *
* *
* Retrieve the pointer to the array of kerning pairs for this font face. *
* The kerning pair array is loaded on demand, so it may or may not already *
* be cached in the PFE. *
* *
* Returns: *
* Count of kerning pairs. *
* *
* History: *
* Mon 22-Mar-1993 21:31:15 -by- Charles Whitmer [chuckwh] *
* WARNING: Never access a pkp (pointer to a kerning pair) without an *
* exception handler! The kerning pairs could be living in a file across *
* the net or even on removable media. I've added the try-except here. *
* *
* 29-Oct-1992 -by- Gilman Wong [gilmanw] *
* Wrote it. *
\**************************************************************************/
COUNT PFEOBJ::cKernPairs(FD_KERNINGPAIR **ppkp)
{
//
// If the pointer cached in the PFE isn't NULL, we already have the answer.
//
if ( (*ppkp = ppfe->pkp) != (FD_KERNINGPAIR *) NULL )
return ppfe->ckp;
//
// Create a PFFOBJ. Needed to create driver user object as well as
// provide info needed to call driver function.
//
PFFOBJ pffo(pPFF());
ASSERTGDI(pffo.bValid(), "gdisrv!cKernPairsPFEOBJ(): invalid PPFF\n");
PDEVOBJ pdo(pffo.hdev());
if ( (ppfe->pkp = (FD_KERNINGPAIR *) (*PPFNDRV(pdo, QueryFontTree)) (
pffo.dhpdev(),
pffo.hff(),
ppfe->iFont,
QFT_KERNPAIRS,
&ppfe->idkp)) == (FD_KERNINGPAIR *) NULL )
{
//
// Font has no kerning pairs and didn't even bother to send back
// an empty list. By setting pointer to a zeroed FD_KERNINGPAIR and
// setting count to zero, we will bail out early and avoid calling
// the driver.
//
ppfe->pkp = &gkpNothing;
ppfe->ckp = 0;
return 0;
}
// Find the end of the kerning pair array (indicated by a zeroed out
// FD_KERNINGPAIR structure).
FD_KERNINGPAIR *pkpEnd = ppfe->pkp;
// Be careful, the table isn't guaranteed to stay around!
#if !defined(_ALPHA_)
__try
#endif
{
while ((pkpEnd->wcFirst) || (pkpEnd->wcSecond) || (pkpEnd->fwdKern))
pkpEnd += 1;
}
#if !defined(_ALPHA_)
__except (EXCEPTION_EXECUTE_HANDLER)
{
pkpEnd = ppfe->pkp = &gkpNothing;
}
#endif
// Return the kerning pair pointer.
*ppkp = ppfe->pkp;
//
// Return count (difference between the beginning and end pointers).
//
return (ppfe->ckp = pkpEnd - ppfe->pkp);
}
/******************************Public*Routine******************************\
* bValidFont
*
* Last minute sanity checks to prevent a font that may crash the system
* from getting in. We're primarily looking for things like potential
* divide-by-zero errors, etc.
*
* History:
* 30-Apr-1993 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL bValidFont(IFIMETRICS *pifi)
{
BOOL bRet = TRUE;
// Em height is used to compute scaling factors. Must not be zero or
// divide-by-zero may result.
if (pifi->fwdUnitsPerEm == 0)
{
WARNING("bValidFont(): fwdUnitsPerEm is zero\n");
bRet = FALSE;
}
// Font height is used to compute scaling factors. Must not be zero or
// divide-by-zero may result.
if ((pifi->fwdWinAscender + pifi->fwdWinDescender) == 0)
{
WARNING("bValidFont(): font height is zero\n");
bRet = FALSE;
}
return bRet;
}
/******************************Public*Routine******************************\
* BOOL PFEMEMOBJ::bInit
*
* This function copies data into the PFE from the supplied buffer. The
* calling routine should use the PFEMEMOBJ to create a PFE large enough
*
* History:
* 14-Jan-1991 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL PFEMEMOBJ::bInit
(
PPFF pPFF, // handle to root PFF
ULONG iFont, // index of font
FD_GLYPHSET *pfdg, // ptr to wc-->hg map
ULONG idfdg, // driver ID for wc-->hg map
PIFIMETRICS pifi, // ptr to IFIMETRICS
ULONG idifi, // driver ID for IFIMETRICS
BOOL bDeviceFont // mark as device font
#ifdef FE_SB
,BOOL bEUDC // mark as EUDC font
#endif
)
{
// Check font's validity. This is not a comprehensive check, but rather
// a last minute check for things that may make the engine crash. Each
// font/device driver still needs to make an effort to weed out its own
// bad fonts.
if (!bValidFont(pifi))
{
WARNING("PFEMEMOBJ::bInit(): rejecting REALLY bad font\n");
return FALSE;
}
// init non-table stuff
ppfe->pPFF = pPFF;
ppfe->iFont = iFont;
ppfe->pfdg = pfdg;
ppfe->idfdg = idfdg;
ppfe->pifi = pifi;
ppfe->idifi = idifi;
ppfe->pkp = (FD_KERNINGPAIR *) NULL;
ppfe->idifi = (ULONG) NULL;
ppfe->ckp = 0;
ppfe->flPFE = 0;
ppfe->pid = 0;
if (bDeviceFont)
{
ppfe->flPFE |= PFE_DEVICEFONT;
}
else if(pPFF->ppfv && (pPFF->ppfv[0]->pwszPath == NULL))
{
// CAUTION: It is enough to check one font only to determine if remote
ppfe->flPFE |= PFE_REMOTEFONT;
ppfe->pid = W32GetCurrentPID();
}
IFIOBJ ifio(ppfe->pifi);
#ifdef FE_SB
if( bEUDC )
{
ppfe->flPFE |= PFE_EUDC;
}
// mark it as a SBCS system font if the facename is right
if((!_wcsicmp(ifio.pwszFaceName(),L"SYSTEM") ||
!_wcsicmp(ifio.pwszFaceName(),L"FIXEDSYS") ||
!_wcsicmp(ifio.pwszFaceName(),L"TERMINAL")))
{
ppfe->flPFE |= PFE_SBCS_SYSTEM;
}
// we need to know quickly if this is vertical or not
ppfe->bVerticalFace = ( pwszFaceName()[0] == (WCHAR) '@' ) ? TRUE : FALSE;
// Initialize EUDC QUICKLOOKUP Table
//
// These field was used, if this font is loaded as FaceName/Default linked EUDC.
//
ppfe->ql.puiBits = NULL;
ppfe->ql.wcLow = 1;
ppfe->ql.wcHigh = 0;
#endif
// Record and increment the time stamp.
ppfe->ulTimeStamp = ulTimerPFE;
InterlockedIncrement((LONG *) &ulTimerPFE);
// Precalculate stuff from the IFIMETRICS.
ppfe->iOrientation = ifio.lfOrientation();
// Compute UFI stuff
if( ifio.TypeOneID() )
{
ppfe->ufi.Index = ifio.TypeOneID();
ppfe->ufi.CheckSum = TYPE1_FONT_TYPE;
}
else
{
ppfe->ufi.CheckSum = pPFF->ulCheckSum;
ppfe->ufi.Index = iFont;
}
// init the GISET
if (!bComputeGISET(pifi, pfdg, &ppfe->pgiset))
return FALSE;
// initialize cAlt for this family name, the number of entries in font sub
// table that point to this fam name.
ppfe->cAlt = 0;
// only tt fonts with multiple charsets can be multiply enumerated
// as being both themselves and whatever font sub table claims they are
if (ppfe->pifi->dpCharSets)
{
PFONTSUB pfs = gpfsTable;
PFONTSUB pfsEnd = gpfsTable + gcfsTable;
WCHAR awchCapName[LF_FACESIZE];
// Want case insensitive search, so capitalize the name.
cCapString(awchCapName, ifio.pwszFamilyName() , LF_FACESIZE);
// Scan through the font substitution table for the key string.
PWCHAR pwcA;
PWCHAR pwcB;
for (; pfs < pfsEnd; pfs++)
{
// Do the following inline for speed:
//
// if (!wcsncmpi(pwchFacename, pfs->fcsFace.awch, LF_FACESIZE))
// return (pfs->fcsAltFace.awch);
// only those entries in the Font Substitution which have the form
// face1,charset1=face2,charset2
// where both charset1 and charset2 are valid charsets
// count for enumeration purposes.
if (!(pfs->fcsAltFace.fjFlags | pfs->fcsFace.fjFlags))
{
for (pwcA=awchCapName,pwcB=pfs->fcsAltFace.awch; *pwcA==*pwcB; pwcA++,pwcB++)
{
if (*pwcA == 0)
{
ppfe->aiFamilyName[ppfe->cAlt++] = pfs-gpfsTable;
}
}
}
}
}
return TRUE;
}
/******************************Public*Routine******************************\
* BOOL PFEOBJ::bEmbedded()
*
* Determine if this is a embedded font by checking the ulID field in PFFOBJ
*
* Returns:
* TRUE if embedded font, FALSE otherwise.
*
* History:
* 12-Jun-1996 -by- Xudong Wu [TessieW]
* Wrote it.
\**************************************************************************/
BOOL PFEOBJ::bEmbedded()
{
return ( (pPFF()->ulID) ? TRUE : FALSE );
}
/******************************Public*Routine******************************\
* BOOL PFEOBJ::bPIDEmbedded()
*
* Determine whether ulID is PID or TID in PFFOBJ
*
* Returns:
* TRUE if PID, FALSE otherwise.
*
* History:
* 12-Jun-1996 -by- Xudong Wu [TessieW]
* Wrote it.
\**************************************************************************/
BOOL PFEOBJ::bPIDEmbedded()
{
return ( (pPFF()->ulID) && ((pPFF()->flEmbed) ? FALSE : TRUE));
}
/******************************Public*Routine******************************\
* ULONG PFEOBJ::ulEmbedID()
*
* Returns:
* PID/TID in PFFOBJ
*
*
* History:
* 12-Jun-1996 -by- Xudong Wu [TessieW]
* Wrote it.
\**************************************************************************/
ULONG PFEOBJ::ulEmbedID()
{
return ((ULONG)pPFF()->ulID);
}
/******************************Public*Routine******************************\
* BOOL PFEOBJ::bFilteredOut(EFFILTER_INFO *peffi)
*
* Determine if this PFE should be rejected from the enumeration. Various
* filtering parameters are passed in via the EFFILTER_INFO structure.
*
* Returns:
* TRUE if font should be rejected, FALSE otherwise.
*
* History:
* 07-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL PFEOBJ::bFilteredOut(EFFILTER_INFO *peffi)
{
IFIOBJ ifio(pifi());
// Always filter out "dead" (fonts waiting to be deleted) fonts and "ghost"
// fonts.
if ( bDead() || ifio.bGhostFont() )
return TRUE;
#ifdef FE_SB
// Always filter out fonts that have been loaded as EUDC fonts.
if( bEUDC() )
return TRUE;
#endif
// Raster font filtering.
if (peffi->bRasterFilter && ifio.bBitmap())
return TRUE;
// TrueType font filtering. The flag is somewhat of a misnomer as it
// is intended to exclude TrueType, even though the flag is named
// bNonTrueTypeFilter.
if (peffi->bNonTrueTypeFilter && ifio.bTrueType())
return(TRUE);
// Non-TrueType font filtering. The flag is somewhat of a misnomer as it
// is intended to exclude non-TrueType, even though the flag is named
// bTrueTypeFilter.
if (peffi->bTrueTypeFilter && !ifio.bTrueType())
return TRUE;
// Aspect ratio filtering. If an engine bitmap font, we will filter out
// unsuitable resolutions.
if ( peffi->bAspectFilter
&& (!bDeviceFont())
&& ifio.bBitmap()
&& ( (peffi->ptlDeviceAspect.x != ifio.pptlAspect()->x)
|| (peffi->ptlDeviceAspect.y != ifio.pptlAspect()->y) ) )
return TRUE;
// GACF_TTIGNORERASTERDUPE compatibility flag filtering.
// If any raster fonts exist in the same list as a TrueType font, then
// they should be excluded.
if ( peffi->bTrueTypeDupeFilter
&& peffi->cTrueType
&& ifio.bBitmap())
return TRUE;
// Filter out embedded fonts. These fonts are hidden from enumeration.
if (bEmbedded())
return TRUE;
// In the case of a Generic text driver we must filter out all engine fonts
if( ( peffi->bEngineFilter ) && !bDeviceFont() )
{
return(TRUE);
}
// if this is a remote font we don't want to enumerate it
if( ppfe->flPFE & PFE_REMOTEFONT )
{
return(TRUE);
}
// finally check out if the font should be eliminated from the
// enumeration because it does not contain the charset requested:
if (peffi->lfCharSetFilter != DEFAULT_CHARSET)
{
// the specific charset has been requested, let us see if the font
// in question supports it:
BYTE jCharSet = jMapCharset((BYTE)peffi->lfCharSetFilter, pifi());
if (jCharSet != (BYTE)peffi->lfCharSetFilter)
return TRUE; // does not support it, filter this font out.
}
// Passed all tests.
return FALSE;
}
#if DBG
/******************************Public*Routine******************************\
* VOID PFEOBJ::vDump ()
*
* Debugging code.
*
* History:
* 25-Feb-1991 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID PFEOBJ::vPrint()
{
IFIOBJ ifio(pifi());
DbgPrint("\nContents of PFE, PPFE = 0x%lx\n", ppfeGet());
DbgPrint("pPFF = 0x%lx\n", ppfe->pPFF);
DbgPrint("iFont = 0x%lx\n", ppfe->iFont);
DbgPrint("lfHeight = 0x%x\n", ifio.lfHeight());
DbgPrint(
"Family Name = %ws\n",
ifio.pwszFamilyName()
);
DbgPrint(
"Face Name = %ws\n",
ifio.pwszFaceName()
);
DbgPrint(
"Unique Name = %s\n\n",
ifio.pwszUniqueName()
);
}
/******************************Public*Routine******************************\
* VOID PFEOBJ::vDumpIFI ()
*
* Debugging code. Prints PFE header and IFI metrics.
*
\**************************************************************************/
VOID PFEOBJ::vPrintAll()
{
DbgPrint("\nContents of PFE, PPFE = 0x%lx\n", ppfeGet());
DbgPrint("pPFF = 0x%lx\n", ppfe->pPFF);
DbgPrint("iFont = 0x%lx\n", ppfe->iFont);
DbgPrint("IFI Metrics\n");
vPrintIFIMETRICS(ppfe->pifi);
DbgPrint("\n");
}
#endif
/******************************Public*Routine******************************\
* EFSMEMOBJ::EFSMEMOBJ(COUNT cefe)
*
* Constructor for font enumeration state (EFSTATE) memory object.
*
* History:
* 07-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
EFSMEMOBJ::EFSMEMOBJ(COUNT cefe, ULONG iEnumType_)
{
fs = 0;
pefs = (PEFSTATE) HmgAlloc((SIZE_T) (offsetof(EFSTATE, aefe) + cefe * sizeof(EFENTRY)),
EFSTATE_TYPE,
HMGR_ALLOC_LOCK);
if (pefs != PEFSTATENULL)
{
vInit(cefe, iEnumType_);
}
}
/******************************Public*Routine******************************\
* EFSMEMOBJ::~EFSMEMOBJ()
*
* Destructor for font enumeration state (EFSTATE) memory object.
*
* History:
* 07-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
EFSMEMOBJ::~EFSMEMOBJ()
{
// If object pointer not null, try to free the object's memory.
if (pefs != PEFSTATENULL)
{
if (fs & EFSMO_KEEPIT)
{
DEC_EXCLUSIVE_REF_CNT(pefs);
}
else
{
#if DBG
if (pefs->cExclusiveLock != 1)
{
RIP("Not 1 EFSMEMOBJ\n");
}
#endif
HmgFree((HOBJ) pefs->hGet());
}
pefs = NULL;
}
}
#define EFS_QUANTUM 16
/******************************Public*Routine******************************\
* BOOL EFSOBJ::bGrow
*
* Expand the EFENTRY table by the quantum amount.
*
* Returns:
* TRUE if successful, FALSE if failed.
*
* History:
* 07-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL EFSOBJ::bGrow (COUNT cefeMinIncrement)
{
COUNT cefe;
BOOL bRet = FALSE;
// Allocate a new EFSTATE bigger by the quantum amount.
cefe = (COUNT) (pefs->pefeBufferEnd - pefs->aefe);
if (cefeMinIncrement < EFS_QUANTUM)
cefeMinIncrement = EFS_QUANTUM;
cefe += cefeMinIncrement;
EFSMEMOBJ efsmo(cefe, this->pefs->iEnumType);
// Validate new EFSTATE.
if (efsmo.bValid())
{
// Copy the enumeration table.
efsmo.vXerox(pefs);
// Swap the EFSTATEs.
if (HmgSwapHandleContents((HOBJ) hefs(),0,(HOBJ) efsmo.hefs(),0,EFSTATE_TYPE))
{
// swap pointers
PEFSTATE pefsTmp = pefs;
pefs = efsmo.pefs;
efsmo.pefs = pefsTmp; // destructor will delete old PFT
bRet = TRUE;
}
else
WARNING("gdisrv!bGrowEFSOBJ(): handle swap failed\n");
}
else
WARNING("bGrowEFSOBJ failed alloc\n");
return(bRet);
}
/******************************Public*Routine******************************\
* BOOL EFSOBJ::bAdd *
* *
* Add a new EFENTRY to the table with the HPFE and ENUMFONTSTYLE. *
* *
* Returns: *
* FALSE if an error occurs, TRUE otherwise. *
* *
* History: *
* 07-Aug-1992 -by- Gilman Wong [gilmanw] *
* Wrote it. *
\**************************************************************************/
BOOL EFSOBJ::bAdd(PFE *ppfe, ENUMFONTSTYLE efsty, FLONG fl, ULONG lfCharSetFilter)
{
// Check if the buffer needs to be expanded.
COUNT cefeMinIncrement = 1; // will always enumerate at least one pfe
// if EnumFontFamilies is called, will enumerate the font under cAlt more names
if (!(fl & FL_ENUMFAMILIESEX))
cefeMinIncrement += ppfe->cAlt;
// if EnumFontFamiliesEx is called, and this font supports multiple charsets,
// this font will be enumerated no more than MAXCHARSETS times.
if
(
(fl & FL_ENUMFAMILIESEX) &&
(lfCharSetFilter == DEFAULT_CHARSET) &&
ppfe->pifi->dpCharSets
)
{
cefeMinIncrement = MAXCHARSETS;
}
if ((pefs->pefeDataEnd + cefeMinIncrement) >= pefs->pefeBufferEnd)
{
if (!bGrow(cefeMinIncrement))
{
// Error code will be saved for us.
WARNING("gdisrv!EFSOBJ__bAdd: cannot grow enumeration table\n");
return FALSE;
}
}
// Add the new data and increment the data pointer.
HPFE hpfe = (HPFE) ppfe->hGet();
pefs->pefeDataEnd->hpfe = hpfe;
pefs->pefeDataEnd->efsty = efsty;
pefs->pefeDataEnd->fjOverride = 0; // do not override
if (fl & FL_ENUMFAMILIESEX)
pefs->pefeDataEnd->fjOverride |= FJ_CHARSETOVERRIDE;
pefs->pefeDataEnd->jCharSetOverride = (BYTE)lfCharSetFilter;
pefs->pefeDataEnd += 1;
// now check if called from EnumFonts or EnumFontFamilies so that the
// names from the
// [FontSubstitutes] section in the registry also need to be enumerated
if (!(fl & FL_ENUMFAMILIESEX) && ppfe->cAlt) // alt names have to be enumerated too
{
for (ULONG i = 0; i < ppfe->cAlt; i++)
{
// the same hpfe, style etc. all the time, only lie about the name and charset
pefs->pefeDataEnd->hpfe = hpfe;
pefs->pefeDataEnd->efsty = efsty;
pefs->pefeDataEnd->fjOverride = (FJ_FAMILYOVERRIDE | FJ_CHARSETOVERRIDE); // do override
pefs->pefeDataEnd->iOverride = ppfe->aiFamilyName[i];
pefs->pefeDataEnd->jCharSetOverride =
gpfsTable[pefs->pefeDataEnd->iOverride].fcsFace.jCharSet;
pefs->pefeDataEnd += 1;
}
}
// now see if this is called from EnumFontFamiliesEx
if ((fl & FL_ENUMFAMILIESEX) && (lfCharSetFilter == DEFAULT_CHARSET))
{
// The font needs to be enumerated once for every charset it supports
if (ppfe->pifi->dpCharSets)
{
BYTE *ajCharSets = (BYTE*)ppfe->pifi + ppfe->pifi->dpCharSets;
BYTE *ajCharSetsEnd = ajCharSets + MAXCHARSETS;
// first fix up the one entry we just filled above
(pefs->pefeDataEnd-1)->jCharSetOverride = ajCharSets[0];
// this is from win95-J sources:
#define FEOEM_CHARSET 254
for
(
BYTE *pjCharSets = ajCharSets + 1; // skip the first one, used already
(*pjCharSets != DEFAULT_CHARSET) &&
(*pjCharSets != OEM_CHARSET) &&
(*pjCharSets != FEOEM_CHARSET) &&
(pjCharSets < ajCharSetsEnd) ;
pjCharSets++
)
{
// the same hpfe, style etc. all the time, only lie about the name and charset
pefs->pefeDataEnd->hpfe = hpfe;
pefs->pefeDataEnd->efsty = efsty;
pefs->pefeDataEnd->fjOverride = FJ_CHARSETOVERRIDE;
pefs->pefeDataEnd->iOverride = 0;
pefs->pefeDataEnd->jCharSetOverride = *pjCharSets;
pefs->pefeDataEnd += 1;
}
}
else // fix up the one entry we just filled above
{
(pefs->pefeDataEnd-1)->jCharSetOverride = ppfe->pifi->jWinCharSet;
}
}
// Success.
return TRUE;
}
/******************************Public*Routine******************************\
* VOID EFSOBJ::vDelete ()
*
* Destroy the font enumeration state (EFSTATE) memory object.
*
* History:
* 07-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID EFSOBJ::vDeleteEFSOBJ()
{
HmgFree((HOBJ) pefs->hGet());
pefs = PEFSTATENULL;
}
/******************************Member*Function*****************************\
* VOID EFSMEMOBJ::vInit
*
* Initialize the EFSTATE object.
*
* History:
* 07-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID EFSMEMOBJ::vInit(COUNT cefe, ULONG iEnumType_)
{
// HPFE array empty, so initialize all pointer to the beginning of the array.
pefs->pefeDataEnd = pefs->aefe;
pefs->pefeEnumNext = pefs->aefe;
// Except for this one. Set this one to the end of the buffer.
pefs->pefeBufferEnd = &pefs->aefe[cefe];
// Initialize the alternate name to NULL.
pefs->pfcsOverride = NULL;
// init the enum type:
pefs->iEnumType = iEnumType_;
// We don't need to bother with initializing the array.
}
/******************************Public*Routine******************************\
* VOID EFSMEMOBJ::vXerox(EFSTATE *pefeSrc)
*
* Copy the EFENTRYs from the source EFSTATE's table into this EFSTATE's table.
* The internal pointers will be updated to be consistent with the data.
*
* History:
* 07-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID EFSMEMOBJ::vXerox(EFSTATE *pefsSrc)
{
//
// Compute size of the table.
//
COUNT cefe = pefsSrc->pefeDataEnd - pefsSrc->aefe;
ASSERTGDI (
cefe >= (COUNT) (pefs->pefeDataEnd - pefs->aefe),
"gdisrv!vXeroxEFSMEMOBJ(): table to small\n"
);
//
// Copy entries.
//
RtlCopyMemory((PVOID) pefs->aefe, (PVOID) pefsSrc->aefe, (SIZE_T) cefe * sizeof(EFENTRY));
//
// Fixup the data pointer.
//
pefs->pefeDataEnd = pefs->aefe + cefe;
}
/******************************Public*Routine******************************\
* bSetEFSTATEOwner
*
* Set the owner of the EFSTATE
*
* if the owner is set to OBJECTOWNER_NONE, this EFSTATE will not be useable
* until bSetEFSTATEOwner is called to explicitly give the lfnt to someone else.
*
* History:
* 07-Aug-1992 by Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL
bSetEFSTATEOwner(
HEFS hefs,
W32PID lPid)
{
if (lPid == OBJECT_OWNER_CURRENT)
{
lPid = W32GetCurrentPID();
}
return HmgSetOwner((HOBJ) hefs, lPid, EFSTATE_TYPE);
}
BOOL
bGetNtoD(
FD_XFORM*,
EXTLOGFONTW*,
IFIOBJ&,
DCOBJ*,
POINTL* const
);
BOOL
bGetNtoD_Win31(
FD_XFORM*,
EXTLOGFONTW*,
IFIOBJ&,
DCOBJ*,
FLONG,
POINTL* const
);
/******************************Public*Routine******************************\
* BOOL bSetFontXform
*
* Sets the FD_XFORM such that it can be used to realize the physical font
* with the dimensions specified in the wish list coordinates). The
* World to Device xform (with translations removed) is also returned.
*
* Returns:
* TRUE if successful, FALSE if an error occurs.
*
* History:
* Tue 27-Oct-1992 23:18:39 by Kirk Olynyk [kirko]
* Moved it from PFEOBJ.CXX
* 19-Sep-1991 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL
PFEOBJ::bSetFontXform (
XDCOBJ &dco, // realize for this device
EXTLOGFONTW *pelfw, // wish list (in logical coords)
PFD_XFORM pfd_xf, // font transform
FLONG fl,
FLONG flSim,
POINTL* const pptlSim,
IFIOBJ& ifio
)
{
BOOL bRet;
EXFORMOBJ xo(dco, WORLD_TO_DEVICE); // synchronize the transformation
if(dco.pdc->iGraphicsMode() == GM_COMPATIBLE)
{
bRet = bGetNtoD_Win31(
pfd_xf,
pelfw,
ifio,
(DCOBJ *)&dco,
fl,
pptlSim
);
}
else // GM_ADVANCED
{
bRet = bGetNtoD(
pfd_xf,
pelfw,
ifio,
(DCOBJ *)&dco,
pptlSim
);
}
if (!bRet)
{
WARNING(
"gdisrv!bSetFontXformPFEOBJ(): failed to get Notional to World xform\n"
);
return FALSE;
}
//
// The next line two lines of code flips the sign of the Notional y-coordinates
// The effect is that the XFORMOBJ passed over the DDI makes the assumption that
// Notional space is such that the y-coordinate increases towards the bottom.
// This is opposite to the usual conventions of notional space and the font
// driver writers must be made aware of this historical anomaly.
//
NEGATE_IEEE_FLOAT(pfd_xf->eYX);
NEGATE_IEEE_FLOAT(pfd_xf->eYY);
//
// If the font can be scaled isotropicslly only then we make sure that we send
// to the font driver isotropic transformations.
//
// If a device has set the TA_CR_90 bit, then it is possible
// that we will send to the driver a transformation that is equivalent to an isotropic
// transformation rotated by a multiple of 90 degress. This is the reason for the
// second line of this transformation.
//
if (ifio.bIsotropicScalingOnly())
{
*(LONG*)&(pfd_xf->eXX) = *(LONG*)&(pfd_xf->eYY);
*(LONG*)&(pfd_xf->eXY) = *(LONG*)&(pfd_xf->eYX);
NEGATE_IEEE_FLOAT(pfd_xf->eXY);
}
return (TRUE);
}