mirror of https://github.com/lianthony/NT4.0
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.
961 lines
25 KiB
961 lines
25 KiB
/************************ Module Header *************************************
|
|
* fonts.c
|
|
* Functions associated with fonts - switching between, downloading etc.
|
|
*
|
|
* Copyright (C) 1991 - 1993 Microsoft Corporation
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
#include <stddef.h>
|
|
#include <windows.h>
|
|
#include <winddi.h>
|
|
|
|
#include "win30def.h"
|
|
#include "udmindrv.h"
|
|
#include "udpfm.h"
|
|
#include "uddevice.h"
|
|
#include "udresrc.h"
|
|
#include "pdev.h"
|
|
#include "udrender.h"
|
|
#include "download.h"
|
|
#include "udfnprot.h"
|
|
#include "libproto.h"
|
|
#include "rasdd.h"
|
|
|
|
|
|
/*
|
|
* Local functions prototypes.
|
|
*/
|
|
|
|
BOOL bSelectFont( PDEV *, FONTMAP *, POINTL * );
|
|
|
|
BOOL bDeselectFont( PDEV *, int );
|
|
|
|
BOOL bSelScalableFont( UD_PDEV *, FONTMAP *, POINTL * );
|
|
|
|
BOOL bGetPSize( UD_PDEV *, POINTL *, FONTMAP * );
|
|
|
|
/**************************** Function Header *****************************
|
|
* bNewFont
|
|
* Switch to a new font. This involves optionally deselecting
|
|
* the old font, selecting the new font, then recording the new
|
|
* font as active AND setting the font's attributes.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE - TRUE if font changed, else FALSE.
|
|
*
|
|
* HISTORY:
|
|
* 16:23 on Mon 18 Mar 1991 -by- Lindsay Harris [lindsayh]
|
|
* Created it for setting attributes.
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOL
|
|
bNewFont( pPDev, iNewFont )
|
|
PDEV *pPDev;
|
|
int iNewFont; /* The font we want, 1 BASED!!!!! */
|
|
{
|
|
|
|
BOOL bRet; /* What we return */
|
|
|
|
POINTL ptl; /* For size comparisons in scalable fonts */
|
|
|
|
UD_PDEV *pUDPDev; /* UNIDRVs PDEV */
|
|
|
|
FONTMAP *pfm;
|
|
|
|
|
|
|
|
pUDPDev = pPDev->pUDPDev;
|
|
|
|
/*
|
|
* First check to see if a new font is needed. Compare the
|
|
* font index first, then check if it is a scalable font, and
|
|
* if so, whether the transform has changed.
|
|
*/
|
|
|
|
pfm = pfmGetIt( pPDev, iNewFont );
|
|
|
|
if( pfm->fFlags & FM_SCALABLE )
|
|
{
|
|
|
|
/*
|
|
* Calculate the new height/width. If we have the same font AND
|
|
* and the same point size, we return as all is now done.
|
|
* Otherwise, go through the works.
|
|
*/
|
|
|
|
if( !bGetPSize( pUDPDev, &ptl, pfm ) )
|
|
return FALSE; /* Some strange effect */
|
|
|
|
if( pUDPDev->ctl.iFont == iNewFont &&
|
|
pUDPDev->ctl.ptlScale.x == ptl.x &&
|
|
pUDPDev->ctl.ptlScale.y == ptl.y )
|
|
{
|
|
return FALSE; /* Same size, no change */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Vanilla bitmap font: only check indices */
|
|
if( iNewFont == pUDPDev->ctl.iFont )
|
|
return FALSE; /* No change */
|
|
}
|
|
|
|
|
|
if (pfm->fFlags & FM_TRUE_TYPE)
|
|
{
|
|
if ( !bGetTTPointSize ( pUDPDev, &ptl, pfm) )
|
|
return FALSE;
|
|
|
|
if ((pUDPDev->ctl.iFont == iNewFont) &&
|
|
(pUDPDev->ctl.ptlScale.y == ptl.y))
|
|
return FALSE; /* Same size, no change */
|
|
|
|
|
|
if ((pUDPDev->ctl.iFont == iNewFont) &&
|
|
(pUDPDev->ctl.ptlScale.y != ptl.y)) /* Same font, different point size*/
|
|
{
|
|
bTTSelScalableFont (pUDPDev, &ptl, pfm);
|
|
/*
|
|
* Can now select the font: this is done using a specific
|
|
* ID. The ID is stored in the FONTMAP structure.
|
|
*/
|
|
|
|
WriteChannel( pUDPDev, CMD_SELECT_FONT_ID, pfm->idDown );
|
|
|
|
}
|
|
}
|
|
|
|
bDeselectFont( pPDev, pUDPDev->ctl.iFont );
|
|
|
|
|
|
if( bRet = bSelectFont( pPDev, pfm, &ptl ) )
|
|
{
|
|
/* New font available - so update the red tape */
|
|
|
|
|
|
pUDPDev->ctl.iFont = (short)iNewFont;
|
|
|
|
/* Set the desired mode info into the UD_PDEV */
|
|
if( (pfm = pfmGetIt( pPDev, iNewFont )) && pfm->fCaps & DF_BKSP_OK )
|
|
pUDPDev->fMode |= PF_BKSP_OK;
|
|
else
|
|
pUDPDev->fMode &= ~PF_BKSP_OK;
|
|
}
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
/************************* Function Header **********************************
|
|
* bSelectFont
|
|
* Switch the printer to use the nominated font. This may mean
|
|
* downloading the font, if it is that type.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE. Error logged on failure, FALSE returned.
|
|
*
|
|
* HISTORY:
|
|
* 11:17 on Fri 06 Mar 1992 -by- Lindsay Harris [lindsayh]
|
|
* Added downloading calls.
|
|
*
|
|
* 15:58 on Fri 08 Mar 1991 -by- Lindsay Harris [lindsayh]
|
|
* First idea
|
|
*
|
|
****************************************************************************/
|
|
|
|
BOOL
|
|
bSelectFont( pPDev, pFM, pptl )
|
|
PDEV *pPDev; /* Our connection to everything */
|
|
FONTMAP *pFM; /* Details of the font to be selected */
|
|
POINTL *pptl; /* New size for scalable fonts */
|
|
{
|
|
/*
|
|
* First implementation is simple - simply send the command stream.
|
|
* Return FALSE if there is no command!
|
|
*/
|
|
|
|
UD_PDEV *pUDPDev;
|
|
CD *pCD; /* The selection data */
|
|
|
|
|
|
|
|
pUDPDev = pPDev->pUDPDev; /* UNIDRV's PDEV */
|
|
|
|
|
|
if( pFM->fFlags & FM_SOFTFONT )
|
|
{
|
|
/*
|
|
* Been downloaded yet?
|
|
*/
|
|
|
|
if( !bSendDLFont( pPDev, pFM ) )
|
|
return FALSE;
|
|
|
|
if (pFM->fFlags & FM_TRUE_TYPE)
|
|
bTTSelScalableFont (pUDPDev, pptl, pFM);
|
|
|
|
/*
|
|
* Can now select the font: this is done using a specific
|
|
* ID. The ID is stored in the FONTMAP structure.
|
|
*/
|
|
|
|
WriteChannel( pUDPDev, CMD_SELECT_FONT_ID, pFM->idDown );
|
|
}
|
|
|
|
|
|
if( pFM->fFlags & FM_SCALABLE )
|
|
{
|
|
/* A scalable font: special function for this special formula */
|
|
|
|
if( !bSelScalableFont( pUDPDev, pFM, pptl ) )
|
|
return FALSE;
|
|
|
|
pUDPDev->ctl.ptlScale = *pptl; /* The new sizes */
|
|
}
|
|
else
|
|
{
|
|
/* A bitmap font: easy to process - simply send the select cmd */
|
|
pCD = pFM->pCDSelect;
|
|
|
|
if( pCD &&
|
|
WriteSpoolBuf( pUDPDev, pCD->rgchCmd, pCD->wLength ) !=
|
|
(int)pCD->wLength )
|
|
{
|
|
return FALSE; /* Not really expected */
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/************************* Function Header **********************************
|
|
* bDeselectFont
|
|
* Issues a deselect command for the given font.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE: FALSE if the command write fails
|
|
*
|
|
* HISTORY:
|
|
* 16:13 on Fri 08 Mar 1991 -by- Lindsay Harris [lindsayh]
|
|
* MK I
|
|
*
|
|
****************************************************************************/
|
|
|
|
BOOL
|
|
bDeselectFont( pPDev, iFont )
|
|
PDEV *pPDev; /* Access to things we need */
|
|
int iFont; /* Font index, 1 based */
|
|
{
|
|
|
|
/*
|
|
* Only thing we need to do is send the command, if there is one.
|
|
*/
|
|
|
|
FONTMAP *pFM;
|
|
UD_PDEV *pUDPDev;
|
|
CD *pCD; /* The selection data */
|
|
|
|
|
|
if( iFont < 1 )
|
|
return TRUE; /* Nothing to do */
|
|
|
|
pUDPDev = pPDev->pUDPDev; /* UNIDRV's PDEV */
|
|
|
|
if( !(pFM = pfmGetIt( pPDev, iFont )) )
|
|
return FALSE;
|
|
|
|
pCD = pFM->pCDDeselect;
|
|
|
|
if( pCD &&
|
|
WriteSpoolBuf( pUDPDev, pCD->rgchCmd, pCD->wLength ) != (int)pCD->wLength )
|
|
{
|
|
return FALSE; /* Tough */
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
/*************************** Funcion Header ********************************
|
|
* pfmGetIt
|
|
* Returns the address of the FONTMAP structure corresponding to the
|
|
* iDLIndex entry of the downloaded GDI fonts.
|
|
*
|
|
* RETURNS:
|
|
* The address of the FONTMAP structure; 0 on error.
|
|
*
|
|
* HISTORY:
|
|
* 10:58 on Tue 30 Mar 1993 -by- Lindsay Harris [lindsayh]
|
|
* Lazy font loading - only load the font when really needed!
|
|
*
|
|
* 15:20 on Mon 20 Jul 1992 -by- Lindsay Harris [lindsayh]
|
|
* First incarnation.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FONTMAP *
|
|
pfmGetIt( pPDev, iIndex )
|
|
PDEV *pPDev; /* Access to all */
|
|
int iIndex; /* Which one */
|
|
{
|
|
UD_PDEV *pUDPDev; /* UniDrive's PDEV */
|
|
FONTMAP *pfm; /* What we return */
|
|
|
|
DL_MAP_LIST *pdml; /* The linked list of chunks */
|
|
|
|
|
|
|
|
pUDPDev = pPDev->pUDPDev;
|
|
pfm = NULL; /* Serious error return value */
|
|
|
|
if( iIndex > 0 )
|
|
{
|
|
/*
|
|
* With lazy fonts, first check that the font count has
|
|
* been initialised. This means that the font infrastructure
|
|
* has been created, and so we can then go on to the more
|
|
* detailed data.
|
|
*/
|
|
|
|
if( pUDPDev->cFonts < 0 )
|
|
{
|
|
/* Not set up, so do it now! */
|
|
iInitFonts( pPDev );
|
|
}
|
|
/* Device or supplied softfont: simply index the array! */
|
|
|
|
if( iIndex >= 1 && iIndex <= pUDPDev->cFonts )
|
|
{
|
|
pfm = pUDPDev->pFontMap + iIndex - 1;
|
|
|
|
if( pfm->pIFIMet == NULL )
|
|
{
|
|
/* Initialise this particular font */
|
|
if( !bFillinFM( pPDev, pfm, iIndex - 1 ) )
|
|
pfm = NULL; /* Bad news */
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Downloaded GDI font: this is a little more complex */
|
|
|
|
pdml = pUDPDev->pvDLMap;
|
|
iIndex = -iIndex; /* Assume +ve from here on in */
|
|
|
|
while( pdml )
|
|
{
|
|
/* Is this chunk the one containing the entry? */
|
|
if( iIndex >= pdml->cEntries )
|
|
{
|
|
/* Not this one, so onto the next */
|
|
iIndex -= pdml->cEntries;
|
|
|
|
pdml = pdml->pDMLNext;
|
|
}
|
|
else
|
|
{
|
|
/* We got it! */
|
|
pfm = &pdml->adlm[ iIndex ].fm;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return pfm;
|
|
}
|
|
|
|
|
|
|
|
/**************************** Function Header ******************************
|
|
* bSelScalableFont
|
|
* Send a PCL 5 scalable font selection command. The basic command
|
|
* is included in the mini-driver data, but we need to interpret it.
|
|
* Parameters are represented by a '#' character in the command. It
|
|
* is followed by a V when a height is required (in points); a following
|
|
* H requires a width (in pitch units).
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE; FALSE means missing cmd or incorrect format.
|
|
*
|
|
* HISTORY:
|
|
* 15:43 on Thu 09 Dec 1993 -by- Derry Durand [derryd]
|
|
* Add CaPSL font selection support
|
|
* 10:00 on Thu 16 Dec 1993 -by- Derry Durand [derryd]
|
|
* Add PPDS font selection support
|
|
* 14:43 on Mon 03 Aug 1992 -by- Lindsay Harris [lindsayh]
|
|
* Adapted from the Win 3.1 version.
|
|
*
|
|
****************************************************************************/
|
|
|
|
BOOL
|
|
bSelScalableFont( pUDPDev, pFM, pptl )
|
|
UD_PDEV *pUDPDev; /* Unidrive's PDEV */
|
|
FONTMAP *pFM; /* The font of interest */
|
|
POINTL *pptl; /* New size required */
|
|
{
|
|
unsigned int iIn; /* Scanning the input string */
|
|
int iOut; /* Output location */
|
|
int iConv; /* The value to convert */
|
|
int iRet; /* for checking return values */
|
|
|
|
CD *pCD; /* The command descriptor for this font */
|
|
|
|
BYTE ajLocal[ 80 ]; /* Generate the command locally */
|
|
BYTE *pjCmd; /* The input command */
|
|
|
|
|
|
#define pIFI ((IFIMETRICS *)(pFM->pIFIMet))
|
|
|
|
|
|
if( !(pCD = pFM->pCDSelect) )
|
|
{
|
|
#if DBG
|
|
DbgPrint( "rasdd!bSelScalableFont: pFM->pCDSelect is NULL\n" );
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
/* Check buffer size: allow 10 bytes for each number */
|
|
if( pCD->wLength > (sizeof( ajLocal ) - 20) )
|
|
{
|
|
/*
|
|
* Converted size would overflow buffer onto stack! NOT GOOD!
|
|
*/
|
|
#if DBG
|
|
DbgPrint( "rasdd!bSelScalableFont: Command too long for conversion\n" );
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
pjCmd = pCD->rgchCmd;
|
|
iOut = 0;
|
|
|
|
for( iIn = 0; iIn < (unsigned int)pCD->wLength; iIn++ )
|
|
{
|
|
if( pjCmd[ iIn ] == '#')
|
|
{
|
|
|
|
/*
|
|
* The next byte tells us what information is required.
|
|
*/
|
|
|
|
switch( pjCmd[ iIn + 1 ] )
|
|
{
|
|
case 'v':
|
|
case 'V': /* Want the font's height */
|
|
iConv = pptl->y;
|
|
/* added by DerryD Dec '93
|
|
Note : The size unit mode is set in the CaPSL minidriver as 1 dot =
|
|
1/300th of an inch so the following conversion will always
|
|
be correct.
|
|
|
|
The font selection cmd therefore needs the number of dots, so
|
|
we must convert from 'points' to 'dots'*/
|
|
|
|
if (pUDPDev->pdh->fTechnology == GPC_TECH_CAPSL )
|
|
{
|
|
iConv = (( pptl->y ) * 300 )/ 72;
|
|
iIn++;
|
|
}
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
case 'H': /* Want the pitch */
|
|
iConv = pptl->x;
|
|
/* added by DerryD Dec '93 */
|
|
if (pUDPDev->pdh->fTechnology == GPC_TECH_CAPSL )
|
|
iIn++;
|
|
break;
|
|
|
|
default: /* This should not happen! */
|
|
#if DBG
|
|
DbgPrint( "rasdd!bSelScalableFont(): Invalid command format\n");
|
|
#endif
|
|
return FALSE; /* Bad news */
|
|
}
|
|
|
|
if (pUDPDev->pdh->fTechnology == GPC_TECH_CAPSL )
|
|
/*
|
|
** CaPSL needs an integer no of dots
|
|
*/
|
|
iOut += iDrvPrintfA(&ajLocal[ iOut ], "%d",(iConv + 50 )/100 );
|
|
else
|
|
iOut += iFont100toStr( &ajLocal[ iOut ], iConv );
|
|
|
|
}
|
|
else if (pjCmd[ iIn ] == '\x0B' && pjCmd[ iIn + 1] == '#')
|
|
/* height param for GPC_TECH_PPDS */
|
|
{
|
|
|
|
ajLocal[ iOut++ ] = '\x0B';
|
|
ajLocal[ iOut++ ] = '\x06';
|
|
iConv = pptl->y;
|
|
|
|
/*
|
|
** Due to restriction of PPDS cmds, param must be sent in
|
|
** xxx.xx format !
|
|
*/
|
|
|
|
if ( ( iRet = iDrvPrintfA(&ajLocal[ iOut ], "%05d",iConv ) )
|
|
!= 5 )
|
|
return FALSE; /* Bad news */
|
|
|
|
/* insert the decimal point */
|
|
ajLocal[ iOut+5 ] = ajLocal[ iOut+4 ];
|
|
ajLocal[ iOut+4 ] = ajLocal[ iOut+3 ];
|
|
ajLocal[ iOut+3 ] = '.';
|
|
|
|
iOut += 6; /* xxx.xx ( ie 6 incl decimal pt */
|
|
iIn++;
|
|
}
|
|
else if (pjCmd[ iIn ] == '\x0E' && pjCmd[ iIn + 1] == '#')
|
|
/* pitch param for GPC_TECH_PPDS */
|
|
{
|
|
ajLocal[ iOut++ ] = '\x0E';
|
|
ajLocal[ iOut++ ] = '\x07';
|
|
ajLocal[ iOut++ ] = '\x30'; /* special byte required */
|
|
iConv = pptl->x;
|
|
if ( ( iRet = iDrvPrintfA(&ajLocal[ iOut ], "%05d",iConv ) )
|
|
!= 5 )
|
|
return FALSE; /* Bad news */
|
|
|
|
/* insert the decimal point */
|
|
ajLocal[ iOut+5 ] = ajLocal[ iOut+4 ];
|
|
ajLocal[ iOut+4 ] = ajLocal[ iOut+3 ];
|
|
ajLocal[ iOut+3 ] = '.';
|
|
|
|
iOut += 6; /* xxx.xx ( ie 6 incl decimal pt */
|
|
iIn++;
|
|
}
|
|
else
|
|
/* No translation necessary */
|
|
ajLocal[ iOut++ ] = pjCmd[ iIn ];
|
|
|
|
}
|
|
WriteSpoolBuf( pUDPDev, ajLocal, iOut );
|
|
|
|
|
|
return TRUE;
|
|
|
|
#undef pIFI
|
|
}
|
|
|
|
|
|
/********************************* Function Header ***************************
|
|
* iFont100toStr
|
|
* Convert a font size parameter to ASCII. Note that the value is
|
|
* 100 times its actual value, and we need to include the decimal
|
|
* point and trailing zeroes should these be significant.
|
|
*
|
|
* RETURNS:
|
|
* Number of bytes added to output buffer.
|
|
*
|
|
* HISTORY:
|
|
* 10:58 on Thu 29 Jul 1993 -by- Lindsay Harris [lindsayh]
|
|
* Moved from up above, as the DeskJet can use it too.
|
|
*
|
|
******************************************************************************/
|
|
|
|
int
|
|
iFont100toStr( pjOut, iVal )
|
|
BYTE *pjOut; /* Output area */
|
|
int iVal; /* Value to convert */
|
|
{
|
|
|
|
int iSize; /* Count bytes placed in output area */
|
|
int cDigits; /* Count number of digits processed */
|
|
|
|
BYTE *pjConv; /* For stepping through local array */
|
|
|
|
BYTE ajConv[ 16 ]; /* Local conversion buffer */
|
|
|
|
/*
|
|
* Convert the value into ASCII, remembering that there are
|
|
* two digits following the decimal point; these need not be
|
|
* sent if they are zero.
|
|
*/
|
|
|
|
pjConv = ajConv;
|
|
cDigits = 0;
|
|
|
|
while( iVal > 0 || cDigits < 3 )
|
|
{
|
|
*pjConv++ = (iVal % 10) + '0';
|
|
iVal /= 10;
|
|
++cDigits;
|
|
|
|
}
|
|
|
|
iSize = 0;
|
|
while( cDigits > 2 )
|
|
{
|
|
pjOut[ iSize++ ] = *--pjConv; /* Backwards from MSD */
|
|
--cDigits;
|
|
}
|
|
|
|
/* Test for digits following the decimal point */
|
|
if( ajConv[ 1 ] != '0' || ajConv[ 0 ] != '0' )
|
|
{
|
|
pjOut[ iSize++ ] = '.';
|
|
pjOut[ iSize++ ] = ajConv[ 1 ];
|
|
|
|
/* Test for the least significant digit */
|
|
if( ajConv[ 0 ] != '0' )
|
|
pjOut[ iSize++ ] = ajConv[ 0 ];
|
|
|
|
}
|
|
|
|
return iSize;
|
|
}
|
|
|
|
|
|
/************************* Function Header *******************************
|
|
* bGetPSize
|
|
* Apply the font transform to obtain the point size for this font.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE, TRUE for success.
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Fri 07 May 1993 -by- Lindsay Harris [lindsayh]
|
|
* Modify to use scaling information in ctl in UD_PDEV.
|
|
*
|
|
* 14:43 on Fri 21 Aug 1992 -by- Lindsay Harris [lindsayh]
|
|
* First incarnation for scalable fonts.
|
|
*
|
|
*************************************************************************/
|
|
|
|
BOOL
|
|
bGetPSize( pUDPDev, pptl, pfm )
|
|
UD_PDEV *pUDPDev; /* Access to stuff */
|
|
POINTL *pptl; /* Where to place the results */
|
|
FONTMAP *pfm; /* Gross font details */
|
|
{
|
|
|
|
|
|
int iTmp; /* Temporary holding variable */
|
|
FLOATOBJ fo;
|
|
|
|
#define pIFI ((IFIMETRICS *)(pfm->pIFIMet))
|
|
|
|
|
|
/*
|
|
* The XFORM gives us the scaling factor from notional
|
|
* to device space. Notional is based on the fwdEmHeight
|
|
* field in the IFIMETRICS, so we use that to convert this
|
|
* font height to scan lines. Then divide by device
|
|
* font resolution gives us the height in inches, which
|
|
* then needs to be converted to point size (multiplication
|
|
* by 72 gives us that). We actually calculate to
|
|
* hundredths of points, as PCL has this resolution. We
|
|
* also need to round to the nearest quarter point.
|
|
*
|
|
* Also adjust the scale factors to reflect the rounding of the
|
|
* point size which is applied.
|
|
*/
|
|
|
|
#ifdef USEFLOATS
|
|
|
|
/* Typically only the height is important: width for fixed pitch */
|
|
iTmp = (int)(0.5 + pUDPDev->ctl.eYScale * pIFI->fwdUnitsPerEm * 7200) /
|
|
pUDPDev->iygRes;
|
|
|
|
pptl->y = ((iTmp + 12) / 25) * 25;
|
|
pUDPDev->ctl.eYScale = (pUDPDev->ctl.eYScale * pptl->y) /iTmp;
|
|
pUDPDev->ctl.eXScale = (pUDPDev->ctl.eXScale * pptl->y) /iTmp;
|
|
|
|
|
|
/* Width factor: fixed pitch fonts only */
|
|
iTmp = (100 * pUDPDev->ixgRes) /
|
|
(int)(pUDPDev->ctl.eXScale * pIFI->fwdAveCharWidth);
|
|
|
|
#else
|
|
|
|
/* Typically only the height is important: width for fixed pitch */
|
|
|
|
fo = pUDPDev->ctl.eYScale;
|
|
FLOATOBJ_MulLong(&fo,pIFI->fwdUnitsPerEm);
|
|
FLOATOBJ_MulLong(&fo,7200);
|
|
FLOATOBJ_AddFloat(&fo,(FLOAT)0.5);
|
|
|
|
iTmp = FLOATOBJ_GetLong(&fo);
|
|
iTmp /= pUDPDev->iygRes;
|
|
|
|
pptl->y = ((iTmp + 12) / 25) * 25;
|
|
|
|
FLOATOBJ_MulLong(&pUDPDev->ctl.eYScale,pptl->y);
|
|
FLOATOBJ_DivLong(&pUDPDev->ctl.eYScale,iTmp);
|
|
|
|
FLOATOBJ_MulLong(&pUDPDev->ctl.eXScale,pptl->y);
|
|
FLOATOBJ_DivLong(&pUDPDev->ctl.eXScale,iTmp);
|
|
|
|
/* Width factor: fixed pitch fonts only */
|
|
fo = pUDPDev->ctl.eXScale;
|
|
FLOATOBJ_MulLong(&fo,pIFI->fwdAveCharWidth);
|
|
iTmp = FLOATOBJ_GetLong(&fo);
|
|
|
|
iTmp = (100 * pUDPDev->ixgRes) / iTmp;
|
|
|
|
#endif
|
|
|
|
pptl->x = ((iTmp + 12) / 25) * 25; /* To nearest quarter point */
|
|
|
|
return TRUE;
|
|
|
|
#undef pIFI
|
|
}
|
|
|
|
|
|
|
|
/**************************** Function Header *******************************
|
|
* iSetScale
|
|
* Looks at the XFORM to determine the nearest right angle direction.
|
|
* This function is useful for scalable fonts on LaserJet printers,
|
|
* where the device can rotate fonts in multiples of 90 degrees only.
|
|
* We select the nearest 90 degree multiple.
|
|
*
|
|
* RETURNS:
|
|
* Multiple of 90 degress, i.e. 0 - 3, 3 being 270 degrees.
|
|
*
|
|
* HISTORY:
|
|
* 18:16 on Thu 06 May 1993 -by- Lindsay Harris [lindsayh]
|
|
* Extended to be more generally useful.
|
|
*
|
|
* 16:13 on Mon 12 Apr 1993 -by- Lindsay Harris [lindsayh]
|
|
* First version to support LJ III font rotations.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
iSetScale( pctl, pxo, bIntellifont )
|
|
OUTPUTCTL *pctl; /* Where the output is placed. */
|
|
XFORMOBJ *pxo; /* The transform of interest */
|
|
BOOL bIntellifont; /* TRUE for Intellifont width adjustment */
|
|
{
|
|
|
|
/*
|
|
* The technique is quite simple. Take a vector and apply the
|
|
* transform. Look at the output and compare the (x, y) components.
|
|
* The vector to transform is (100 000, 0), so any rotations, shears
|
|
* etc are very obvious.
|
|
*/
|
|
|
|
int iRet; /* Value to return */
|
|
|
|
#ifdef USEFLOATS
|
|
|
|
XFORM xform; /* Obtain the full XFORM then select */
|
|
|
|
XFORMOBJ_iGetXform( pxo, &xform );
|
|
|
|
|
|
/*
|
|
* This logic is based on the following data:-
|
|
*
|
|
* Angle eM11 eM12 eM21 eM22
|
|
* 0 S 0 0 S
|
|
* 90 0 -S S 0
|
|
* 180 -S 0 0 -S
|
|
* 270 0 S -S 0
|
|
*
|
|
* The value S is some non-zero value, being the scaling
|
|
* factor from notional to device.
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
* Further notes on the eXScale and eYScale values. The eXScale field
|
|
* is hereby defined as being the value by which x values in font metrics
|
|
* are scaled to produce the desired value. IF the font is rotated
|
|
* by either 90 or 270 degrees, then this x value ultimately ends up
|
|
* in the y direction, but this is not important.
|
|
*/
|
|
|
|
if( xform.eM11 )
|
|
{
|
|
/* Either 0 or 180 rotation */
|
|
|
|
if( xform.eM11 > 0 )
|
|
{
|
|
/* Normal case, 0 degree rotation */
|
|
iRet = 0;
|
|
pctl->eXScale = xform.eM11;
|
|
pctl->eYScale = xform.eM22;
|
|
}
|
|
else
|
|
{
|
|
/* Reverse case, 180 degree rotation */
|
|
iRet = 2;
|
|
pctl->eXScale = -xform.eM11;
|
|
pctl->eYScale = -xform.eM22;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Must be 90 or 270 degree rotation */
|
|
|
|
if( xform.eM12 < 0 )
|
|
{
|
|
/* The 90 degree case */
|
|
iRet = 1;
|
|
pctl->eXScale = xform.eM21;
|
|
pctl->eYScale = -xform.eM12;
|
|
}
|
|
else
|
|
{
|
|
/* The 270 degree case */
|
|
iRet = 3;
|
|
pctl->eXScale = -xform.eM21;
|
|
pctl->eYScale = xform.eM12;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Width tables are based on Intellifont's 72.31 points to the inch.
|
|
*/
|
|
|
|
if( bIntellifont )
|
|
pctl->eXScale = pctl->eXScale * (FLOAT)72.0 / (FLOAT)72.31;
|
|
|
|
return iRet;
|
|
|
|
#else
|
|
|
|
FLOATOBJ_XFORM xform; /* Obtain the full XFORM then select */
|
|
|
|
XFORMOBJ_iGetFloatObjXform( pxo, &xform );
|
|
|
|
//XFORMOBJ_iGetXform( pxo, (XFORM *)&xform );
|
|
|
|
/*
|
|
* This logic is based on the following data:-
|
|
*
|
|
* Angle eM11 eM12 eM21 eM22
|
|
* 0 S 0 0 S
|
|
* 90 0 -S S 0
|
|
* 180 -S 0 0 -S
|
|
* 270 0 S -S 0
|
|
*
|
|
* The value S is some non-zero value, being the scaling
|
|
* factor from notional to device.
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
* Further notes on the eXScale and eYScale values. The eXScale field
|
|
* is hereby defined as being the value by which x values in font metrics
|
|
* are scaled to produce the desired value. IF the font is rotated
|
|
* by either 90 or 270 degrees, then this x value ultimately ends up
|
|
* in the y direction, but this is not important.
|
|
*/
|
|
|
|
if(!FLOATOBJ_EqualLong(&xform.eM11,0) )
|
|
{
|
|
/* Either 0 or 180 rotation */
|
|
|
|
if( FLOATOBJ_GreaterThanLong(&xform.eM11,0) )
|
|
{
|
|
/* Normal case, 0 degree rotation */
|
|
iRet = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Reverse case, 180 degree rotation */
|
|
iRet = 2;
|
|
FLOATOBJ_Neg(&xform.eM11);
|
|
FLOATOBJ_Neg(&xform.eM22);
|
|
|
|
}
|
|
pctl->eXScale = xform.eM11;
|
|
pctl->eYScale = xform.eM22;
|
|
}
|
|
else
|
|
{
|
|
/* Must be 90 or 270 degree rotation */
|
|
|
|
if( FLOATOBJ_LessThanLong(&xform.eM12,0) )
|
|
{
|
|
/* The 90 degree case */
|
|
iRet = 1;
|
|
|
|
FLOATOBJ_Neg(&xform.eM12);
|
|
}
|
|
else
|
|
{
|
|
/* The 270 degree case */
|
|
iRet = 3;
|
|
|
|
FLOATOBJ_Neg(&xform.eM21);
|
|
}
|
|
|
|
pctl->eXScale = xform.eM21;
|
|
pctl->eYScale = xform.eM12;
|
|
}
|
|
|
|
/*
|
|
* Width tables are based on Intellifont's 72.31 points to the inch.
|
|
*/
|
|
|
|
if( bIntellifont )
|
|
{
|
|
FLOATOBJ_MulLong(&pctl->eXScale,72);
|
|
FLOATOBJ_DivFloat(&pctl->eXScale,(FLOAT)72.31);
|
|
}
|
|
|
|
return iRet;
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
/********************************* Function Header ***************************
|
|
* bSetRotation
|
|
* Function to set the angular rotation for PCL 5 printers. These allow
|
|
* fonts to be rotated in multiples of 90 degrees relative to graphics.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE, TRUE being that the data was queued to be sent OK.
|
|
*
|
|
* HISTORY:
|
|
* 13:10 on Tue 25 May 1993 -by- Lindsay Harris [lindsayh]
|
|
* Added to support PCL5 printers.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL
|
|
bSetRotation( pUDPDev, iRot )
|
|
UD_PDEV *pUDPDev;
|
|
int iRot; /* Rotation amount, range 0 to 3 */
|
|
{
|
|
|
|
BOOL bRet;
|
|
|
|
|
|
bRet = TRUE; /* Do nothing return code */
|
|
|
|
if( iRot != pUDPDev->ctl.iRotate )
|
|
{
|
|
/* Rotation angle is different, so change it now */
|
|
|
|
|
|
bRet = WriteChannel( pUDPDev, CMD_PC_PRINT_DIR, iRot * 90 ) != NOOCD;
|
|
pUDPDev->ctl.iRotate = iRot;
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
}
|