Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1149 lines
33 KiB

/****************************** MODULE HEADER *******************************
* download.c
* Functions associated with downloading fonts to printers. This
* specifically applies to LaserJet style printers. There are really
* two sets of functions here: those for downloading fonts supplied
* by the user (and installed with the font installer), and those
* we generate internally to cache TT style fonts in the printer.
*
*
* Copyright (C) 1992 - 1993 Microsoft Corporation.
*
*****************************************************************************/
#include <stddef.h>
#include <windows.h>
#include <winddi.h>
#include <libproto.h>
#include "win30def.h"
#include "udmindrv.h"
#include "udpfm.h"
#include "uddevice.h"
#include "udresrc.h"
#include "pdev.h"
#include "stretch.h"
#include "udrender.h"
#include "udfnprot.h"
#include "download.h"
#include <kmfntrd.h>
#include <fileio.h>
#include "fontinst.h"
#include "rasdd.h"
#define DL_BUF_SZ 4096 /* Size of data chunks for download */
/*
* Local function prototypes.
*/
int iGetDL_ID( PDEV * );
DL_MAP_LIST *NewDLMap( HANDLE );
IFIMETRICS *pGetIFI( HANDLE, FONTOBJ * );
void vFreeDLMAP( HANDLE, DL_MAP * );
/**************************** Function Header ******************************
* bSendDLFont
* Called to download an existing softfont. Checks to see if the
* font has been downloaded, and if so, does nothing. Otherwise
* goes through the motions of downloading.
*
* RETURNS:
* TRUE/FALSE; FALSE only if there is a problem during the load.
*
* HISTORY:
* 11:28 on Fri 06 Mar 1992 -by- Lindsay Harris [lindsayh]
* First incarnation.
*
***************************************************************************/
BOOL
bSendDLFont( pPDev, pFM )
PDEV *pPDev; /* Connections */
FONTMAP *pFM; /* The particular font of interest */
{
DWORD dwLeft; /* Bytes remaining to send */
HANDLE hFile; /* The font installer file, for access */
BYTE ajData[ DL_BUF_SZ ]; /* Buffer for reading from font inst file */
#define pUDPDev ((UD_PDEV *)(pPDev->pUDPDev))
/*
* First see if it has already been downloaded!
*/
if( pFM->fFlags & (FM_SENT | FM_GEN_SFONT) )
return TRUE; /* All clear! */
/*
* Check if there is memory to fit this font. These are all
* approximations, but it is better than running out of memory
* in the printer.
*/
if( (pUDPDev->dwFontMemUsed + PCL_FONT_OH + pFM->dwDLSize) >
pUDPDev->dwFontMem )
{
/*
* This will exceed our font memory, so reject the call.
*/
return FALSE;
}
/*
* Time to be serious about downloading. UniDrive provides some
* of the control stuff we need. As well, we need to select an ID.
* The font itself is memory mapped, so we need only to shuffle it
* off to WriteSpoolBuf().
*/
pFM->idDown = iGetDL_ID( pPDev ); /* Down load index to use */
if( pFM->idDown < 0 )
return FALSE; /* Have run out of slots! */
/*
* Downloading is quite simple. First send an identifying command
* (to label the font for future selection) and then copy the font
* data (in the *.fi_ file) to the printer.
*/
WriteChannel( pUDPDev, CMD_SET_FONT_ID, pFM->idDown );
if( pUDPDev->pFMCurDL && !(pUDPDev->fDLFormat & DLI_FMT_INCREMENT) )
{
/*
* We have a partially downloaded font on a printer that does
* not support incremental downloading. SO, we must flag
* this font as being unavailable for further downloads.
*/
((DL_MAP *)(pUDPDev->pFMCurDL->u.pvDLData))->cAvail = 0;
pUDPDev->pFMCurDL = NULL;
}
dwLeft = pFM->dwDLSize;
hFile = ((FI_MEM *)(pUDPDev->pvFIMem))->hFont;
DrvSetFilePointer( hFile, pFM->u.ulOffset, DRV_FILE_BEGIN, pPDev );
while( dwLeft )
{
DWORD cjSize; /* Number of bytes to send */
DWORD dwSize; /* Number actually read */
cjSize = min( dwLeft, DL_BUF_SZ );
if( !DrvReadFile( hFile, ajData, cjSize, &dwSize, pPDev ) ||
cjSize != dwSize ||
WriteSpoolBuf( pUDPDev, ajData, cjSize ) != (int)cjSize )
{
break; /* Outta here */
}
if( pUDPDev->fMode & PF_ABORTED )
break;
dwLeft -= cjSize;
}
/*
* If dwLeft is 0, then everything completed as expected. Under these
* conditions, we flag the data as having been sent, and thus available
* for use. Even if we failed, we should assume we have consumed
* all the font's memory and adjust our records accordingly.
*/
if( dwLeft == 0 )
pFM->fFlags |= FM_SENT; /* Now done */
/*
* Account for memory used by this font.
*/
pUDPDev->dwFontMemUsed += PCL_FONT_OH + pFM->dwDLSize;
return dwLeft == 0;
#undef pUDPDev
}
/******************************* Function Header ***************************
* iGetDL_ID
* Returns the font index to use for the next download font. Verifies
* that the number is within range.
*
* RETURNS:
* Font index if OK, else -1 on error (over limit).
*
* HISTORY:
* 17:22 on Sat 12 Jun 1993 -by- Lindsay Harris [lindsayh]
* Implemented limits.
*
* 11:47 on Fri 06 Mar 1992 -by- Lindsay Harris [lindsayh]
* Starting.
*
***************************************************************************/
int
iGetDL_ID( pPDev )
PDEV *pPDev;
{
UD_PDEV *pUDPDev;
pUDPDev = pPDev->pUDPDev;
if( pUDPDev->iNextSFIndex > pUDPDev->iLastSFIndex ||
pUDPDev->iUsedSoftFonts >= pUDPDev->iMaxSoftFonts )
{
#if DBG
DbgPrint( "rasdd!iGetDL_ID: softfont limit reached (%d/%d, %d/%d)\n",
pUDPDev->iNextSFIndex, pUDPDev->iLastSFIndex,
pUDPDev->iUsedSoftFonts, pUDPDev->iMaxSoftFonts );
#endif
return -1; /* Too many - stop now */
}
/*
* We'll definitely use this one, so add to the used count.
*/
pUDPDev->iUsedSoftFonts++;
return pUDPDev->iNextSFIndex++;
}
/******************************* Module Header ******************************
* iFindDLIndex
* Function to decide whether this font should be down loaded. We do
* not do the download, simply decide whether we should. Note that
* if this font is already loaded, then we also return the index.
*
* RETURNS:
* Download font index if font is/can be downloaded; else < 0
*
* HISTORY:
* 09:51 on Wed 09 Jun 1993 -by- Lindsay Harris [lindsayh]
* Use pvConsumer to distinguish fonts.
*
* 14:47 on Tue 05 Jan 1993 -by- Lindsay Harris [lindsayh]
* Handle fixed pitch fonts as fixed pitch.
*
* 16:28 on Wed 15 Jul 1992 -by- Lindsay Harris [lindsayh]
* First incarnation.
*
*****************************************************************************/
int
iFindDLIndex( pPDev, pfo, pstro )
PDEV *pPDev; /* Access to all that we need */
FONTOBJ *pfo; /* The font of interest */
STROBJ *pstro; /* The "width" of fixed pitch font glyphs */
{
int iGlyphsDL; /* The number of glyphs to download */
DWORD cjMemUsed; /* Guess of amount of memory font will use */
int cDL; /* Number of download chars available */
int iRet; /* The value we return: # of entry */
DWORD dwMem; /* For recording memory consumption */
BOOL bReLoad; /* TRUE if we are reloading a previous font */
UD_PDEV *pUDPDev; /* UniDrive's PDEV */
DL_MAP_LIST *pdml; /* The linked list of font information */
DL_MAP *pdm; /* Individual map element */
FONTMAP *pFM; /* The FONTMAP structure we build up */
OUTPUTCTL ctl; /* For checking on font rotations */
IFIMETRICS *pIFI; /* Returned from elsewhere */
FONTINFO fi; /* Details about this font */
HGLYPH_MAP *phgm; /* Maps HGLYPH to printer byte */
short *psWide; /* Allocate and have FONTMAP point at it */
bReLoad = FALSE; /* Normal case, until proven otherwise */
if( iRet = (int)pfo->pvConsumer )
{
/*
* As we control the pvConsumer field, we have the choice
* of what to put in there. SO, we decide as follows:
* > 0 - index into our data structures
* < 0 - font not cached, for whatever reason
* 0 - virgin data, so look to see what to do.
*/
if( iRet < 0 )
return iRet; /* Do not process this one! */
--iRet; /* pvConsumer is 1 based! */
/*
* When printing direct multiple times, we have the condition
* where the downloaded fonts have been deleted from the printer,
* yet we still have records of them. When we detect the fonts
* are erased, we set the cAvail field in the DL_MAP structure
* to -1. If we see that now, we should pretend that we have not
* seen this font before.
*/
pFM = pfmGetIt( pPDev, -iRet );
//ASSERTRASDD(pFM,"RASDD!iFindDLIndex:pFM shouldn't be NULL\n");
/* pFM shouldn't be null,looks like bad pvConsumer */
if( !pFM )
{
return -1; /* Can't do it, so farewell */
}
else if( pFM->u.pvDLData &&
((DL_MAP *)(pFM->u.pvDLData))->cAvail >= 0 )
{
/* Font is in good shape, so continue with it's use */
return iRet;
}
bReLoad = TRUE; /* It's been erased - send again */
}
(int)pfo->pvConsumer = -1; /* Default of no download */
/*
* This is now a NEW font, so we need to decide whether to download
* it or not. This decision may take a while to decide, since
* there are a number of factors to consider.
*/
/*
* FIRST test is to check for font rotations. If there is any,
* we do NOT download this font, as the complications of keeping
* track with how (or if) the printer allows it are far too great,
* and, in any event, it is not likely to gain us much, given the
* relative infrequency of this event.
*/
if( iSetScale( &ctl, FONTOBJ_pxoGetXform( pfo ), FALSE ) )
return -1; /* Rotation, therefore no cache */
pUDPDev = pPDev->pUDPDev; /* For our convenience */
dwMem = 0; /* Record our memory consumption */
if( !(pUDPDev->dwSelBits & FDH_PORTRAIT) )
{
/* !!!LindsayH - don't yet support landscape mode */
/* REMOVE THIS TEST WHEN SO DONE */
/* ONLY APPLIES TO LaserJet Series II */
return -1;
}
/*
* First check to see if this font has already been loaded. This
* should be fast, since it will mostly be TRUE.
*/
if( !bReLoad )
{
pdml = pUDPDev->pvDLMap;
iRet = 0; /* Start at the bottom */
if( pdml == NULL )
{
/* None there, so create an initial one. */
if( pdml = NewDLMap( pPDev->hheap ) )
pUDPDev->pvDLMap = pdml;
else
{
return -1; /* Can't do it, so farewell */
}
}
/*
* Time to add a new entry. To do so, find the end of the current
* list, and tack on a new entry. THEN decide whether we will
* download this font.
*/
iRet = 0;
for( pdml = pUDPDev->pvDLMap; pdml->pDMLNext; pdml = pdml->pDMLNext )
{
/* While looking for the end, also count the number we pass */
iRet += pdml->cEntries;
}
if( pdml->cEntries >= DL_MAP_CHUNK )
{
if( !(pdml->pDMLNext = NewDLMap( pPDev->hheap )) )
{
return -1;
}
pdml = pdml->pDMLNext; /* The new current model */
iRet += DL_MAP_CHUNK; /* Add in the full one! */
}
iRet += pdml->cEntries;
pdm = &pdml->adlm[ pdml->cEntries ];
}
else
pdm = pFM->u.pvDLData; /* It's already there */
pdm->cGlyphs = -1; /* NOT downloaded */
/*
* Must now decide whether to cache this font or not. Because of
* the "not cached" settings above, we can bail out at any time
* by returning -1.
*/
if( (pIFI = pGetIFI( pPDev->hheap, pfo )) == NULL )
{
return -1; /* NBG */
}
if( pIFI->flInfo & FM_INFO_CONSTANT_WIDTH )
{
/* Fixed pitch fonts are handled a little differently */
if( pstro->ulCharInc == 0 )
{
HeapFree( pPDev->hheap, 0, (LPSTR)pIFI );
#if DBG
DbgPrint( "rasdd!iFindDLIndex: Fixed pitch font, ulCharInc == 0 - FONT NOT DOWNLOADED\n" );
#endif
return -1;
}
pIFI->fwdMaxCharInc = (FWORD)pstro->ulCharInc;
pIFI->fwdAveCharWidth = (FWORD)pstro->ulCharInc;
}
FONTOBJ_vGetInfo( pfo, sizeof( fi ), &fi );
/*
* Check on memory usage. Assume all glyphs are the largest size:
* this is pessimistic for a proportional font, but safe, given
* the vaguaries of tracking memory usage.
*/
iGlyphsDL = min( 255, fi.cGlyphsSupported );
cjMemUsed = iGlyphsDL * fi.cjMaxGlyph1;
if( !(pIFI->flInfo & FM_INFO_CONSTANT_WIDTH) )
{
/*
* If this is a proportionally spaced font, we should reduce
* the estimate of memory size for this font. The reason is
* that the above estimate is the size of the biggest glyph
* in the font. There will (for Latin fonts, anyway) be many
* smaller glyphs, some much smaller.
*/
cjMemUsed /= PCL_PITCH_ADJ;
}
if( (pUDPDev->dwFontMemUsed + cjMemUsed) > pUDPDev->dwFontMem ||
cjMemUsed > (pUDPDev->dwFontMem / 4) )
{
/* TOO BIG for download, so give up now */
#if PRINT_INFO
DbgPrint("Rasdd!iFindDLIndex:Not Downloading the font:TOO BIG for download\n");
#endif
HeapFree( pPDev->hheap, 0, (LPSTR)pIFI );
return -1;
}
/*
* Fill in the FONTMAP structure with the details of this font.
*/
pFM = &pdm->fm; /* So we can find it later! */
pFM->u.pvDLData = pdm; /* For later access! */
pFM->pIFIMet = pIFI; /* The real stuff */
if( (pFM->idDown = iGetDL_ID( pPDev )) < 0 )
{
/*
* We have run out of soft fonts - must not use any more.
*/
vFreeDLMAP( pPDev->hheap, pdm );
return -1;
}
pFM->wFirstChar = 0; /* These two entries are meaningless */
pFM->wLastChar = 0xffff;
pFM->wXRes = pUDPDev->ixgRes;
pFM->wYRes = pUDPDev->iygRes;
if( !(pUDPDev->fMDGeneral & MD_ALIGN_BASELINE) )
pFM->syAdj = pIFI->fwdWinAscender;
pFM->fFlags = FM_SENT | FM_SOFTFONT | FM_GEN_SFONT;
/*
* Send the header down first. This is based on the IFIMETRICS
* data we obtained earlier.
*/
cDL = iDLHeader( pUDPDev, pIFI, pFM->idDown, pdm->abAvail, &dwMem );
if( cDL <= 0 )
{
/* Some sort of hiccup - so decide against cache */
vFreeDLMAP( pPDev->hheap, pdm );
return -1;
}
/*
* If this printer does not support incremental downloading, we
* need to mark the current font as no longer usable for downloading.
*/
if( pUDPDev->pFMCurDL && !(pUDPDev->fDLFormat & DLI_FMT_INCREMENT) )
{
/* Terminate the old download mode by setting old cAvail to 0 */
((DL_MAP *)(pUDPDev->pFMCurDL->u.pvDLData))->cAvail = 0;
}
pUDPDev->pFMCurDL = pFM; /* The new one */
/*
* Need some temporary storage to allocate the glyph handle data
* that is required to pass the engine for individual glyph info.
*/
cDL = min( (ULONG)cDL, fi.cGlyphsSupported ); /* Number of glyphs to DL */
pdm->cAvail = cDL;
/* Allow room for an HGLYPH_INVALID at the end of the data */
phgm = (HGLYPH_MAP *)HeapAlloc( pPDev->hheap, 0,
sizeof( HGLYPH_MAP ) * (cDL + 1) );
if( phgm == NULL )
{
vFreeDLMAP( pPDev->hheap, pdm );
return -1;
}
if( !(pIFI->flInfo & FM_INFO_CONSTANT_WIDTH) )
{
psWide = (short *)HeapAlloc( pPDev->hheap, 0, 256 * sizeof( short ) );
if( psWide == NULL )
{
/* Allocation failed, so free this memory and give up */
vFreeDLMAP( pPDev->hheap, pdm );
return -1; /* Don't try any more */
}
pFM->psWidth = psWide; /* For later use */
ZeroMemory( psWide, 256 * sizeof( *psWide ) );
}
else
psWide = NULL; /* Used later */
pFM->pUCTree = phgm; /* It's sort of related */
/*
* We wait until the glyphs are needed before downloading them.
* The actual glyph downloading happens in iHG2Index().
*/
/* Update memory consumption before return */
pFM->dwDLSize = dwMem; /* For the record */
pUDPDev->dwFontMemUsed += dwMem;
pdm->cGlyphs = 0; /* Downloaded AOK */
phgm->hg = HGLYPH_INVALID; /* Marks the end of the list */
/*
* All is now really serious. This font is being downloaded, so
* we need to update counts AND the pvConsumer field in the FONTOBJ
* to include this one.
*/
(int)pfo->pvConsumer = iRet + 1; /* We really do accept it! */
if( !bReLoad )
pdml->cEntries++;
return iRet;
}
/******************************* Function Header ****************************
* iHG2Index
* Given a HGLYPH and FONTMAP structure, returns the index of this
* glyph in the font, or -1 for not mapped.
*
* RETURNS:
* The index of this glyph, >= 0 && < 256; < 0 for error.
*
* HISTORY:
* 13:13 on Wed 24 Mar 1993 -by- Lindsay Harris [lindsayh]
* Incremental download - download as and when needed.
*
* 13:29 on Thu 23 Jul 1992 -by- Lindsay Harris [lindsayh]
* First incarnation.
*
****************************************************************************/
int
iHG2Index( pTOD )
TO_DATA *pTOD; /* Access to all the font/text stuff */
{
/*
* For now, use a simple linear scan. THIS MUST BE CHANGED TO A
* HASHING operation - later!
*/
int iWide; /* Width of downloaded glyph */
int iIndex; /* Next available character index */
int iI;
DWORD dwMem; /* Track our memory usage */
HGLYPH hg;
PDEV *pPDev;
UD_PDEV *pUDPDev;
HGLYPH_MAP *phgm; /* For scanning the list */
FONTMAP *pFM;
DL_MAP *pdm; /* Details of this downloaded font */
GLYPHDATA gd; /* Info from engine */
GLYPHDATA *pgd; /* Points to the above */
pFM = pTOD->pfm;
pPDev = pTOD->pPDev;
pUDPDev = pPDev->pUDPDev;
hg = pTOD->pgp->hg;
for( phgm = pFM->pUCTree; phgm->hg != HGLYPH_INVALID; ++phgm )
{
if( phgm->hg == hg )
return phgm->iByte; /* What the user wants */
}
/*
* Not there. If we are still able, perform an incremental download.
* There are 2 conditions that allow this. First is a printer that
* has incremental download; second is the case where this font is
* "still being downloaded". This will happen relatively frequently,
* so is worth pursuing. A "still being downloaded" font is the last
* one whose header was sent down. The download mode persists until
* another header is sent.
*/
pdm = pFM->u.pvDLData; /* Easy when you know how! */
if( pdm->cAvail <= 0 )
{
return -1; /* No longer available! */
}
/* Is this still the same font? */
if( pUDPDev->pFMCurDL != pFM )
{
/*
* There is a need to switch fonts for the download. This is
* only possible for printers with incremental download ability,
* If that exists, send the new header (for an old font) and
* then the glyph data. Otherwise, terminate the downloading
* of the old font
*/
if( pUDPDev->fDLFormat & DLI_FMT_INCREMENT )
{
/*
* Switch to the new font, which is, of course, an old font.
*/
if( !bDLContinue( pUDPDev, pFM->idDown ) )
return -1;
pUDPDev->pFMCurDL = pFM; /* It is now! */
}
else
{
/*
* No incremental, and we are no longer being downloaded, so
* there is nothing we can do but fail and have the glyph image
* blt'd to the drawing surface.
*/
if( pUDPDev->pFMCurDL )
{
/* Set to no more available for this font download */
((DL_MAP *)(pUDPDev->pFMCurDL->u.pvDLData))->cAvail = 0;
}
return -1; /* No Can Do */
}
}
/* Can still download some more, so do it */
/*
* Find the next available index. This is done by looking at
* the available bits array byte at a time to find the region
* of the next available glyph.
*/
for( iIndex = 0; iIndex < sizeof( pdm->abAvail ); iIndex++ )
{
if( pdm->abAvail[ iIndex ] )
break;
}
#if DBG
if( iIndex >= sizeof( pdm->abAvail ) )
{
DbgPrint( "rasdd!iHG2Index: pdm->cAvail > 0; nothing left\n" );
return -1;
}
#endif
/* Found right area, so look at each bit! */
for( iI = 0; iI < BBITS; ++iI )
{
if( pdm->abAvail[ iIndex ] & (1 << iI) )
{
pdm->abAvail[ iIndex ] &= ~(1 << iI);
iIndex = iIndex * BBITS + iI;
pdm->cAvail--;
break;
}
}
/*
* All set, so get the bits from the engine before calling
* the device specific code to send the data off.
*/
pgd = &gd;
dwMem = 0; /* For accumulating our memory consumption */
if( !FONTOBJ_cGetGlyphs( pTOD->pfo, FO_GLYPHBITS, (ULONG)1,
&pTOD->pgp->hg, &pgd ) ||
!(iWide = iDLGlyph( pUDPDev, iIndex, pgd, &dwMem )) )
{
/* Bad news - restore this as an available glyph & return */
pdm->cAvail++;
pdm->abAvail[ iIndex / BBITS ] |= 1 << (iIndex & (BBITS - 1));
return -1;
}
phgm->hg = pTOD->pgp->hg;
phgm->iByte = iIndex;
++phgm;
phgm->hg = HGLYPH_INVALID; /* Mark the new end of list */
if( pFM->psWidth )
{
/* Proportionally spaced font, so record the width */
pFM->psWidth[ iIndex ] = (SHORT)iWide;
}
/* Update memory consumption usage */
pUDPDev->dwFontMemUsed += dwMem;
pFM->dwDLSize += dwMem;
pdm->cGlyphs++; /* One more down there */
return iIndex;
}
/******************************* Function Header ****************************
* NewDLMap
* Allocate and initialise a new DL_MAP_LIST structure. These
* are placed in a linked list (by our caller).
*
* RETURNS:
* The address of the structure, or NULL on failure.
*
* HISTORY:
* 09:14 on Thu 16 Jul 1992 -by- Lindsay Harris [lindsayh]
* First pass.
*
*****************************************************************************/
DL_MAP_LIST *
NewDLMap( hheap )
HANDLE hheap; /* Heap handle, from whence storage is allocated */
{
DL_MAP_LIST *pdml; /* Value returned */
/*
* Little to do: if we can allocate the storage, then set it to 0.
*/
if( pdml = (DL_MAP_LIST *)HeapAlloc( hheap, 0, sizeof( DL_MAP_LIST ) ) )
{
/* All fields are set to zero as the initial state */
ZeroMemory( pdml, sizeof( DL_MAP_LIST ) );
}
return pdml;
}
/****************************** Function Header ****************************
* pGetIFI
* Given a pointer to a FONTOBJ, return a pointer to the IFIMETRICS
* of the font. If this is a TT font, the metrics will be converted
* with current scaling information. The IFIMETRICS data is allocated
* on the heap, and it is the caller's repsonsibility to free it.
*
* RETURNS:
* Heap address of IFIMETRICS, else NULL for failure.
*
* HISTORY:
* 14:48 on Tue 05 Jan 1993 -by- Lindsay Harris [lindsayh]
* Correct handling of fixed pitch fonts.
*
* 10:28 on Tue 21 Jul 1992 -by- Lindsay Harris [lindsayh]
* First version.
*
****************************************************************************/
IFIMETRICS *
pGetIFI( hheap, pfo )
HANDLE hheap; /* To allow us to allocate memory */
FONTOBJ *pfo; /* The font of interest */
{
IFIMETRICS *pIFI; /* Obtained from engine */
IFIMETRICS *pIFIRet; /* Returned to caller */
XFORMOBJ *pxo; /* For adjusting scalable font metrics */
#define CONVERT_COUNT 7
POINTL aptlIn[ CONVERT_COUNT ]; /* Input values to xform */
POINTL aptlOut[ CONVERT_COUNT ]; /* Output values from xform */
pIFI = FONTOBJ_pifi( pfo );
if( pIFI == NULL )
return NULL; /* May happen when journalling is in progress */
/*
* We need to make a copy of this, since we are going to clobber it.
* This may not be required if we are dealing with a bitmap font, but
* it is presumed most likely to be a TrueType font.
*/
if( pIFIRet = (IFIMETRICS *)HeapAlloc( hheap, 0, pIFI->cjThis ) )
{
/*
* First copy the IFIMETRICS as is. Then, if a scalable font,
* we need to adjust the various sizes with the appropriate
* transform.
*/
CopyMemory( pIFIRet, pIFI, pIFI->cjThis );
if( (pIFIRet->flInfo & (FM_INFO_ISOTROPIC_SCALING_ONLY|FM_INFO_ANISOTROPIC_SCALING_ONLY|FM_INFO_ARB_XFORMS)) &&
(pxo = FONTOBJ_pxoGetXform( pfo )))
{
/*
* Scalable, and transform available, so go do the
* transformations to get the font size in device pels.
*
***********************************************************
* ONLY SOME FIELDS ARE TRANSFORMED, AS WE USE ONLY A FEW.
***********************************************************
*/
ZeroMemory( aptlIn, sizeof( aptlIn ) ); /* Zero default */
aptlIn[ 0 ].y = pIFI->fwdTypoAscender;
aptlIn[ 1 ].y = pIFI->fwdTypoDescender;
aptlIn[ 2 ].y = pIFI->fwdTypoLineGap;
aptlIn[ 3 ].x = pIFI->fwdMaxCharInc;
aptlIn[ 4 ].x = pIFI->rclFontBox.left;
aptlIn[ 4 ].y = pIFI->rclFontBox.top;
aptlIn[ 5 ].x = pIFI->rclFontBox.right;
aptlIn[ 5 ].y = pIFI->rclFontBox.bottom;
aptlIn[ 6 ].x = pIFI->fwdAveCharWidth;
/*
* Perform the transform, and verify that there is no
* rotation component. Return NULL (failure) if any of
* this fails.
*/
if( !XFORMOBJ_bApplyXform( pxo, XF_LTOL, CONVERT_COUNT,
aptlIn, aptlOut ) ||
aptlOut[ 0 ].x || aptlOut[ 1 ].x ||
aptlOut[ 2 ].x || aptlOut[ 3 ].y )
{
HeapFree( hheap, 0, (LPSTR)pIFIRet );
return NULL;
}
/* Simply install the new values into the output IFIMETRICS */
pIFIRet->fwdTypoAscender = (FWORD) aptlOut[0].y;
pIFIRet->fwdTypoDescender = (FWORD) aptlOut[1].y;
pIFIRet->fwdTypoLineGap = (FWORD) aptlOut[2].y;
pIFIRet->fwdWinAscender = pIFIRet->fwdTypoAscender;
pIFIRet->fwdWinDescender = -pIFIRet->fwdTypoDescender;
pIFIRet->fwdMacAscender = pIFIRet->fwdTypoAscender;
pIFIRet->fwdMacDescender = pIFIRet->fwdTypoDescender;
pIFIRet->fwdMacLineGap = pIFIRet->fwdTypoLineGap;
pIFIRet->fwdMaxCharInc = (FWORD)aptlOut[3].x;
/*
* PCL is fussy about the limits of the character cell.
* We allow some slop here by expanding the rclFontBox by
* one pel on each corner.
*/
pIFIRet->rclFontBox.left = aptlOut[ 4 ].x - 1;
pIFIRet->rclFontBox.top = aptlOut[ 4 ].y + 1;
pIFIRet->rclFontBox.right = aptlOut[ 5 ].x + 1;
pIFIRet->rclFontBox.bottom = aptlOut[ 5 ].y - 1;
pIFIRet->fwdAveCharWidth = (FWORD)aptlOut[ 6 ].x;
#if PRINT_INFO
DbgPrint("\nRasdd!pGetIFI:pIFI->fwdTypoAscender = %d,pIFI->fwdTypoDescender = %d\n",pIFI->fwdTypoAscender,pIFI->fwdTypoDescender);
DbgPrint("Rasdd!pGetIFI:pIFI->fwdWinAscender = %d, pIFI->fwdWinDescender = %d\n", pIFI->fwdWinAscender,pIFI->fwdWinDescender );
DbgPrint("Rasdd!pGetIFI:pIFI->rclFontBox.top = %d,pIFI->rclFontBox.bottom = %d\n", pIFI->rclFontBox.top, pIFI->rclFontBox.bottom);
DbgPrint("Rasdd!pGetIFI: AFTER SCALING THE FONT\n");
DbgPrint("Rasdd!pGetIFI:pIFIRet->fwdTypoAscender = %d,pIFIRet->fwdTypoDescender = %d\n",pIFIRet->fwdTypoAscender,pIFIRet->fwdTypoDescender);
DbgPrint("Rasdd!pGetIFI:pIFIRet->fwdWinAscender = %d, pIFIRet->fwdWinDescender = %d\n", pIFIRet->fwdWinAscender,pIFIRet->fwdWinDescender );
DbgPrint("Rasdd!pGetIFI:pIFIRet->rclFontBox.top = %d,pIFIRet->rclFontBox.bottom = %d\n", pIFIRet->rclFontBox.top, pIFIRet->rclFontBox.bottom);
#endif
}
}
return pIFIRet;
#undef CONVERT_COUNT
}
/*************************** Function Header ********************************
* vFreeDLMAP
* The DL_MAP structure contents should be freed - but NOT the map.
*
* RETURNS:
* Nothing
*
* HISTORY:
* 15:32 on Tue 21 Jul 1992 -by- Lindsay Harris [lindsayh]
* First version.
*
*****************************************************************************/
void
vFreeDLMAP( hheap, pdm )
HANDLE hheap; /* Heap access */
DL_MAP *pdm; /* Points to data to free! */
{
FONTMAP *pFM;
/*
* Simply free the storage contained within the FONTMAP structure.
*/
pFM = &pdm->fm;
if( pFM->pIFIMet )
{
HeapFree( hheap, 0, (LPSTR)pFM->pIFIMet );
pFM->pIFIMet = NULL;
}
if( pFM->psWidth )
{
HeapFree( hheap, 0, (LPSTR)pFM->psWidth );
pFM->psWidth = NULL;
}
if( pFM->pUCTree )
{
HeapFree( hheap, 0, (LPSTR)pFM->pUCTree );
pFM->pUCTree = NULL;
}
pdm->cAvail = -1; /* It's available for use */
return;
}
/**************************** Function Header *******************************
* vFreeDL
* Function to free up all the downloaded information. Basically
* work through the list, calling vFreeDLMAP for each entry.
*
*
* RETURNS:
* Nothing.
*
* HISTORY:
* 18:50 on Mon 14 Jun 1993 -by- Lindsay Harris [lindsayh]
* Do not free - data structures - they are re-used in direct printing.
*
* 13:28 on Wed 09 Jun 1993 -by- Lindsay Harris [lindsayh]
* First version, although needed long ago!
*
****************************************************************************/
void
vFreeDL( pPDev )
PDEV *pPDev; /* Access to our data */
{
DL_MAP_LIST *pdml; /* The linked list of font information */
UD_PDEV *pUDPDev; /* It's used a few times */
pUDPDev = pPDev->pUDPDev;
if( pdml = pUDPDev->pvDLMap )
{
/*
* There is downloaded data, so off we go.
*/
int iI;
HANDLE hheap;
hheap = pPDev->hheap;
/*
* Scan through each of the arrays of header data.
*/
while( pdml )
{
DL_MAP_LIST *pdmlTmp = NULL; /* The linked list of font information */
/*
* Scan through each entry in the array of header data.
*/
for( iI = 0; iI < pdml->cEntries; ++iI )
vFreeDLMAP( hheap, &pdml->adlm[ iI ] );
pdmlTmp = pdml;
pdml = pdml->pDMLNext; /* Remember the next one */
HeapFree(hheap,0,(LPSTR)pdmlTmp);
}
}
/* Reset ID to reduce chances of running out. */
pUDPDev->pvDLMap = NULL;
pUDPDev->iNextSFIndex = pUDPDev->iFirstSFIndex;
pUDPDev->iUsedSoftFonts = 0;
pUDPDev->pFMCurDL = NULL; /* No longer available */
pUDPDev->ctl.iFont = 0x7fffffff; /* Clearly invalid */
return;
}