Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1405 lines
39 KiB

/*++
Copyright (c) 1996 - 1999 Microsoft Corporation
Module Name:
fminit.c
Abstract:
Font Module: device font intialization modules.
Environment:
Windows NT Unidrv driver
Revision History:
11/28/96 -ganeshp-
Created
--*/
#include "font.h"
//
// Forward declarations
//
INT
IFontID2Index( FONTPDEV *pFontPDev,
int iID
);
VOID
VLoadDeviceFontsResDLLs(
PDEV *pPDev
);
DWORD
CopyMemoryRLE(
PVOID pvData,
PBYTE pubSrc,
DWORD dwSize
);
//
// Functions
//
INT
IInitDeviceFonts (
PDEV *pPDev
)
/*++
Routine Description:
Doing the actual grovelling around for font data. We have a bit
array of available fonts (created above), so we use that as the
basis of filling in the rest of the information.
Arguments:
pPDev Pointer to PDEV
Return Value:
The number of fonts available.
Note:
11-27-96: Created it -ganeshp-
--*/
{
INT iIndex; // Loop index
INT cBIFonts; // Fonts built in to mini-driver
INT cXFonts = 0; // Non-minidriver font count
INT cFonts; // Total number of fonts
//TODEL BOOL bExpand; Set when font derivatives are available.
FONTMAP *pfm; // Create this data
PFONTPDEV pFontPDev = pPDev->pFontPDev;
//
// So how many fonts do we have? Count them so that we can allocate
// storage for the array of FONTMAPs.
//
cBIFonts = pFontPDev->iDevFontsCt;
if (!pFontPDev->hUFFFile)
#ifdef KERNEL_MODE
pFontPDev->hUFFFile = FIOpenFontFile(pPDev->devobj.hPrinter, pPDev->devobj.hEngine, NULL);
#else
pFontPDev->hUFFFile = FIOpenFontFile(pPDev->devobj.hPrinter, NULL);
#endif
if (pFontPDev->hUFFFile)
cXFonts = FIGetNumFonts(pFontPDev->hUFFFile);
else
cXFonts = 0;
pFontPDev->iSoftFontsCt = cXFonts;
//
// Allocate enough memory to hold font map table.
//
cFonts = cBIFonts + cXFonts;
pfm = (FONTMAP *)MemAllocZ( cFonts * SIZEOFDEVPFM() );
if( pfm == 0 )
{
//
// Failed to allocate memory
//
cFonts = cBIFonts = cXFonts = 0;
ERR(("Failed to allocate memory"));
}
else
{
pFontPDev->pFontMap = pfm;
//
// Select the first font as the default font, just in case the
// value is not initialised in the loop below.
//
pFontPDev->pFMDefault = pfm;
//
// Continue only if there are device fonts.
//
if( cFonts )
{
//
// Initialize the default font: we always do this now, as it is
// required to return the default font at DrvEnablePDEV time,
// and it is also simpler for us.
//
iIndex = IFontID2Index( pFontPDev, pFontPDev->dwDefaultFont );
if( iIndex >= 0 && iIndex < cFonts )
{
// Found the default font ID, so now set up details
pfm = (PFONTMAP)( (PBYTE)pFontPDev->pFontMap
+ SIZEOFDEVPFM() * iIndex);
//
// Index returned by IFontID2Index is 0 based. So no need to
// Convert it to 0 based.
// BFillinDeviceFM assumes it to be 0 based.
//
if( BFillinDeviceFM( pPDev, pfm, iIndex) )
{
pFontPDev->pFMDefault = pfm;
}
else
{
WARNING(("BFillinDeviceFM Fails\n"));
cFonts = cBIFonts = cXFonts = 0;
}
}
else
WARNING(("No Default Font Using first as default\n"));
//
// Fill in some default font sensitive numbers!
//
pfm->flFlags |= FM_DEFAULT;
//
// Set the size of the default font
//
if (pfm->pIFIMet)
{
pPDev->ptDefaultFont.y = ((IFIMETRICS *)pfm->pIFIMet)->fwdWinAscender/2;
pPDev->ptDefaultFont.x = ((IFIMETRICS *)pfm->pIFIMet)->fwdAveCharWidth;
}
else
{
ERR(("Bad IFI Metrics Pointer\n"));
cFonts = cBIFonts = cXFonts = 0;
}
}
}
//
// Check for error condition. If an error has occured set devfont to 0
//
if (!cFonts)
{
pFontPDev->iDevFontsCt =
pFontPDev->iDevResFontsCt =
pFontPDev->iSoftFontsCt = 0;
}
//
// Now load any alternate resource DLLs from where device font has to be
// loaded. This is necessary now because snapshot will be unloaded after
// DrvEnablePDev and WinResData.pUIInfo will be invalid. Because of this
// DLL load will fail.
//
VLoadDeviceFontsResDLLs(pPDev);
pPDev->iFonts = cFonts; /* As many as we got */
return cFonts;
}
BOOL
BFillinDeviceFM(
PDEV *pPDev,
FONTMAP *pfm,
int iIndex
)
/*++
Routine Description:
Fill in (most) of the FONTMAP structure passed in. The data is
obtained from either the minidriver resources or from from the
font installer file. The only part we do not set is the NTRLE
data, as that is a little more complex.
Arguments:
pPDev - Pointer to PDEV.
pfm - The FONTMAP structure to fill in
iIndex - The 0 based index of the font to fill in
Return Value:
TRUE - for success
FALSE - for failure
Note:
12-04-96: Created it -ganeshp-
--*/
{
PFONTPDEV pFontPDev; /* More specific data */
PFONTMAP_DEV pfmdev;
RES_ELEM ResElem; /* For manipulating resource data */
pFontPDev = pPDev->pFontPDev;
pfm->dwSignature = FONTMAP_ID;
pfm->dwSize = sizeof(FONTMAP);
pfm->dwFontType = FMTYPE_DEVICE;
pfm->pSubFM = (PFONTMAP_DEV)(pfm+1);
pfmdev = pfm->pSubFM;
/*
* Activity depends upon whether we have an internal or
* external font. Externals are softfonts, other than GDI downloaded.
*/
if( iIndex < pFontPDev->iDevFontsCt )
{
DWORD dwFont; /* Convert index to resource number */
/* Get the font ID for this index */
dwFont = pFontPDev->FontList.pdwList[iIndex];
//
// Check the Font Format of the resource. The new font IFI is stored
// with RC_UFM tag. The old one was stored using RC_FONT.
//
if( BGetWinRes( &(pPDev->WinResData), (PQUALNAMEEX)&dwFont, RC_FONT, &ResElem ) )
{
pfm->flFlags |= FM_IFIVER40;
if( !BGetOldFontInfo( pfm, ResElem.pvResData ) )
return FALSE;
}
else
if(BGetWinRes( &(pPDev->WinResData),(PQUALNAMEEX)&dwFont,RC_UFM,&ResElem) )
{
if ( !BGetNewFontInfo(pfm, ResElem.pvResData) )
return FALSE;
if (pPDev->bTTY)
((FONTMAP_DEV*)pfm->pSubFM)->ulCodepage = pFontPDev->dwTTYCodePage;
}
else
{
ERR(("Can't Load the font data for res_id= %d\n", dwFont));
return FALSE;
}
//
// Create the data we need. Unidrv5 only supports NT specific data.
//
pfmdev->dwResID = dwFont;
}
else
{
INT iFont = iIndex - pFontPDev->iDevFontsCt;
/*
* This must be an external font, so we need to call the
* code that understands how external font files are built.
*/
if( !BFMSetupXF( pfm, pPDev, iFont ) )
return FALSE;
pfmdev->dwResID = iFont;
}
/*
* If needed, scale the numbers to fit the desired resolution.
*/
if( !BIFIScale( pfm, pPDev->ptGrxRes.x, pPDev->ptGrxRes.y ) )
return FALSE;
/*
* Miscellaneous FM fields that can now be filled in.
*/
pfm->wFirstChar = ((IFIMETRICS *)pfm->pIFIMet)->wcFirstChar;
pfm->wLastChar = ((IFIMETRICS *)pfm->pIFIMet)->wcLastChar;
/*
* If this is an outline font, then mark it as scalable. This
* piece of information is required at font selection time.
*/
if (((IFIMETRICS *)pfm->pIFIMet)->flInfo & (FM_INFO_ISOTROPIC_SCALING_ONLY|FM_INFO_ANISOTROPIC_SCALING_ONLY|FM_INFO_ARB_XFORMS))
pfm->flFlags |= FM_SCALABLE;
/*
* Select the translation table for this font. If it is zero,
* then use the default translation table, contained in ModelData.
*/
if( pfmdev->sCTTid == 0 )
pfmdev->sCTTid = (SHORT)pFontPDev->sDefCTT;
/*
* Some printers output the character with the cursor positioned
* at the baseline, others with it located at the top of the
* character cell. We store the needed offset in the FONTMAP
* data, to simplify life during output. The data returned by
* DrvQueryFontData is relative to the baseline. For baseline
* based fonts, we need do nothing. For top of cell fonts,
* the fwdWinAscender value needs to be SUBTRACTED from the Y position
* to determine the glyph's location on the page.
*/
//
// Set for non-scalable font
// This value has to be scaled for scalable device font.
//
if( !(pFontPDev->flFlags & FDV_ALIGN_BASELINE) )
pfm->syAdj = -((IFIMETRICS *)(pfm->pIFIMet))->fwdWinAscender;
else
pfm->syAdj = 0; /* There is none */
/*
* Dot matrix printers also do funny things with double high
* characters. To handle this, the GPC spec contains a move
* amount to add to the Y position before printing with these
* characters. There is also the adjustment for position
* movement after printing.
*/
pfmdev->sYAdjust = (SHORT)(pfmdev->sYAdjust * pPDev->ptGrxRes.y / pfm->wYRes);
pfmdev->sYMoved = (SHORT)(pfmdev->sYMoved * pPDev->ptGrxRes.y / pfm->wYRes);
//
// Funciton pointer initialization.
//
pfm->pfnDownloadFontHeader = NULL;
pfm->pfnDownloadGlyph = NULL;
pfm->pfnCheckCondition = NULL;
//
// PCL-XL hack
//
if (pPDev->ePersonality == kPCLXL)
{
pfm->pfnGlyphOut = DwOutputGlyphCallback;
pfm->pfnSelectFont = BSelectFontCallback;
pfm->pfnDeSelectFont = BDeselectFontCallback;
}
else
if( pfm->flFlags & FM_IFIVER40 )
{
pfm->pfnGlyphOut = BRLEOutputGlyph;
pfm->pfnSelectFont = BRLESelectFont;
pfm->pfnDeSelectFont = BRLEDeselectFont;
}
else
{
pfm->pfnGlyphOut = BGTTOutputGlyph;
pfm->pfnSelectFont = BGTTSelectFont;
pfm->pfnDeSelectFont = BGTTDeselectFont;
}
if (pfm->flFlags & FM_SOFTFONT)
{
pfm->pfnSelectFont = BSelectTrueTypeBMP;
}
if (pPDev->pOemHookInfo)
{
if (pPDev->pOemHookInfo[EP_OEMOutputCharStr].pfnHook)
{
pfm->pfnGlyphOut = DwOutputGlyphCallback;
}
if (pPDev->pOemHookInfo[EP_OEMSendFontCmd].pfnHook)
{
pfm->pfnSelectFont = BSelectFontCallback;
pfm->pfnDeSelectFont = BDeselectFontCallback;
}
}
if (pfm->flFlags & FM_SCALABLE)
{
switch (pfmdev->wDevFontType)
{
case DF_TYPE_HPINTELLIFONT:
case DF_TYPE_TRUETYPE:
pfmdev->pfnDevSelFont = BSelectPCLScalableFont;
break;
case DF_TYPE_PST1:
pfmdev->pfnDevSelFont = BSelectPPDSScalableFont;
break;
case DF_TYPE_CAPSL:
pfmdev->pfnDevSelFont = BSelectCapslScalableFont;
break;
}
}
else
{
pfmdev->pfnDevSelFont = BSelectNonScalableFont;
}
//
// Get Glyph data (RLE/GTT)
//
VFillinGlyphData( pPDev, pfm );
return TRUE;
}
BOOL
BFMSetupXF(
FONTMAP *pfm,
PDEV *pPDev,
INT iIndex
)
/*++
Routine Description:
Function to setup the FONTMAP data for an external font. We take the
next entry in the file, which is presumed to have been rewound
before we start being called.
Arguments:
pfm - Pointer to FONTMAP.
pPDev - Pointer to PDEV.
iIndex - Index of the font.
Return Value:
TRUE - for success
FALSE - for EOF
Note:
12-05-96: Created it -ganeshp-
--*/
{
FONTPDEV *pFontPDev = pPDev->pFontPDev;
UFF_FONTDIRECTORY *pFontDir;
DATA_HEADER *pDataHeader;
FONTMAP_DEV *pFMSub;
BOOL bRet;
//
// Not much to do. We basically need to convert the offsets in
// the FONTMAP in the file (mapped into memory) into absolute
// addresses so that the remainder of the driver is ignorant of
// We also set some flags to make it clear
// what type of font and memory we are.
//
if (!(pDataHeader = FIGetFontData(pFontPDev->hUFFFile, iIndex)))
{
ERR(( "FIGetFontData returns FALSE!!\n" ));
return FALSE;
}
pFMSub = pfm->pSubFM;
if (pFontDir = FIGetFontDir(pFontPDev->hUFFFile))
{
pFMSub->pFontDir = pFontDir + iIndex;
}
//
// Check if this is a cartridge font and set flag
//
if (!pFMSub->pFontDir->offCartridgeName)
pfm->flFlags |= FM_SOFTFONT;
pfm->flFlags |= FM_EXTERNAL;
switch (pDataHeader->dwSignature)
{
case DATA_IFI_SIG:
pfm->flFlags |= FM_GLYVER40 | FM_IFIVER40;
BGetOldFontInfo(pfm, (PBYTE)pDataHeader + pDataHeader->wSize);
bRet = TRUE;
break;
case DATA_UFM_SIG:
BGetNewFontInfo(pfm, (PBYTE)pDataHeader + pDataHeader->wSize);
bRet = TRUE;
break;
default:
bRet = FALSE;
break;
}
return bRet;
}
//
// Misc functions
//
#define XSCALE( x ) (x) = (FWORD)((( x ) * xdpi + iXDiv / 2) / iXDiv)
#define YSCALE( y ) (y) = (FWORD)((( y ) * ydpi + iYDiv / 2) / iYDiv)
#define YSCALENEG( y ) (y) = (FWORD)((( y ) * ydpi - iYDiv / 2) / iYDiv)
BOOL
BIFIScale(
FONTMAP *pfm,
INT xdpi,
INT ydpi
)
/*++
Routine Description:
Scale the IFIMETRICS fields to match the device resolution. The
IFIMETRICS are created using the device's master units, which
may not correspond with the resolution desired this time around.
If they are different, then we adjust. May also need to allocate
memory, because resource data cannot be written to.
Arguments:
pfm - Pointer to FONTMAP.
xdpi - Selcted X Graphics Resolution.
ydpi - Selcted Y Graphics Resolution.
Return Value:
TRUE - for success
FALSE - for failure
Note:
12-05-96: Created it -ganeshp-
--*/
{
IFIMETRICS *pIFI;
int iXDiv, iYDiv; /* Used in scaling */
pIFI = pfm->pIFIMet;
if (NULL == pIFI)
{
return FALSE;
}
if( (int)pfm->wXRes != xdpi || (int)pfm->wYRes != ydpi )
{
/* Need to scale, so need memory to create writeable version */
BYTE *pbMem; /* For convenience */
if( pfm->flFlags & FM_IFIRES )
{
/*
* The data is in a resource, so we need to do something
* civilised: copy the data to memory that can be written.
*/
if( pbMem = MemAllocZ( pIFI->cjThis ) )
{
/* Got the memory, so copy it and off we go */
CopyMemory( pbMem, (BYTE *)pIFI, pIFI->cjThis );
pIFI = (IFIMETRICS *)pbMem;
pfm->pIFIMet = pIFI;
pfm->flFlags &= ~FM_IFIRES; /* No longer */
}
else
return FALSE;
}
if( (int)pfm->wXRes != xdpi )
{
/* Adjust the X values, as required */
if( !(iXDiv = pfm->wXRes) )
iXDiv = xdpi; /* Better than div by 0 */
XSCALE( pIFI->fwdMaxCharInc );
XSCALE( pIFI->fwdAveCharWidth );
XSCALE( pIFI->fwdSubscriptXSize );
XSCALE( pIFI->fwdSubscriptXOffset );
XSCALE( pIFI->fwdSuperscriptXSize );
XSCALE( pIFI->fwdSuperscriptXOffset );
XSCALE( pIFI->ptlAspect.x );
XSCALE( pIFI->rclFontBox.left );
XSCALE( pIFI->rclFontBox.right );
if (pIFI->dpFontSim)
{
PTRDIFF dpTmp;
FONTDIFF* pFontDiff;
FONTSIM* pFontSim;
pFontSim = (FONTSIM*) ((PBYTE) pIFI + pIFI->dpFontSim);
if (dpTmp = pFontSim->dpBold)
{
pFontDiff = (FONTDIFF*)((PBYTE)pFontSim + dpTmp);
XSCALE( pFontDiff->fwdMaxCharInc );
XSCALE( pFontDiff->fwdAveCharWidth );
}
if (dpTmp = pFontSim->dpItalic)
{
pFontDiff = (FONTDIFF*)((PBYTE)pFontSim + dpTmp);
XSCALE( pFontDiff->fwdMaxCharInc );
XSCALE( pFontDiff->fwdAveCharWidth );
}
if (dpTmp = pFontSim->dpBoldItalic)
{
pFontDiff = (FONTDIFF*)((PBYTE)pFontSim + dpTmp);
XSCALE( pFontDiff->fwdMaxCharInc );
XSCALE( pFontDiff->fwdAveCharWidth );
}
}
}
if( (int)pfm->wYRes != ydpi )
{
/*
* Note that some of these numbers are negative, and so
* we need to round them correctly - i.e. subtract the rounding
* factor to move the value further from 0.
*/
int iPixHeight;
if( !(iYDiv = pfm->wYRes) )
iYDiv = ydpi;
/* Adjust the Y values, as required */
/*
* NOTE: simply scaling will NOT produce the same values
* as Win 3.1 This is because of what gets rounded. Win 3.1
* does not have the WinDescender field, but calculates it
* from dfPixHeight and dfAscent AFTER THESE HAVE BEEN SCALED
* (INCLUDING ROUNDING!!). To emulate that, we calculate
* the dfPixHeight value, then scale that and dfAscent to
* allow us to "properly" calculate WinDescender. This stuff
* is needed for Win 3.1 compatability!
*/
YSCALE( pIFI->fwdUnitsPerEm );
iPixHeight = pIFI->fwdWinAscender + pIFI->fwdWinDescender;
YSCALE( iPixHeight );
YSCALE( pIFI->fwdWinAscender );
pIFI->fwdWinDescender = iPixHeight - pIFI->fwdWinAscender;
YSCALE( pIFI->fwdMacAscender );
pIFI->fwdMacDescender = -pIFI->fwdWinDescender;
YSCALE( pIFI->fwdMacLineGap );
YSCALE( pIFI->fwdTypoAscender );
YSCALE( pIFI->fwdTypoDescender );
YSCALE( pIFI->fwdTypoLineGap);
YSCALE( pIFI->fwdCapHeight );
YSCALE( pIFI->fwdXHeight );
YSCALE( pIFI->fwdSubscriptYSize );
YSCALENEG( pIFI->fwdSubscriptYOffset );
YSCALE( pIFI->fwdSuperscriptYSize );
YSCALE( pIFI->fwdSuperscriptYOffset );
YSCALE( pIFI->fwdUnderscoreSize );
if( pIFI->fwdUnderscoreSize == 0 )
pIFI->fwdUnderscoreSize = 1; /* In case it vanishes */
YSCALENEG( pIFI->fwdUnderscorePosition );
if( pIFI->fwdUnderscorePosition == 0 )
pIFI->fwdUnderscorePosition = -1;
YSCALE( pIFI->fwdStrikeoutSize );
if( pIFI->fwdStrikeoutSize == 0 )
pIFI->fwdStrikeoutSize = 1; /* In case it vanishes */
YSCALE( pIFI->fwdStrikeoutPosition );
YSCALE( pIFI->ptlAspect.y );
YSCALE( pIFI->rclFontBox.top );
YSCALE( pIFI->rclFontBox.bottom );
#undef XSCALE
#undef YSCALE
#undef YSCALENEG
}
}
return TRUE;
}
HANDLE
HLoadUniResDll(PDEV *pPDev)
{
PWSTR pwstrTmp, pwstrResFileName, pwstrDrvName;
HANDLE hHandle = NULL;
HRESULT hr = S_FALSE;
SIZE_T cchBuf = 0;
if (pPDev->pDriverInfo3)
pwstrDrvName = pPDev->pDriverInfo3->pDriverPath;
else
return NULL;
cchBuf = 1 + wcslen(pwstrDrvName);
pwstrResFileName = MemAlloc( cchBuf * sizeof(WCHAR));
if (pwstrResFileName == NULL)
return NULL;
hr = StringCchCopy ( pwstrResFileName, cchBuf, pwstrDrvName);
if ( SUCCEEDED (hr) )
{
#ifdef WINNT_40
if (!(pwstrTmp = wcsstr(pwstrResFileName, TEXT("UNIDRV4.DLL"))))
#else
if (!(pwstrTmp = wcsstr(pwstrResFileName, TEXT("UNIDRV.DLL"))))
#endif
{
MemFree(pwstrResFileName);
return NULL;
}
*pwstrTmp = UNICODE_NULL;
hr = StringCchCat ( pwstrResFileName, cchBuf, TEXT("unires.dll"));
if ( SUCCEEDED (hr) )
{
hHandle = EngLoadModule(pwstrResFileName);
#ifdef DBG
if (!hHandle)
{
ERR(("UNIDRV: Failed to load UNIRES.DLL\n"));
}
#endif
}
} // if StringCchCopy succeeds.
MemFree(pwstrResFileName);
return hHandle;
}
VOID
VFillinGlyphData(
PDEV *pPDev,
FONTMAP *pfm
)
/*++
Routine Description:
Provide the RLE data required for this font. Basically look to see
if some other font has this RLE data already loaded; if so, then
point to that and return. Otherwise, load the resource etc.
Arguments:
pPDev - Pointer to PDEV.
pfm - The FONTMAP whose Gyphy Translation data is required
Return Value:
Nothing
Note:
12-05-96: Created it -ganeshp-
--*/
{
int iIndex; /* Scan the existing array */
short sCurVal; /* Speedier access */
BOOL bSymbol;
DWORD dwCurVal;
PQUALNAMEEX pQualName = (PQUALNAMEEX)&dwCurVal;
PVOID pvData; /* The FD_GLYPHSET format we want */
FONTMAP *pfmIndex; /* Speedy scanning of existing list */
FONTMAP_DEV *pfmdev, *pfmdevIndex;
FONTPDEV *pFontPDev; /* More specialised data */
TRACE(\nUniFont!VFillinGlyphData:START);
pvData = NULL; /* In case Nothing we can do! */
pfmdev = pfm->pSubFM;
bSymbol = IS_SYMBOL_CHARSET(pfm);
/*
* First step is to look through the existing FONTMAP array, and
* if we find one with the same sCTTid and same format as us, use it!
* Otherwise,we need to load the resource and do it the hard way!
*/
pFontPDev = pPDev->pFontPDev;
if (pfm->flFlags & FM_EXTERNAL)
{
sCurVal = pfmdev->pFontDir->sGlyphID;
}
else
{
//
// Minidriver Resource case.
// RLE/GTT file must be in the same DLL as IFI/UFM is.
//
//
// Convert the resource ID to fully qualied ID. The format is
// OptionID.ResFeatureID.ResourceID. Get the option and feature ID from
// fontmap dwRes
//
pQualName->wResourceID = sCurVal = pfmdev->sCTTid;
pQualName->bFeatureID = pfmdev->QualName.bFeatureID;
pQualName->bOptionID = pfmdev->QualName.bOptionID;
}
pfmIndex = pFontPDev->pFontMap;
for( iIndex = 0;
iIndex < pPDev->iFonts;
++iIndex, pfmIndex = (PFONTMAP)((PBYTE)pfmIndex + SIZEOFDEVPFM()) )
{
pfmdevIndex = (PFONTMAP_DEV) pfmIndex->pSubFM;
if( (pfmdevIndex &&
pfmdevIndex->pvNTGlyph) &&
pfmIndex->pIFIMet &&
(pfmdevIndex->sCTTid == sCurVal) &&
((pfmIndex->flFlags & FM_IFIVER40) ==
(pfm->flFlags & FM_IFIVER40)) &&
((pfmIndex->flFlags & FM_EXTERNAL) ==
(pfm->flFlags & FM_EXTERNAL)) &&
pfm->pIFIMet->jWinCharSet ==
pfmIndex->pIFIMet->jWinCharSet )
{
//
// Found it, so use that address!!
//
pfmdev->pvNTGlyph = pfmdevIndex->pvNTGlyph;
//
//Mark the flag for Glyph Data Format.
//
if (pfmIndex->flFlags & FM_GLYVER40)
pfm->flFlags |= FM_GLYVER40;
if (bSymbol)
{
pfm->wLastChar = SYMBOL_END;
if (!(pfm->flFlags & FM_IFIRES))
pfm->pIFIMet->wcLastChar = SYMBOL_END;
}
TRACE(Using a Already Loaded Translation Table.)
PRINTVAL((pfm->flFlags & FM_GLYVER40), 0X%x);
PRINTVAL((pfm->flFlags & FM_IFIVER40), 0X%x);
TRACE(UniFont!VFillinGlyphData:END\n);
return;
}
}
/*
* Do it the hard way - load the resource, convert as needed etc.
*/
if( sCurVal < 0 )
{
/* Use Predefined resource */
DWORD dwSize; /* Data size of resource */
int iRCType;
HMODULE hUniResDLL;
BYTE *pb;
if (!pPDev->hUniResDLL)
pPDev->hUniResDLL = HLoadUniResDll(pPDev);
hUniResDLL = pPDev->hUniResDLL;
/*
* These are resources we have, so we need to use
* the normal resource mechanism to get the data.
*/
ASSERTMSG( hUniResDLL,("UNIDRV!vFillinGlyphData - Null Module handle \n"));
//VERBOSE(("Using prdefined Glyph Data for Font res_id = %d!!!\n",pfmdev->dwResID));
PRINTVAL( (LONG)sCurVal, %ld );
//
// Load the old format RLE if the font format is NT40.
// Otherwise, New Format PreDefined Glyph Data.
//
if ( hUniResDLL )
{
if (pfm->flFlags & FM_IFIVER40)
{
iRCType = RC_TRANSTAB;
}
else
{
iRCType = RC_GTT;
}
pb = EngFindResource( hUniResDLL, (-sCurVal), iRCType, &dwSize );
if( pb )
{
if (pfm->flFlags & FM_IFIVER40)
{
NT_RLE_res *pntrle_res = (NT_RLE_res*)pb;
dwSize = sizeof(NT_RLE) +
(pntrle_res->fdg_cRuns - 1) * sizeof(WCRUN) +
pntrle_res->cjThis - pntrle_res->fdg_wcrun_awcrun[0].dwOffset_phg;
if( !(pvData = (VOID *)MemAllocZ( dwSize )) ||
dwSize != CopyMemoryRLE( pvData, pb, dwSize ) )
{
MemFree(pvData);
pvData = NULL;
ERR(("\n!!!UniFont!VFillinGlyphData:MemAllocZ Failed.\
\nFontID = %d,Name = %ws,CTTid = %d\n\n",pfmdev->dwResID,\
(PBYTE)pfm->pIFIMet + pfm->pIFIMet->dpwszFaceName,(-sCurVal)));
}
pfm->flFlags |= FM_GLYVER40;
}
else
{
if( pvData = (VOID *)MemAllocZ( dwSize ) )
CopyMemory( pvData, pb, dwSize );
else
{
ERR(("\n!!!UniFont!VFillinGlyphData:MemAllocZ Failed.\
\nFontID = %d,Name = %ws,CTTid = %d\n\n",pfmdev->dwResID,\
(PBYTE)pfm->pIFIMet + pfm->pIFIMet->dpwszFaceName,(-sCurVal)));
}
}
/* This One wil be freed when done */
pfm->flFlags |= FM_FREE_GLYDATA;
}
else
{
ERR(("\n!!!UniFont!VFillinGlyphData:EngFindResource Failed\n"));
}
}
}
else if( pfm->flFlags & FM_EXTERNAL)
{
PDATA_HEADER pDataHeader;
pDataHeader = FIGetGlyphData(pFontPDev->hUFFFile, sCurVal);
if (pDataHeader)
pvData = (PBYTE)pDataHeader + pDataHeader->wSize;
}
else
{
/* Use Minidriver Resources */
RES_ELEM re; /* Resource summary */
/*
* First step: locate the resource, then grab some
* memory for it, copy data across.The minidriver trans
* table can be in two formats. NT 4.0 resource uses
* RC_TRANSTAB tag and the new one uses RC_GTT tag. So
* try using both of the and set the flFlag accordingly.
* If FM_GLYVER40 is off that means the resource is new
* format and On means old format.
*/
if ( BGetWinRes( &(pPDev->WinResData), pQualName, RC_GTT, &re ) )
{
pvData = re.pvResData;
//VERBOSE(("Using New Format Glyph Data for Font res_id = %d!!!\n",pfmdev->dwResID));
}
else if( BGetWinRes( &(pPDev->WinResData), pQualName, RC_TRANSTAB, &re ) )
{
NT_RLE_res *pntrle_res = (NT_RLE_res*)re.pvResData;
DWORD dwSize = sizeof(NT_RLE) +
(pntrle_res->fdg_cRuns - 1) * sizeof(WCRUN) +
pntrle_res->cjThis - pntrle_res->fdg_wcrun_awcrun[0].dwOffset_phg;
if( !(pvData = (VOID *)MemAllocZ( dwSize )) ||
dwSize != CopyMemoryRLE( pvData, (PBYTE)pntrle_res, dwSize ) )
{
MemFree(pvData);
pvData = NULL;
ERR(("\n!!!UniFont!VFillinGlyphData:MemAllocZ Failed.\
\nFontID = %d,Name = %ws,CTTid = %d\n\n",pfmdev->dwResID,\
(PBYTE)pfm->pIFIMet + pfm->pIFIMet->dpwszFaceName,(-sCurVal)));
}
if (pvData)
{
pfm->flFlags |= FM_FREE_GLYDATA;
}
pfm->flFlags |= FM_GLYVER40;
//VERBOSE(("Using Old Format Glyph Data for Font res_id = %d!!!\n",pfmdev->dwResID));
}
else
pvData = NULL; /* No translation data! */
}
if( pvData == NULL )
{
/*
* Presume this to mean that no translation is required.
* We build a special RLE table for this, to make life
* easier for us.
*/
//VERBOSE(("No specific Glyph Data for Font res_id = %d!!!\n",pfmdev->dwResID));
if (pfm->flFlags & FM_IFIVER40)
{
pvData = PNTRLE1To1(bSymbol, 0x20, 0xff );
pfm->flFlags |= FM_GLYVER40;
TRACE(\tUsing OLD Format default Translation);
}
else //New Format
{
pvData = PNTGTT1To1(pfmdev->ulCodepage, bSymbol, 0x20, 0xff);
TRACE(\tUsing NEW Format default Translation);
}
if (pvData)
{
pfm->flFlags |= FM_FREE_GLYDATA; /* This one will be freed when done */
if (bSymbol)
{
pfm->wLastChar = SYMBOL_END;
if (!(pfm->flFlags & FM_IFIRES))
pfm->pIFIMet->wcLastChar = SYMBOL_END;
}
}
else
WARNING(("vFillInRLE - pvData was NULL\n"));
}
PRINTVAL((pfm->flFlags & FM_GLYVER40), 0X%x);
PRINTVAL((pfm->flFlags & FM_IFIVER40), 0X%x);
pfmdev->pvNTGlyph = pvData; /* Save it for posterity */
TRACE(UniFont!VFillinGlyphData:END\n);
return ;
}
INT
IFontID2Index(
FONTPDEV *pFontPDev,
int iID
)
/*++
Routine Description:
Turns the given font ID into an index into the resource data. The
Font ID is a sequential number, starting at 1, which the engine
uses to reference our fonts.
Arguments:
pFontPDev For Access to device font resID list.
iID The font resource ID whose index is required
Return Value:
0 based font index, else -1 on error.
Note:
11-27-96: Created it -ganeshp-
--*/
{
int iFontIndex;
/*
* Just go through the font list. When a match is found return the index.
*/
for( iFontIndex = 0; iFontIndex < pFontPDev->iDevFontsCt; iFontIndex++)
{
if( pFontPDev->FontList.pdwList[iFontIndex] == (DWORD)iID)
{
//
// This function returns 0 based font index.
//
return iFontIndex;
}
}
/*
* We get here when we fail to match the desired ID. This should
* never happen!
*/
return -1;
}
VOID
VLoadDeviceFontsResDLLs(
PDEV *pPDev
)
/*++
Routine Description:
This routine loads all the DLLs which has device fonts. This is needed as
snapshot is unloaded after DrvEnablePDEV. So in Drv Calls for font query
pPDev->UIInfo will be NULL and BGetWinRes will fail.
Arguments:
pPDev - Pointer to PDEV.
Return Value:
None
Note:
11-06-98: Created it -ganeshp-
--*/
{
INT iFontIndex;
DWORD dwFontResID;
PQUALNAMEEX pQualifiedID;
FONTPDEV *pFontPDev;
RES_ELEM ResElem;
pFontPDev = pPDev->pFontPDev;
pQualifiedID = (PQUALNAMEEX)&dwFontResID;
/*
* Just go through the font list and load each one of them if they are
* from other resource DLL.
*/
for( iFontIndex = 0; iFontIndex < pFontPDev->iDevFontsCt; iFontIndex++)
{
dwFontResID = pFontPDev->FontList.pdwList[iFontIndex];
//
// Check if this font is from root resource DLL. If yes then goto
// next one.
//
if (pQualifiedID->bFeatureID == 0 && (pQualifiedID->bOptionID & 0x7f) == 0)
continue;
else
{
//
// This font is not from root resource DLL so load it. We don't need
// to look for error as we are only interested in loading the DLL.
//
BGetWinRes( &(pPDev->WinResData), (PQUALNAMEEX)&dwFontResID, RC_FONT, &ResElem );
}
}
}
DWORD
CopyMemoryRLE(
PVOID pvData,
PBYTE pubSrc,
DWORD dwSize)
{
NT_RLE_res *pntrle_res;
NT_RLE *pntrle;
HGLYPH *pHGlyph;
DWORD dwOutSize = 0;
DWORD dwRestOfData;
DWORD dwSubtractNT_RLE_Header;
ULONG ulI;
if (pvData == NULL ||
pubSrc == NULL )
return 0;
pntrle_res = (NT_RLE_res*)pubSrc;
pntrle = (NT_RLE*)pvData;
//
// Copy first 12 bytes.
// struct {
// WORD wType;
// BYTE bMagic0;
// BYTE bMagic1;
// DWORD cjThis;
// WORD wchFirst;
// WORD wchLast;
//
if (dwSize < dwOutSize + 12)
{
ERR(("UNIDRV!CopyMemoryRLE: dwSize < 12\n"));
return 0;
}
CopyMemory(pntrle, pntrle_res, 12);
dwOutSize += offsetof(NT_RLE, fdg);
//
// FD_GLYPHSET
// On IA64 machine, a padding DWORD is inserted before FD_GLYPHSET.
//
if (dwSize < dwOutSize + sizeof(FD_GLYPHSET) - sizeof(WCRUN))
{
ERR(("UNIDRV!CopyMemoryRLE: dwSize < sizeof(NT_RLE)\n"));
return 0;
}
pntrle->fdg.cjThis = offsetof(FD_GLYPHSET, awcrun) +
pntrle_res->fdg_cRuns * sizeof(WCRUN);
pntrle->fdg.flAccel = pntrle_res->fdg_flAccel;
pntrle->fdg.cGlyphsSupported = pntrle_res->fdg_cGlyphSupported;
pntrle->fdg.cRuns = pntrle_res->fdg_cRuns;
dwOutSize += sizeof(FD_GLYPHSET) - sizeof(WCRUN);
pHGlyph = (HGLYPH*)((PBYTE)pntrle + sizeof(NT_RLE) +
(pntrle_res->fdg_cRuns - 1) * sizeof(WCRUN));
//
// WCRUN
//
if (dwSize < dwOutSize + sizeof(WCRUN) * pntrle_res->fdg_cRuns)
{
ERR(("UNIDRV!CopyMemoryRLE: dwSize < sizeof(WCRUN)\n"));
return 0;
}
dwOutSize += sizeof(WCRUN) * pntrle_res->fdg_cRuns;
//
// NT_RLE bug workaround.
// Some of *.RLE files have an offset from the top of NT_RLE to HGLYPH array in FD_GLYPHSET.WCRUN.phg.
// phg needs to have an offset from the top of FD_GLYPHSET to HGLYPH array.
//
// Check if the offset to the last HGLYPH is larger than the whole size of memory allocation.
// If it is, it means the offset is from the top of NT_RLE. We need to subtract offsetof(NT_RLE< fdg),
// the size of NT_RLE header.
//
if (pntrle_res->fdg_wcrun_awcrun[pntrle_res->fdg_cRuns - 1].dwOffset_phg +
sizeof(HGLYPH) * (pntrle_res->fdg_wcrun_awcrun[pntrle_res->fdg_cRuns - 1].cGlyphs - 1)
>= dwSize - offsetof(NT_RLE, fdg))
{
dwSubtractNT_RLE_Header = offsetof(NT_RLE, fdg);
}
else
{
dwSubtractNT_RLE_Header = 0;
}
//
// IA64 fix. WCRUN has the pointer to HGLYPH. The size of pointer is 8 on IA64 or 4 on X86.
// We need to adjust phg, depending on the platform.
// The padding DWORD before FD_GLYPHSET don't have to be considered. phg has an offset from top of FD_GLYPHSET
// to the HGLYPH array.
//
for (ulI = 0; ulI < pntrle_res->fdg_cRuns; ulI ++)
{
pntrle->fdg.awcrun[ulI].wcLow = pntrle_res->fdg_wcrun_awcrun[ulI].wcLow;
pntrle->fdg.awcrun[ulI].cGlyphs = pntrle_res->fdg_wcrun_awcrun[ulI].cGlyphs;
pntrle->fdg.awcrun[ulI].phg = (HGLYPH*)IntToPtr(pntrle_res->fdg_wcrun_awcrun[ulI].dwOffset_phg +
pntrle_res->fdg_cRuns * (sizeof(HGLYPH*) - sizeof(DWORD)) - dwSubtractNT_RLE_Header);
}
//
// HGLYPH and offset data
//
if (dwSize < dwOutSize + sizeof(HGLYPH) * pntrle_res->fdg_cGlyphSupported)
{
ERR(("UNIDRV!CopyMemoryRLE: dwSize < HGLYLH array\n"));
return 0;
}
if (dwSubtractNT_RLE_Header)
{
dwRestOfData = pntrle_res->cjThis - offsetof(NT_RLE_res, fdg_wcrun_awcrun) - pntrle_res->fdg_wcrun_awcrun[0].dwOffset_phg;
}
else
{
dwRestOfData = pntrle_res->cjThis - pntrle_res->fdg_wcrun_awcrun[0].dwOffset_phg;
}
dwOutSize += dwRestOfData;
CopyMemory(pHGlyph, (PBYTE)pntrle_res + pntrle_res->fdg_wcrun_awcrun[0].dwOffset_phg, dwRestOfData);
if (pntrle_res->wType == RLE_LI_OFFSET)
{
WORD wDiff = (WORD)(pntrle_res->fdg_cRuns * (sizeof(HGLYPH*) - sizeof(DWORD)));
for (ulI = 0; ulI < pntrle_res->fdg_cGlyphSupported; ulI++, pHGlyph++)
{
((RLI*)pHGlyph)->wOffset += wDiff;
}
}
return dwOutSize;
}