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.
1879 lines
52 KiB
1879 lines
52 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-1999 Microsoft Corporation
|
|
\**************************************************************************/
|
|
// #pragma warning (disable: 4509)
|
|
|
|
|
|
#include "precomp.hxx"
|
|
#include "flhack.hxx"
|
|
|
|
BOOL bExtendGlyphSet(FD_GLYPHSET **ppfdgIn, FD_GLYPHSET **ppfdgOut);
|
|
|
|
INT
|
|
__cdecl CompareRoutine(WCHAR *pwc1, WCHAR *pwc2)
|
|
{
|
|
|
|
return(*pwc1-*pwc2);
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* ULONG cComputeGISET
|
|
*
|
|
* similar to cComputeGlyphSet in mapfile.c, computes the number of
|
|
*(_wcsicmp(pwszFaceName, pFaceName) == 0)* 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, PFE * ppfe, GISET **ppgiset)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
*ppgiset = NULL;
|
|
GISET *pgiset;
|
|
|
|
PFEOBJ pfeObj(ppfe);
|
|
PFFOBJ pffo(pfeObj.pPFF());
|
|
PFD_GLYPHSET pfdg = NULL;
|
|
BOOL bTT = (BOOL)(pffo.hdev() == (HDEV) gppdevTrueType);
|
|
|
|
if (!bTT)
|
|
{
|
|
if (!(pfdg = pfeObj.pfdg()))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (bTT || (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 (bTT && (cig == 0)) // most likely a corrupt font
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
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
|
|
|
|
|
|
qsort((void*)pgiBegin, pfdg->cGlyphsSupported, sizeof(WORD),
|
|
(int (__cdecl *)(const void *, const void *))CompareRoutine);
|
|
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bTT)
|
|
pfeObj.vFreepfdg();
|
|
|
|
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******************************\
|
|
* VOID PFEOBJ::vDelete() *
|
|
* *
|
|
* Destroy the PFE physical font entry object. *
|
|
* *
|
|
* History: *
|
|
* 30-Oct-1990 -by- Gilman Wong [gilmanw] *
|
|
* Wrote it. *
|
|
\**************************************************************************/
|
|
|
|
VOID PFEOBJ::vDelete()
|
|
{
|
|
PDEVOBJ pdo(ppfe->pPFF->hdev);
|
|
|
|
// Save driver allocated resources in PFECLEANUP so that we can later
|
|
// call the driver to free them.
|
|
|
|
if ((ppfe->pifi->jWinCharSet == SYMBOL_CHARSET) &&
|
|
(ppfe->pfdg != NULL) &&
|
|
(ppfe->pfdg->flAccel & GS_EXTENDED))
|
|
{
|
|
VFREEMEM(ppfe->pfdg);
|
|
}
|
|
else
|
|
{
|
|
if ((ppfe->pfdg != NULL) && PPFNVALID(pdo,Free))
|
|
{
|
|
pdo.Free(ppfe->pfdg, ppfe->idfdg);
|
|
}
|
|
}
|
|
|
|
if (PPFNVALID(pdo,Free))
|
|
{
|
|
pdo.Free(ppfe->pifi, ppfe->idifi);
|
|
if (ppfe->pkp != &gkpNothing)
|
|
{
|
|
pdo.Free(ppfe->pkp , ppfe->idkp );
|
|
}
|
|
}
|
|
|
|
ppfe->pfdg = NULL;
|
|
ppfe->pifi = NULL;
|
|
|
|
ppfe->pkp = NULL;
|
|
|
|
if (ppfe->pgiset)
|
|
{
|
|
VFREEMEM(ppfe->pgiset);
|
|
ppfe->pgiset = NULL;
|
|
}
|
|
|
|
// Free object memory and invalidate pointer.
|
|
|
|
ppfe = PPFENULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* dpNtmi()
|
|
*
|
|
* offset to NTMW_INTERNAL within ENUMFONTDATAW, needed in enumeration
|
|
*
|
|
* History:
|
|
* 19-Nov-1996 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
|
|
ULONG PFEOBJ::dpNtmi()
|
|
{
|
|
ULONG dpRet = DP_NTMI0;
|
|
|
|
if (ppfe->pifi->flInfo & FM_INFO_TECH_MM)
|
|
{
|
|
PTRDIFF dpDesVec = 0;
|
|
DESIGNVECTOR *pdvSrc;
|
|
|
|
if (ppfe->pifi->cjIfiExtra > offsetof(IFIEXTRA, dpDesignVector))
|
|
{
|
|
dpDesVec = ((IFIEXTRA *)(ppfe->pifi + 1))->dpDesignVector;
|
|
pdvSrc = (DESIGNVECTOR *)((BYTE *)ppfe->pifi + dpDesVec);
|
|
dpRet += (pdvSrc->dvNumAxes * sizeof(LONG));
|
|
}
|
|
else
|
|
{
|
|
DbgPrint("Test it %d %d \n", ppfe->pifi->cjIfiExtra, offsetof(IFIEXTRA, dpDesignVector));
|
|
ASSERTGDI(dpDesVec, "dpDesignVector == 0 for mm instance\n");
|
|
}
|
|
|
|
}
|
|
|
|
return dpRet;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* IsAnyCharsetDbcs
|
|
*
|
|
* Does this font support any DBCS charset?
|
|
*
|
|
* History:
|
|
* 22-Jun-1998 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
extern "C" BOOL IsAnyCharsetDbcs(IFIMETRICS *pifi)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
if (IS_ANY_DBCS_CHARSET(pifi->jWinCharSet))
|
|
return TRUE;
|
|
|
|
if (pifi->dpCharSets)
|
|
{
|
|
BYTE *aCharSets = (BYTE *)pifi + pifi->dpCharSets;
|
|
|
|
for ( ;*aCharSets != DEFAULT_CHARSET; aCharSets++)
|
|
{
|
|
if (IS_ANY_DBCS_CHARSET(*aCharSets))
|
|
{
|
|
bRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* PFEOBG::pfdg()
|
|
*
|
|
* If pfdg is NULL then we need to get it from font driver
|
|
* If pfdg is valid then we only need to return it.
|
|
*
|
|
* Return
|
|
* FD_GLYPHSET *
|
|
*
|
|
* History
|
|
* 08-March-1999 -by- Yung-Jen Tony Tsai [yungt]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
FD_GLYPHSET * PFEOBJ::pfdg()
|
|
{
|
|
PFFOBJ pffo(pPFF());
|
|
PDEVOBJ pdo(pffo.hdev());
|
|
BOOL bFreeTmp = FALSE;
|
|
FD_GLYPHSET *pfdgTmp = NULL;
|
|
ULONG_PTR idGlyphSet;
|
|
|
|
GreAcquireSemaphore(ghsemGlyphSet);
|
|
|
|
if (ppfe->pfdg == NULL)
|
|
{
|
|
ASSERTGDI(ppfe->cPfdgRef == 0, "PFEOBJ::pfdg is not matched with cRef\n");
|
|
|
|
GreReleaseSemaphore(ghsemGlyphSet);
|
|
|
|
BOOL bUMPD = pdo.bUMPD();
|
|
|
|
pfdgTmp = (FD_GLYPHSET *) pdo.QueryFontTree(pffo.dhpdev(),
|
|
pffo.hff(),
|
|
iFont(),
|
|
QFT_GLYPHSET,
|
|
&idGlyphSet);
|
|
GreAcquireSemaphore(ghsemGlyphSet);
|
|
|
|
if (pfdgTmp)
|
|
{
|
|
if (ppfe->pfdg == NULL)
|
|
{
|
|
ppfe->pfdg = pfdgTmp;
|
|
ppfe->idfdg = idGlyphSet;
|
|
|
|
// For UMPD
|
|
|
|
if (bUMPD)
|
|
{
|
|
if (ppfe->pifi->jWinCharSet == SYMBOL_CHARSET)
|
|
{
|
|
FD_GLYPHSET *pfdgNew = NULL;
|
|
|
|
if (bExtendGlyphSet(&pfdgTmp, &pfdgNew))
|
|
{
|
|
bFreeTmp = TRUE;
|
|
ppfe->pfdg = pfdgNew;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
bFreeTmp = TRUE;
|
|
}
|
|
}
|
|
|
|
if (ppfe->pfdg)
|
|
ppfe->cPfdgRef++;
|
|
|
|
GreReleaseSemaphore(ghsemGlyphSet);
|
|
|
|
if (bFreeTmp)
|
|
{
|
|
if (PPFNVALID(pdo,Free))
|
|
{
|
|
pdo.Free(pfdgTmp, idGlyphSet);
|
|
}
|
|
}
|
|
|
|
return ppfe->pfdg;
|
|
}
|
|
|
|
extern "C" VOID ttfdFreeGlyphset(ULONG_PTR iFile, ULONG iFace);
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* PFEOBG::vFreepfdg()
|
|
*
|
|
* If pfdg is valid then we free it.
|
|
* If pfdg is NULL then return.
|
|
*
|
|
* Return
|
|
* VOID
|
|
*
|
|
* History
|
|
* 08-March-1999 -by- Yung-Jen Tony Tsai [yungt]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
VOID PFEOBJ::vFreepfdg()
|
|
{
|
|
PFFOBJ pffo(pPFF());
|
|
FD_GLYPHSET *pfdgTmp = NULL;
|
|
ULONG_PTR idGlyphSet;
|
|
|
|
GreAcquireSemaphore(ghsemGlyphSet);
|
|
|
|
ASSERTGDI(ppfe->cPfdgRef, "cRef of pfdg is wrong\n");
|
|
|
|
ppfe->cPfdgRef--;
|
|
|
|
if (ppfe->cPfdgRef == 0)
|
|
{
|
|
if (pffo.hdev() == (HDEV) gppdevTrueType)
|
|
{
|
|
ttfdFreeGlyphset(pffo.hff(), iFont()) ;
|
|
ppfe->pfdg = NULL;
|
|
}
|
|
else
|
|
{
|
|
PDEVOBJ pdo(pffo.hdev());
|
|
if (pdo.bUMPD() && PPFNVALID(pdo,Free))
|
|
{
|
|
if ((ppfe->pifi->jWinCharSet == SYMBOL_CHARSET) &&
|
|
(ppfe->pfdg != NULL) &&
|
|
(ppfe->pfdg->flAccel & GS_EXTENDED))
|
|
{
|
|
VFREEMEM(ppfe->pfdg);
|
|
}
|
|
else
|
|
{
|
|
pfdgTmp = ppfe->pfdg;
|
|
idGlyphSet = ppfe->idfdg;
|
|
}
|
|
ppfe->pfdg = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
GreReleaseSemaphore(ghsemGlyphSet);
|
|
|
|
if (pfdgTmp)
|
|
{
|
|
PDEVOBJ pdo(pffo.hdev());
|
|
pdo.Free(pfdgTmp, idGlyphSet);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/******************************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;
|
|
|
|
// check if this is a postscript font
|
|
|
|
if (pifi()->flInfo & FM_INFO_TECH_TYPE1)
|
|
{
|
|
flRet |= FO_POSTSCRIPT;
|
|
|
|
if (pifi()->flInfo & FM_INFO_TECH_MM)
|
|
flRet |= FO_MULTIPLEMASTER;
|
|
|
|
if (pifi()->flInfo & FM_INFO_TECH_CFF)
|
|
flRet |= FO_CFF;
|
|
}
|
|
|
|
if (ppfe->flPFE & PFE_DBCS_FONT)
|
|
{
|
|
flRet |= FO_DBCS_FONT;
|
|
|
|
if (ppfe->flPFE & PFE_VERT_FACE)
|
|
flRet |= FO_VERT_FACE;
|
|
}
|
|
|
|
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*)
|
|
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!
|
|
|
|
__try
|
|
{
|
|
while ((pkpEnd->wcFirst) || (pkpEnd->wcSecond) || (pkpEnd->fwdKern))
|
|
pkpEnd += 1;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
pkpEnd = ppfe->pkp = &gkpNothing;
|
|
}
|
|
|
|
// Return the kerning pair pointer.
|
|
|
|
*ppkp = ppfe->pkp;
|
|
|
|
//
|
|
// Return count (difference between the beginning and end pointers).
|
|
//
|
|
|
|
//Sundown truncation
|
|
|
|
ASSERT4GB((LONGLONG)(pkpEnd - ppfe->pkp));
|
|
|
|
return (ppfe->ckp = (ULONG)(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_PTR idfdg, // driver ID for wc-->hg map
|
|
PIFIMETRICS pifi, // ptr to IFIMETRICS
|
|
ULONG_PTR idifi, // driver ID for IFIMETRICS
|
|
BOOL bDeviceFont, // mark as device font
|
|
PUNIVERSAL_FONT_ID pufi, // PFE_UFIMATCH flag for remote printing
|
|
BOOL bEUDC // mark as EUDC font
|
|
|
|
)
|
|
{
|
|
// 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->idkp = (ULONG_PTR) NULL;
|
|
ppfe->ckp = 0;
|
|
ppfe->flPFE = 0;
|
|
ppfe->pid = 0;
|
|
ppfe->tid = 0;
|
|
ppfe->cPfdgRef = 0;
|
|
|
|
IFIOBJ ifio(ppfe->pifi);
|
|
|
|
if (IsAnyCharsetDbcs(ppfe->pifi))
|
|
ppfe->flPFE |= PFE_DBCS_FONT;
|
|
|
|
if (*ifio.pwszFamilyName() == U_COMMERCIAL_AT)
|
|
ppfe->flPFE |= PFE_VERT_FACE;
|
|
|
|
// for base font attach full axes info, else, do not.
|
|
|
|
ppfe->cjEfdwPFE = ALIGN4(dpNtmi() + CJ_NTMI0);
|
|
|
|
if (pifi->flInfo & FM_INFO_TECH_MM) // if base mm font
|
|
{
|
|
PTRDIFF dpAXIW = 0;
|
|
AXESLISTW *paxlSrc;
|
|
|
|
if (pifi->cjIfiExtra > offsetof(IFIEXTRA, dpAxesInfoW))
|
|
{
|
|
dpAXIW = ((IFIEXTRA *)(pifi + 1))->dpAxesInfoW;
|
|
paxlSrc = (AXESLISTW *)((BYTE*)pifi + dpAXIW);
|
|
ppfe->cjEfdwPFE += (paxlSrc->axlNumAxes * sizeof(AXISINFOW));
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI(dpAXIW, "AxesInfoW needed for base MM font\n");
|
|
}
|
|
}
|
|
|
|
ASSERTGDI(ppfe->cjEfdwPFE >= CJ_EFDW0, "cjEfdwPFE problem\n");
|
|
|
|
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
|
|
// or memory
|
|
|
|
if (pPFF->flState & PFF_STATE_MEMORY_FONT)
|
|
{
|
|
ppfe->flPFE |= PFE_MEMORYFONT;
|
|
}
|
|
else
|
|
{
|
|
ppfe->flPFE |= PFE_REMOTEFONT;
|
|
}
|
|
ppfe->pid = W32GetCurrentPID();
|
|
ppfe->tid = (PW32THREAD)PsGetCurrentThread();
|
|
}
|
|
|
|
// For remote printing, fonts are added to the public font table with FR_NOT_ENUM and PFE_UFIMATCH
|
|
// flags set so that other process won't be able to enum or map the fonts.
|
|
|
|
if (pufi)
|
|
{
|
|
ppfe->flPFE |= PFE_UFIMATCH;
|
|
}
|
|
|
|
#ifdef FE_SB
|
|
if( bEUDC )
|
|
{
|
|
ppfe->flPFE |= PFE_EUDC;
|
|
}
|
|
|
|
// mark it as a SBCS system font if the facename is right
|
|
|
|
PWSZ pwszFace = ifio.pwszFaceName();
|
|
|
|
if(pwszFace[0] == '@')
|
|
{
|
|
pwszFace += 1;
|
|
}
|
|
|
|
if(!_wcsicmp(pwszFace,L"SYSTEM") ||
|
|
!_wcsicmp(pwszFace,L"FIXEDSYS") ||
|
|
!_wcsicmp(pwszFace,L"TERMINAL") ||
|
|
((!_wcsicmp(pwszFace,L"SMALL FONTS") &&
|
|
ifio.lfCharSet() == SHIFTJIS_CHARSET)))
|
|
{
|
|
ppfe->flPFE |= PFE_SBCS_SYSTEM;
|
|
}
|
|
|
|
// 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;
|
|
if (pufi)
|
|
{
|
|
// need to ensure that ufi of this pfe on the server machine is
|
|
// the same as it used to be on the client. Client side ufi
|
|
// one of the pfe's corresponding to this font is pointed to by pufi.
|
|
|
|
ppfe->ufi.Index += ((pufi->Index - 1) & ~1);
|
|
}
|
|
|
|
}
|
|
|
|
// init the GISET
|
|
|
|
if(!bComputeGISET(pifi, ppfe, &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++] = (BYTE)(pfs-gpfsTable);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL PFEOBJ::bCheckFamilyName(const WCHAR * pwszFaceName, BOOL bIgonreVertical, BOOL *pbAliasMatch)
|
|
{
|
|
PWSZ pFaceName;
|
|
BOOL bRet;
|
|
|
|
if (pbAliasMatch)
|
|
{
|
|
*pbAliasMatch = FALSE;
|
|
}
|
|
|
|
pFaceName = (PWSZ) (((BYTE*) ppfe->pifi) + ppfe->pifi->dpwszFamilyName);
|
|
|
|
if (bIgonreVertical && (*pFaceName == L'@'))
|
|
pFaceName++;
|
|
|
|
bRet = (_wcsicmp(pwszFaceName, pFaceName) == 0);
|
|
|
|
if (!bRet && (ppfe->pifi->flInfo & FM_INFO_FAMILY_EQUIV))
|
|
{
|
|
pFaceName += (wcslen(pFaceName) + 1);
|
|
while(!bRet && *pFaceName)
|
|
{
|
|
if (bIgonreVertical && (*pFaceName == L'@'))
|
|
pFaceName++;
|
|
bRet = (_wcsicmp(pwszFaceName, pFaceName) == 0);
|
|
pFaceName += (wcslen(pFaceName) + 1);
|
|
}
|
|
|
|
// for the font mapper only: If match is found among family name aliases,
|
|
// increase the font mapping penalty
|
|
|
|
if (pbAliasMatch)
|
|
{
|
|
*pbAliasMatch = bRet;
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL PFEOBJ::bFilterNotEnum()
|
|
*
|
|
* Used by bFilterOut() in GreEnumOpen(). It checks whether the pfe should
|
|
* be filtered out because it is either an embedded font or it is loaded to
|
|
* the system with FR_NOT_ENUM bit set.
|
|
*
|
|
* Returns:
|
|
* TRUE if embedded or FR_NOT_ENUM set, FALSE otherwise.
|
|
*
|
|
* History:
|
|
*
|
|
* 12-Jun-1996 -by- Xudong Wu [TessieW]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
BOOL PFEOBJ::bFilterNotEnum()
|
|
{
|
|
PFFOBJ pffo(pPFF());
|
|
ASSERTGDI(pffo.bValid(), "win32k!PFEOBJ::bFilterEmbPvt(): invalid PPFF\n");
|
|
PVTDATA *pPvtData;
|
|
BOOL bRet = TRUE;
|
|
|
|
if (pffo.bInPrivatePFT())
|
|
{
|
|
// Look for a PvtData block for the current process
|
|
|
|
if ((pPvtData = pffo.pPvtDataMatch()) && (pPvtData->cNotEnum == 0))
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
// public fonts, filter out FR_NOT_ENUM only
|
|
|
|
else if (pffo.cLoaded())
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/***********************Public*Routine***********************\
|
|
* BOOL PFEOBJ::bPrivate()
|
|
*
|
|
* Determine whether the pfe is in private PFT table
|
|
*
|
|
* History:
|
|
*
|
|
* 16-April-1997 -by- Xudong Wu [TessieW]
|
|
* Wrote it.
|
|
*************************************************************/
|
|
BOOL PFEOBJ::bPrivate()
|
|
{
|
|
return (ppfe->pPFF->pPFT == gpPFTPrivate);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL PFEOBJ::bEmbedOk()
|
|
*
|
|
* Determine if the font is added as embedded by the current process
|
|
*
|
|
* Returns:
|
|
* TRUE if the font is added by the current process as embedded font
|
|
* FALSE otherwise.
|
|
*
|
|
* History:
|
|
*
|
|
* 24-Sept-1996 -by- Xudong Wu [TessieW]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
BOOL PFEOBJ::bEmbedOk()
|
|
{
|
|
PVTDATA *pPvtData;
|
|
|
|
PFFOBJ pffo(pPFF());
|
|
ASSERTGDI(pffo.bValid(), "win32k!PFEOBJ::bEmbedOk(): invalid PPFF\n");
|
|
ASSERTGDI(pffo.bInPrivatePFT(), "win32k!PFEOBJ::bEmbedOk(): pfe not in private PFT\n");
|
|
|
|
// embedded font added by the current process
|
|
|
|
if ((pPvtData = pffo.pPvtDataMatch()) && (pPvtData->fl & (FRW_EMB_TID | FRW_EMB_PID)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL PFEOBJ::bEmbPvtOk()
|
|
*
|
|
* Determine whether the current process has right to mapping this font
|
|
*
|
|
* Returns:
|
|
* TRUE pfe in public PFT or
|
|
* font has been loaded into Private PFT by the current process
|
|
*
|
|
* FALSE otherwise
|
|
*
|
|
* History:
|
|
*
|
|
* 24-Sept-1996 -by- Xudong Wu [TessieW]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
BOOL PFEOBJ::bEmbPvtOk()
|
|
{
|
|
PFFOBJ pffo(pPFF());
|
|
ASSERTGDI(pffo.bValid(), "win32k!PFEOBJ::bEmbPvtOk(): invalid PPFF\n");
|
|
|
|
// can't find the current process ID in the PvtData link list
|
|
|
|
if (pffo.bInPrivatePFT() && (pffo.pPvtDataMatch() == NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* HPFEC PFEOBJ::hpfecGet()
|
|
*
|
|
* Get the handle of PFE collect, a new object to reduce the consumption of object handle
|
|
*
|
|
* Returns:
|
|
* Hanlde of PFEC object
|
|
* History:
|
|
*
|
|
* 2-June-1996 -by- Yung-Jen Tony Tsai [YungT]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HPFEC PFEOBJ::hpfecGet()
|
|
{
|
|
PFFOBJ pffo(ppfe->pPFF);
|
|
|
|
ASSERTGDI(((HPFEC)pffo.pfec()->hGet()) != HPFEC_INVALID, " PFEOBJ::hpfecGet error\n");
|
|
return((HPFEC)pffo.pfec()->hGet());
|
|
}
|
|
|
|
/******************************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 or the fonts with FR_NOT_ENUM bit set.
|
|
|
|
if (bFilterNotEnum())
|
|
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/memory font we don't want to enumerate it
|
|
|
|
if( ppfe->flPFE & (PFE_REMOTEFONT | PFE_MEMORYFONT) )
|
|
{
|
|
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, *this);
|
|
|
|
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%p\n", ppfeGet());
|
|
DbgPrint("pPFF = 0x%p\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%p\n", ppfeGet());
|
|
DbgPrint("pPFF = 0x%p\n", ppfe->pPFF);
|
|
DbgPrint("iFont = 0x%p\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((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.
|
|
|
|
PFEOBJ pfeo(ppfe);
|
|
|
|
HPFEC hpfec = pfeo.hpfecGet();
|
|
ULONG iFont = ppfe->iFont;
|
|
pefs->pefeDataEnd->hpfec = hpfec;
|
|
pefs->pefeDataEnd->iFont = iFont;
|
|
|
|
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;
|
|
pefs->cjEfdwTotal += ppfe->cjEfdwPFE;
|
|
|
|
// 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->hpfec = hpfec;
|
|
pefs->pefeDataEnd->iFont = iFont;
|
|
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;
|
|
pefs->cjEfdwTotal += ppfe->cjEfdwPFE;
|
|
}
|
|
}
|
|
|
|
// 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->hpfec = hpfec;
|
|
pefs->pefeDataEnd->iFont = iFont;
|
|
pefs->pefeDataEnd->efsty = efsty;
|
|
pefs->pefeDataEnd->fjOverride = FJ_CHARSETOVERRIDE;
|
|
pefs->pefeDataEnd->iOverride = 0;
|
|
pefs->pefeDataEnd->jCharSetOverride = *pjCharSets;
|
|
pefs->pefeDataEnd += 1;
|
|
pefs->cjEfdwTotal += ppfe->cjEfdwPFE;
|
|
}
|
|
}
|
|
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->pfsubOverride = NULL;
|
|
|
|
// init the enum type:
|
|
|
|
pefs->iEnumType = iEnumType_;
|
|
|
|
// empty for now, total enumeration data size is zero
|
|
|
|
pefs->cjEfdwTotal = 0;
|
|
|
|
// 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.
|
|
//
|
|
|
|
// Sundown truncation
|
|
ASSERT4GB ((ULONGLONG)(pefs->pefeDataEnd - pefs->aefe));
|
|
COUNT cefe = (COUNT)(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 and size of enumeration data
|
|
|
|
pefs->pefeDataEnd = pefs->aefe + cefe;
|
|
pefs->cjEfdwTotal = pefsSrc->cjEfdwTotal;
|
|
|
|
// iEnumType has been set at the vInit time, it does not have to be reset now.
|
|
// Therefore we are done.
|
|
|
|
|
|
}
|
|
|
|
|
|
/******************************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);
|
|
}
|
|
|
|
|
|
|
|
/******************************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
|
|
LOGFONTW *pelfw, // wish list (in logical coords)
|
|
PFD_XFORM pfd_xf, // font transform
|
|
FLONG fl,
|
|
FLONG flSim,
|
|
POINTL* const pptlSim,
|
|
IFIOBJ& ifio,
|
|
BOOL bIsLinkedFont // TRUE if the font is linked, FALSE otherwise
|
|
)
|
|
{
|
|
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,
|
|
bIsLinkedFont
|
|
);
|
|
}
|
|
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);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* PFE * PFECOBJ::GetPFE(ULONG iFont)
|
|
*
|
|
* Get PFE from PFE collect, a new object to reduce the consumption of object handle
|
|
*
|
|
* Returns:
|
|
* memory pointer of PFE
|
|
* History:
|
|
*
|
|
* 2-June-1996 -by- Yung-Jen Tony Tsai [YungT]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PFE * PFECOBJ::GetPFE(ULONG iFont)
|
|
{
|
|
PFE * ppfe = NULL;
|
|
|
|
if (ppfec)
|
|
{
|
|
ASSERTGDI(ppfec->pvPFE, "PFECOBJ::GetPFE ppfset->pvPFE is null \n");
|
|
ppfe = (PFE *) ((PBYTE) ppfec->pvPFE + ((iFont - 1) * ppfec->cjPFE));
|
|
}
|
|
|
|
return ppfe;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* HPFEC PFECOBJ::GetHPFEC()
|
|
*
|
|
* Get handle of PFEC from PFE collect, a new object to reduce the consumption of object handle
|
|
*
|
|
* Returns:
|
|
* Handle of PFEC
|
|
* History:
|
|
*
|
|
* 2-June-1996 -by- Yung-Jen Tony Tsai [YungT]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HPFEC PFECOBJ::GetHPFEC()
|
|
{
|
|
ASSERTGDI(ppfec, "PFECOBJ::GetHPFEC ppfec is NULL \n");
|
|
|
|
return((HPFEC) ppfec->hGet());
|
|
}
|