|
|
/*++
Copyright (c) 1996 - 1999 Microsoft Corporation
Module Name:
qfontdat.c
Abstract:
Implements the DrvQueryFontData function - returns information about glyphs (size, position wrt box) or kerning information.
Environment:
Windows NT Unidrv driver
Revision History:
12/19/96 -ganeshp- Created
--*/ #include "font.h"
/*
* The values for pteBase, pteSide in FD_DEVICEMETRICS, allowing * for rotation by 90 degree multiples. */
#if defined(USEFLOATS) || defined(WINNT_40)
static const POINTE pteRotBase[] = { { (FLOAT) 1.0, (FLOAT) 0.0 }, { (FLOAT) 0.0, (FLOAT)-1.0 }, { (FLOAT)-1.0, (FLOAT) 0.0 }, { (FLOAT) 0.0, (FLOAT) 1.0 } };
static const POINTE pteRotSide[] = { { (FLOAT) 0.0, (FLOAT)-1.0 }, { (FLOAT)-1.0, (FLOAT) 0.0 }, { (FLOAT) 0.0, (FLOAT) 1.0 }, { (FLOAT) 1.0, (FLOAT) 0.0 } };
#else
static const POINTE pteRotBase[] = { { (FLOATL) FLOATL_1_0, (FLOATL) FLOATL_0_0 }, { (FLOATL) FLOATL_0_0, (FLOATL) FLOATL_1_0M }, { (FLOATL) FLOATL_1_0M,(FLOATL) FLOATL_0_0 }, { (FLOATL) FLOATL_0_0, (FLOATL) FLOATL_1_0 } };
static const POINTE pteRotSide[] = { { (FLOATL) FLOATL_0_0, (FLOATL) FLOATL_1_0M }, { (FLOATL) FLOATL_1_0M,(FLOATL) FLOATL_0_0 }, { (FLOATL) FLOATL_0_0, (FLOATL) FLOATL_1_0 }, { (FLOATL) FLOATL_1_0, (FLOATL) FLOATL_0_0 } }; #endif //defined(USEFLOATS) || defined(WINNT_40)
/* The X dimension rotation cases */
static const POINTL ptlXRot[] = { { 1, 0 }, { 0, -1 }, { -1, 0 }, { 0, 1 }, };
/* The Y dimension rotation cases */
static const POINTL ptlYRot[] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 }, };
LONG FMQueryFontData( PDEV *pPDev, FONTOBJ *pfo, ULONG iMode, HGLYPH hg, GLYPHDATA *pgd, PVOID pv, ULONG cjSize ) /*++
Routine Description: Return information about glyphs in the font, OR kerning data.
Arguments: pPDev Really a pPDev pfo The font of interest iMode Glyphdata or kerning information hg Handle to glyph pgd Place to put metrics pv Output area cjSize Size of output area
Return Value:
Number of bytes needed or written, 0xffffffff for error.
Note: 12-29-96: Created it -ganeshp-
--*/ {
FONTPDEV *pFontPDev; int iRot; /* Rotation multiple of 90 degrees */ LONG lRet; /* Value returned */ FONTMAP *pFM; /* Font data */ FONTMAP_DEV *pFMDev; /* Font data */ FONTCTL ctl; /* Font scale/rotation adjustments */ IFIMETRICS *pIFI; XFORMOBJ *pxo; LONG lAscender; LONG lDescender; FLOATOBJ fo;
pFontPDev = pPDev->pFontPDev; lRet = FD_ERROR;
if( pfo->iFace < 1 || (int)pfo->iFace > pPDev->iFonts ) { ERR(("Bad FONTOBJ, iFace is %d",pfo->iFace)); SetLastError( ERROR_INVALID_PARAMETER ); return lRet; }
pFM = PfmGetDevicePFM( pPDev, pfo->iFace ); if( pFM == NULL ) return lRet;
VDBGDUMPFONTMAP(pFM);
pFMDev = pFM->pSubFM; pIFI = pFM->pIFIMet; /* IFIMETRICS - useful to have */
if( pgd || pv ) { /*
* Need to obtain a transform to adjust these numbers as to * how the engine wants them. */
if( !(pxo = FONTOBJ_pxoGetXform( pfo )) ) { ERR(( "UniFont!FMQueryFontData: FONTOBJ_pxoGetXform fails\n" )); return lRet; }
/* Can now obtain the transform! */
//Added Check for HP Intellifont
iRot = ISetScale( &ctl, pxo, ((pFM->flFlags & FM_SCALABLE) && (pFMDev->wDevFontType == DF_TYPE_HPINTELLIFONT)), (pFontPDev->flText & TC_CR_ANY)?TRUE:FALSE);
if (pFontPDev->flText & TC_CR_ANY) iRot = (iRot + 45) / 90;
/*
* There are some adjustments to make to the scale factors. One * is to compensate for resolutions (these are coarse, integral * adjustments), the others are to to do with Intellifont. First * is the Intellifont point is 1/72.31 inches (!), and secondly * the LaserJet only adjusts font size to the nearest 0.25 point, * and hence when we round to that multiple, we need to adjust * the width accordingly. */
if( pFM->flFlags & FM_SCALABLE ) {
int iPtSize, iAdjustedPtSize; /* For scale factor adjustment */
#ifdef USEFLOATS
/* The limited font size resolution */ iPtSize = (int)(0.5 + ctl.eYScale * pIFI->fwdUnitsPerEm * 7200) / pPDev->ptGrxRes.y;
/* if the tranform is very small (Less than a quarter of point size)
* then make it atleast a quarter point. This was causing AV in certain * cases. */
if (iPtSize < 25) { iPtSize = 25;
} iAdjustedPtSize = ((iPtSize + 12) / 25) * 25;
//Adjust the Scale Factor for quarter point adjustment.
ctl.eXScale = (ctl.eXScale * iAdjustedPtSize) / iPtSize; ctl.eYScale = (ctl.eYScale * iAdjustedPtSize) / iPtSize;
#else
fo = ctl.eYScale; FLOATOBJ_MulLong(&fo,pIFI->fwdUnitsPerEm); FLOATOBJ_MulLong(&fo,7200);
#ifndef WINNT_40 //NT 5.0
FLOATOBJ_AddFloat(&fo,(FLOATL)FLOATL_00_50);
#else // NT 4.0
FLOATOBJ_AddFloat(&fo,(FLOAT)0.5);
#endif //!WINNT_40
iPtSize = FLOATOBJ_GetLong(&fo); iPtSize /= pPDev->ptGrxRes.y;
/* if the trannform is very small (Less than a quarter of point size)
* then make it atleast a quarter point. This was causing AV in certain * cases. */
if (iPtSize < 25) { iPtSize = 25;
}
iAdjustedPtSize = ((iPtSize + 12) / 25) * 25;
//Adjust the Scale Factor for quarter point adjustment.
FLOATOBJ_MulLong(&ctl.eXScale,iAdjustedPtSize); FLOATOBJ_DivLong(&ctl.eXScale,iPtSize);
FLOATOBJ_MulLong(&ctl.eYScale,iAdjustedPtSize); FLOATOBJ_DivLong(&ctl.eYScale,iPtSize); #endif
} }
/*
* precompute the lDescender and lAscender */
lDescender = LMulFloatLong(&ctl.eYScale,pIFI->fwdWinDescender); lAscender = LMulFloatLong(&ctl.eYScale,pIFI->fwdWinAscender);
switch( iMode ) { case QFD_GLYPHANDBITMAP: /* Glyph width etc data */ // size is now just the size of the bitmap, which in this
// case doesn't exist.
lRet = 0;
if( pgd ) {
int iWide; /* Glyph's width */
/*
* First get the width of this glyph, as this is needed * in several places.The width returned by IGetGlyphWidth * is not scaled in device units. To convert in device units * multily with the scale factor calculated earlier. */
iWide = IGetGlyphWidth( pPDev, pFM, hg);
iWide = LMulFloatLong(&ctl.eXScale,iWide);
switch( iRot ) { case 0: pgd->rclInk.left = 0; pgd->rclInk.top = lDescender; pgd->rclInk.right = iWide; pgd->rclInk.bottom = -lAscender; break;
case 1: pgd->rclInk.left = lDescender; pgd->rclInk.top = iWide; pgd->rclInk.right = -lAscender; pgd->rclInk.bottom = 0; break;
case 2: pgd->rclInk.left = -iWide; pgd->rclInk.top = -lAscender; pgd->rclInk.right = 0; pgd->rclInk.bottom = lDescender; break;
case 3: pgd->rclInk.left = lAscender; pgd->rclInk.top = 0; pgd->rclInk.right = -lDescender; pgd->rclInk.bottom = -iWide; break; }
pgd->fxD = LTOFX( iWide ); pgd->ptqD.x.HighPart = pgd->fxD * ptlXRot[ iRot ].x; pgd->ptqD.x.LowPart = 0; pgd->ptqD.y.HighPart = pgd->fxD * ptlXRot[ iRot ].y; pgd->ptqD.y.LowPart = 0;
pgd->fxA = 0; pgd->fxAB = pgd->fxD;
pgd->fxInkTop = (FIX)LTOFX( lAscender ); pgd->fxInkBottom = -(FIX)LTOFX( lDescender );
pgd->hg = hg; pgd->gdf.pgb = NULL;
} break;
case QFD_MAXEXTENTS: /* Alternative form of the above */
lRet = sizeof( FD_DEVICEMETRICS );
if( pv ) { LONG lTmp; /* Rotated case */ FD_DEVICEMETRICS *pdm = ((FD_DEVICEMETRICS *)pv);
/*
* Check that the size is reasonable! */
if( cjSize < sizeof( FD_DEVICEMETRICS ) ) { SetLastError( ERROR_INSUFFICIENT_BUFFER ); ERR(( "rasdd!DrvQueryFontData: cjSize (%ld) too small\n", cjSize )); return -1; } // BUG 757060 - set this to 0 explicitly, because some drivers
// were using this before it was set, and may have code paths that
// break if this is a reasonable value. Before this fix, the value
// was the 0xCD pattern, and on newer IA64 machines, requests for this
// much memory (>3GB) could be handled, but at the expense of locking up
// the machine for minutes or even hours.
pdm->cjGlyphMax = 0;
/*
* These are accelerator flags - it is not obvious to me * that any of them are relevant to printer driver fonts. */ pdm->flRealizedType = 0;
/*
* Following fields set this as a normal type of font. */
pdm->pteBase = pteRotBase[ iRot ]; pdm->pteSide = pteRotSide[ iRot ];
pdm->cxMax = LMulFloatLong(&ctl.eXScale,pIFI->fwdMaxCharInc);
//
// DBCS fonts are not monospaced, have halfwidth glyphs and
// fullwidth glyphs.
//
if ( pFMDev->W.psWidth || IS_DBCSCHARSET(((IFIMETRICS*)pFM->pIFIMet)->jWinCharSet)) { pdm->lD = 0; /* Proportionally spaced font */ } else { pdm->lD = pdm->cxMax; }
pdm->fxMaxAscender = (FIX)LTOFX( lAscender ); pdm->fxMaxDescender = (FIX)LTOFX( lDescender );
lTmp = -LMulFloatLong(&ctl.eYScale,pIFI->fwdUnderscorePosition); pdm->ptlUnderline1.x = lTmp * ptlYRot[ iRot ].x; pdm->ptlUnderline1.y = lTmp * ptlYRot[ iRot ].y;
lTmp = -LMulFloatLong(&ctl.eYScale,pIFI->fwdStrikeoutPosition); pdm->ptlStrikeOut.x = lTmp * ptlYRot[ iRot ].x; pdm->ptlStrikeOut.y = lTmp * ptlYRot[ iRot ].y;
lTmp = LMulFloatLong(&ctl.eYScale,pIFI->fwdUnderscoreSize); pdm->ptlULThickness.x = lTmp * ptlYRot[ iRot ].x; pdm->ptlULThickness.y = lTmp * ptlYRot[ iRot ].y;
lTmp = LMulFloatLong(&ctl.eYScale,pIFI->fwdStrikeoutSize); pdm->ptlSOThickness.x = lTmp * ptlYRot[ iRot ].x; pdm->ptlSOThickness.y = lTmp * ptlYRot[ iRot ].y; } break;
default: ERR(( "Rasdd!DrvQueryFontData: unprocessed iMode value - %ld",iMode )); SetLastError( ERROR_INVALID_PARAMETER ); break; }
return lRet; }
|