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.
428 lines
12 KiB
428 lines
12 KiB
/*++
|
|
|
|
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;
|
|
}
|