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.
2037 lines
60 KiB
2037 lines
60 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: pffobj.cxx
|
|
*
|
|
* Non-inline methods for physical font file objects.
|
|
*
|
|
* Copyright (c) 1991-1999 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
extern PW32PROCESS gpidSpool;
|
|
|
|
// Define the global PFT semaphore. This must be held to access any of the
|
|
// physical font information.
|
|
|
|
#if DBG
|
|
extern FLONG gflFontDebug;
|
|
#endif
|
|
|
|
extern "C" void FreeFileView(PFONTFILEVIEW *ppfv, ULONG cFiles);
|
|
extern "C" ULONG ComputeFileviewCheckSum(PVOID, ULONG);
|
|
|
|
ULONG ComputeFileviewCheckSum(PVOID pvView, ULONG cjView)
|
|
{
|
|
ULONG sum;
|
|
PULONG pulCur,pulEnd;
|
|
|
|
pulCur = (PULONG) pvView;
|
|
|
|
__try
|
|
{
|
|
for (sum = 0, pulEnd = pulCur + cjView / sizeof(ULONG); pulCur < pulEnd; pulCur += 1)
|
|
{
|
|
sum += 256 * sum + *pulCur;
|
|
}
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("win32k: exception while computing font check sum\n");
|
|
sum = 0; // oh well, not very unique.
|
|
}
|
|
|
|
return ( sum < 2 ) ? 2 : sum; // 0 is reserved for device fonts
|
|
// 1 is reserved for TYPE1 fonts
|
|
}
|
|
|
|
PFFMEMOBJ::PFFMEMOBJ(
|
|
PFF *pPFFCloned,
|
|
FLONG fl, // indicates if a permanent font
|
|
FLONG flEmbed, // embedding flag
|
|
PFT *pPFTParent // contains this pff
|
|
)
|
|
{
|
|
if ( pPFF = (PFF *) PALLOCMEM((size_t)pPFFCloned->sizeofThis, 'ffpG'))
|
|
{
|
|
RtlCopyMemory((PBYTE) pPFF, (PBYTE) pPFFCloned, offsetof(PFF,aulData));
|
|
|
|
pPFF->pPFFPrev = 0;
|
|
pPFF->pPFFNext = 0;
|
|
|
|
// Wet the implicit stuff.
|
|
|
|
pPFF->cFonts = 0; // faces not loaded into table yet
|
|
pPFF->cRFONT = 0; // nothing realized from this file yet
|
|
pPFF->flState = fl;
|
|
pPFF->pfhFace = 0;
|
|
pPFF->pfhFamily = 0;
|
|
pPFF->pfhUFI = 0;
|
|
pPFF->prfntList = 0; // initialize to NULL list
|
|
pPFF->pPFT = pPFTParent;
|
|
|
|
pPFF->pPvtDataHead = NULL; // initialize to NULL link list
|
|
|
|
// loaded with FR_PRIVATE, FR_PRIVATE | FR_NOT_ENUM, FRW_EMB_PID, FRW_EMB_TID
|
|
// the load count (cPirvate or cNotEnum) is initialized in PvtData structure per process
|
|
|
|
if (flEmbed & (FR_PRIVATE | FRW_EMB_PID | FRW_EMB_TID))
|
|
{
|
|
pPFF->cLoaded = 0;
|
|
pPFF->cNotEnum = 0;
|
|
bAddPvtData(flEmbed);
|
|
}
|
|
|
|
// file is loaded as NOT_ENUM only
|
|
|
|
else if ( flEmbed & FR_NOT_ENUM )
|
|
{
|
|
pPFF->cLoaded = 0;
|
|
pPFF->cNotEnum = 1;
|
|
}
|
|
|
|
// file is loaded as public
|
|
|
|
else
|
|
{
|
|
pPFF->cLoaded = 1;
|
|
pPFF->cNotEnum = 0;
|
|
}
|
|
|
|
// Mark this PFF as cloned
|
|
pPFFCloned->pPFFClone = pPFF;
|
|
pPFF->pPFFClone = pPFFCloned;
|
|
|
|
}
|
|
else
|
|
{
|
|
WARNING("invalid PFFMEMOBJ\n");
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* PFFMEMOBJ::PFFMEMOBJ
|
|
*
|
|
* Constructor for default sized physical font file memory object.
|
|
*
|
|
* cFonts = # fonts in file or device
|
|
* pwsz = pointer to upper case Unicode string containing the full
|
|
* path to the font file. This pointer is set to zero, by
|
|
* default for fonts loaded from a device.
|
|
*
|
|
* History:
|
|
* Thu 01-Sep-1994 06:29:47 by Kirk Olynyk [kirko]
|
|
* Put the size calculation logic in the constructor thereby modularizing
|
|
* and shrinking the code.
|
|
* Tue 09-Nov-1993 -by- Patrick Haluptzok [patrickh]
|
|
* Remove from handle manager
|
|
* 02-Jan-1991 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PFFMEMOBJ::PFFMEMOBJ(
|
|
unsigned cFonts // number of fonts in file|device
|
|
, PWSZ pwsz // if font file this is an upper case path
|
|
, ULONG cwc // number of characters in the mul path above
|
|
, ULONG cFiles // number of files
|
|
, DESIGNVECTOR *pdv // design vector, only present for mm instances
|
|
, ULONG cjDV // size of design vector
|
|
, HFF hffFontFile // IFI driver's handle to file
|
|
, HDEV hdevDevice // physical device handle
|
|
, DHPDEV dhpdevDevice // driver's pdev handle
|
|
, PFT *pPFTParent // contains this pff
|
|
, FLONG fl // indicates if a permanent font
|
|
, FLONG flEmbed // embedding flag
|
|
, PFNTCHECKSUM pFntCheckSum
|
|
, PFONTFILEVIEW *ppfv // ptr to FILEVIEW structure
|
|
, PUNIVERSAL_FONT_ID pufi // ptr to original UFI used in remote printing
|
|
)
|
|
{
|
|
ULONG size = offsetof(PFF,aulData) + cFonts * sizeof(PFE*);
|
|
ULONG dpDV = 0;
|
|
ULONG dpPathName = 0;
|
|
|
|
ASSERTGDI(hdevDevice, "PFFMEMOBJ passed NULL hdevDevice\n");
|
|
ASSERTGDI(pFntCheckSum, "pFntCheckSum is NULL\n");
|
|
|
|
fs = 0;
|
|
|
|
if (pwsz)
|
|
{
|
|
dpPathName = size;
|
|
size += ALIGN4(cwc*sizeof(WCHAR));
|
|
}
|
|
|
|
if (cjDV)
|
|
{
|
|
dpDV = size;
|
|
size += cjDV;
|
|
}
|
|
|
|
if (pPFF = (PFF *) PALLOCMEM(size, 'ffpG'))
|
|
{
|
|
pPFF->sizeofThis = size;
|
|
pPFF->pPFFPrev = 0;
|
|
pPFF->pPFFNext = 0;
|
|
pPFF->hff = hffFontFile;
|
|
pPFF->hdev = hdevDevice;
|
|
pPFF->dhpdev = dhpdevDevice;
|
|
pPFF->pPFT = pPFTParent;
|
|
pPFF->cFiles = cFiles;
|
|
|
|
pPFF->cwc = cwc;
|
|
if (cwc)
|
|
{
|
|
pPFF->pwszPathname_ = (PWSZ)((BYTE *)pPFF + dpPathName);
|
|
RtlCopyMemory(pPFF->pwszPathname_, pwsz, cwc * sizeof(WCHAR));
|
|
}
|
|
else
|
|
{
|
|
pPFF->pwszPathname_ = 0;
|
|
}
|
|
|
|
pPFF->cjDV_ = cjDV;
|
|
if (cjDV)
|
|
{
|
|
pPFF->pdv_ = (DESIGNVECTOR *)((BYTE *)pPFF + dpDV);
|
|
RtlCopyMemory(pPFF->pdv_, pdv, cjDV);
|
|
}
|
|
else
|
|
{
|
|
pPFF->pdv_ = NULL;
|
|
}
|
|
|
|
pPFF->ppfv = ppfv;
|
|
|
|
// Wet the implicit stuff.
|
|
|
|
pPFF->cFonts = 0; // faces not loaded into table yet
|
|
pPFF->cRFONT = 0; // nothing realized from this file yet
|
|
pPFF->flState = fl;
|
|
pPFF->pfhFace = 0;
|
|
pPFF->pfhFamily = 0;
|
|
pPFF->pfhUFI = 0;
|
|
pPFF->prfntList = 0; // initialize to NULL list
|
|
|
|
pPFF->pPvtDataHead = NULL; // initialize to NULL link list
|
|
|
|
// loaded with FR_PRIVATE, FR_PRIVATE | FR_NOT_ENUM, FRW_EMB_PID, FRW_EMB_TID
|
|
// the load count (cPirvate or cNotEnum) is initialized in PvtData structure per process
|
|
|
|
if (flEmbed & (FR_PRIVATE | FRW_EMB_PID | FRW_EMB_TID))
|
|
{
|
|
pPFF->cLoaded = 0;
|
|
pPFF->cNotEnum = 0;
|
|
bAddPvtData(flEmbed);
|
|
}
|
|
|
|
// file is loaded as NOT_ENUM only
|
|
|
|
else if ( flEmbed & FR_NOT_ENUM )
|
|
{
|
|
pPFF->cLoaded = 0;
|
|
pPFF->cNotEnum = 1;
|
|
}
|
|
|
|
// file is loaded as public
|
|
|
|
else
|
|
{
|
|
pPFF->cLoaded = 1;
|
|
pPFF->cNotEnum = 0;
|
|
}
|
|
|
|
// Mark this PFF as not cloned
|
|
|
|
pPFF->pPFFClone = NULL;
|
|
|
|
pPFF->ulCheckSum = 0; // for device fonts it is zero
|
|
|
|
if(pufi != NULL)
|
|
{
|
|
pPFF->ulCheckSum = pufi->CheckSum;
|
|
}
|
|
else
|
|
{
|
|
if (ppfv != NULL)
|
|
{
|
|
|
|
pPFF->ulCheckSum = pFntCheckSum->ulCheckSum;
|
|
|
|
|
|
if (!pPFF->ulCheckSum)
|
|
{
|
|
// not in the boot, or could not find it in the ttfcache for some reason
|
|
// Now compute the UFI
|
|
|
|
KeAttachProcess(PsGetProcessPcb(gpepCSRSS));
|
|
for (ULONG iFile = 0; iFile < cFiles; iFile ++)
|
|
{
|
|
pPFF->ulCheckSum += ComputeFileviewCheckSum(ppfv[iFile]->fv.pvViewFD, ppfv[iFile]->fv.cjView);
|
|
}
|
|
KeDetachProcess();
|
|
|
|
PutFNTCacheCheckSum(pFntCheckSum->ulFastCheckSum, pPFF->ulCheckSum);
|
|
}
|
|
|
|
ASSERTGDI(pPFF->ulCheckSum, "pPFF->ulCheckSum must not be zero\n");
|
|
|
|
if (pPFF->cjDV_)
|
|
{
|
|
pPFF->ulCheckSum += ComputeFileviewCheckSum(pdv, cjDV);
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
// do it old way, and compare values in DBG mode
|
|
|
|
if (ppfv != NULL)
|
|
{
|
|
ULONG ulCheckSumTest = 0;
|
|
|
|
// Now compute the UFI
|
|
|
|
KeAttachProcess(PsGetProcessPcb(gpepCSRSS));
|
|
for (ULONG iFile = 0; iFile < cFiles; iFile ++)
|
|
{
|
|
ulCheckSumTest += ComputeFileviewCheckSum(ppfv[iFile]->fv.pvViewFD, ppfv[iFile]->fv.cjView);
|
|
}
|
|
KeDetachProcess();
|
|
|
|
if (pPFF->cjDV_)
|
|
{
|
|
ulCheckSumTest += ComputeFileviewCheckSum(pdv, cjDV);
|
|
}
|
|
|
|
if (ulCheckSumTest != pPFF->ulCheckSum)
|
|
{
|
|
DbgPrint(" TrueType font cache failed, if you see these message \n");
|
|
DbgPrint(" Please contact YungT or NTFonts \n");
|
|
DbgPrint(" it is ok to hit 'g' \n");
|
|
DbgBreakPoint();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("invalid PFFMEMOBJ\n");
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* PFFMEMOBJ::~PFFMEMOBJ()
|
|
*
|
|
* Destructor for physical font file memory object.
|
|
*
|
|
* History:
|
|
* Tue 09-Nov-1993 -by- Patrick Haluptzok [patrickh]
|
|
* Remove from handle manager
|
|
*
|
|
* 02-Jan-1991 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PFFMEMOBJ::~PFFMEMOBJ()
|
|
{
|
|
if ((fs & PFFMO_KEEPIT) == 0)
|
|
{
|
|
if (pPFF)
|
|
{
|
|
VFREEMEM(pPFF);
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL PFFOBJ::bCreatePFEC(ULONG cFonts)
|
|
*
|
|
* Create the handle of PFE collect, a object to reduce the consumption of object handle
|
|
*
|
|
* Returns:
|
|
* TRUE means we create successfully
|
|
*
|
|
* History:
|
|
*
|
|
* 2-June-1996 -by- Yung-Jen Tony Tsai [YungT]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL PFFOBJ::bCreatePFEC(ULONG cFonts)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
ASSERTGDI(cFonts, "PFFOBJ::bCreateHPFE cFonts is zero \n");
|
|
|
|
pPFF->pPFEC = (PFEC *) HmgAlloc(sizeof(PFEC), PFE_TYPE, HMGR_ALLOC_ALT_LOCK | HMGR_MAKE_PUBLIC);
|
|
|
|
if (pPFF->pPFEC)
|
|
{
|
|
pPFF->pPFEC->pvPFE = (PVOID) PALLOCMEM(SZ_PFE(gcfsCharSetTable) * cFonts, 'efpG');
|
|
pPFF->pPFEC->cjPFE = SZ_PFE(gcfsCharSetTable);
|
|
|
|
if (pPFF->pPFEC->pvPFE)
|
|
bRet = TRUE;
|
|
else
|
|
{
|
|
HmgFree((HOBJ)pPFF->pPFEC->hGet());
|
|
pPFF->pPFEC = NULL;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID PFFOBJ::vDeletePFEC(PVOID *ppvPFE)
|
|
*
|
|
* Delete the handle of PFE collect, a object to reduce the consumption of object handle
|
|
*
|
|
* Returns:
|
|
* None
|
|
*
|
|
* History:
|
|
*
|
|
* 2-June-1996 -by- Yung-Jen Tony Tsai [YungT]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID PFFOBJ::vDeletePFEC(PVOID *ppvPFE)
|
|
{
|
|
*ppvPFE = NULL;
|
|
|
|
if (pPFF->pPFEC != NULL)
|
|
{
|
|
*ppvPFE = pPFF->pPFEC->pvPFE;
|
|
HmgFree((HOBJ)pPFF->pPFEC->hGet());
|
|
pPFF->pPFEC = NULL;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* PFFOBJ::bAddHash
|
|
*
|
|
* Adds the PFF and all its PFEs to the font hashing table. The font
|
|
* hashing tabled modified is in the PFT if a font driver managed font;
|
|
* otherwise, the font hashing table is in the PFF itself.
|
|
*
|
|
* The caller should hold the ghsemPublicPFT while calling this function.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* History:
|
|
* 11-Mar-1993 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL PFFOBJ::bAddHash(BOOL bEUDC)
|
|
{
|
|
// Caller must hold the ghsemPublicPFT semaphore to protect access to
|
|
// the hash tables.
|
|
|
|
//
|
|
// Add the entry to the appropriate font hash tables
|
|
//
|
|
FONTHASH **ppfhFace, **ppfhFamily,**ppfhUFI;
|
|
|
|
if (!bDeviceFonts())
|
|
{
|
|
//
|
|
// Hash tables for the font driver loaded fonts exist off of
|
|
// the font table.
|
|
//
|
|
PUBLIC_PFTOBJ pfto( bInPrivatePFT() ? gpPFTPrivate : gpPFTPublic );
|
|
ASSERTGDI(pfto.bValid(),"PFFOBJ::vAddHash -- invalid Public PFTOBJ\n");
|
|
|
|
ppfhFace = &(pfto.pPFT->pfhFace);
|
|
ppfhFamily = &(pfto.pPFT->pfhFamily);
|
|
ppfhUFI = &(pfto.pPFT->pfhUFI);
|
|
|
|
//
|
|
// If this is a TrueType font, increment the count.
|
|
//
|
|
if ( pPFF->hdev == (HDEV) gppdevTrueType )
|
|
{
|
|
gcTrueTypeFonts++; // protected by ghsemPublicPFT
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Hash tables for device fonts exist off of the PFF that
|
|
// encapsulates them.
|
|
//
|
|
|
|
#if DBG
|
|
if (gflFontDebug & DEBUG_FONTTABLE)
|
|
{
|
|
RIP("\n\n[kirko] PFFMEMOBJ::vAddHash -- Adding to the Driver's font hash table\n\n");
|
|
}
|
|
#endif
|
|
|
|
ppfhFace = &pPFF->pfhFace;
|
|
ppfhFamily = &pPFF->pfhFamily;
|
|
ppfhUFI = &pPFF->pfhUFI;
|
|
}
|
|
|
|
//
|
|
// Now that we have figured out where the tables are, add the PFEs to them.
|
|
//
|
|
FHOBJ fhoFamily(ppfhFamily);
|
|
FHOBJ fhoFace(ppfhFace);
|
|
FHOBJ fhoUFI(ppfhUFI);
|
|
|
|
ASSERTGDI(fhoFamily.bValid(), "bAddHashPFFOBJ(): fhoFamily not valid\n");
|
|
ASSERTGDI(fhoFace.bValid(), "bAddHashPFFOBJ(): fhoFace not valid\n");
|
|
ASSERTGDI(fhoUFI.bValid(), "bAddHashPFFOBJ(): fhoUFI not valid\n");
|
|
|
|
if (! (fhoUFI.bValid() && fhoFamily.bValid() && fhoFace.bValid()))
|
|
return FALSE;
|
|
|
|
for (COUNT c = 0; c < pPFF->cFonts; c++)
|
|
{
|
|
PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
|
|
ASSERTGDI(pfeo.bValid(), "bAddHashPFFOBJ(): bad HPFE\n");
|
|
|
|
if(!fhoUFI.bInsert(pfeo) )
|
|
{
|
|
WARNING("PFFOBJ::bAddHash -- fhoUFI.bInsert failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// If we only need to add it to the UFI hash table (we need to add it there
|
|
// so that the remote printing code can request the bits of it needs to).
|
|
|
|
if(bEUDC)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!fhoFamily.bInsert(pfeo))
|
|
{
|
|
WARNING("PFFOBJ::bAddHash -- fhoFamily.bInsert failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
#if DBG
|
|
if (gflFontDebug & DEBUG_FONTTABLE)
|
|
{
|
|
DbgPrint("PFFMEMOBJ::vAddHash(\"%ws\")\n",pfeo.pwszFamilyName());
|
|
}
|
|
// Need level 2 checking to see this.
|
|
if (gflFontDebug & DEBUG_FONTTABLE_EXTRA)
|
|
{
|
|
fhoFamily.vPrint((VPRINT) DbgPrint);
|
|
}
|
|
#endif
|
|
|
|
|
|
#if DBG
|
|
if (gflFontDebug & DEBUG_FONTTABLE)
|
|
{
|
|
UNIVERSAL_FONT_ID ufi;
|
|
pfeo.vUFI(&ufi);
|
|
DbgPrint("PFFMEMOBJ::vAddHash(\"%x\")\n",ufi.CheckSum);
|
|
}
|
|
// Need level 2 checking to see this.
|
|
if (gflFontDebug & DEBUG_FONTTABLE_EXTRA)
|
|
{
|
|
fhoUFI.vPrint((VPRINT) DbgPrint);
|
|
}
|
|
#endif
|
|
|
|
if(!fhoFace.bInsert(pfeo))
|
|
{
|
|
WARNING("PFFMEMOBJ::vAddHash -- fhoFace.bInsert failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
#if DBG
|
|
if (gflFontDebug & DEBUG_FONTTABLE)
|
|
{
|
|
DbgPrint("gdisrv!PFFMEMOBJ::vAddHash(\"%ws\")\n",pfeo.pwszFaceName());
|
|
}
|
|
if (gflFontDebug & DEBUG_FONTTABLE_EXTRA)
|
|
{
|
|
fhoFace.vPrint((VPRINT) DbgPrint);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* PFFOBJ::vRemoveHash
|
|
*
|
|
* Removes the PFF and all its PFEs from the font hashing table, preventing
|
|
* the font from being enumerated or mapped.
|
|
*
|
|
* The caller should hold the ghsemPublicPFT while calling this function.
|
|
*
|
|
* History:
|
|
* 10-Mar-1993 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID PFFOBJ::vRemoveHash ()
|
|
{
|
|
// Caller must hold the ghsemPublicPFT semaphore to protect access to
|
|
// the hash tables.
|
|
|
|
if (bDeviceFonts())
|
|
{
|
|
//
|
|
// Hash tables for device fonts exist off of the PFF that
|
|
// encapsulates the device fonts. Font driver loaded fonts
|
|
// are handled later while deleting the PFEs.
|
|
//
|
|
|
|
//
|
|
// Kill the entire table for the device. No more processing
|
|
// of font hash table stuff is necssary for device fonts
|
|
// after we leave this scope.
|
|
//
|
|
|
|
FHOBJ fhoFace(&(pPFF->pfhFace));
|
|
if (fhoFace.bValid())
|
|
{
|
|
fhoFace.vFree();
|
|
}
|
|
|
|
FHOBJ fhoFamily(&(pPFF->pfhFamily));
|
|
if (fhoFamily.bValid())
|
|
{
|
|
fhoFamily.vFree();
|
|
}
|
|
|
|
FHOBJ fhoUFI(&(pPFF->pfhUFI));
|
|
if (fhoUFI.bValid())
|
|
{
|
|
fhoUFI.vFree();
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
PUBLIC_PFTOBJ pfto( bInPrivatePFT() ? gpPFTPrivate : gpPFTPublic );
|
|
ASSERTGDI(pfto.bValid(),"vRemoveHashPFFOBJ(): invalid PFTOBJ\n");
|
|
|
|
//
|
|
// Hash tables for the font driver managed fonts exist off of
|
|
// the font table (PFT).
|
|
//
|
|
|
|
FHOBJ fhoFace(&(pfto.pPFT->pfhFace));
|
|
FHOBJ fhoFamily(&(pfto.pPFT->pfhFamily));
|
|
FHOBJ fhoUFI(&(pfto.pPFT->pfhUFI));
|
|
|
|
for (COUNT c = 0; c < pPFF->cFonts; c++)
|
|
{
|
|
PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
|
|
ASSERTGDI(pfeo.bValid(), "vRemoveHashPFFOBJ(): bad HPFE\n");
|
|
|
|
//
|
|
// Remove PFE from hash tables.
|
|
//
|
|
|
|
if( !pfeo.bEUDC() )
|
|
{
|
|
// EUDC fonts arent added to these two tables
|
|
if (fhoFace.bValid())
|
|
fhoFace.vDelete(pfeo);
|
|
|
|
if (fhoFamily.bValid())
|
|
fhoFamily.vDelete(pfeo);
|
|
}
|
|
|
|
if (fhoUFI.bValid())
|
|
fhoUFI.vDelete(pfeo);
|
|
|
|
|
|
|
|
#if DBG
|
|
if (gflFontDebug & DEBUG_FONTTABLE)
|
|
{
|
|
DbgPrint("gdisrv!vRemoveHashPFFOBJ() hpfe 0x%lx (\"%ws\")\n",
|
|
pfeo.ppfeGet(), pfeo.pwszFamilyName());
|
|
}
|
|
// Need level 2 checking to see this extra detail.
|
|
if (gflFontDebug & DEBUG_FONTTABLE_EXTRA)
|
|
{
|
|
fhoFamily.vPrint((VPRINT) DbgPrint);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// If this is a TrueType font, decrement the count.
|
|
//
|
|
|
|
if ( pPFF->hdev == (HDEV) gppdevTrueType )
|
|
{
|
|
gcTrueTypeFonts--; // protected by ghsemPublicPFT
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* BOOL PFFOBJ::bPermanent()
|
|
*
|
|
*
|
|
* Effects:
|
|
*
|
|
* Warnings:
|
|
*
|
|
* History:
|
|
* 06-Dec-1993 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL PFFOBJ::bPermanent()
|
|
{
|
|
// in the new version of the code every remote font is flagged at
|
|
// AddFontResourceTime. The difference in behavior from 3.51
|
|
// is that now fonts added by the applicaitons, if local, will not
|
|
// be removed at log on time.
|
|
|
|
if (pPFF->flState & PFF_STATE_NETREMOTE_FONT)
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* PFFOBJ::vPFFC_Delete
|
|
*
|
|
* Deletes the PFF and its PFEs. Information needed to call the driver
|
|
* to unload the font file and release driver allocated data is stored
|
|
* in the PFFCLEANUP structure. The PFFCLEANUP structure is allocated
|
|
* within this routine. It is the caller's responsibility to release
|
|
* the PFFCLEANUP structure (calling vCleanupFontFile() calls the drivers
|
|
* AND releases the structure).
|
|
*
|
|
* Changed so that it does not return a pointer to a PFFCLEANUP
|
|
* structure. Instead, it takes a pointer to a PFFCLEANUP
|
|
* structure as an argument. Thus, the caller must allocate
|
|
* and free the memory to the PFFCLEANUP structure. [dchinn 11/24/98]
|
|
*
|
|
* Returns:
|
|
* void. The contents of the PFFCLEANUP structure passed in will be altered
|
|
* as appropriate.
|
|
*
|
|
* History:
|
|
* 10-Mar-1993 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID PFFOBJ::vPFFC_Delete(PFFCLEANUP *pPFFC)
|
|
{
|
|
|
|
PVOID pvPFE;
|
|
|
|
TRACE_FONT(("Entering PFFOBJ::vPFFC_Delete()\n\tpPFF=%-#x\n", pPFF));
|
|
|
|
// check to see if a NULL pointer to a PFFCLEANUP structure was passed in
|
|
ASSERTGDI(pPFFC, "vPFFC_Delete(): passed in a NULL\n");
|
|
|
|
vDeletePFEC(&pvPFE);
|
|
|
|
//
|
|
// Delete all the PFE entries.
|
|
//
|
|
for (COUNT c = 0; c < pPFF->cFonts; c++)
|
|
{
|
|
PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
|
|
ASSERTGDI(pfeo.bValid(), "vPFFC_DeletePFFOBJ(): bad HPFE (device font)\n");
|
|
|
|
//
|
|
// Delete the PFE. The vDelete function will copy the driver allocated
|
|
// resource information from the PFE into the PFECLEANUP structure.
|
|
// We will call DrvFree for these resources later (when we're not under
|
|
// semaphore).
|
|
//
|
|
pfeo.vDelete();
|
|
}
|
|
|
|
|
|
//
|
|
// Save stuff about the PFF also.
|
|
//
|
|
pPFFC->hff = pPFF->hff;
|
|
pPFFC->hdev = pPFF->hdev;
|
|
pPFFC->pPFFClone = pPFF->pPFFClone;
|
|
|
|
//
|
|
// Free object memory and invalidate pointer.
|
|
//
|
|
|
|
TRACE_FONT(("Freeing pPFF=%-#x\n",pPFF));
|
|
|
|
// If this was a remote font then we must delete the memory for the file.
|
|
// If this is a normal font then we must still delete the view.
|
|
|
|
if (!pPFF->pPFFClone)
|
|
{
|
|
if (pPFF->ppfv && pPFF->cFiles)
|
|
{
|
|
FreeFileView(pPFF->ppfv, pPFF->cFiles);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// We release the pPFFClone.
|
|
|
|
pPFF->pPFFClone->pPFFClone = NULL;
|
|
}
|
|
|
|
if (pvPFE)
|
|
VFREEMEM(pvPFE);
|
|
|
|
VFREEMEM(pPFF);
|
|
|
|
pPFF = 0;
|
|
TRACE_FONT(("Exiting PFFOBJ::vPFFC_Delete\n\treturn value = %x\n", pPFFC));
|
|
return;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* PFFOBJ::vPFFC_DeleteAndCleanup
|
|
*
|
|
* This function creates a pointer to a PFFCLEANUP structure, calls vPFFC_Delete(),
|
|
* and then calls vCleanupFontFile(). This is the recommended way to handle
|
|
* unloading a font file, because it avoids the possibility (when a font file
|
|
* contains fewer than CFONTS_PFFCLEANUP fonts) that under a Hydra scenario
|
|
* it will fail to free up all the memory.
|
|
*
|
|
* (The old way of doing the cleanup was to call vPFFC_Delete() and then
|
|
* vCleanupFontFile(). However, the old vPFFC_Delete() allocated a PFFCLEANUP
|
|
* structure. If that allocation failed, then the rest of the cleanup would
|
|
* not occur, and so memory would leak from a Hydra session. This new way of
|
|
* doing the cleanup does not allocate memory from the heap. Instead, it allocates
|
|
* it on the stack.)
|
|
*
|
|
* If for some reason the two calls (vPFFC_Delete() and vCleanupFontFile() ) need
|
|
* to be done separately (for example, if one of the calls is protected by a
|
|
* semaphore), then one must wrap code similar to that below around the two calls.
|
|
*
|
|
* Returns:
|
|
* void.
|
|
*
|
|
* History:
|
|
* 24-Nov-1998 -by- Donald Chinn [dchinn]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID PFFOBJ::vPFFC_DeleteAndCleanup()
|
|
{
|
|
PFFCLEANUP pffc;
|
|
|
|
// now call vPFFC_Delete() and vCleanupFontFile()
|
|
|
|
vPFFC_Delete (&pffc);
|
|
vCleanupFontFile (&pffc);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL PFFOBJ::bDeleteLoadRef ()
|
|
*
|
|
* Remove a load reference. Caller must hold the ghsemPublicPFT semaphore.
|
|
*
|
|
* Returns:
|
|
* TRUE if caller should delete, FALSE if caller shouldn't delete.
|
|
*
|
|
* History:
|
|
* 23-Feb-1991 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL PFFOBJ::bDeleteLoadRef(ULONG fl, PVTDATA *pPvtData, BOOL *pbWrongFlags)
|
|
{
|
|
// ghsemPublicPFT protects the ref counts (cLoaded and cRFONT). Caller
|
|
// must grab the semaphore before calling this function.
|
|
|
|
// Decrement the load count. Must prevent underflow. Who knows if some
|
|
// app might not randomly go around doing extra RemoveFont calls. Isn't
|
|
// it too bad that we have to run APPS on our nice clean OS? :-)
|
|
|
|
BOOL bRet = FALSE;
|
|
*pbWrongFlags = FALSE;
|
|
|
|
TRACE_FONT(("Enterning PFFOBJ::bDeleteLoadRef\n"
|
|
"\tpPFF=%-#x\n"
|
|
"\tcLoaded=%d\n",
|
|
"\tcNotEnum=%d\n",pPFF ,pPFF->cLoaded ,pPFF->cNotEnum));
|
|
|
|
// Embedded/Private fonts
|
|
|
|
if (bInPrivatePFT())
|
|
{
|
|
ASSERTGDI(pPvtData, "bDeleteLoadRef: pPvtData is NULL\n");
|
|
|
|
if (pPvtData == NULL)
|
|
{
|
|
return bRet;
|
|
}
|
|
// called by cleanup routine when the process terminates
|
|
|
|
if (fl == FRW_PVT_CLEANUP)
|
|
{
|
|
pPvtData->cPrivate = 0;
|
|
pPvtData->cNotEnum = 0;
|
|
}
|
|
|
|
// decreament cNotEnum for Embedded or FR_NOT_ENUM set font
|
|
|
|
else if (fl & (FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID | FR_PRINT_EMB_FONT))
|
|
{
|
|
if (pPvtData->fl & fl)
|
|
{
|
|
if ( pPvtData->cNotEnum )
|
|
{
|
|
pPvtData->cNotEnum--;
|
|
if (fl == FR_PRINT_EMB_FONT)
|
|
{
|
|
pPvtData->fl &= ~FR_PRINT_EMB_FONT;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pbWrongFlags = TRUE;
|
|
}
|
|
}
|
|
|
|
// decreament cPrivate for FR_PRIVATE set only font
|
|
|
|
else
|
|
{
|
|
if (pPvtData->fl & fl)
|
|
{
|
|
if ( pPvtData->cPrivate )
|
|
{
|
|
pPvtData->cPrivate--;
|
|
}
|
|
else
|
|
{
|
|
*pbWrongFlags = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove the PvtData block if both cPrivate and cNotEnum counts are zero.
|
|
|
|
if ((pPvtData->cPrivate | pPvtData->cNotEnum) == 0)
|
|
{
|
|
bRemovePvtData(pPvtData);
|
|
}
|
|
|
|
// Mark it to Ready2Die if the PvtData list is NULL.
|
|
|
|
if (pPvtDataHeadGet() == NULL)
|
|
{
|
|
ASSERTGDI( (pPFF->cLoaded | pPFF->cNotEnum) == 0, "win32k!bDeleteLoadRef(): global (cLoaded | cNotEnum) in private PFF is not 0\n");
|
|
|
|
vKill();
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// remove a public font
|
|
|
|
if (fl == 0)
|
|
{
|
|
if (pPFF->cLoaded)
|
|
{
|
|
pPFF->cLoaded--;
|
|
}
|
|
}
|
|
|
|
// remove a FR_NOT_ENUM font in the public PFT
|
|
|
|
else
|
|
{
|
|
ASSERTGDI(fl == FR_NOT_ENUM, "win32k!bDeletLoadRef(): attempt to delete a font in public PFT with fl!=FR_NOT_ENUM \n");
|
|
|
|
if (pPFF->cNotEnum)
|
|
{
|
|
pPFF->cNotEnum--;
|
|
}
|
|
}
|
|
|
|
if ((pPFF->cLoaded | pPFF->cNotEnum) == 0)
|
|
{
|
|
ASSERTGDI(pPFF->pPvtDataHead == NULL, "win32k!bDeleteLoadRef(): pPvtDataHead in public PFF is not NULL\n");
|
|
|
|
vKill(); // mark as "dead"
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
TRACE_FONT(("Exiting PFFOBJ::bDeleteLoadRef\n\treturn value = %d\n",bRet));
|
|
return( bRet );
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL PFFOBJ::bDeleteRFONTRef ()
|
|
*
|
|
* Destroy the PFF physical font file object (message from a RFONT).
|
|
*
|
|
* Conditions that need to be met before deletion:
|
|
*
|
|
* must delete all RFONTs before PFF can be deleted (cRFONT must be zero)
|
|
* must delete all PFEs before deleting PFF
|
|
*
|
|
* After decrementing the cRFONT:
|
|
*
|
|
* If cRFONT != 0 OR flState != PFF_STATE_READY2DIE, just exit.
|
|
*
|
|
* If cRFONT == 0 and flState == PFF_STATE_READY2DIE, delete the PFF.
|
|
*
|
|
* Note:
|
|
* This function has the side effect of decrementing the RFONT count.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE if error occurs (which means PFF still lives!)
|
|
*
|
|
* Warning:
|
|
* This should only be called from RFONTOBJ::bDelete()
|
|
*
|
|
* History:
|
|
* 23-Feb-1991 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL PFFOBJ::bDeleteRFONTRef()
|
|
{
|
|
PFFCLEANUP pffc;
|
|
BOOL bCleanUp = FALSE;
|
|
|
|
{
|
|
// Need to stabilize table to access cRFONT and to modify font table.
|
|
|
|
SEMOBJ so(ghsemPublicPFT);
|
|
|
|
// Decrement the RFONT count.
|
|
|
|
ASSERTGDI(pPFF->cRFONT > 0,"bDeleteRFONTRefPFFOBJ(): bad ref count in PFF\n");
|
|
pPFF->cRFONT--;
|
|
|
|
// If load count is zero and no more RFONTs for this PFF, OK to delete.
|
|
|
|
if ( (pPFF->cLoaded == 0) && (pPFF->cNotEnum == 0) && (pPFF->pPvtDataHead == NULL) && (pPFF->cRFONT == 0) )
|
|
{
|
|
// If the load count is zero, the PFF is already out of the PFT.
|
|
// It is now safe to delete the PFF.
|
|
|
|
vPFFC_Delete(&pffc);
|
|
bCleanUp = TRUE;
|
|
}
|
|
}
|
|
|
|
// Call the driver outside of the semaphore.
|
|
|
|
if (bCleanUp)
|
|
vCleanupFontFile(&pffc); // function can handle NULL case
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vKill
|
|
*
|
|
* Puts the PFF and its PFEs to death. In other words, the PFF and PFEs are
|
|
* put in a dead state that prevents them from being mapped to or enumerated.
|
|
* It also means that the font file is in a state in which the system wants
|
|
* to delete it (load count is zero), but the deletion is delayed because
|
|
* RFONTs still exist which reference this PFF.
|
|
*
|
|
* History:
|
|
* 29-May-1992 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID PFFOBJ::vKill()
|
|
{
|
|
// Put into a dead state if not already there.
|
|
TRACE_FONT(("Entering PFFOBJ::vKill\n\tpPFF=%-#x\n", pPFF));
|
|
if ( !bDead() )
|
|
{
|
|
// Set state.
|
|
pPFF->flState |= PFF_STATE_READY2DIE;
|
|
|
|
// Run the list of PFEs and set each to death.
|
|
for (COUNT c = 0; c < pPFF->cFonts; c++)
|
|
{
|
|
PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
|
|
|
|
if (pfeo.bValid())
|
|
{
|
|
// Mark PFE as dead state.
|
|
|
|
pfeo.vKill();
|
|
}
|
|
else
|
|
{
|
|
WARNING("vDiePFFOBJ(): cannot make PFEOBJ\n");
|
|
}
|
|
}
|
|
}
|
|
TRACE_FONT(("Exiting PFFOBJ::vKill\n"));
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vRevive
|
|
*
|
|
* Restores the PFF and its PFEs to life. In other words, the states are
|
|
* cleared so that the PFF and PFEs are available for mapping and enumeration.
|
|
*
|
|
* History:
|
|
* 29-May-1992 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID PFFOBJ::vRevive ()
|
|
{
|
|
// If dead, then revive.
|
|
|
|
if ( bDead() )
|
|
{
|
|
// Reset state.
|
|
|
|
pPFF->flState &= ~PFF_STATE_READY2DIE;
|
|
|
|
// Run the list of PFEs and revive each one.
|
|
|
|
for (COUNT c = 0; c < pPFF->cFonts; c++)
|
|
{
|
|
PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
|
|
|
|
if (pfeo.bValid())
|
|
{
|
|
// Mark PFE as dead state.
|
|
|
|
pfeo.vRevive();
|
|
}
|
|
else
|
|
{
|
|
WARNING("vRevivePFFOBJ(): cannot make PFEOBJ\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL PFFMEMOBJ::bLoadFontFileTable
|
|
*
|
|
* Creates a PFE for each of the faces in a font file and loads the IFI
|
|
* metrics and mapping tables into each of the PFEs. The font file is
|
|
* uniquely identified by the driver, hoDriver, and IFI font file handle,
|
|
* hff, stored in the PFF object. However, rather than hitting the handle
|
|
* manager an extra time, a PFDEVOBJ is passed into this function.
|
|
*
|
|
* After all the PFE entries are added, the font files pathname is added
|
|
* to the end of the data buffer.
|
|
*
|
|
* It is assumed that the PFF ahpfe table has enough room for cFontsToLoad
|
|
* new HPFE handles as well as the font files pathname.
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE if error.
|
|
*
|
|
* History:
|
|
* 16-Jan-1991 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL PFFMEMOBJ::bLoadFontFileTable (
|
|
PWSZ pwszPathname, // upper case
|
|
COUNT cFontsToLoad,
|
|
HANDLE hdc,
|
|
PUNIVERSAL_FONT_ID pufi
|
|
#ifdef FE_SB
|
|
,PEUDCLOAD pEudcLoadData
|
|
#endif
|
|
)
|
|
{
|
|
ULONG iFont; // font face index
|
|
|
|
// Create PFE's for each of the fonts in the font file.
|
|
// (Note: iFont indices for IFI fonts are 1-based, not 0-based)
|
|
|
|
PDEVOBJ ppdo(hdev());
|
|
|
|
if (!bCreatePFEC(cFontsToLoad))
|
|
return FALSE;
|
|
|
|
for (iFont = 1; iFont <= cFontsToLoad; iFont++)
|
|
{
|
|
FD_GLYPHSET *pfdg;
|
|
PIFIMETRICS pifi; // storage for the pointer to ifi
|
|
ULONG_PTR idMetrics;
|
|
|
|
// Grab the IFIMETRICS pointer.
|
|
|
|
if ( (pifi = ppdo.QueryFont(
|
|
pPFF->dhpdev,
|
|
pPFF->hff,
|
|
iFont,
|
|
&idMetrics)) == (PIFIMETRICS) NULL )
|
|
{
|
|
WARNING("bLoadFontFileTablePFFMEMOBJ(): error getting metrics\n");
|
|
return (FALSE);
|
|
}
|
|
|
|
// Put into a new PFE.
|
|
|
|
#ifdef FE_SB
|
|
BOOL bRet = TRUE;
|
|
if( bReadyToInitializeFontAssocDefault )
|
|
{
|
|
// This should be Base font, not be EUDC.
|
|
//
|
|
if ( pEudcLoadData == NULL )
|
|
{
|
|
// check this base font should be RE-load as default linked font ?
|
|
// if so, the pathname for this font will be registerd as default linked font.
|
|
bRet = FindDefaultLinkedFontEntry(
|
|
(const WCHAR *)(((BYTE*) pifi) + pifi->dpwszFamilyName),pwszPathname);
|
|
}
|
|
}
|
|
|
|
if (!bRet || !bAddEntry(iFont, NULL, 0, pifi, idMetrics, (HANDLE)0, pufi, pEudcLoadData))
|
|
{
|
|
// Failed to get the FD_GLYPHSET information. The entry is
|
|
// partially valid (IFIMETRICS), so lets invalidate the good part.
|
|
|
|
if (PPFNVALID(ppdo,Free))
|
|
{
|
|
ppdo.Free(pifi, idMetrics);
|
|
}
|
|
|
|
WARNING("bLoadFontFileTablePFFMEMOBJ(): error getting glyphset\n");
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
/*************************Public*Routine**************************\
|
|
* BOOL bExtendGlyphset
|
|
* Check the glyph set returned by the printer driver. Tack on the
|
|
* f0xx unicode range if missing for symbol font.
|
|
*
|
|
* History:
|
|
* Oct-10-97 Xudong Wu [TessieW]
|
|
* Wrote it.
|
|
*
|
|
\*****************************************************************/
|
|
BOOL bExtendGlyphSet(FD_GLYPHSET **ppfdgIn, FD_GLYPHSET **ppfdgOut)
|
|
{
|
|
WCHAR awch[256], *pwsz = awch, wcLow, wcHigh;
|
|
UCHAR ach[256];
|
|
USHORT AnsiCodePage, OemCodePage;
|
|
INT cjWChar, cjChar;
|
|
|
|
ULONG cjSize, iRun, jRun, i, j;
|
|
FD_GLYPHSET *pfdgNew, *pfdg;
|
|
ULONG cRuns;
|
|
BOOL bRet = FALSE, bNeedExt = FALSE;
|
|
|
|
pfdg = *ppfdgIn;
|
|
cRuns = pfdg->cRuns;
|
|
if (cRuns == 0)
|
|
{
|
|
WARNING("bExtendGlyphSet - empty glyphset\n");
|
|
return FALSE;
|
|
}
|
|
|
|
wcLow = pfdg->awcrun[0].wcLow;
|
|
wcHigh = pfdg->awcrun[cRuns-1].wcLow + (WCHAR)pfdg->awcrun[cRuns-1].cGlyphs - 1 ;
|
|
|
|
// mixing CP_SYMBOL mapping
|
|
// e0 is the number of glyphs in f020-f0ff range in symbol CP
|
|
|
|
// We shall extend the glypset if [f020,f0ff] does not intersect any
|
|
// of the runs specified in the old pfdg. We check that by making sure that
|
|
// [f020,f0ff] is entirely contained in the complement of the old glyphset.
|
|
|
|
if (pfdg->cGlyphsSupported <= 256)
|
|
{
|
|
if ((wcHigh < 0xf020) || (wcLow > 0xf0ff))
|
|
{
|
|
bNeedExt = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// bNeedExt = FALSE; // already initialized
|
|
|
|
for (iRun = 0; iRun < (cRuns - 1); iRun++)
|
|
{
|
|
wcLow = pfdg->awcrun[iRun].wcLow + pfdg->awcrun[iRun].cGlyphs - 1;
|
|
wcHigh = pfdg->awcrun[iRun+1].wcLow;
|
|
|
|
if ((wcLow < 0xf020) && (wcHigh > 0xf0ff))
|
|
{
|
|
bNeedExt = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bNeedExt)
|
|
{
|
|
cjSize = SZ_GLYPHSET(cRuns + 1, pfdg->cGlyphsSupported + 0x00e0);
|
|
pfdgNew = (FD_GLYPHSET*) PALLOCMEM(cjSize,'slgG');
|
|
|
|
if (pfdgNew)
|
|
{
|
|
HGLYPH *phgS, *phgD;
|
|
|
|
cjWChar = sizeof(WCHAR) * pfdg->cGlyphsSupported;
|
|
cjChar = 256;
|
|
|
|
for (iRun = 0; iRun < cRuns; iRun++)
|
|
{
|
|
for (i = 0; i < pfdg->awcrun[iRun].cGlyphs; i++)
|
|
{
|
|
*pwsz++ = pfdg->awcrun[iRun].wcLow + (WCHAR)i;
|
|
}
|
|
}
|
|
|
|
RtlGetDefaultCodePage(&AnsiCodePage, &OemCodePage);
|
|
if(IS_ANY_DBCS_CODEPAGE(AnsiCodePage))
|
|
{
|
|
AnsiCodePage = 1252;
|
|
}
|
|
if(EngWideCharToMultiByte(AnsiCodePage, awch, cjWChar, (CHAR*)ach, cjChar) == -1)
|
|
{
|
|
VFREEMEM(pfdgNew);
|
|
return bRet;
|
|
}
|
|
|
|
pfdgNew->cjThis = cjSize;
|
|
pfdgNew->flAccel = pfdg->flAccel | GS_EXTENDED;
|
|
|
|
pfdgNew->cGlyphsSupported = pfdg->cGlyphsSupported + 0x00e0;
|
|
pfdgNew->cRuns = cRuns + 1;
|
|
|
|
phgS = phgD = (HGLYPH*) &pfdgNew->awcrun[cRuns+1];
|
|
|
|
for ( iRun = 0;
|
|
(iRun < cRuns) && (pfdg->awcrun[iRun].wcLow < 0xf020);
|
|
iRun++)
|
|
{
|
|
pfdgNew->awcrun[iRun].wcLow = pfdg->awcrun[iRun].wcLow;
|
|
pfdgNew->awcrun[iRun].cGlyphs = pfdg->awcrun[iRun].cGlyphs;
|
|
pfdgNew->awcrun[iRun].phg = phgD;
|
|
|
|
RtlCopyMemory(phgD, pfdg->awcrun[iRun].phg,
|
|
sizeof(HGLYPH) * pfdg->awcrun[iRun].cGlyphs);
|
|
|
|
phgD += pfdg->awcrun[iRun].cGlyphs;
|
|
}
|
|
|
|
// fill in the f0xx range
|
|
|
|
pfdgNew->awcrun[iRun].wcLow = 0xf020;
|
|
pfdgNew->awcrun[iRun].cGlyphs = 0x00e0;
|
|
pfdgNew->awcrun[iRun].phg = phgD;
|
|
|
|
RtlZeroMemory((PVOID)phgD, 0x00e0 * sizeof(HGLYPH));
|
|
|
|
j = 0;
|
|
for (jRun = 0; jRun < cRuns; jRun++)
|
|
{
|
|
for (i = 0; i < pfdg->awcrun[jRun].cGlyphs; i++)
|
|
{
|
|
if (ach[j] >= 0x20)
|
|
{
|
|
phgD[ach[j] - 0x20] = pfdg->awcrun[jRun].phg[i];
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
|
|
phgD += 0x00e0;
|
|
for (; iRun < cRuns; iRun++)
|
|
{
|
|
pfdgNew->awcrun[iRun+1].wcLow = pfdg->awcrun[iRun].wcLow;
|
|
pfdgNew->awcrun[iRun+1].cGlyphs = pfdg->awcrun[iRun].cGlyphs;
|
|
pfdgNew->awcrun[iRun+1].phg = phgD;
|
|
|
|
RtlCopyMemory(phgD,
|
|
pfdg->awcrun[iRun].phg,
|
|
sizeof(HGLYPH) * pfdg->awcrun[iRun].cGlyphs);
|
|
|
|
phgD += pfdg->awcrun[iRun].cGlyphs;
|
|
}
|
|
|
|
*ppfdgOut = pfdgNew;
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
WARNING("bExtentGlyphSet(): failed to allocate pGlyphset\n");
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL PFFMEMOBJ::bLoadDeviceFontTable (
|
|
*
|
|
* Creates a PFE object for each device font and stores the IFIMETRICS and
|
|
* FD_MAPPINGS (UNICODE->HGLYPH) structures of that font. The device is
|
|
* identified by the pair (ppdo, dhpdev). There are cFonts number of device
|
|
* fonts to load.
|
|
*
|
|
* Note:
|
|
* It is assumed that there is enough storage in the PFF for the number
|
|
* of device fonts requested.
|
|
*
|
|
* History:
|
|
* 18-Mar-1991 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
PFFMEMOBJ::bLoadDeviceFontTable (
|
|
PDEVOBJ *ppdo // physical device
|
|
)
|
|
{
|
|
ULONG iFont; // font face index
|
|
ULONG cFonts = ppdo->cFonts();
|
|
BOOL bUMPD = ppdo->bUMPD();
|
|
BOOL bRet = FALSE;
|
|
|
|
PIFIMETRICS pifi; // pointer to font's IFIMETRICS
|
|
FD_GLYPHSET *pfdg; // pointer to font's GLYPHSETs
|
|
|
|
ULONG_PTR idifi; // driver id's
|
|
ULONG_PTR idfdg;
|
|
|
|
if (cFonts)
|
|
{
|
|
|
|
if (!bCreatePFEC(cFonts))
|
|
return bRet;
|
|
|
|
//
|
|
// If the device has some fonts, allocate two FONTHASH strcutures
|
|
// and save the addresses of the tables on the PFF
|
|
//
|
|
|
|
FHMEMOBJ fhmoFace( &pPFF->pfhFace, FHT_FACE , cFonts);
|
|
FHMEMOBJ fhmoFamily(&pPFF->pfhFamily, FHT_FAMILY, cFonts);
|
|
FHMEMOBJ fhmoUFI(&pPFF->pfhUFI, FHT_UFI, cFonts);
|
|
}
|
|
|
|
// Create PFE's for each of the fonts in the font file
|
|
// (Note: iFont indices for device fonts are 1-based, not 0-based)
|
|
|
|
for (iFont = 1; iFont<=cFonts; iFont++)
|
|
{
|
|
|
|
// Set as NULL before we start to allocate ifi and fd_glyphset
|
|
pfdg = NULL;
|
|
pifi = NULL;
|
|
|
|
// Get pointer to metrics
|
|
|
|
if (( pifi = ppdo->QueryFont(pPFF->dhpdev, 0, iFont, &idifi )) == NULL )
|
|
{
|
|
SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
|
|
#if DBG
|
|
DbgPrint("gdisrv!PFFMEMOBJ::bLoadDeviceFontTable(): error getting metrics \
|
|
for iFace = %ld\n", iFont);
|
|
#endif
|
|
goto CleanUp;
|
|
}
|
|
|
|
// Get pointer to the UNICODE->HGLYPH mappings
|
|
|
|
if (bUMPD)
|
|
{
|
|
pfdg = NULL;
|
|
}
|
|
else
|
|
{
|
|
if ( (pfdg = (FD_GLYPHSET *) ppdo->QueryFontTree(
|
|
pPFF->dhpdev,
|
|
0,
|
|
iFont,
|
|
QFT_GLYPHSET,
|
|
&idfdg)) == NULL )
|
|
{
|
|
// Failed to get the FD_GLYPHSET information. The entry is
|
|
// partially valid (IFIMETRICS), so lets invalidate the good part.
|
|
|
|
SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
|
|
goto CleanUp;
|
|
}
|
|
|
|
// extend the glyph set,
|
|
// it may not contain [f020,f0ff] range for the older drivers
|
|
|
|
if (pifi->jWinCharSet == SYMBOL_CHARSET)
|
|
{
|
|
FD_GLYPHSET *pfdgNew = NULL;
|
|
|
|
if (bExtendGlyphSet(&pfdg, &pfdgNew))
|
|
{
|
|
if (PPFNVALID(*ppdo,Free))
|
|
{
|
|
ppdo->Free(pfdg, idfdg);
|
|
}
|
|
pfdg = pfdgNew;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Put into a new PFE
|
|
|
|
// add entry logs error
|
|
|
|
if (bAddEntry(iFont, pfdg, idfdg, pifi, idifi,(HANDLE)0,NULL) == FALSE)
|
|
{
|
|
WARNING("bLoadDeviceFontTable():adding PFE\n");
|
|
goto CleanUp;
|
|
}
|
|
}
|
|
|
|
bRet = TRUE;
|
|
|
|
CleanUp:
|
|
|
|
if (!bRet)
|
|
{
|
|
|
|
// Free font hash
|
|
|
|
FHOBJ fhoFace(&(pPFF->pfhFace));
|
|
if (fhoFace.bValid())
|
|
{
|
|
fhoFace.vFree();
|
|
}
|
|
|
|
FHOBJ fhoFamily(&(pPFF->pfhFamily));
|
|
if (fhoFamily.bValid())
|
|
{
|
|
fhoFamily.vFree();
|
|
}
|
|
|
|
FHOBJ fhoUFI(&(pPFF->pfhUFI));
|
|
if (fhoUFI.bValid())
|
|
{
|
|
fhoUFI.vFree();
|
|
}
|
|
|
|
// Free pfdg
|
|
|
|
if ( (pifi != NULL) &&
|
|
(pifi->jWinCharSet == SYMBOL_CHARSET) &&
|
|
(pfdg != NULL) &&
|
|
(pfdg->flAccel & GS_EXTENDED))
|
|
{
|
|
VFREEMEM(pfdg);
|
|
}
|
|
else
|
|
{
|
|
if ((pfdg != NULL) && PPFNVALID(*ppdo,Free))
|
|
{
|
|
ppdo->Free(pfdg, idfdg);
|
|
}
|
|
}
|
|
|
|
// Free pifi
|
|
|
|
if (pifi)
|
|
{
|
|
if (PPFNVALID(*ppdo,Free))
|
|
{
|
|
ppdo->Free(pifi, idifi);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL PFFMEMOBJ::bAddEntry *
|
|
* *
|
|
* This function creates a new physical font entry object and adds it to the*
|
|
* end of the table. The iFont parameter identifies the font within this *
|
|
* file. The cjSize and pjMetrics identify a buffer containing face *
|
|
* information including the IFI metrics and the mapping structures *
|
|
* (defining the UNICODE->HGLYPH mapping). *
|
|
* *
|
|
* Returns FALSE if the function fails. *
|
|
* *
|
|
* History: *
|
|
* 02-Jan-1991 -by- Gilman Wong [gilmanw] *
|
|
* Wrote it. *
|
|
\**************************************************************************/
|
|
|
|
BOOL PFFMEMOBJ::bAddEntry
|
|
(
|
|
ULONG iFont, // index of the font (IFI or device)
|
|
FD_GLYPHSET *pfdg, // pointer to UNICODE->HGLYPH map
|
|
ULONG_PTR idfdg, // driver id for FD_GLYPHSET
|
|
PIFIMETRICS pifi, // pointer to IFIMETRICS
|
|
ULONG_PTR idifi, // driver id for IFIMETRICS
|
|
HANDLE hdc, // handle of DC if this is a remote font
|
|
PUNIVERSAL_FONT_ID pufi, // used when adding remote fonts
|
|
PEUDCLOAD pEudcLoadData // pointer to EUDCLOAD
|
|
)
|
|
{
|
|
|
|
// Allocate memory for a new PFE
|
|
PFECOBJ pfeco(pPFF->pPFEC);
|
|
|
|
PFEMEMOBJ pfemo(pfeco.GetPFE(iFont));
|
|
|
|
// Validate new object, hmgr logs error if needed
|
|
|
|
if (!pfemo.bValid())
|
|
return (FALSE);
|
|
|
|
// Initialize the new PFE
|
|
|
|
#ifdef FE_SB
|
|
|
|
BOOL bEUDC = ( pEudcLoadData != NULL );
|
|
PPFE *pppfeEUDC = ((bEUDC) ? pEudcLoadData->pppfeData : NULL);
|
|
|
|
if( !pfemo.bInit(pPFFGet(), iFont, pfdg, idfdg, pifi, idifi, bDeviceFonts(), pufi, bEUDC ))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
if( bEUDC )
|
|
{
|
|
//
|
|
// This font file is loaded as EUDC font.
|
|
//
|
|
if( pEudcLoadData->LinkedFace == NULL )
|
|
{
|
|
//
|
|
// No face name is specified.
|
|
//
|
|
switch( iFont )
|
|
{
|
|
case 1:
|
|
pppfeEUDC[PFE_NORMAL] = pfemo.ppfeGet();
|
|
pppfeEUDC[PFE_VERTICAL] = pppfeEUDC[PFE_NORMAL];
|
|
break;
|
|
|
|
case 2:
|
|
//
|
|
// if more than one face name the second face must be an @face
|
|
//
|
|
if( pfemo.pwszFaceName()[0] == (WCHAR) '@' )
|
|
{
|
|
pppfeEUDC[PFE_VERTICAL] = pfemo.ppfeGet();
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & (DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_INIT) )
|
|
{
|
|
DbgPrint("EUDC font has vertical face %ws %x\n",
|
|
pfemo.pwszFaceName(), pppfeEUDC[PFE_VERTICAL] );
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
WARNING("bAddEntryPFFMEMOBJ -- second face not a @face.\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
WARNING("bAddEntryPFFMEMOBJ -- too many faces in EUDC font.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( iFont == 1 )
|
|
{
|
|
//
|
|
// link first face as default, because this font file might not
|
|
// contains user's specified face name, but the user want to link
|
|
// this font file. I don't know which is better link it as default
|
|
// or fail link.
|
|
//
|
|
pppfeEUDC[PFE_NORMAL] = pfemo.ppfeGet();
|
|
pppfeEUDC[PFE_VERTICAL] = pppfeEUDC[PFE_NORMAL];
|
|
}
|
|
else
|
|
{
|
|
ULONG iPfeOffset = PFE_NORMAL;
|
|
PWSTR pwszEudcFace = pfemo.pwszFaceName();
|
|
|
|
//
|
|
// Is this a vertical face ?
|
|
//
|
|
if( pwszEudcFace[0] == (WCHAR) '@' )
|
|
{
|
|
iPfeOffset = PFE_VERTICAL;
|
|
}
|
|
|
|
//
|
|
// Is this a face that we want ?
|
|
//
|
|
if( pfemo.bCheckFamilyName(pEudcLoadData->LinkedFace,1) )
|
|
{
|
|
//
|
|
// Yes....., keep it.
|
|
//
|
|
pppfeEUDC[iPfeOffset] = pfemo.ppfeGet();
|
|
|
|
//
|
|
// if this is a PFE for Normal face, also keep it for Vertical face.
|
|
// after this, this value might be over-written by CORRRCT vertical
|
|
// face's PFE.
|
|
//
|
|
// NOTE :
|
|
// This code assume Normal face come faster than Vertical face...
|
|
//
|
|
if( iPfeOffset == PFE_NORMAL )
|
|
pppfeEUDC[PFE_VERTICAL] = pfemo.ppfeGet();
|
|
}
|
|
}
|
|
}
|
|
|
|
// mark the FaceNameEUDC pfe list as NULL
|
|
|
|
pfemo.vSetLinkedFontEntry( NULL );
|
|
}
|
|
else
|
|
{
|
|
|
|
PWSZ pwszAlias = NULL;
|
|
BOOL bIsFamilyNameAlias = FALSE;
|
|
PFLENTRY pFlEntry = NULL;
|
|
|
|
// Here we see if there is an EUDC font for this family name.
|
|
|
|
pwszAlias = pfemo.pwszFamilyNameAlias(&bIsFamilyNameAlias);
|
|
|
|
pFlEntry = FindBaseFontEntry(pwszAlias);
|
|
|
|
if (!pFlEntry && bIsFamilyNameAlias)
|
|
{
|
|
|
|
pwszAlias += (wcslen(pwszAlias) + 1);
|
|
|
|
if (bIsFamilyNameAlias)
|
|
{
|
|
pFlEntry = FindBaseFontEntry(pwszAlias);
|
|
}
|
|
}
|
|
|
|
if( pFlEntry != NULL )
|
|
{
|
|
//
|
|
// set eudc list..
|
|
//
|
|
|
|
pfemo.vSetLinkedFontEntry( pFlEntry );
|
|
|
|
#if DBG
|
|
if( gflEUDCDebug & DEBUG_FACENAME_EUDC )
|
|
{
|
|
PLIST_ENTRY p = pfemo.pGetLinkedFontList()->Flink;
|
|
|
|
DbgPrint("Found FaceName EUDC for %ws is ",pfemo.pwszFamilyName());
|
|
|
|
while( p != &(pFlEntry->linkedFontListHead) )
|
|
{
|
|
PPFEDATA ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList);
|
|
PFEOBJ pfeo( ppfeData->appfe[PFE_NORMAL] );
|
|
PFFOBJ pffo( pfeo.pPFF() );
|
|
|
|
DbgPrint(" %ws ",pffo.pwszPathname());
|
|
|
|
p = p->Flink;
|
|
}
|
|
|
|
DbgPrint("\n");
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// mark the FaceNameEUDC pfe as NULL
|
|
|
|
pfemo.vSetLinkedFontEntry( NULL );
|
|
}
|
|
|
|
}
|
|
#endif
|
|
// Put PFE pointer into the PFF's table
|
|
|
|
((PFE **) (pPFF->aulData))[pPFF->cFonts++] = pfemo.ppfeGet();
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
#if DBG
|
|
/******************************Public*Routine******************************\
|
|
* VOID PFFOBJ::vDump ()
|
|
*
|
|
* Debugging code.
|
|
*
|
|
* History:
|
|
* Thu 02-Apr-1992 12:10:28 by Kirk Olynyk [kirko]
|
|
* DbgPrint supports %ws
|
|
*
|
|
* 25-Feb-1991 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID PFFOBJ::vDump ()
|
|
{
|
|
DbgPrint("\nContents of PFF, pPFF = 0x%lx\n", pPFFGet());
|
|
if (*(WCHAR *)pwszPathname())
|
|
{
|
|
DbgPrint("Filename = %ws\n", pwszPathname());
|
|
}
|
|
DbgPrint("flState = 0x%lx\n", pPFF->flState);
|
|
DbgPrint("cLoaded = %ld\n", pPFF->cLoaded);
|
|
DbgPrint("cNotEnum = %ld\n", pPFF->cNotEnum);
|
|
DbgPrint("pPvtDataHead = 0x%lx\n", pPFF->pPvtDataHead);
|
|
DbgPrint("cRFONT = %ld\n", pPFF->cRFONT);
|
|
DbgPrint("hff = 0x%lx\n", pPFF->hff);
|
|
DbgPrint("cFonts = %ld\n", pPFF->cFonts);
|
|
DbgPrint("HPFE table\n");
|
|
for (ULONG i=0; i<pPFF->cFonts; i++)
|
|
DbgPrint(" 0x%lx\n", ((PFE **) (pPFF->aulData))[i]);
|
|
DbgPrint("\n");
|
|
}
|
|
#endif
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vCleanupFontFile
|
|
*
|
|
* Parses the PFFCLEANUP structure and calls the driver to release
|
|
* its resources and to unload the font file.
|
|
*
|
|
* History:
|
|
* 10-Mar-1993 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID vCleanupFontFile(PFFCLEANUP *pPFFC)
|
|
{
|
|
// Create PDEV user object so we can call driver functions.
|
|
|
|
PDEVOBJ pdo(pPFFC->hdev);
|
|
|
|
//
|
|
// If font driver loaded font, call to unload font file.
|
|
//
|
|
if (pPFFC->hff != HFF_INVALID && pPFFC->pPFFClone == NULL)
|
|
{
|
|
BOOL bOK = pdo.UnloadFontFile( pPFFC->hff );
|
|
ASSERTGDI(bOK, "PFFOBJ::vCleanupFontFile(): DrvUnloadFontFile failed\n");
|
|
|
|
#if DBG
|
|
if(bOK == -1){
|
|
RIP("PFFOBJ::vCleanupFontFile(): DrvUnloadFontFile failed2\n");
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* pPvtDataMatch() *
|
|
* *
|
|
* Search for existing PvtData for the current process *
|
|
* *
|
|
* Return *
|
|
* if found, return the address of the pPvtData block *
|
|
* *
|
|
* otherwise, return NULL
|
|
* *
|
|
* History: *
|
|
* 11-Aug-1996 -by- Xudong Wu [TessieW] *
|
|
* Wrote it. *
|
|
\**************************************************************************/
|
|
|
|
PVTDATA *PFFOBJ::pPvtDataMatch()
|
|
{
|
|
PVTDATA *pPvtDataCur;
|
|
|
|
for (pPvtDataCur = pPvtDataHeadGet();
|
|
pPvtDataCur;
|
|
pPvtDataCur = pPvtDataCur->pPvtDataNext)
|
|
{
|
|
if ((pPvtDataCur->fl & FRW_EMB_TID) && (pPvtDataCur->dwID == (DWORD) W32GetCurrentTID()))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (pPvtDataCur->dwID == (DWORD) W32GetCurrentPID())
|
|
{
|
|
break;
|
|
}
|
|
|
|
// spooler has the right of using any fonts
|
|
|
|
if ((gpidSpool == (PW32PROCESS)W32GetCurrentProcess()) &&
|
|
(pPvtDataCur->fl & FR_PRINT_EMB_FONT))
|
|
break;
|
|
}
|
|
|
|
return (pPvtDataCur);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* bAddPvtData(ULONG flEmbed) *
|
|
* *
|
|
* Add PvtData data block to the tail of pPvtDataHead link list *
|
|
* *
|
|
* Return FALSE if function fails *
|
|
* *
|
|
* History: *
|
|
* 11-Aug-1996 -by- Xudong Wu [TessieW] *
|
|
* Wrote it. *
|
|
\**************************************************************************/
|
|
|
|
BOOL PFFOBJ::bAddPvtData(ULONG flEmbed)
|
|
{
|
|
PVTDATA *pPvtData;
|
|
|
|
// Search for the existing PvtData block for the current process
|
|
|
|
pPvtData = pPvtDataMatch();
|
|
|
|
// PvtData exists for the calling process
|
|
|
|
if (pPvtData)
|
|
{
|
|
if (flEmbed & (FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID))
|
|
{
|
|
pPvtData->cNotEnum++;
|
|
}
|
|
else
|
|
{
|
|
pPvtData->cPrivate++;
|
|
}
|
|
|
|
pPvtData->fl |= flEmbed & (FR_PRIVATE | FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// no PvtData exists for the current process
|
|
|
|
else
|
|
{
|
|
if (pPvtData = (PVTDATA *) PALLOCMEM(sizeof(PVTDATA), 'pvtG'))
|
|
{
|
|
pPvtData->fl = flEmbed & (FR_PRIVATE | FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID);
|
|
|
|
// Embedded fonts can't be enumed, so we set cNotEnum to 1
|
|
|
|
if (flEmbed & (FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID))
|
|
{
|
|
pPvtData->cPrivate = 0;
|
|
pPvtData->cNotEnum = 1;
|
|
}
|
|
else
|
|
{
|
|
pPvtData->cPrivate = 1;
|
|
pPvtData->cNotEnum = 0;
|
|
}
|
|
pPvtData->dwID = (flEmbed & FRW_EMB_TID) ? (DWORD)W32GetCurrentTID() : (DWORD)W32GetCurrentPID() ;
|
|
|
|
pPvtData->pPvtDataNext = pPFF->pPvtDataHead;
|
|
pPFF->pPvtDataHead = pPvtData;
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
WARNING("PFFOBJ::bAddPvtData(): memory allocation failed\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* bRemovePvtData(PVTDATA *pPvtData) *
|
|
* *
|
|
* Rmove the PvtData data block from the pPvtDataHead link list *
|
|
* *
|
|
* Return FALSE if function fails *
|
|
* *
|
|
* History: *
|
|
* 27-Set-1996 -by- Xudong Wu [TessieW] *
|
|
* Wrote it. *
|
|
\**************************************************************************/
|
|
|
|
BOOL PFFOBJ::bRemovePvtData(PVTDATA *pPvtData)
|
|
{
|
|
PVTDATA *pPrev, *pCur;
|
|
|
|
pPrev = pPvtDataHeadGet();
|
|
|
|
if (!pPrev)
|
|
{
|
|
WARNING("PFFOBJ::bRemovePvtData: try to remove PvtData block from NULL list\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// remove the PvtData block from the head of the list
|
|
|
|
if ( pPrev == pPvtData)
|
|
{
|
|
pPFF->pPvtDataHead = pPvtData->pPvtDataNext;
|
|
|
|
VFREEMEM(pPvtData);
|
|
return TRUE;
|
|
}
|
|
|
|
while (pCur = pPrev->pPvtDataNext)
|
|
{
|
|
if (pCur == pPvtData)
|
|
{
|
|
pPrev->pPvtDataNext = pPvtData->pPvtDataNext;
|
|
|
|
VFREEMEM(pPvtData);
|
|
return TRUE;
|
|
}
|
|
|
|
pPrev = pCur;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|