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.
 
 
 
 
 
 

448 lines
11 KiB

/*++
Copyright (c) 1996 - 1999 Microsoft Corporation
Module Name:
qfontree.c
Abstract:
Routines Generates the trees required by the engine. There are three
tree types defined, UNICODE (handle <-> glyph), ligatures and kerning
pairs.
Environment:
Windows NT Unidrv driver
Revision History:
12/30/96 -ganeshp-
Created
--*/
#include "font.h"
//
//
// Functions
//
//
PVOID
FMQueryFontTree(
PDEV *pPDev,
ULONG_PTR iFile,
ULONG iFace,
ULONG iMode,
ULONG_PTR *pid
)
/*++
Routine Description:
Returns tree structured data describing the mapping between UNICODE
and printer glyphs, or ligature information or kerning pair data.
Arguments:
pPDev Pointer to PDEV
iFile Not Used.
iFace Font about which information is desired
iMode Type of information requested
pid Our field: fill as needed for recognition
Return Value:
A pointer to the relevant structure.
Note:
12-30-96: Created it -ganeshp-
--*/
{
/*
* Processing differs dramatically, depending upon iMode. We will
* always handle the QFT_GLYPHSET case, the others we may not have
* any information about.
*/
void *pvRet; /* Return value */
UNREFERENCED_PARAMETER(iFile);
if( PFDV->dwSignature != FONTPDEV_ID )
{
ERR(( "UniFont!FMQueryFontTree: Invalid FONTPDEV\n" ));
SetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
if( iFace < 1 || (int)iFace > pPDev->iFonts )
{
ERR(( "UniFont!FMQueryFontTree: Illegal value for iFace (%ld)", iFace ));
SetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
pvRet = NULL; /* Default return value: error */
/*
* The pid field is one which allows us to put identification data in
* the font information, and which we can use later in DrvFree().
*/
*pid = 0;
switch( iMode )
{
case QFT_GLYPHSET: /* RLE style UNICODE -> glyph handle mapping */
pvRet = PVGetUCGlyphSetData( pPDev, iFace );
break;
case QFT_LIGATURES: /* Ligature variant information */
SetLastError( ERROR_NO_DATA );
break;
case QFT_KERNPAIRS: /* Kerning information */
pvRet = PVGetUCKernPairData( pPDev, iFace );
break;
default:
ERR(( "Rasdd!DrvQueryFontTree: iMode = %ld - illegal value\n", iMode ));
SetLastError( ERROR_INVALID_PARAMETER );
break;
}
return pvRet;
}
VOID *
PVGetUCGlyphSetData(
PDEV *pPDev,
UINT iFace
)
/*++
Routine Description:
Generates the array of WCRUN data used as a mapping between UNICODE and
our internal representation.
Arguments:
pPDev Pointer to PDEV
iFace Font about which information is desired
Return Value:
A pointer to the array of WCRUN structure.
Note:
12-30-96: Created it -ganeshp-
--*/
{
FONTMAP *pFM; /* Details of the particular font */
FONTMAP_DEV *pFMDev;
VOID *pvData = NULL;
if (pFM = PfmGetDevicePFM( pPDev, iFace ) )
{
pFMDev = pFM->pSubFM;
if (!pFMDev->pUCTree) //No FD_GLYPHSET data for this font.
{
if( pFM->flFlags & FM_GLYVER40 ) //NT 4.0 RLE
pvData = PVGetUCRLE(pPDev, pFM);
else // New stuff
pvData = PVGetUCFD_GLYPHSET(pPDev, pFM);
}
else
pvData = pFMDev->pUCTree;
}
// VDBGDUMPUCGLYPHDATA(pFM);
return pvData;
}
VOID *
PVGetUCKernPairData(
PDEV *pPDev,
UINT iFace
)
/*++
Routine Description:
Generates the array of FD_KERNPAIR data for the given font.
Arguments:
pPDev Pointer to PDEV
iFace Font about which information is desired
Return Value:
A pointer to the array of WCRUN structure.
Note:
12-30-96: Created it -ganeshp-
--*/
{
FONTMAP *pFM; /* Details of the particular font */
FONTMAP_DEV *pFMDev;
VOID *pvData = NULL;
if (pFM = PfmGetDevicePFM( pPDev, iFace ) )
{
pFMDev = pFM->pSubFM;
if (!pFMDev->pUCKernTree) //No FD_GLYPHSET data for this font.
{
/* pvUCKernPair should allocate the appropriate buffer, if
* necessary and store the value in FONTMAP, pFM->pUCKernTree.
*/
if( pFM->flFlags & FM_GLYVER40 ) //NT 4.0 RLE
{
SetLastError( ERROR_NO_DATA );
}
else
pvData = PVUCKernPair(pPDev, pFM);
}
else
pvData = pFMDev->pUCKernTree;
}
return pvData;
}
VOID *
PVGetUCRLE(
PDEV *pPDev,
FONTMAP *pFM
)
/*++
Routine Description:
Generates the array of WCRUN data used as a mapping between
UNICODE and our internal representation. The format of this
data is explained in the DDI, but basically for each group of
glyphs we support, we provide starting glyph and count info.
There is an overall structure to define the number and location
of each of the run data.
Arguments:
pPDev Pointer to PDEV.
pFM FONTMAP struct of the Font about for which information is
desired.
Return Value:
A pointer to the array of WCRUN structure.
Note:
12-30-96: Created it -ganeshp-
--*/
{
/*
* Basically all we need do is allocate storage for the FD_GLYPHSET
* structure we will return. Then the WCRUN entries in this need
* to have the offsets (contained in the resource format data) changed
* to addresses, and we are done. One minor point is to amend the
* WCRUN data to only point to glyphs actually available with this
* font. This means limiting the lower and upper bounds as
* determined by the IFIMETRICS.
*/
INT cbReq; /* Bytes to allocate for tables */
INT cRuns; /* Number of runs we discover */
INT iI; /* Loop index */
INT iStart, iStop; /* First and last WCRUNs to use */
INT iDiff; /* For range limiting operations */
FD_GLYPHSET *pGLSet; /* Base of returned data */
IFIMETRICS *pIFI; /* For convenience */
NT_RLE *pntrle; /* RLE style data already available */
WCRUN *pwcr;
FONTMAP_DEV *pFMDev;
#if DBG
PWSTR pwszFaceName;
#endif
pIFI = pFM->pIFIMet;
pFMDev = pFM->pSubFM;
#if DBG
pwszFaceName = (PWSTR)(((BYTE*) pIFI) + pIFI->dpwszFaceName );
#endif
TRACE(\nUniFont!PVGetUCRLE:START);
PRINTVAL(pwszFaceName, %ws);
PRINTVAL((pFM->flFlags & FM_GLYVER40), 0X%x);
/*
* Start working on memory requirements. First generate the bit
* array of available glyphs. In the process, count the number
* of glyphs too! This tells us how much storage will be needed
* just for the glyph handles.
*/
cRuns = 0; /* Count number of runs */
pntrle = pFMDev->pvNTGlyph; /* Translation table */
if( !pntrle )
{
ERR(( "!!!UniFont!PVGetUCRLE:( NULL Glyph Translation Data, pwszFaceName = %s )\n",pwszFaceName ));
TRACE(UniFont!PVGetUCRLE:END\n);
return NULL; /* Should not happen */
}
/*
* The hard part is deciding whether to trim the number of glyph
* handles returned due to limitiations of the font metrics.
*/
cRuns = pntrle->fdg.cRuns; /* Max number of runs */
iStart = 0;
iStop = cRuns;
/*
* Look to see if the first glyph in the font is higher than the lowest
* in the RLE data. If so, we need to amend the lower limit.
*/
if( pFM->wFirstChar > pntrle->wchFirst )
{
/* Need to amend the lower end */
pwcr = &pntrle->fdg.awcrun[ iStart ];
for( ; iStart < iStop; ++iStart, ++pwcr )
{
if( pFM->wFirstChar < (pwcr->wcLow + pwcr->cGlyphs) )
break;
}
}
if( pFM->wLastChar < pntrle->wchLast )
{
/* The top end goes too far! */
pwcr = &pntrle->fdg.awcrun[ iStop - 1 ];
for( ; iStop > iStart; --iStop, --pwcr )
{
if( pFM->wLastChar >= pwcr->wcLow )
break;
}
}
/* Now have a new count of runs (sometimes, anyway) */
cRuns = iStop - iStart;
if( cRuns == 0 )
{
/* SHOULD NEVER HAPPEN! */
cRuns = 1;
ERR(( "UniFont!DrvQueryFontTree: cRuns == 0, pwszFaceName = %s\n", pwszFaceName ));
}
/*
* Allocate the storage required for the header. Note that the
* FD_GLYPHSET structure contains 1 WCRUN, so we reduce the number
* required by one.
*/
cbReq = sizeof( FD_GLYPHSET ) + (cRuns - 1) * sizeof( WCRUN );
pFMDev->pUCTree = (void *)MemAllocZ(cbReq );
if( pFMDev->pUCTree == NULL )
{
/* Tough - give up now */
ERR(( "!!!UniFont!PVGetUCRLE:( MemAlloc Failed for pUCTree \n"));
TRACE(UniFont!PVGetUCRLE:END\n);
return NULL;
}
pGLSet = pFMDev->pUCTree;
CopyMemory( pGLSet, &pntrle->fdg, sizeof( FD_GLYPHSET ) );
/*
* Copy the WCRUN data as appropriate. Some of those in the
* resource may be dropped at this time, depending upon the range
* of glyphs in the font. It is also time to convert the offsets
* stored in the phg field to an address.
*/
pwcr = &pntrle->fdg.awcrun[ iStart ];
pGLSet->cGlyphsSupported = 0; /* Add them up as we go! */
pGLSet->cRuns = cRuns;
for( iI = 0; iI < cRuns; ++iI, ++pwcr )
{
pGLSet->awcrun[ iI ].wcLow = pwcr->wcLow;
pGLSet->awcrun[ iI ].cGlyphs = pwcr->cGlyphs;
pGLSet->cGlyphsSupported += pwcr->cGlyphs;
pGLSet->awcrun[ iI ].phg = (HGLYPH *)((BYTE *)pntrle + (ULONG_PTR)pwcr->phg);
}
/* Do the first and last entries need modifying?? */
if( (iDiff = (UINT)pGLSet->awcrun[0].wcLow - (UINT)pFM->wFirstChar) > 0 )
{
/* The first is not the first, so adjust values */
pGLSet->awcrun[ 0 ].wcLow += (WORD)iDiff;
pGLSet->awcrun[ 0 ].cGlyphs -= (WORD)iDiff;
pGLSet->awcrun[ 0 ].phg += (ULONG_PTR)iDiff;
pGLSet->cGlyphsSupported -= iDiff;
}
if( (iDiff = (UINT)pGLSet->awcrun[ cRuns - 1 ].wcLow +
(UINT)pGLSet->awcrun[ cRuns - 1 ].cGlyphs - 1 -
(UINT)pFM->wLastChar) > 0 )
{
/* Need to limit the top one too! */
pGLSet->awcrun[ cRuns - 1 ].cGlyphs -= (WORD)iDiff;
pGLSet->cGlyphsSupported -= (ULONG)iDiff;
}
TRACE(UniFont!PVGetUCRLE:END\n);
return pFMDev->pUCTree;
}