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.
787 lines
21 KiB
787 lines
21 KiB
/*++
|
|
|
|
Copyright (c) 1996 - 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
oldfont.c
|
|
|
|
Abstract:
|
|
|
|
Implementation of the functions to use NT4.0 font format.
|
|
|
|
Environment:
|
|
|
|
Windows NT Unidrv driver
|
|
|
|
Revision History:
|
|
|
|
06/02/97 -eigos-
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include "font.h"
|
|
|
|
//
|
|
// Macro
|
|
//
|
|
|
|
#define ADDR_CONV(x) ((BYTE *)pFDH + pFDH->x)
|
|
|
|
ULONG UlCharsetToCodepage(
|
|
BYTE ubCharSet)
|
|
{
|
|
CHARSETINFO CharsetInfo;
|
|
|
|
//
|
|
// Initialize CharsetInfo
|
|
//
|
|
CharsetInfo.ciCharset = 0;
|
|
CharsetInfo.ciACP = 1252;
|
|
CharsetInfo.fs.fsUsb[0] = 0x01;
|
|
CharsetInfo.fs.fsUsb[1] = CharsetInfo.fs.fsUsb[2] = CharsetInfo.fs.fsUsb[3] = 0;
|
|
CharsetInfo.fs.fsCsb[0] = 0x01;
|
|
CharsetInfo.fs.fsCsb[1] = 0;
|
|
|
|
PrdTranslateCharsetInfo((UINT)ubCharSet, &CharsetInfo, TCI_SRCCHARSET);
|
|
return CharsetInfo.ciACP;
|
|
}
|
|
|
|
BOOL
|
|
BGetOldFontInfo(
|
|
FONTMAP *pfm,
|
|
BYTE *pRes
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Fill in the FONTMAP data using the NT format data passed to us.
|
|
There is not too much for us to do, since the NT data is
|
|
all in the desired format. However, we do have to update some
|
|
addresses.
|
|
|
|
Arguments:
|
|
|
|
pfm - Pointer to FONTMAP.
|
|
|
|
pRes - Pointer to Font Resource.
|
|
|
|
Return Value:
|
|
|
|
TRUE - for success
|
|
FALSE - for failure
|
|
|
|
Note:
|
|
12-05-96: Created it -ganeshp-
|
|
--*/
|
|
{
|
|
|
|
FI_DATA_HEADER *pFDH;
|
|
FONTMAP_DEV *pfmdev;
|
|
|
|
ASSERT(pfm != NULL &&
|
|
pRes != NULL &&
|
|
pfm->dwFontType == FMTYPE_DEVICE &&
|
|
pfm->flFlags & FM_IFIVER40);
|
|
|
|
pfmdev = pfm->pSubFM;
|
|
|
|
pfmdev->pvFontRes = pRes;
|
|
|
|
//
|
|
// Old Format Data
|
|
//
|
|
pFDH = (FI_DATA_HEADER *)pRes;
|
|
|
|
//
|
|
// Verify that there is some semblance of correctness
|
|
//
|
|
if( pFDH->cjThis != sizeof( FI_DATA_HEADER ) )
|
|
{
|
|
ERR(( "BGetOldFontInfo: invalid FI_DATA_HEADER\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Mark this data as being in a resource
|
|
//
|
|
pfm->flFlags |= (FM_IFIRES | FM_FONTCMD);
|
|
|
|
|
|
pfm->pIFIMet = (IFIMETRICS *)ADDR_CONV( dwIFIMet );
|
|
|
|
if (!(pfm->flFlags & FM_SOFTFONT))
|
|
{
|
|
if( pFDH->dwCDSelect )
|
|
{
|
|
pfmdev->cmdFontSel.pCD = (CD *)ADDR_CONV( dwCDSelect );
|
|
ASSERT(pfmdev->cmdFontSel.pCD);
|
|
}
|
|
|
|
if( pFDH->dwCDDeselect )
|
|
{
|
|
pfmdev->cmdFontDesel.pCD = (CD *)ADDR_CONV( dwCDDeselect );
|
|
ASSERT(pfmdev->cmdFontDesel.pCD);
|
|
}
|
|
|
|
}
|
|
|
|
if( pFDH->dwETM )
|
|
{
|
|
pfmdev->pETM = (EXTTEXTMETRIC *)ADDR_CONV( dwETM );
|
|
}
|
|
|
|
if( pFDH->dwWidthTab )
|
|
{
|
|
pfmdev->W.psWidth = (short *)ADDR_CONV( dwWidthTab );
|
|
pfm->flFlags |= FM_WIDTHRES; /* Width vector too! */
|
|
}
|
|
|
|
/*
|
|
* Miscellaneous odds & ends.
|
|
*/
|
|
|
|
pfmdev->ulCodepage = UlCharsetToCodepage(pfm->pIFIMet->jWinCharSet);
|
|
|
|
pfmdev->sCTTid = pFDH->u.sCTTid;
|
|
pfmdev->fCaps = pFDH->fCaps;
|
|
pfmdev->wDevFontType = pFDH->wFontType;
|
|
pfm->wXRes = pFDH->wXRes;
|
|
pfm->wYRes = pFDH->wYRes;
|
|
pfmdev->sYAdjust = pFDH->sYAdjust;
|
|
pfmdev->sYMoved = pFDH->sYMoved;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
BRLEOutputGlyph(
|
|
TO_DATA *pTod
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Send printer commands to print the glyph passed in. Basically
|
|
we do the translation from ANSI to the printer's representation,
|
|
|
|
Arguments:
|
|
hg HGLYPH of interest
|
|
|
|
Return Value:
|
|
TRUE for success and FALSE for failure.FALSE being a failure of Spool
|
|
|
|
Note:
|
|
|
|
1/22/1997 -ganeshp-
|
|
Created it.
|
|
--*/
|
|
|
|
{
|
|
PDEV *pPDev; // UNIDRV PDEV
|
|
FONTPDEV *pFontPDev; // Font PDEV
|
|
FONTMAP_DEV *pFMDev; // Device font PDEV
|
|
FONTMAP *pFM; // Fontmap data structure
|
|
NT_RLE *pntrle; // Access to data to send to printer
|
|
COMMAND *pCmd; // Command Pointer
|
|
PGLYPHPOS pgp;
|
|
POINTL ptlRem;
|
|
|
|
HGLYPH hg;
|
|
UHG uhg; // Various flavours of HGLYPH contents
|
|
INT iLen; // Length of string
|
|
INT iIndex; // Index from glyph to width table
|
|
INT cGlyphs;
|
|
INT iX, iY, iXInc, iYInc;
|
|
BYTE *pb; // Determining length for above
|
|
BOOL bRet; // Returned to caller
|
|
BOOL bSetCursorForEachGlyph;
|
|
|
|
ASSERT(pTod);
|
|
|
|
pPDev = pTod->pPDev;
|
|
pFontPDev = pPDev->pFontPDev;
|
|
pFM = pTod->pfm;
|
|
pFMDev = pFM->pSubFM;
|
|
pntrle = pFMDev->pvNTGlyph;
|
|
cGlyphs = pTod->cGlyphsToPrint;
|
|
pgp = pTod->pgp;
|
|
|
|
ASSERT(pPDev && pFontPDev && pFM && pFMDev && pntrle && pgp);
|
|
|
|
bSetCursorForEachGlyph = SET_CURSOR_FOR_EACH_GLYPH(pTod->flAccel);
|
|
|
|
if (!bSetCursorForEachGlyph)
|
|
VSetCursor( pPDev, pgp->ptl.x, pgp->ptl.y, MOVE_ABSOLUTE, &ptlRem);
|
|
|
|
pTod->flFlags |= TODFL_FIRST_GLYPH_POS_SET;
|
|
|
|
bRet = FALSE; /* Default case */
|
|
iX = iY = 0;
|
|
|
|
while (cGlyphs --)
|
|
{
|
|
hg = uhg.hg = pgp->hg; /* Lets us look at it however we want */
|
|
iX = pgp->ptl.x;
|
|
iY = pgp->ptl.y;
|
|
|
|
//
|
|
// Move to the next character's position
|
|
//
|
|
if (bSetCursorForEachGlyph)
|
|
VSetCursor( pPDev, iX, iY, MOVE_ABSOLUTE, &ptlRem);
|
|
|
|
if( pntrle )
|
|
{
|
|
/* The normal case - a standard device font */
|
|
|
|
switch( pntrle->wType )
|
|
{
|
|
case RLE_DIRECT: /* Up to 2 bytes of data */
|
|
iLen = uhg.rd.b1 ? 2 : 1;
|
|
iIndex = uhg.rd.wIndex;
|
|
|
|
bRet = WriteSpoolBuf( pPDev, &uhg.rd.b0, iLen ) == iLen;
|
|
|
|
break;
|
|
|
|
case RLE_PAIRED: /* Two glyphs (1 byte), overstruck */
|
|
/*
|
|
* First, try to use cursor push/pop escapes to
|
|
* overlay the 2 characters. If they are not
|
|
* available, try the backspace. If it doesn't exist
|
|
* either, ignore the second character.
|
|
*/
|
|
|
|
pCmd = COMMANDPTR(pPDev->pDriverInfo, CMD_PUSHCURSOR);
|
|
|
|
if ( uhg.rd.b1 && (pCmd != NULL) )
|
|
{
|
|
/* Pushed the position; output ch1, pop position, ch2 */
|
|
bRet = WriteSpoolBuf( pPDev, &uhg.rd.b0, 1 ) == 1;
|
|
WriteChannel( pPDev, pCmd );
|
|
bRet = WriteSpoolBuf( pPDev, &uhg.rd.b1, 1 ) == 1;
|
|
}
|
|
else
|
|
{
|
|
pCmd = COMMANDPTR(pPDev->pDriverInfo, CMD_BACKSPACE);
|
|
|
|
bRet = WriteSpoolBuf( pPDev, &uhg.rd.b0, 1 ) == 1;
|
|
if( uhg.rd.b1 && (pFontPDev->flFlags & FDV_BKSP_OK) )
|
|
{
|
|
WriteChannel( pPDev, pCmd );
|
|
bRet = WriteSpoolBuf( pPDev, &uhg.rd.b1, 1 ) == 1;
|
|
}
|
|
}
|
|
iIndex = uhg.rd.wIndex;
|
|
|
|
break;
|
|
|
|
case RLE_LI_OFFSET: /* Compact format of offset mode */
|
|
if( uhg.rli.bLength <= 2 )
|
|
{
|
|
/* Compact format: the data is in the offset field */
|
|
pb = &uhg.rlic.b0;
|
|
}
|
|
else
|
|
{
|
|
/* Standard format: the offset points to the data */
|
|
pb = (BYTE *)pntrle + uhg.rli.wOffset;
|
|
}
|
|
iLen = uhg.rli.bLength;
|
|
iIndex = uhg.rli.bIndex;
|
|
|
|
bRet = WriteSpoolBuf(pPDev, pb, iLen ) == iLen;
|
|
break;
|
|
|
|
|
|
case RLE_L_OFFSET: /* Arbitrary length strings */
|
|
/*
|
|
* The HGLYPH contains a 3 byte offset from the beginning of
|
|
* the memory area, and a 1 byte length field.
|
|
*/
|
|
pb = (BYTE *)pntrle + (hg & 0xffffff);
|
|
iLen = (hg >> 24) & 0xff;
|
|
|
|
iIndex = *((WORD *)pb);
|
|
pb += sizeof( WORD );
|
|
|
|
bRet = WriteSpoolBuf(pPDev, pb, iLen ) == iLen;
|
|
|
|
break;
|
|
|
|
default:
|
|
ERR(( "Rasdd!bOutputGlyph: Unknown HGLYPH format %d\n",
|
|
pntrle->wType ));
|
|
SetLastError( ERROR_INVALID_DATA );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// After drawing the character, in the printer, the cursor position
|
|
// moves. Update the UNIDRV internal value to reduce the amount of
|
|
// command to send.
|
|
//
|
|
if (bSetCursorForEachGlyph)
|
|
{
|
|
if( pFMDev->W.psWidth)
|
|
{
|
|
iXInc = pFMDev->W.psWidth[iIndex];
|
|
iXInc = iXInc * pPDev->ptGrxRes.x / pFM->wXRes;
|
|
}
|
|
else
|
|
iXInc = ((IFIMETRICS *)(pFM->pIFIMet))->fwdMaxCharInc;
|
|
|
|
if( pFM->flFlags & FM_SCALABLE )
|
|
{
|
|
iXInc = LMulFloatLong(&pFontPDev->ctl.eXScale,iXInc);
|
|
}
|
|
|
|
if (pTod->flAccel & SO_VERTICAL)
|
|
{
|
|
iYInc = iXInc;
|
|
iXInc = 0;
|
|
}
|
|
else
|
|
{
|
|
iYInc = 0;
|
|
}
|
|
|
|
VSetCursor( pPDev,
|
|
iXInc,
|
|
iYInc,
|
|
MOVE_RELATIVE|MOVE_UPDATE,
|
|
&ptlRem);
|
|
}
|
|
|
|
pgp ++;
|
|
}
|
|
|
|
/*
|
|
* If the output succeeded, update our view of the printer's
|
|
* cursor position. Typically, this will be to move along the
|
|
* width of the glyph just printed.
|
|
*/
|
|
|
|
if( bRet && pFM)
|
|
{
|
|
//
|
|
// Output may have succeeded, so update the position for default
|
|
// placement.
|
|
//
|
|
|
|
if( !bSetCursorForEachGlyph)
|
|
{
|
|
if( pFMDev->W.psWidth )
|
|
{
|
|
/*
|
|
* Proportional font - so use the width table. Note that
|
|
* it will also need scaling, since the fontwidths are stored
|
|
* in the text resolution units.
|
|
*/
|
|
/* This also scales correctly for downloaded fonts */
|
|
|
|
iXInc = pFMDev->W.psWidth[iIndex];
|
|
iXInc = iXInc * pPDev->ptGrxRes.x / pFM->wXRes;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Fixed pitch font - metrics contains the information. NOTE
|
|
* that scaling is NOT required here, since the metrics data
|
|
* has already been scaled.
|
|
*/
|
|
iXInc = ((IFIMETRICS *)(pFM->pIFIMet))->fwdMaxCharInc;
|
|
}
|
|
|
|
if( pFM->flFlags & FM_SCALABLE )
|
|
{
|
|
iXInc = LMulFloatLong(&pFontPDev->ctl.eXScale,iXInc);
|
|
}
|
|
|
|
if (pTod->flAccel & SO_VERTICAL)
|
|
{
|
|
iYInc = iXInc;
|
|
iXInc = 0;
|
|
}
|
|
else
|
|
{
|
|
iYInc = 0;
|
|
}
|
|
|
|
VSetCursor( pPDev,
|
|
(iX + iXInc) - pTod->pgp->ptl.x,
|
|
(iY + iYInc) - pTod->pgp->ptl.y,
|
|
MOVE_RELATIVE | MOVE_UPDATE,
|
|
&ptlRem);
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL
|
|
BRLESelectFont(
|
|
PDEV *pPDev,
|
|
PFONTMAP pFM,
|
|
POINTL *pptl)
|
|
{
|
|
FONTMAP_DEV *pfmdev = pFM->pSubFM;
|
|
CD *pCD;
|
|
|
|
ASSERT(pPDev && pfmdev);
|
|
|
|
if (!(pCD = pfmdev->cmdFontSel.pCD))
|
|
return FALSE;
|
|
|
|
pfmdev->pfnDevSelFont(pPDev,
|
|
pCD->rgchCmd,
|
|
pCD->wLength,
|
|
pptl);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
BSelectNonScalableFont(
|
|
PDEV *pPDev,
|
|
BYTE *pbCmd,
|
|
INT iCmdLength,
|
|
POINTL *pptl)
|
|
{
|
|
if( iCmdLength > 0 && pbCmd &&
|
|
WriteSpoolBuf( pPDev, pbCmd, iCmdLength ) != iCmdLength)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
BSelectPCLScalableFont(
|
|
PDEV *pPDev,
|
|
BYTE *pbCmd,
|
|
INT iCmdLength,
|
|
POINTL *pptl)
|
|
{
|
|
INT iIn, iConv, iOut, iLen;
|
|
BYTE aubLocal[80];
|
|
|
|
ASSERT(pPDev && pbCmd && pptl);
|
|
|
|
iOut = 0;
|
|
|
|
for( iIn = 0; (iIn < iCmdLength) && (iOut < CCHOF (aubLocal)); iIn++ )
|
|
{
|
|
if( pbCmd[ iIn ] == '#')
|
|
{
|
|
//
|
|
// The next byte tells us what information is required.
|
|
//
|
|
|
|
switch ( pbCmd[ iIn + 1 ] )
|
|
{
|
|
case 'v':
|
|
case 'V': /* Want the font's height */
|
|
iConv = pptl->y;
|
|
break;
|
|
|
|
case 'h':
|
|
case 'H': /* Want the pitch */
|
|
iConv = pptl->x;
|
|
break;
|
|
|
|
default: /* This should not happen! */
|
|
ERR(( "UniFont!BSelScalableFont(): Invalid command format\n"));
|
|
return FALSE; /* Bad news */
|
|
}
|
|
|
|
iLen = IFont100toStr( &aubLocal[ iOut ], CCHOF(aubLocal) - iOut, iConv );
|
|
|
|
|
|
if ( (iLen < 0) || iLen > ( (INT) CCHOF(aubLocal) - iOut ) )
|
|
{
|
|
ERR(( "UniFont!BSelectPCLScalableFont(): Error. Command may be too big\n"));
|
|
return FALSE; /* Bad news */
|
|
}
|
|
|
|
iOut += iLen;
|
|
|
|
|
|
}
|
|
else
|
|
aubLocal[iOut++] = pbCmd[iIn];
|
|
}
|
|
|
|
WriteSpoolBuf( pPDev, aubLocal, iOut);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
BSelectCapslScalableFont(
|
|
PDEV *pPDev,
|
|
BYTE *pbCmd,
|
|
INT iCmdLength,
|
|
POINTL *pptl)
|
|
{
|
|
INT iIn, iConv, iOut, iLen;
|
|
BYTE aubLocal[80];
|
|
|
|
ASSERT(pPDev && pbCmd && pptl);
|
|
|
|
iOut = 0;
|
|
|
|
for( iIn = 0; iIn < iCmdLength && (iOut < CCHOF (aubLocal) ) ; iIn++ )
|
|
{
|
|
if( pbCmd[ iIn ] == '#')
|
|
{
|
|
//
|
|
// The next byte tells us what information is required.
|
|
//
|
|
|
|
switch ( pbCmd[ iIn + 1 ] )
|
|
{
|
|
case 'v':
|
|
case 'V':
|
|
iConv = pptl->y * 300 / 72;
|
|
break;
|
|
|
|
case 'h':
|
|
case 'H':
|
|
iConv = pptl->x;
|
|
break;
|
|
|
|
default:
|
|
ERR(( "Invalid command format\n"));
|
|
return FALSE;
|
|
}
|
|
iIn ++;
|
|
|
|
iLen = iDrvPrintfSafeA(&aubLocal[iOut], CCHOF(aubLocal)-iOut, "%d", (iConv + 50)/100);
|
|
if ( iLen <= 0 || iLen > (INT)CCHOF(aubLocal)-iOut )
|
|
{
|
|
ERR( ("Invalid command format. Command maybe too big\n"));
|
|
return FALSE;
|
|
}
|
|
iOut += iLen;
|
|
}
|
|
else
|
|
aubLocal[iOut++] = pbCmd[iIn];
|
|
}
|
|
|
|
WriteSpoolBuf( pPDev, aubLocal, iOut);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
BSelectPPDSScalableFont(
|
|
PDEV *pPDev,
|
|
BYTE *pbCmd,
|
|
INT iCmdLength,
|
|
POINTL *pptl)
|
|
{
|
|
INT iIn, iOut, iConv;
|
|
BYTE aubLocal[80];
|
|
|
|
ASSERT(pPDev && pbCmd && pptl);
|
|
|
|
iOut = 0;
|
|
|
|
for( iIn = 0; iIn < iCmdLength && (iOut < CCHOF (aubLocal) ); iIn++ )
|
|
{
|
|
if (pbCmd[ iIn ] == '\x0B' && pbCmd[ iIn + 1] == '#')
|
|
//
|
|
// Height param for PPDS
|
|
//
|
|
{
|
|
if ( iOut + 8 < CCHOF (aubLocal) ) //8 chars to be written into aubLocal
|
|
{
|
|
|
|
aubLocal[ iOut++ ] = '\x0B';
|
|
aubLocal[ iOut++ ] = '\x06';
|
|
iConv = pptl->y;
|
|
|
|
//
|
|
// Due to restriction of PPDS cmds, param must be sent in
|
|
// xxx.xx format !
|
|
//
|
|
|
|
if ( ( iDrvPrintfSafeA(&aubLocal[ iOut ], CCHOF(aubLocal)-iOut, "%05d",iConv ) ) != 5 )
|
|
return FALSE; /* Bad news */
|
|
|
|
//
|
|
// insert the decimal point
|
|
//
|
|
aubLocal[ iOut+5 ] = aubLocal[ iOut+4 ];
|
|
aubLocal[ iOut+4 ] = aubLocal[ iOut+3 ];
|
|
aubLocal[ iOut+3 ] = '.';
|
|
|
|
iOut += 6; // xxx.xx ( ie 6 incl decimal pt
|
|
iIn++;
|
|
}
|
|
else
|
|
{
|
|
ERR( ("Invalid command format. Command maybe too big\n"));
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if (pbCmd[ iIn ] == '\x0E' && pbCmd[ iIn + 1] == '#')
|
|
//
|
|
// Pitch param for GPC_TECH_PPDS
|
|
//
|
|
{
|
|
if ( iOut + 9 < CCHOF (aubLocal) ) //9 chars to be written into aubLocal
|
|
{
|
|
aubLocal[ iOut++ ] = '\x0E';
|
|
aubLocal[ iOut++ ] = '\x07';
|
|
aubLocal[ iOut++ ] = '\x30'; // special byte required
|
|
iConv = pptl->x;
|
|
|
|
if ( ( iDrvPrintfSafeA(&aubLocal[ iOut ], CCHOF(aubLocal)-iOut, "%05d",iConv ) ) != 5 )
|
|
return FALSE;
|
|
|
|
//
|
|
// insert the decimal point
|
|
//
|
|
|
|
aubLocal[ iOut+5 ] = aubLocal[ iOut+4 ];
|
|
aubLocal[ iOut+4 ] = aubLocal[ iOut+3 ];
|
|
aubLocal[ iOut+3 ] = '.';
|
|
|
|
iOut += 6; // xxx.xx ( ie 6 incl decimal pt
|
|
iIn++;
|
|
}
|
|
else
|
|
{
|
|
ERR( ("Invalid command format. Command maybe too big\n"));
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
//
|
|
// No translation necessary
|
|
//
|
|
aubLocal[ iOut++ ] = pbCmd[ iIn ];
|
|
|
|
}
|
|
|
|
WriteSpoolBuf( pPDev, aubLocal, iOut );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
BOOL
|
|
BRLEDeselectFont(
|
|
PDEV *pPDev,
|
|
PFONTMAP pFM)
|
|
{
|
|
PFONTMAP_DEV pfmdev;
|
|
CD *pCD;
|
|
BOOL bRet = TRUE;
|
|
|
|
ASSERT(pPDev && pFM);
|
|
|
|
pfmdev = pFM->pSubFM;
|
|
pCD = pfmdev->cmdFontDesel.pCD;
|
|
|
|
if (pCD &&
|
|
pCD->wLength != 0 &&
|
|
pCD->rgchCmd &&
|
|
pCD->wLength != WriteSpoolBuf(pPDev, pCD->rgchCmd, pCD->wLength))
|
|
bRet = FALSE;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
INT
|
|
IGetIFIGlyphWidth(
|
|
PDEV *pPDev,
|
|
FONTMAP *pFM,
|
|
HGLYPH hg)
|
|
{
|
|
FONTMAP_DEV *pfmdev;
|
|
NT_RLE *pntrle; // The RLE stuff - may be needed
|
|
UHG uhg; // Defined access to HGLYPH contents
|
|
INT iWide = 0;
|
|
|
|
ASSERT(pPDev && pFM);
|
|
|
|
pfmdev = pFM->pSubFM;
|
|
pntrle = pfmdev->pvNTGlyph;
|
|
|
|
ASSERT(pfmdev && pntrle);
|
|
|
|
if( pfmdev->W.psWidth )
|
|
{
|
|
/* Proportional font - width varies per glyph */
|
|
|
|
uhg.hg = (HGLYPH)hg;
|
|
|
|
/*
|
|
* We need the index value from the HGLYPH. The
|
|
* index is the offset in the width table. For all
|
|
* but the >= 24 bit offset types, the index is
|
|
* included in the HGLYPH. For the 24 bit offset,
|
|
* the first WORD of the destination is the index,
|
|
* while for the 32 bit offset, it is the second WORD
|
|
* at the offset.
|
|
*/
|
|
|
|
switch( pntrle->wType )
|
|
{
|
|
case RLE_DIRECT:
|
|
case RLE_PAIRED:
|
|
iWide = uhg.rd.wIndex;
|
|
break;
|
|
|
|
case RLE_LI_OFFSET:
|
|
iWide = uhg.rli.bIndex;
|
|
break;
|
|
|
|
case RLE_L_OFFSET:
|
|
iWide = (DWORD)uhg.hg & 0x00ffffff;
|
|
iWide = *((WORD *)((BYTE *)pntrle + iWide));
|
|
break;
|
|
|
|
case RLE_OFFSET:
|
|
iWide = (DWORD)uhg.hg + sizeof( WORD );
|
|
iWide = *((WORD *)((BYTE *)pntrle + iWide));
|
|
break;
|
|
}
|
|
|
|
iWide = pfmdev->W.psWidth[iWide];
|
|
|
|
//
|
|
// If this is a proportionally spaced font,
|
|
// we need to adjust the width table entries
|
|
// to the current resolution. The width tables are NOT
|
|
// converted for lower resolutions, so we add the factor in now.
|
|
// Fixed pitch fonts must not be adjusted, since the width is converted
|
|
// in the font metrics.
|
|
//
|
|
|
|
iWide = iWide * pPDev->ptGrxRes.x / pFM->wXRes;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Fixed pitch fonts come from IFIMETRICS
|
|
//
|
|
|
|
iWide = ((IFIMETRICS *)(pFM->pIFIMet))->fwdMaxCharInc;
|
|
|
|
}
|
|
|
|
return iWide;
|
|
}
|
|
|