|
|
/******************************Module*Header*******************************\
* Module Name: enumgdi.cxx * * Enumeration routines. * hefs * Created: 28-Mar-1992 16:18:45 * Author: Gilman Wong [gilmanw] * * Copyright (c) 1992-199 Microsoft Corporation * \**************************************************************************/
#include "precomp.hxx"
// gaclrEnumColorTable
//
// Colors used for GreEnumPens and GreEnumBrushes. This color table is
// set up so that:
//
// - the first 2 entries are for monochrome devices
//
// - the first 8 entries are for 8-color devices
//
// - the first 16 are for 4 BPP color devices
//
// - the first 20 are for 8 BPP and up color devices
static COLORREF gaclrEnumColorTable[] = { 0x00000000, // black
0x00ffffff, // white (monochrome)
0x000000ff, // red
0x0000ff00, // green
0x0000ffff, // yellow
0x00ff0000, // blue
0x00ff00ff, // magenta
0x00ffff00, // cyan (EGA hi-intensity)
0x00808080, // dark grey
0x00c0c0c0, // light grey
0x00000080, // red
0x00008000, // green
0x00008080, // yellow
0x00800000, // blue
0x00800080, // magenta
0x00808000, // cyan (EGA lo-intensity)
0x00c0dcc0, // money green
0x00f0c8a4, // cool blue
0x00f0fbff, // off white
0x00a4a0a0 // med grey (extra colors)
};
static ULONG gulEnumColorTableSize = sizeof(gaclrEnumColorTable) / sizeof(COLORREF);
#define ECT_1BPP 2 // use this many colors for 1 BPP
#define ECT_EGA 8 // use this many colors for EGA
#define ECT_4BPP 16 // use this many colors for 4 BPP
#define ECT_8BPP min(gulEnumColorTableSize, 256) // use this many colors for 8 BPP
#define ENUM_FILTER_NONE 0
#define ENUM_FILTER_TT 1
#define ENUM_FILTER_NONTT 2
// gaulEnumPenStyles
//
// Pen styles used for GreEnumPens.
static ULONG gaulPenStyles[] = { PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT };
static ULONG gulPenStylesTableSize = sizeof(gaulPenStyles) / sizeof(ULONG);
// gaulEnumBrushStyles
//
// Brush hatch styles used for GreEnumBrushes.
ULONG gaulHatchStyles[] = { HS_HORIZONTAL, HS_VERTICAL, HS_FDIAGONAL, HS_BDIAGONAL, HS_CROSS, HS_DIAGCROSS };
static ULONG gulHatchStylesTableSize = sizeof(gaulHatchStyles) / sizeof(ULONG);
/******************************Public*Routine******************************\
* NtGdiEnumObjects() * * * Returns: * Number of objects copied into the return buffer. If buffer is NULL, * then the object capacity needed for the buffer is returned. If an * error occurs, then ERROR is returned. * \**************************************************************************/
ULONG APIENTRY NtGdiEnumObjects( HDC hdc, int iObjectType, ULONG cjBuf, PVOID pvBuf ) { ULONG cRet = ERROR;
if ( (cjBuf == 0) == (pvBuf == (PVOID) NULL) ) { // Create and validate DC user object.
DCOBJ dco(hdc);
if (dco.bValid()) { PDEVOBJ pdo(dco.hdev());
// For color devices, we grab the colors out of the
// gaclrEnumColorTable color table. For better results, a
// driver should implement DrvEnumObj.
ULONG cclrDevice = pdo.GdiInfoNotDynamic()->ulNumColors; ULONG cObjects;
//
// Determine the number of colors to grab out of the table.
//
if ( cclrDevice >= ECT_8BPP ) cclrDevice = ECT_8BPP; else if ( cclrDevice >= ECT_4BPP ) cclrDevice = ECT_4BPP; else if ( cclrDevice >= ECT_EGA ) cclrDevice = ECT_EGA; else if ( cclrDevice >= ECT_1BPP ) cclrDevice = ECT_1BPP;
switch (iObjectType) { case OBJ_PEN: cObjects = cjBuf / sizeof(LOGPEN); cRet = cclrDevice * gulPenStylesTableSize;
break;
case OBJ_BRUSH: cObjects = cjBuf / sizeof(LOGBRUSH); cRet = cclrDevice * (gulHatchStylesTableSize + 1); // the "1" is the solid brush
break;
default: WARNING("NtGdiEnumObjects(): bad object type\n"); return cRet; }
//
// If the buffer is big enough, return the data
//
if (cObjects >= cRet) { __try { ProbeForWrite(pvBuf, cjBuf, sizeof(DWORD));
COLORREF *pclr; COLORREF *pclrEnd = gaclrEnumColorTable + cclrDevice;
PULONG pulPenStyle; PULONG pulPenStyleEnd = gaulPenStyles + gulPenStylesTableSize;
PULONG pulHatchStyle; PULONG pulHatchStyleEnd = gaulHatchStyles + gulHatchStylesTableSize;
PLOGPEN plpBuf = ((PLOGPEN)pvBuf); PLOGBRUSH plbBuf = ((PLOGBRUSH)pvBuf);
switch (iObjectType) { case OBJ_PEN:
//
// Fill buffer will LOGPENs of all styles, in all colors.
//
for (pulPenStyle = gaulPenStyles; pulPenStyle < pulPenStyleEnd; pulPenStyle += 1) { for (pclr = gaclrEnumColorTable; pclr < pclrEnd; pclr += 1) { // Fill in the LOGPEN fields.
plpBuf->lopnWidth.x = 0; // nominal width
plpBuf->lopnWidth.y = 0; // ignored
plpBuf->lopnStyle = (UINT) *pulPenStyle; plpBuf->lopnColor = *pclr;
// Next LOGPEN.
plpBuf += 1; } }
break;
case OBJ_BRUSH:
//
// Fill buffer will LOGBRUSHs of BS_SOLID style, in all colors.
//
for (pclr = gaclrEnumColorTable; pclr < pclrEnd; pclr += 1) { // Fill in the LOGBRUSH fields.
plbBuf->lbStyle = BS_SOLID; plbBuf->lbColor = *pclr; plbBuf->lbHatch = 0;
// Next LOGBRUSH.
plbBuf += 1; }
//
// Now fill the buffer with LOGBRUSHs of BS_HATCH, in all
// hatch styles and colors.
//
for (pulHatchStyle = gaulHatchStyles; pulHatchStyle < pulHatchStyleEnd; pulHatchStyle += 1) { for (pclr = gaclrEnumColorTable; pclr < pclrEnd; pclr += 1) { // Fill in the LOGBRUSH fields.
plbBuf->lbStyle = BS_HATCHED; plbBuf->lbColor = *pclr; plbBuf->lbHatch = *pulHatchStyle;
// Next LOGBRUSH.
plbBuf += 1; } }
break;
default: WARNING("NtGdiEnumObjects(): bad object type 2\n"); } } __except(EXCEPTION_EXECUTE_HANDLER) { // SetLastError(GetExceptionCode());
cRet = ERROR; } } else if (cObjects) { //
// If the buffer is not large enough (and it is not zero)
// then return an error,
//
cRet = ERROR; } } }
return cRet; }
BOOL bScanFamily( FHOBJ *pfho1, ULONG ulFilter1, FHOBJ *pfho2, ULONG ulFilter2, FHOBJ *pfho3, ULONG ulFilter3, EFSOBJ *pefsmo, ULONG iEnumType, EFFILTER_INFO *peffi, PWSZ pwszName );
BOOL bScanFamilyAndFace( FHOBJ *pfhoEngFamily, FHOBJ *pfhoEngFace, FHOBJ *pfhoDevFamily, FHOBJ *pfhoDevFace, EFSOBJ *pefsmo, ULONG iEnumType, EFFILTER_INFO *peffi, PWSZ pwszName );
#define EFS_DEFAULT 32
/******************************Public*Routine******************************\
* HEFS hefsEngineOnly * * Enumerates engine fonts only. * * PFEs are accumulated in an EFSTATE (EnumFont State) object. If a non-NULL * pwszName is specified, then only fonts that match the given name are added * to the EFS. If a NULL pwszFace is specified, then one font of each name is * added to the EFS. * * If any of the filtering flags in the EFFILTER_INFO structure are specified, * then PFEs are tested in additional filtering stages before they are added * to the EFS. * * The EFS is allocated by this function. It is the responsibility of the * caller to ensure that the EFS is eventually freed. * * Returns: * Handle to allocated EFS object, HEFS_INVALID if an error occurs. * * History: * * 19-Aug-1996 -by- Xudong Wu [TessieW] * Add enumeration for Private PFT. * * 07-Aug-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
HEFS hefsEngineOnly ( PWSZ pwszName, // enumerate this font family
ULONG lfCharSet, ULONG iEnumType, // TRUE if processing EnumFonts()
EFFILTER_INFO *peffi, // filtering information
PUBLIC_PFTOBJ &pfto, // public PFT user object
PUBLIC_PFTOBJ &pftop, // private PFT user object
ULONG *pulCount ) { // ulEnumFontOpen, the caller, has already grabbed the ghsemPublicPFT,
// so the font hash tables are stable.
// Create and validate FHOBJ for engine (family list).
FHOBJ fhoEngineFamily(&pfto.pPFT->pfhFamily);
if ( !fhoEngineFamily.bValid() ) { WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (family)\n"); return HEFS_INVALID; }
// Create and validate FHOBJ for engine (face list).
FHOBJ fhoEngineFace(&pfto.pPFT->pfhFace);
if ( !fhoEngineFace.bValid() ) { WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (face)\n"); return HEFS_INVALID; }
// For NULL pwszName, an example of each family needs to be enumerated. In
// other words, we scan ACROSS the names.
if (pwszName == (PWSZ) NULL) { // Allocate a new EFSTATE for the enumeration. Use total number
// of lists as a hint for the initial size. This is reasonable
// since we will probably enumerate back all of the list heads.
EFSMEMOBJ efsmo(fhoEngineFamily.cLists(), iEnumType);
if ( !efsmo.bValid() ) { WARNING("win32k!GreEnumFontOpen(): could not allocate enumeration state\n"); return HEFS_INVALID; }
// Enumerate engine fonts in public PFT.
// For Win3.1 compatability Non-TT,TT.
if ( !bScanFamily(&fhoEngineFamily, ENUM_FILTER_NONTT, &fhoEngineFamily, ENUM_FILTER_TT, (FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) ) { return HEFS_INVALID; }
// Scan through private PFT if gpPFTPrivate!=NULL
if (pftop.pPFT != NULL) { FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
if ( !fhoPrivateFamily.bValid() ) { WARNING("win32k!hefsEngineOnly(): cannot lock private font hash (family)\n"); return HEFS_INVALID; }
if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_NONTT, &fhoPrivateFamily, ENUM_FILTER_TT, (FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) ) { return HEFS_INVALID; } }
*pulCount = efsmo.cjEfdwTotal();
// Keep the EFSTATE around.
efsmo.vKeepIt();
// Return the EFSOBJ handle.
return efsmo.hefs(); }
// For non-NULL pwszName, all the fonts of a particular family are enumerated.
// In other words, we scan DOWN a name.
else { // Allocate a new EFSTATE. Use a default size.
EFSMEMOBJ efsmo(EFS_DEFAULT, iEnumType);
if ( !efsmo.bValid() ) { WARNING("gdisrv!hefsEnumFontsState(): could not allocate enumeration state\n"); return HEFS_INVALID; }
if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, (FHOBJ*)NULL, (FHOBJ*)NULL, &efsmo, iEnumType, peffi, pwszName)) { return HEFS_INVALID; }
// Scan through the Privat PFT with family name lists.
if (pftop.pPFT != NULL) { FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily); FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid()) { WARNING("win32k!hefsEngineOnly(): cannot lock private font hash\n"); return HEFS_INVALID; }
if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL, &efsmo, iEnumType, peffi, pwszName)) { return HEFS_INVALID; } }
// Repeat with the alternate facename (if any). Since a LOGFONT can
// map via the alternate facenames, it is appropriate to enumerate the
// alternate facename fonts as if they really had this face name.
PFONTSUB pfsub = pfsubAlternateFacename(pwszName); PWSZ pwszAlt = pfsub ? (PWSZ)pfsub->fcsAltFace.awch : NULL;
if ( pwszAlt != (PWSZ) NULL ) { // Enumerate engine fonts.
if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, (FHOBJ*)NULL, (FHOBJ*)NULL, &efsmo, iEnumType, peffi, pwszAlt)) { return HEFS_INVALID; }
// Enumerate the private fonts.
if (pftop.pPFT != NULL) { FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily); FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid()) { WARNING("win32k!hefsEngineOnly(): cannot lock private font hash\n"); return HEFS_INVALID; }
if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL, &efsmo, iEnumType, peffi, pwszAlt)) { return HEFS_INVALID; } }
// Inform the enumeration state that an alternate name was used.
efsmo.vUsedAltName(pfsub); }
*pulCount = efsmo.cjEfdwTotal();
// Keep the EFSTATE around.
efsmo.vKeepIt();
// Return the EFSOBJ handle.
return efsmo.hefs(); } }
/******************************Public*Routine******************************\
* HEFS hefsDeviceAndEngine * * Enumerates device and engine fonts. * * PFEs are accumulated in an EFSTATE (EnumFont State) object. If a non-NULL * pwszName is specified, then only fonts that match the given name are added * to the EFS. If a NULL pwszFace is specified, then one font of each name is * added to the EFS. * * If any of the filtering flags in the EFFILTER_INFO structure are specified, * then PFEs are tested in additional filtering stages before they are added * to the EFS. * * The EFS is allocated by this function. It is the responsibility of the * caller to ensure that the EFS is eventually freed. * * Returns: * Handle to allocated EFS object, HEFS_INVALID if an error occurs. * * * History: * * 18-Sept-1996 -by- Xudong Wu [TessieW] * Add the enumeration for private PFT. * * 07-Aug-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
HEFS hefsDeviceAndEngine ( PWSZ pwszName, // enumerate this font family
ULONG lfCharSet, ULONG iEnumType, EFFILTER_INFO *peffi, // filtering information
PUBLIC_PFTOBJ &pfto, // public PFT user object
PUBLIC_PFTOBJ &pftop, // private PFT user object
PFFOBJ &pffoDevice, // PFFOBJ for device fonts
PDEVOBJ &pdo, // PDEVOBJ for device
ULONG *pulCount ) { // ulEnumFontOpen, the caller, has already grabbed the ghsemPublicPFT,
// so the font hash tables are stable.
// Create and validate FHOBJ for device (family list).
FHOBJ fhoDeviceFamily(&pffoDevice.pPFF->pfhFamily);
if ( !fhoDeviceFamily.bValid() ) { WARNING("gdisrv!hefsEnumFontsState(): cannot lock device font hash (family)\n"); return HEFS_INVALID; }
// Create and validate FHOBJ for engine (family list).
FHOBJ fhoEngineFamily(&pfto.pPFT->pfhFamily);
if ( !fhoEngineFamily.bValid() ) { WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (family)\n"); return HEFS_INVALID; }
// Create and validate FHOBJ for device (face list).
FHOBJ fhoDeviceFace(&pffoDevice.pPFF->pfhFace);
if ( !fhoDeviceFace.bValid() ) { WARNING("gdisrv!hefsEnumFontsState(): cannot lock device font hash (face)\n"); return HEFS_INVALID; }
// Create and validate FHOBJ for engine (face list).
FHOBJ fhoEngineFace(&pfto.pPFT->pfhFace);
if ( !fhoEngineFace.bValid() ) { WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (face)\n"); return HEFS_INVALID; }
// For NULL pwszName, an example of each family needs to be enumerated. In
// other words, we scan ACROSS the names.
if (pwszName == (PWSZ) NULL) { // Allocate a new EFSTATE for the enumeration. Use total number of lists
// as a hint for the initial size. This is reasonable since we will probably
// enumerate back all of the list heads.
ASSERTGDI(peffi->bNonTrueTypeFilter == FALSE, "ERROR not FALSE");
EFSMEMOBJ efsmo(fhoDeviceFamily.cLists() + fhoEngineFamily.cLists(), iEnumType);
if ( !efsmo.bValid() ) { WARNING("gdisrv!hefsEnumFontsState(): could not allocate enumeration state\n"); return HEFS_INVALID; }
//
// Enumerate device and engine fonts.
//
if (pdo.flTextCaps() & TC_RA_ABLE) { //
// For Win3.1 compatability Enum Device,Non-TT,TT
// This is for Displays and PaintJets under 3.1
//
if ( !bScanFamily(&fhoDeviceFamily, ENUM_FILTER_NONE, &fhoEngineFamily, ENUM_FILTER_NONTT, &fhoEngineFamily, ENUM_FILTER_TT, &efsmo, iEnumType, peffi, NULL) ) { return HEFS_INVALID; }
// scan through private PFT if gpPFTPrivate!=NULL
if (pftop.pPFT != NULL) { FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
if ( !fhoPrivateFamily.bValid() ) { WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash (family)\n"); return HEFS_INVALID; }
if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_NONTT, &fhoPrivateFamily, ENUM_FILTER_TT, (FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) ) { return HEFS_INVALID; } } } #if 0
// If we ever need this, this is how Postscript should do it. We would
// need to call the driver at Enable Printer time to see if it's Postscript
// and set a bit for quick checking here.
else if (pdo.bPostScript()) { //
// For Win3.1 compatability Enum TT,Device,Non-TT,
//
if (!bScanFamily(&fhoEngineFamily, ENUM_FILTER_TT, &fhoDeviceFamily, ENUM_FILTER_NONE, &fhoEngineFamily, ENUM_FILTER_NONTT, &efsmo, iEnumType, peffi, NULL) ) { return HEFS_INVALID; }
// scan throught private PFT if gpPFTPrivate!=NULL
if (pftop.pPFT != NULL) { FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
if ( !fhoPrivateFamily.bValid() ) { WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash (family)\n"); return HEFS_INVALID; }
if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_TT, &fhoPrivateFamily, ENUM_FILTER_NONTT, (FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) ) { return HEFS_INVALID; } } } #endif
else { //
// Win3.1 compatability.
// Enum Device, TT, Non-TT.
//
if ( !bScanFamily(&fhoDeviceFamily, ENUM_FILTER_NONE, &fhoEngineFamily, ENUM_FILTER_TT, &fhoEngineFamily, ENUM_FILTER_NONTT, &efsmo, iEnumType, peffi, NULL) ) { return HEFS_INVALID; }
if (pftop.pPFT != NULL) { FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
if ( !fhoPrivateFamily.bValid() ) { WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash (family)\n"); return HEFS_INVALID; }
if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_TT, &fhoPrivateFamily, ENUM_FILTER_NONTT, (FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) ) { return HEFS_INVALID; } } }
*pulCount = efsmo.cjEfdwTotal();
// Keep the EFSTATE around.
efsmo.vKeepIt();
// Return the EFSOBJ handle.
return efsmo.hefs(); } else { // For non-NULL pwszName, all the fonts of a particular family are enumerated.
// In other words, we scan DOWN a name.
// Allocate a new EFSTATE. Use a default size.
EFSMEMOBJ efsmo(EFS_DEFAULT, iEnumType);
if ( !efsmo.bValid() ) { WARNING("gdisrv!hefsEnumFontsState(): could not allocate enumeration state\n"); return HEFS_INVALID; }
// Enumerate device and engine fonts.
if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, &fhoDeviceFamily, &fhoDeviceFace, &efsmo, iEnumType, peffi, pwszName)) { return HEFS_INVALID; }
// Enumerate the private fonts if any
if (pftop.pPFT != NULL) { FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily); FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid()) { WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash\n"); return HEFS_INVALID; }
if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL, &efsmo, iEnumType, peffi, pwszName)) { return HEFS_INVALID; } }
// Repeat with the alternate facename (if any). Since a LOGFONT can
// map via the alternate facenames, it is appropriate to enumerate the
// alternate facename fonts as if they really had this face name.
//
// However, to be Win 3.1 compatible, we will NOT do this if the device
// is a non-display device.
//
// It appears that Windows 95 no longer does this. Additionally, we need
// to enumerate manufactured EE names (i.e. Arial Cyr, Arial Grk, etc)
// on printer DC's as well now. If we don't we break Word Perfect 94 a 16 bit
// winstone application.
//
//
// if ( pdo.bDisplayPDEV() )
{ PFONTSUB pfsub = pfsubAlternateFacename(pwszName); PWSZ pwszAlt = pfsub ? (PWSZ)pfsub->fcsAltFace.awch : NULL;
if ( pwszAlt != (PWSZ) NULL ) { // Enumerate device and engine fonts.
if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, &fhoDeviceFamily, &fhoDeviceFace, &efsmo, iEnumType, peffi, pwszAlt)) { return HEFS_INVALID; }
// Enumerate private fonts if any
if (pftop.pPFT != NULL) { FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily); FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid()) { WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash\n"); return HEFS_INVALID; }
if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL, &efsmo, iEnumType, peffi, pwszAlt)) { return HEFS_INVALID; } }
// Inform the enumeration state that an alternate name was used.
efsmo.vUsedAltName(pfsub); } }
*pulCount = efsmo.cjEfdwTotal();
// Keep the EFSTATE around.
efsmo.vKeepIt();
// Return the EFSOBJ handle.
return efsmo.hefs(); }
}
/******************************Public*Routine******************************\
* ULONG ulEnumFontOpen * * First phase of the enumeration. Fonts from the engine and device are * chosen and saved in a EFSTATE (font enumeration state) object. A handle * to this object is passed back. The caller can use this handle to * initiate the second pass in which the data is sent back over the client * server interface in chunks. * * This function is also responsible for determining what types of filters * will be applied in choosing fonts for the enumeration. Filters which * are controllable are: * * TrueType filtering non-TrueType fonts are discarded * * Raster filering raster fonts are discarded * * Aspect ratio filtering fonts not matching resolution are discarded * * Returns: * EFS handle (as a ULONG) if successful, HEFS_INVALID (0) otherwise. * * Note: * The function may still return valid HEFS even if the EFSTATE is empty. * * History: * 08-Aug-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
ULONG_PTR GreEnumFontOpen ( HDC hdc, // device to enumerate on
ULONG iEnumType, // EnumFonts, EnumFontFamilies or EnumFontFamiliesEx
FLONG flWin31Compat, // Win 3.1 compatibility flags
ULONG cwchMax, // maximum name length (for paranoid CSR code)
PWSZ pwszName, // font name to enumerate
ULONG lfCharSet, ULONG *pulCount ) { DONTUSE(cwchMax);
HEFS hefsRet = HEFS_INVALID;
//
// Create and validate user object for DC.
//
DCOBJ dco(hdc);
if(!dco.bValid()) { WARNING("gdisrv!ulEnumFontOpen(): cannot access DC\n"); SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
return ((ULONG_PTR) hefsRet); }
//
// Get PDEV user object. We also need to make
// sure that we have loaded device fonts before we go off to the font mapper.
// This must be done before the semaphore is locked.
//
PDEVOBJ pdo(dco.hdev()); ASSERTGDI ( pdo.bValid(), "gdisrv!ulEnumFontOpen(): cannot access PDEV\n");
if (!pdo.bGotFonts()) pdo.bGetDeviceFonts();
// Stabilize public PFT.
SEMOBJ so(ghsemPublicPFT);
// Compute font enumeration filter info.
EFFILTER_INFO effi;
effi.lfCharSetFilter = lfCharSet; effi.bNonTrueTypeFilter = FALSE;
//
// If not raster capable, then use raster font filtering.
//
//
// If it weren't hacked, we might be able to get this info
// from GetDeviceCaps(). As it is, we will assume only
// plotters are non-raster capable.
//
effi.bRasterFilter = (pdo.ulTechnology() == DT_PLOTTER);
effi.bEngineFilter = (pdo.ulTechnology() == DT_CHARSTREAM);
//
// Aspect ratio filter (use device's logical x and y resolutions).
//
// Note: [Windows 3.1 compatiblity] Aspect ratio filtering is turned ON for
// non-display devices. This is because most printers in Win 3.1
// do aspect ratio filtering. And since the Win 3.1 DDI gives
// enumeration to the drivers, display bitmap fonts usually are not
// enumerated on these devices. The NT DDI, however, gives the graphics
// engine control over enumeration. So we need to provide this
// compatibility here. Hopefully, all devices in Win3.1 do this
// filtering, because we do now.
//
// Note that we check the PDEV directly rather than the DC because
// DCOBJ::bDisplay() is not TRUE for display ICs (just display DCs
// which are DCTYPE_DIRECT).
//
effi.bAspectFilter = (BOOL) ( (dco.pdc->flFontMapper() & ASPECT_FILTERING) || !pdo.bDisplayPDEV() );
effi.ptlDeviceAspect.x = pdo.ulLogPixelsX(); effi.ptlDeviceAspect.y = pdo.ulLogPixelsY();
//
// If set for TrueType only, use TrueType filtering.
//
effi.bTrueTypeFilter = ((gulFontInformation & FE_FILTER_TRUETYPE) != 0);
//
// Set the Win3.1 compatibility flag.
//
effi.bTrueTypeDupeFilter = (BOOL) (flWin31Compat & GACF_TTIGNORERASTERDUPE);
// assume failure
hefsRet = 0;
{ // Find the device PFF
DEVICE_PFTOBJ pftoDevice; PFF *pPFF; if (pPFF = pftoDevice.pPFFGet(dco.hdev())) { PFFOBJ pffoDev(pPFF); if (pffoDev.bValid()) { PUBLIC_PFTOBJ pftoPublic; PUBLIC_PFTOBJ pftoPrivate(gpPFTPrivate);
hefsRet = hefsDeviceAndEngine( pwszName , lfCharSet , iEnumType , &effi , pftoPublic , pftoPrivate , pffoDev , pdo , pulCount ); } else { WARNING("ulEnumFontOpen: invalid pffoDev\n"); } } } if (!hefsRet) { PUBLIC_PFTOBJ pftoPublic; PUBLIC_PFTOBJ pftoPrivate(gpPFTPrivate);
// If no device font PFFOBJ was found, do enumeration without a PFFOBJ.
// pulls all the fonts into an enumeration state.
hefsRet = hefsEngineOnly(pwszName, lfCharSet, iEnumType, &effi, pftoPublic, pftoPrivate, pulCount); }
return ((ULONG_PTR) hefsRet); }
/******************************Public*Routine******************************\
* BOOL bEnumFontChunk * * Second phase of the enumeration. HPFEs are pulled out of the enumeration * state one-by-one, converted into an ENUMFONTDATA structure, and put into * the return buffer. The size of the return buffer is determined by the * client side and determines the granularity of the "chunking". * * This function signals the client side that the enumeration data has been * exhausted by returning FALSE. Note that it is possible that in the pass * pass through here that the EFSTATE may already be empty. The caller must * check both the function return value and the pcefdw value. * * Note: * Caller should set *pcefd to the capacity of the pefp buffer. * Upon return, iEnumType will set pefb.cefp to the number of * ENUMFONTDATA structures copied into the pefb.aefd array. * * Also, pefdw is user memory, which might be asynchronously changed * at any time. So, we cannot trust any values read from that buffer. * * Returns: * TRUE if there are more to go, FALSE otherwise, * * History: * 08-Aug-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL bEnumFontChunk( HDC hdc, // device to enumerate on
ULONG_PTR idEnum, COUNT cjEfdwTotal, // (in) capacity of buffer
COUNT *pcjEfdw, // (out) number of ENUMFONTDATAs returned
PENUMFONTDATAW pefdw // return buffer
) { // Initialize position in buffer in which to copy data
PENUMFONTDATAW pefdwCur = pefdw; *pcjEfdw = 0;
// Validate DC and EnumFontState. If either fail lock bug out.
DCOBJ dco(hdc); EFSOBJ efso((HEFS) idEnum);
if ((!efso.bValid()) || (!dco.bValid())) { WARNING("gdisrv!bEnumFontChunk(): bad HEFS or DC handle\n"); return FALSE; }
// since as of 4.0 we do not go through this a chunk at the time
// we must have
if (cjEfdwTotal != efso.cjEfdwTotal()) { WARNING("gdisrv!bEnumFontChunk(): efso.cjEfdwTotal() problem\n"); return FALSE; }
ASSERTGDI(cjEfdwTotal >= efso.cefe() * CJ_EFDW0, "cjEfdwTotal NOT BIG enough \n");
// Counter to track number of ENUMFONTDATAW structures copied into buffer.
COUNT cjEfdwCopied = 0; EFENTRY *pefe;
// Before we access PFEs, grab the ghsemPublicPFT so no one can delete
// PFE while we are in the loop (note that PFEs can get deleted
// once we are outside of this--like between chunks!).
SEMOBJ so(ghsemPublicPFT);
// In each font file, try each font face
// We are sure that we will not overwrite the buffer because
// the size of buffer is big enough to take all the enumfont data.
while((pefe = efso.pefeEnumNext())) { // Create a PFE Collect user object. We're using real handle instead of
// pointers because someone may have deleted by the time we get
// around to enumerating.
// Get the PFE through PFE Collect object.
HPFECOBJ pfeco(pefe->hpfec); PFEOBJ pfeo(pfeco.GetPFE(pefe->iFont));
SIZE_T cjEfdwCur = 0;
// Validate user object and copy data into buffer. Because PFE
// may have been deleted between chunks, we need to check validity.
PWSZ pwszFamilyOverride = NULL; BOOL bCharSetOverride = FALSE; ULONG lfCharSetOverride = DEFAULT_CHARSET;
if (efso.pwszFamilyOverride()) { pwszFamilyOverride = efso.pwszFamilyOverride();
if (pefe->fjOverride & FJ_CHARSETOVERRIDE) { bCharSetOverride = TRUE; lfCharSetOverride = pefe->jCharSetOverride; } else { bCharSetOverride = efso.bCharSetOverride(); lfCharSetOverride = (ULONG)efso.jCharSetOverride(); } } else { if (pefe->fjOverride & FJ_FAMILYOVERRIDE) { pwszFamilyOverride = gpfsTable[pefe->iOverride].awchOriginal; } if (pefe->fjOverride & FJ_CHARSETOVERRIDE) { bCharSetOverride = TRUE; lfCharSetOverride = pefe->jCharSetOverride; } }
if ( pfeo.bValid() && (cjEfdwCur = cjCopyFontDataW( dco, pefdwCur, pfeo, pefe->efsty, pwszFamilyOverride, lfCharSetOverride, bCharSetOverride, efso.iEnumType() )) ) { cjEfdwCopied += (ULONG) cjEfdwCur; pefdwCur = (ENUMFONTDATAW *)((BYTE*)pefdwCur + cjEfdwCur); } }
*pcjEfdw = cjEfdwCopied;
// we are done: pefe has to be zero:
ASSERTGDI(!pefe, "not all fonts are enumerated yet\n"); ASSERTGDI(cjEfdwCopied <= cjEfdwTotal, "cjEfdwCopied > cjEfdwTotal\n");
// true means success, it used to mean that there are more fonts to come for
// enumeration. Now, we do not do "chunking" any more. Assert above makes sure
// that this is the case [bodind]
return TRUE; }
/*************************Public*Routine********************************\
* BOOL bScanTheList() * * Scan through the font hash table using the given filter mode * * History: * * 07-Nov-1996 -by- Xudong Wu [TessieW] * Wrote it. * ************************************************************************/
BOOL bScanTheList( FHOBJ *pfho, ULONG ulFilter, EFSOBJ *pefsmo, ULONG iEnumType, EFFILTER_INFO *peffi, PWSZ pwszName ) { BOOL bRet;
if (pwszName) { bRet = pfho->bScanLists(pefsmo, pwszName, iEnumType, peffi); } else { BOOL bTempFilter; if (ulFilter == ENUM_FILTER_TT) { bTempFilter = peffi->bTrueTypeFilter; peffi->bTrueTypeFilter = TRUE; } else if (ulFilter == ENUM_FILTER_NONTT) { peffi->bNonTrueTypeFilter = TRUE; }
bRet = pfho->bScanLists(pefsmo, iEnumType, peffi);
if (ulFilter == ENUM_FILTER_TT) { peffi->bTrueTypeFilter = bTempFilter; } else if (ulFilter == ENUM_FILTER_NONTT) { peffi->bNonTrueTypeFilter = FALSE; } }
return bRet; }
/*************************Public*Routine********************************\
* BOOL bScanFamily() * * Scan through the family font hash table in the different filter * order given by the input flag. * * History: * * 23-Oct-1996 -by- Xudong Wu [TessieW] * Wrote it. * ************************************************************************/
BOOL bScanFamily( FHOBJ *pfho1, ULONG ulFilter1, FHOBJ *pfho2, ULONG ulFilter2, FHOBJ *pfho3, ULONG ulFilter3, EFSOBJ *pefsmo, ULONG iEnumType, EFFILTER_INFO *peffi, PWSZ pwszName ) { return ( (!pfho1 || bScanTheList(pfho1, ulFilter1, pefsmo, iEnumType, peffi, pwszName)) && (!pfho2 || bScanTheList(pfho2, ulFilter2, pefsmo, iEnumType, peffi, pwszName)) && (!pfho3 || bScanTheList(pfho3, ulFilter3, pefsmo, iEnumType, peffi, pwszName)) ); }
/*************************Public*Routine********************************\
* BOOL bScanFamilyAndFace() * * Frist scan through the family font hash table. If no match is found, * scan through the face font hash table. * * History: * * 23-Oct-1996 -by- Xudong Wu [TessieW] * Wrote it. * ************************************************************************/
BOOL bScanFamilyAndFace( FHOBJ *pfhoEngFamily, FHOBJ *pfhoEngFace, FHOBJ *pfhoDevFamily, FHOBJ *pfhoDevFace, EFSOBJ *pefsmo, ULONG iEnumType, EFFILTER_INFO *peffi, PWSZ pwszName ) { BOOL bRet = FALSE;
if (bScanFamily(pfhoDevFamily, ENUM_FILTER_NONE, pfhoEngFamily, ENUM_FILTER_NONE, (FHOBJ *) NULL, 0, pefsmo, iEnumType, peffi, pwszName)) { // If list is empty, try the face name lists, else we are done
if (pefsmo->bEmpty() ) { bRet = bScanFamily(pfhoDevFace, ENUM_FILTER_NONE, pfhoEngFace, ENUM_FILTER_NONE, (FHOBJ*) NULL, 0, pefsmo, iEnumType, peffi, pwszName); #if DBG
if (!bRet) WARNING("win32k!bScanFamilyAndFace(): scan face failed\n"); #endif
} else { bRet = TRUE; }
} #if DBG
else { WARNING("win32k!bScanFamilyAndFace(): scan family failed\n"); } #endif
return bRet; }
|