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.
3305 lines
94 KiB
3305 lines
94 KiB
/********************************************************
|
|
* True Type implemementation functions.
|
|
*
|
|
*
|
|
*********************************************************/
|
|
|
|
|
|
#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 <ntrle.h>
|
|
#include "download.h"
|
|
#include "udfnprot.h"
|
|
|
|
#include <fontread.h>
|
|
#include "fontinst.h"
|
|
|
|
|
|
#include <sf_pcl.h>
|
|
#include "rasdd.h"
|
|
|
|
/*
|
|
* Local function prototypes
|
|
*/
|
|
void DumpTrueTypeFile (PVOID );
|
|
|
|
/* Function to retrieve True Type font information from the
|
|
True Type file and store into the ttheader font structure.*/
|
|
BOOL iParseTTFile (UD_PDEV *, PVOID , TABLEDIR *, TABLEDIR *, BOOL * );
|
|
|
|
BOOL bTagCompare (PVOID , char *, int);
|
|
|
|
BOOL bDLTTInfo (PDEV *, PVOID , TT_HEADER , int, int, void *, BYTE *);
|
|
|
|
USHORT SendFontData (UD_PDEV *, void *, FONT_DATA *, TABLEDIR *, int, BYTE *);
|
|
|
|
BOOL bTTOutputGlyph( PDEV *, HGLYPH, NT_RLE *, FONTMAP *, int );
|
|
|
|
BOOL bTTRealGlyphOut( TO_DATA * );
|
|
|
|
/* Send an individual glyph */
|
|
int iTTDLGlyph( PDEV *, int, TO_DATA *, GLYPHDATA *, DWORD * );
|
|
|
|
/* Turns an HGLYPH into a byte code for the printer */
|
|
|
|
int iTTHG2Index( TO_DATA * );
|
|
|
|
USHORT GetGlyphInfo ( UD_PDEV *, GLYPHPOS * , BYTE **);
|
|
|
|
BOOL bReadInTable (void *, void *, char *, void *, int);
|
|
|
|
BOOL bMakeGlyphList (PDEV *, GLYPHLIST *, void *);
|
|
BOOL CopyGlyphData (PDEV *, CMAP_TABLE, void *, void *);
|
|
|
|
ULONG CalcTableCheckSum (ULONG *, ULONG);
|
|
|
|
USHORT CalcCheckSum (BYTE *, ULONG);
|
|
|
|
void BuildTrueTypeHeader (void *, TRUETYPEHEADER *, int);
|
|
|
|
BOOL GetFontName (PDEV *, void *, NAME_TABLE, char *, void *);
|
|
|
|
int GetCharCode (HGLYPH, PDEV *);
|
|
|
|
USHORT GetGlyphId (USHORT, PDEV *);
|
|
|
|
IFIMETRICS *pGetIFI( HANDLE, FONTOBJ * );
|
|
|
|
void NameCpy (char *, void *, USHORT);
|
|
|
|
|
|
BYTE *GetTableMem (char *, TABLEDIR *, void *);
|
|
void GetHmtxInfo (BYTE *, USHORT, USHORT, HMTX_INFO *);
|
|
void GetDefStyle (USHORT *, USHORT, USHORT);
|
|
SBYTE GetDefStrokeWeight (USHORT, USHORT);
|
|
BOOL GetDefPitch (USHORT *, PDEV *, HHEA_TABLE, TABLEDIR *);
|
|
void GetPCLTInfo (PDEV *, TT_HEADER *, PCLT_TABLE, BOOL, OS2_TABLE, HEAD_TABLE, POST_TABLE, HHEA_TABLE, TABLEDIR *);
|
|
|
|
/* deletes older glyph lists if memory is needed */
|
|
void FreeGlyphLists (PDEV *);
|
|
void SetFontFlags (FONTMAP *, IFIMETRICS *);
|
|
|
|
/******************************* Module Header ******************************
|
|
* iFindTTIndex
|
|
* 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:
|
|
*
|
|
* 12:28 on Thu 15 Oct 1995 -by- Sandra Matts
|
|
* First version.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
int
|
|
iFindTTIndex( 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 */
|
|
ULONG pcjFile; /* size of True Type file */
|
|
PVOID pTT; /* pointer to True Type file */
|
|
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 );
|
|
|
|
/* If This font was not downloaded by TT downloader */
|
|
if( pFM && !(pFM->fFlags & FM_TRUE_TYPE) )
|
|
return -1;
|
|
|
|
if( pFM && 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;
|
|
|
|
/* If we allocated a glyphList for a previous font - we
|
|
* should free up the memory since we will want to create
|
|
* a new glyphList. Otherwise we can potentially use up
|
|
* all of the free heap memory.
|
|
*/
|
|
if (iRet > 2)
|
|
FreeGlyphLists (pPDev);
|
|
|
|
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( (pTT = FONTOBJ_pvTrueTypeFontFile ( pfo, &pcjFile)) == NULL )
|
|
{
|
|
DbgPrint ("RASDD: pvTrueTypeFontFile failed\n");
|
|
return -1; /* NBG */
|
|
}
|
|
|
|
if( (pIFI = pGetIFI( pPDev->hheap, pfo )) == NULL )
|
|
{
|
|
DbgPrint ("RASDD: pGetIFI failed\n");
|
|
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->pTTFile = pTT; /* Save the address of True Type File */
|
|
SetFontFlags (pFM, pIFI);
|
|
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 = pIFI->wcFirstChar;
|
|
pFM->wLastChar = pIFI->wcLastChar;
|
|
|
|
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 (font definition) down first. This is based
|
|
* on the True Type data we obtained earlier.
|
|
*/
|
|
|
|
pFM->bBound = TRUE;
|
|
pUDPDev->pFM = pFM;
|
|
cDL = iDLBoundTTHeader( pPDev, pTT, pFM->idDown,
|
|
pFM->pGlyphList, 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 the font has proportional spacing (not monospaced) - then
|
|
* keep track of the width of each character with an array
|
|
*/
|
|
if (pFM->bSpacing == (BYTE)PROPORTIONAL_SPACING)
|
|
{
|
|
// 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 ) );
|
|
pFM->psWidth = NULL;
|
|
psWide = NULL;
|
|
}
|
|
else
|
|
{
|
|
psWide = NULL;
|
|
pFM->psWidth = NULL;
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
/*
|
|
* SWAL - swaps bytes
|
|
* b1 b2 b3 b4 becomes b4 b3 b2 b1
|
|
*/
|
|
|
|
#define SWAL( x ) ((ULONG)(x) = (ULONG)((((((x) >> 24) & 0x000000ff)|(((((x)>>8)&0x0000ff00)|((((x)<<8)&0x00ff0000)|(((x)<<24)&0xff000000))))))))
|
|
/****************************** Function Header ******************************
|
|
* iDLBoundTTHeader
|
|
* Given a pointer to the True Type Font file, and it's download ID,
|
|
* create and send off the font definition header.
|
|
*
|
|
* RETURNS:
|
|
* The number of usable glyphs; < 1 is an error. Also fills in pbGlyphBits
|
|
*
|
|
* HISTORY:
|
|
*
|
|
* 09:37 on Fri 22 Oct 1995 -by- Sandra Matts
|
|
* First version.
|
|
*
|
|
****************************************************************************/
|
|
int
|
|
iDLBoundTTHeader( pPDev, pTT, id, pGlyphList, pbGlyphBits, pdwMem )
|
|
PDEV *pPDev; /* Used in WriteSpoolBuf() call */
|
|
PVOID pTT; /* pointer to True Type File */
|
|
int id; /* Selection ID */
|
|
GLYPHLIST *pGlyphList; /* list of glyph ids and corresponding char codes */
|
|
BYTE *pbGlyphBits; /* Bit array of usable byte values */
|
|
DWORD *pdwMem; /* Estimate of memory consumption */
|
|
{
|
|
UD_PDEV *pUDPDev;
|
|
TT_HEADER ttheader;
|
|
int iNumTags;
|
|
int iRet;
|
|
BOOL bRet;
|
|
BOOL existPCLTTable = FALSE; /* TRUE if the optional PCLT Table is in TT file */
|
|
|
|
HEAD_TABLE headTable;
|
|
POST_TABLE postTable;
|
|
MAXP_TABLE maxpTable;
|
|
PCLT_TABLE pcltTable;
|
|
CMAP_TABLE cmapTable;
|
|
NAME_TABLE nameTable;
|
|
OS2_TABLE OS2Table;
|
|
HHEA_TABLE hheaTable;
|
|
BYTE PanoseNumber[LEN_PANOSE];
|
|
|
|
TABLEDIR PCLTableDir[8]; /* Tables needed for PCL download */
|
|
TABLEDIR TableDir[8]; /* Other tables needed for info but not sent to printer */
|
|
|
|
pUDPDev = pPDev->pUDPDev; /* For our convenience */
|
|
ZeroMemory( &ttheader, sizeof(ttheader) ); /* Safe default values */
|
|
ZeroMemory (&PCLTableDir, sizeof (PCLTableDir));
|
|
|
|
/*
|
|
* First fill in the stuff that is easy to find
|
|
*/
|
|
ttheader.usSize = sizeof (TT_HEADER);
|
|
SWAB (ttheader.usSize);
|
|
ttheader.bFormat = PCL_FM_TT;
|
|
|
|
ttheader.bFontType = TT_BOUND_FONT;
|
|
|
|
|
|
/*
|
|
* Now fill in the entries from the True Type File
|
|
* pvPCLTableDir is the table directory that is downloaded
|
|
* to the printer.
|
|
* pvTableDir is the table directory containing info that
|
|
* is needed for the font but it is not downloaded to
|
|
* the printer. Keep the two tables separate so it's easier
|
|
* to dump to the printer later - simply dump the pvPCLTableDir
|
|
* and free the pvTableDir memory.
|
|
*/
|
|
|
|
iNumTags = iParseTTFile (pUDPDev, pTT, PCLTableDir, TableDir, &existPCLTTable);
|
|
|
|
|
|
/*
|
|
* Get the various tables so we can parse the font information
|
|
*/
|
|
bReadInTable (pTT, PCLTableDir, TABLEHEAD, &headTable, sizeof ( headTable ));
|
|
(pUDPDev->pFM)->indexToLoc = headTable.indexToLocFormat;
|
|
|
|
bReadInTable (pTT, PCLTableDir, TABLEMAXP, &maxpTable, sizeof ( maxpTable ));
|
|
(pUDPDev->pFM)->numGlyphs = maxpTable.numGlyphs;
|
|
|
|
bReadInTable (pTT, TableDir, TABLEPOST, &postTable, sizeof ( postTable ));
|
|
bReadInTable (pTT, TableDir, TABLECMAP, &cmapTable, sizeof ( cmapTable ));
|
|
bReadInTable (pTT, TableDir, TABLENAME, &nameTable, sizeof ( nameTable ));
|
|
bReadInTable (pTT, PCLTableDir, TABLEHHEA, &hheaTable, sizeof ( hheaTable ));
|
|
|
|
|
|
bReadInTable (pTT, TableDir, TABLEOS2, &OS2Table, sizeof (OS2Table));
|
|
|
|
if (existPCLTTable)
|
|
bReadInTable (pTT, TableDir, TABLEPCLT, &pcltTable, sizeof ( pcltTable ));
|
|
|
|
/*
|
|
* Fill in the True Type header with the info from the True
|
|
* Type file.
|
|
*/
|
|
SWAB (headTable.xMax);
|
|
SWAB (headTable.xMin);
|
|
SWAB (headTable.yMax);
|
|
SWAB (headTable.yMin);
|
|
ttheader.wCellWide = (headTable.xMax - headTable.xMin) ;
|
|
SWAB (ttheader.wCellWide);
|
|
ttheader.wCellHeight = (headTable.yMax - headTable.yMin);
|
|
SWAB (ttheader.wCellHeight);
|
|
|
|
ttheader.bSpacing = postTable.isFixedPitch ? FIXED_SPACING:1;
|
|
pUDPDev->pFM->bSpacing = postTable.isFixedPitch ? FIXED_SPACING:1;
|
|
|
|
/*
|
|
* Build the Glyph linked list. Each node contains a character
|
|
* code and its corresponding Glyph ID from the True Type file.
|
|
*/
|
|
CopyGlyphData (pPDev, cmapTable, pTT, TableDir);
|
|
if (!bMakeGlyphList (pPDev, pGlyphList, pTT) )
|
|
return -1;
|
|
|
|
/* Get the PCL table. If it's not present generate defaults. */
|
|
GetPCLTInfo (pPDev, &ttheader, pcltTable, existPCLTTable, OS2Table, headTable, postTable, hheaTable, PCLTableDir);
|
|
|
|
ttheader.bQuality = TT_QUALITY_LETTER;
|
|
|
|
|
|
ttheader.wFirstCode = OS2Table.usFirstCharIndex;
|
|
ttheader.wLastCode = OS2Table.usLastCharIndex;
|
|
ttheader.wLastCode = 0xff00;
|
|
|
|
/* Get the font name from the True Type Font file and put
|
|
* it into the ttheader
|
|
*/
|
|
GetFontName (pPDev, pTT, nameTable, ttheader.FontName, TableDir);
|
|
|
|
ttheader.wScaleFactor = headTable.unitsPerEm;
|
|
SWAB (headTable.unitsPerEm);
|
|
|
|
ttheader.sMasterUnderlinePosition = postTable.underlinePosition;
|
|
ttheader.sMasterUnderlinePosition = -(SHORT) (headTable.unitsPerEm/5);
|
|
SWAB (ttheader.sMasterUnderlinePosition);
|
|
|
|
ttheader.usMasterUnderlineHeight = postTable.underlineThickness;
|
|
ttheader.usMasterUnderlineHeight = (USHORT) (headTable.unitsPerEm/20);
|
|
SWAB (ttheader.usMasterUnderlineHeight);
|
|
|
|
ttheader.usTextHeight = SWAB(OS2Table.sTypoLineGap) +
|
|
headTable.unitsPerEm;
|
|
SWAB (ttheader.usTextHeight);
|
|
|
|
ttheader.usTextWidth = OS2Table.xAvgCharWidth;
|
|
|
|
ttheader.bFontScaling = 1;
|
|
|
|
if (ttheader.wSymSet == 0)
|
|
ttheader.wSymSet = DEF_SYMBOLSET;
|
|
|
|
memcpy (&PanoseNumber, &OS2Table.Panose, LEN_PANOSE);
|
|
|
|
|
|
/*
|
|
* Send the font info from the True Type file to the printer
|
|
*/
|
|
bRet = bDLTTInfo (pPDev, pTT, ttheader, id, iNumTags, PCLTableDir, PanoseNumber);
|
|
if (bRet == FALSE)
|
|
return -1;
|
|
|
|
/*
|
|
* Fill in the bit array of usable glyphs. !!!CHANGE: pbGlyphBits Not
|
|
* Used remove Later. Also change the return value.
|
|
*/
|
|
|
|
FillMemory( pbGlyphBits, 256 / BBITS, 0xff );
|
|
|
|
/* Use the PC-8 set */
|
|
|
|
/*
|
|
* It is better to not use some character values. For PC-8 mode,
|
|
* we do not use: 0, 7 - 15, 27 (esc), 32 (space) - all in decimal.
|
|
* This amounts to 12 characters in toto: disable now.
|
|
* CHANGE: can use the space code, 32, so now only 11 drop out.
|
|
*/
|
|
|
|
pbGlyphBits[ 0 ] &= 0x7e; /* 0 and 7 */
|
|
pbGlyphBits[ 1 ] &= 0x00; /* 8 - 15 */
|
|
pbGlyphBits[ 3 ] &= 0xf7; /* 27 <ESC> */
|
|
|
|
iRet = 256 - 11;
|
|
|
|
return iRet;
|
|
}
|
|
|
|
|
|
/******************************* Module Header ******************************
|
|
* iParseTTFile
|
|
* Function to retrieve True Type font information from the
|
|
* True Type file and store into the ttheader font structure.
|
|
* Modifies existPCLTable: True if PCLT table is in the True
|
|
* Type file otherwise existPCLTable becomes FALSE.
|
|
*
|
|
* RETURNS:
|
|
* The number of tags in the True Type file.
|
|
*
|
|
*
|
|
* HISTORY:
|
|
*
|
|
* 12:28 on Thu 15 Oct 1995 -by- Sandra Matts
|
|
* First version.
|
|
*
|
|
*****************************************************************************/
|
|
int iParseTTFile (pUDPDev, pTT, pvPCLTableDir, pvTableDir, existPCLTable )
|
|
UD_PDEV *pUDPDev;
|
|
PVOID pTT; /* pointer to True Type file */
|
|
TABLEDIR *pvPCLTableDir; /* Pointer to PCL Tables Total 8, They are sent to printer */
|
|
TABLEDIR *pvTableDir; /* Pointer to General Tables Total 3, used for other info. */
|
|
BOOL *existPCLTable; /* True if PCLT table is in True Type file */
|
|
{
|
|
BYTE *pTrueType;
|
|
BYTE *pbTmp;
|
|
BYTE *pbTableDir;
|
|
int iNumTags;
|
|
ULONG *ulOffset;
|
|
|
|
pbTmp = (BYTE*)pvPCLTableDir;
|
|
pbTableDir = (BYTE *)pvTableDir;
|
|
iNumTags = 0;
|
|
|
|
/*
|
|
* Find the first required table "OS/2"
|
|
*/
|
|
pTrueType = pTT;
|
|
pTrueType+= 12;
|
|
while (!bTagCompare (pTrueType, TABLEOS2, 4))
|
|
{
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
}
|
|
/*
|
|
* pTT should point to the first table directory 'OS/2'
|
|
*/
|
|
memcpy (pbTableDir, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)pbTableDir+2;
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTableDir += TABLE_DIR_ENTRY;
|
|
|
|
if (bTagCompare (pTrueType, TABLEPCLT, 4))
|
|
{
|
|
memcpy (pbTableDir, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)pbTableDir+2;
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTableDir += TABLE_DIR_ENTRY;
|
|
*existPCLTable = TRUE;
|
|
}
|
|
|
|
|
|
while (!bTagCompare (pTrueType, TABLECMAP, 4))
|
|
{
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
}
|
|
memcpy (pbTableDir, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)pbTableDir+2;
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTableDir += TABLE_DIR_ENTRY;
|
|
|
|
/*
|
|
* Need to parse through and pick up the tables needed for the
|
|
* PCL spec.
|
|
* There are 8 tables of which 5 are required and three are
|
|
* optional. Tables are sorted in alphabetical order.
|
|
* The PCL tables needed are:
|
|
* cvt - optional
|
|
* fpgm - optional
|
|
* gdir - required
|
|
* head - required
|
|
* hhea - required
|
|
* hmtx - required
|
|
* maxp - required
|
|
* prep - optional
|
|
* The optional tables are used in hinted fonts.
|
|
* iNumTags is incremented only for PCL tables.
|
|
*/
|
|
|
|
if (bTagCompare (pTrueType, TABLECVT, 3))
|
|
{
|
|
// read into TT_Header
|
|
memcpy (pbTmp, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)(pbTmp+(2*sizeof(ULONG)));
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTmp += TABLE_DIR_ENTRY;
|
|
iNumTags += 1;
|
|
}
|
|
|
|
|
|
if (bTagCompare (pTrueType, TABLEFPGM, 4))
|
|
{
|
|
// read into TT_Header
|
|
memcpy (pbTmp, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)(pbTmp+(2*sizeof(ULONG)));
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTmp += TABLE_DIR_ENTRY;
|
|
iNumTags += 1;
|
|
}
|
|
|
|
// add gdir table here
|
|
memcpy (pbTmp, TABLEGDIR, 4);
|
|
pbTmp += TABLE_DIR_ENTRY;
|
|
iNumTags += 1;
|
|
|
|
|
|
while (!bTagCompare (pTrueType, TABLEGLYF, 4))
|
|
{
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
}
|
|
memcpy (&(pUDPDev->pFM)->ulGlyphTable, (pTrueType + 2*sizeof(ULONG)),
|
|
sizeof ((pUDPDev->pFM)->ulGlyphTable));
|
|
memcpy (&(pUDPDev->pFM)->ulGlyphTabLength, (pTrueType + 3*sizeof (ULONG)),
|
|
sizeof ((pUDPDev->pFM)->ulGlyphTabLength));
|
|
SWAL ((pUDPDev->pFM)->ulGlyphTable);
|
|
SWAL ((pUDPDev->pFM)->ulGlyphTabLength);
|
|
|
|
while (!bTagCompare (pTrueType, TABLEHEAD, 4))
|
|
{
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
}
|
|
|
|
if (bTagCompare (pTrueType, TABLEHEAD, 4))
|
|
{
|
|
// read into TT_Header
|
|
memcpy (pbTmp, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)(pbTmp+(2*sizeof(ULONG)));
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTmp += TABLE_DIR_ENTRY;
|
|
iNumTags += 1;
|
|
}
|
|
|
|
if (bTagCompare (pTrueType, TABLEHHEA, 4))
|
|
{
|
|
// read into TT_Header
|
|
memcpy (pbTmp, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)(pbTmp+(2*sizeof(ULONG)));
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTmp += TABLE_DIR_ENTRY;
|
|
iNumTags += 1;
|
|
}
|
|
|
|
if (bTagCompare (pTrueType, TABLEHMTX, 4))
|
|
{
|
|
// read into TT_Header
|
|
memcpy (pbTmp, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)(pbTmp+(2*sizeof(ULONG)));
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTmp += TABLE_DIR_ENTRY;
|
|
iNumTags += 1;
|
|
}
|
|
|
|
while (!bTagCompare (pTrueType, TABLELOCA, 4))
|
|
{
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
}
|
|
memcpy (pbTableDir, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)pbTableDir+2;
|
|
SWAL (*ulOffset);
|
|
(pUDPDev->pFM)->ulLocaTable = *ulOffset;
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTableDir += TABLE_DIR_ENTRY;
|
|
|
|
while (!bTagCompare (pTrueType, TABLEMAXP, 4))
|
|
{
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
}
|
|
|
|
if (bTagCompare (pTrueType, TABLEMAXP, 4))
|
|
{
|
|
// read into TT_Header
|
|
memcpy (pbTmp, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)(pbTmp+(2*sizeof(ULONG)));
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTmp += TABLE_DIR_ENTRY;
|
|
iNumTags += 1;
|
|
}
|
|
|
|
if (bTagCompare (pTrueType, TABLENAME, 4))
|
|
{
|
|
memcpy (pbTableDir, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)pbTableDir+2;
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTableDir += TABLE_DIR_ENTRY;
|
|
}
|
|
|
|
if (bTagCompare (pTrueType, TABLEPOST, 4))
|
|
{
|
|
memcpy (pbTableDir, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)(pbTableDir+(2*sizeof(ULONG)));
|
|
SWAL (*ulOffset);
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
pbTableDir += TABLE_DIR_ENTRY;
|
|
}
|
|
|
|
while (!bTagCompare (pTrueType, TABLEPREP, 4))
|
|
{
|
|
pTrueType += TABLE_DIR_ENTRY;
|
|
}
|
|
|
|
if (bTagCompare (pTrueType, TABLEPREP, 4))
|
|
{
|
|
// read into TT_Header
|
|
memcpy (pbTmp, pTrueType, TABLE_DIR_ENTRY);
|
|
ulOffset = (ULONG *)(pbTmp+(2*sizeof(ULONG)));
|
|
SWAL (*ulOffset);
|
|
iNumTags += 1;
|
|
}
|
|
|
|
return iNumTags;
|
|
}
|
|
|
|
/******************************* Module Header ******************************
|
|
* bTagCompare
|
|
* Compares the memory and tag to see if they are equal
|
|
*
|
|
* RETURNS:
|
|
* TRUE if the tag and memory are equal. FALSE otherwise.
|
|
*
|
|
* HISTORY:
|
|
*
|
|
* 12:28 on Thu 15 Oct 1995 -by- Sandra Matts
|
|
* First version.
|
|
*
|
|
*****************************************************************************/
|
|
BOOL bTagCompare (pTT, Tag, iLength)
|
|
PVOID pTT;
|
|
char *Tag;
|
|
int iLength;
|
|
{
|
|
BYTE *tmp;
|
|
int iIndex;
|
|
|
|
tmp = (char *)pTT;
|
|
for (iIndex = 0; iIndex < iLength; iIndex++)
|
|
{
|
|
if (tmp[iIndex] != Tag[iIndex])
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************* Module Header ******************************
|
|
* bDLTTInfo
|
|
* Function to retrieve build a new True Type header structure
|
|
* relative to the PCL file that is sent to the printer
|
|
* and also send the font data from the True Type
|
|
* file.
|
|
*
|
|
* RETURNS:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
*
|
|
* HISTORY:
|
|
*
|
|
* 12:28 on Thu 15 Oct 1995 -by- Sandra Matts
|
|
* First version.
|
|
*
|
|
*****************************************************************************/
|
|
BOOL bDLTTInfo (pPDev, pTT, ttheader, id, iNumTags, pvPCLTableDir, PanoseNumber )
|
|
PDEV *pPDev;
|
|
PVOID pTT;
|
|
TT_HEADER ttheader;
|
|
int id;
|
|
int iNumTags;
|
|
TABLEDIR *pvPCLTableDir;
|
|
BYTE *PanoseNumber;
|
|
{
|
|
BYTE *pbTableDir,
|
|
*pbTTFile;
|
|
ULONG ulOffset;
|
|
ULONG *pulOffset;
|
|
ULONG *ulLength;
|
|
int iI;
|
|
int cjSend,
|
|
cjTotalBytes;
|
|
int tableLen = 0;
|
|
USHORT checkSum = 0; /* font header checkSum */
|
|
|
|
|
|
UD_PDEV *pUDPDev; /* UNIDRV based PDEV */
|
|
|
|
TABLEDIR PCLtableDir[8]; /* Table directory sent to printer,PCL takes 8 table dirs */
|
|
TABLEDIR TTtableDir[8]; /* Temporary Buffer for PCL tables. Needed for
|
|
* Calculating new field valued*/
|
|
TRUETYPEHEADER trueTypeHeader;
|
|
|
|
USHORT PanoseID[2]; /* PCL Data Segment - PANOSE description */
|
|
USHORT SegHead[2]; /* PCL Data Segment - */
|
|
USHORT NullSegment[2]; /* PCL Data Segment - Terminates segmented font data */
|
|
|
|
FONT_DATA fontData[8]; /* There are eight PCL tables */
|
|
BYTE pad[8]; /* Padding array, Contains num of bytes to be
|
|
padded for each table */
|
|
|
|
ULONG ul;
|
|
BOOL ret;
|
|
|
|
pUDPDev = pPDev->pUDPDev; /* The important stuff */
|
|
|
|
FillMemory (&PCLtableDir, sizeof (PCLtableDir), 0x00);
|
|
FillMemory (&pad, sizeof (pad), 0x00);
|
|
|
|
pbTableDir = (BYTE *)pvPCLTableDir;
|
|
ulOffset = SIZEOF_TABLEDIR;
|
|
ulOffset += TRUE_TYPE_HEADER;
|
|
|
|
memcpy (&TTtableDir, (BYTE *)pvPCLTableDir, sizeof (TTtableDir));
|
|
|
|
/*
|
|
* Build the True Type Header with information from the
|
|
* True Type file.
|
|
*/
|
|
BuildTrueTypeHeader (pTT, &trueTypeHeader, iNumTags);
|
|
|
|
/*
|
|
* Fill in the New Table Dir - which is sent to printer -
|
|
* with the recalculated offsets.
|
|
*/
|
|
for (iI = 0; iI < iNumTags; iI += 1)
|
|
{
|
|
memcpy (&PCLtableDir[iI].uTag, pbTableDir, sizeof (TT_TAG));
|
|
pbTableDir += 3*sizeof (ULONG);
|
|
if (!bTagCompare (&PCLtableDir[iI].uTag, TABLEGDIR, sizeof (TABLEGDIR)-1))
|
|
{
|
|
memcpy (&PCLtableDir[iI].uOffset, &ulOffset, sizeof (ulOffset));
|
|
}
|
|
ulLength = (ULONG *)pbTableDir;
|
|
SWAL( *ulLength );
|
|
if (*ulLength % (sizeof (DWORD)) != 0)
|
|
{
|
|
*ulLength += sizeof(DWORD) - (*ulLength % (sizeof (DWORD)));
|
|
}
|
|
ulOffset += *ulLength;
|
|
tableLen += *ulLength;
|
|
memcpy (&PCLtableDir[iI].uLength, ulLength, sizeof (ULONG));
|
|
pbTableDir += sizeof (ULONG);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Now send the actual font data from the True Type file.
|
|
* Read in the offsets from the original table directory
|
|
* and fetch the data at the offset in the True Type file.
|
|
* Then dump it to the spooler file.
|
|
*/
|
|
pbTableDir = (BYTE *)pvPCLTableDir;
|
|
for (iI = 0; iI < iNumTags; iI += 1)
|
|
{
|
|
pbTTFile = (BYTE *)pTT;
|
|
|
|
/* To get the offset, as first two filelds of table dir are ULONG
|
|
* !!!CHANGE: make pbTableDir to a Long pointer
|
|
*/
|
|
pbTableDir += (2 * sizeof (ULONG));
|
|
|
|
pulOffset = (ULONG *)pbTableDir;
|
|
pbTableDir += sizeof (ULONG);
|
|
ulLength = (ULONG *)pbTableDir;
|
|
pbTTFile += *pulOffset;
|
|
fontData[iI].ulOffset = TTtableDir[iI].uOffset;
|
|
|
|
SWAL (TTtableDir[iI].uLength);
|
|
fontData[iI].ulLength = TTtableDir[iI].uLength;
|
|
|
|
/*
|
|
* Since the tables have to be DWORD aligned, we make
|
|
* the adjustments here. Pad to the next word with zeros.
|
|
*/
|
|
if (TTtableDir[iI].uLength != PCLtableDir[iI].uLength)
|
|
{
|
|
pad[iI] = (BYTE)(PCLtableDir[iI].uLength - TTtableDir[iI].uLength);
|
|
PCLtableDir[iI].uLength = TTtableDir[iI].uLength;
|
|
}
|
|
|
|
|
|
PCLtableDir[iI].uCheckSum = CalcTableCheckSum ((ULONG *)pbTTFile, *ulLength);
|
|
SWAL (PCLtableDir[iI].uCheckSum);
|
|
SWAL (PCLtableDir[iI].uOffset);
|
|
SWAL (PCLtableDir[iI].uLength);
|
|
pbTableDir += sizeof (ULONG);
|
|
}
|
|
|
|
/*
|
|
* Calculate the total number of bytes being sent
|
|
* and send it all to the printer.
|
|
*/
|
|
cjSend = cjTotalBytes = sizeof (TT_HEADER);
|
|
cjTotalBytes += (int)ulOffset;
|
|
cjTotalBytes += (int)LEN_PANOSE;
|
|
cjTotalBytes += (int)sizeof (PanoseID);
|
|
cjTotalBytes += (int) sizeof (SegHead);
|
|
cjTotalBytes += (int) sizeof (NullSegment);
|
|
cjTotalBytes += sizeof (checkSum); /*ending checksum */
|
|
|
|
WriteChannel( pUDPDev, CMD_SET_FONT_ID, id );
|
|
WriteChannel( pUDPDev, CMD_SEND_FONT_DCPT, cjTotalBytes );
|
|
|
|
if( WriteSpoolBuf( pUDPDev, (BYTE *)&ttheader, cjSend ) != cjSend )
|
|
return 0;
|
|
|
|
checkSum = CalcCheckSum ((BYTE*)&ttheader.wScaleFactor,
|
|
sizeof (ttheader.wScaleFactor));
|
|
|
|
checkSum += CalcCheckSum ((BYTE*)&ttheader.sMasterUnderlinePosition,
|
|
sizeof (ttheader.sMasterUnderlinePosition));
|
|
|
|
checkSum += CalcCheckSum ((BYTE*)&ttheader.usMasterUnderlineHeight,
|
|
sizeof (ttheader.usMasterUnderlineHeight));
|
|
|
|
checkSum += CalcCheckSum ((BYTE*)&ttheader.bFontScaling,
|
|
sizeof (ttheader.bFontScaling));
|
|
|
|
checkSum += CalcCheckSum ((BYTE*)&ttheader.bVariety,
|
|
sizeof (ttheader.bVariety));
|
|
|
|
/*
|
|
* Send the Panose structure. This include a 2 bytes tag "PA",
|
|
* the size of the Panose Number, and the Panose number.
|
|
*/
|
|
PanoseID[0] = PANOSE_TAG;
|
|
PanoseID[1] = LEN_PANOSE;
|
|
SWAB (PanoseID[1]);
|
|
if( WriteSpoolBuf( pUDPDev, (BYTE*)&PanoseID, 4 ) != 4 )
|
|
return 0;
|
|
if( WriteSpoolBuf( pUDPDev, PanoseNumber, LEN_PANOSE ) != LEN_PANOSE )
|
|
return 0;
|
|
|
|
checkSum += CalcCheckSum ((BYTE*)&PanoseID,
|
|
sizeof (PanoseID));
|
|
|
|
checkSum += CalcCheckSum ((BYTE*)PanoseNumber,
|
|
LEN_PANOSE);
|
|
/*
|
|
* Send some other stuff
|
|
*/
|
|
SegHead[0] = SEG_TAG;
|
|
ul = sizeof (TRUETYPEHEADER) + ((iNumTags ) * sizeof (TABLEDIR));
|
|
ul += tableLen;
|
|
SegHead[1] = (USHORT) ul;
|
|
SWAB (SegHead[1]);
|
|
|
|
if( WriteSpoolBuf( pUDPDev, (BYTE*)&SegHead, sizeof(SegHead) ) != sizeof(SegHead) )
|
|
return 0;
|
|
checkSum += CalcCheckSum ((BYTE*)&SegHead,
|
|
sizeof (SegHead));
|
|
/*
|
|
* Send the True Type Header
|
|
*/
|
|
|
|
if( WriteSpoolBuf( pUDPDev, (BYTE *)&trueTypeHeader, TRUE_TYPE_HEADER)
|
|
!= TRUE_TYPE_HEADER)
|
|
return 0;
|
|
|
|
checkSum += CalcCheckSum ((BYTE*)&trueTypeHeader, TRUE_TYPE_HEADER);
|
|
|
|
|
|
/*
|
|
* Send the True Type table directory and the font data.
|
|
*/
|
|
cjSend = SIZEOF_TABLEDIR;
|
|
if( WriteSpoolBuf( pUDPDev, (BYTE*)PCLtableDir, SIZEOF_TABLEDIR) != SIZEOF_TABLEDIR)
|
|
return 0;
|
|
|
|
checkSum += CalcCheckSum ((BYTE*)PCLtableDir, (USHORT)SIZEOF_TABLEDIR);
|
|
|
|
checkSum += SendFontData (pUDPDev, pTT, fontData, PCLtableDir, iNumTags, pad);
|
|
|
|
NullSegment[0] = Null_TAG;
|
|
NullSegment[1] = 0;
|
|
if( WriteSpoolBuf( pUDPDev, (BYTE*)&NullSegment, sizeof(NullSegment) )
|
|
!= sizeof(NullSegment) )
|
|
return 0;
|
|
checkSum += CalcCheckSum ((BYTE*)&NullSegment,
|
|
sizeof (NullSegment));
|
|
|
|
|
|
checkSum = 256 - (checkSum % 256);
|
|
SWAB (checkSum);
|
|
|
|
if( WriteSpoolBuf( pUDPDev, (BYTE *)&checkSum, sizeof (checkSum) ) != sizeof (checkSum) )
|
|
return 0;
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************* Module Header ******************************
|
|
* SendFontData
|
|
* Function to retrieve the actual font information
|
|
* from the true type file and then send the data to
|
|
* the printer.
|
|
*
|
|
* RETURNS:
|
|
* The checksum of all of the data that was sent to the printer.
|
|
*
|
|
*
|
|
* HISTORY:
|
|
*
|
|
* 12:28 on Thu 15 Oct 1995 -by- Sandra Matts
|
|
* First version.
|
|
*
|
|
*****************************************************************************/
|
|
USHORT SendFontData (pUDPDev, pTT, fontData, PCLtableDir, iNumTags, pad)
|
|
UD_PDEV *pUDPDev;
|
|
void *pTT;
|
|
FONT_DATA *fontData;
|
|
TABLEDIR *PCLtableDir;
|
|
int iNumTags;
|
|
BYTE *pad;
|
|
{
|
|
ULONG ulLength;
|
|
BYTE *pbTTFile;
|
|
BYTE ZeroArray[4];
|
|
int iI;
|
|
USHORT checkSum = 0;
|
|
|
|
FillMemory (&ZeroArray, sizeof (ZeroArray), 0x00);
|
|
for (iI = 0; iI < iNumTags; iI += 1)
|
|
{
|
|
pbTTFile = (BYTE *)pTT + fontData[iI].ulOffset;
|
|
checkSum += CalcCheckSum (pbTTFile, fontData[iI].ulLength);
|
|
if( WriteSpoolBuf( pUDPDev, (BYTE *)pbTTFile, fontData[iI].ulLength ) != (LONG)fontData[iI].ulLength )
|
|
return 0;
|
|
/* DWORD align */
|
|
if (pad[iI] != 0)
|
|
{
|
|
if( WriteSpoolBuf( pUDPDev, ZeroArray, pad[iI] ) != pad[iI] )
|
|
return 0;
|
|
}
|
|
}
|
|
return checkSum;
|
|
}
|
|
|
|
/************************** Function Header **********************************
|
|
* bDLTTGlyphOut
|
|
* Function to process a glyph for a GDI font we have downloaded. We
|
|
* either treat this as a normal character if this glyph has been
|
|
* downloaded, or BitBlt it to the page bitmap if it is one we did
|
|
* not download.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE; TRUE for success.
|
|
*
|
|
* HISTORY:
|
|
* 13:21 on Tue 2 Jan 1996 -by- Sandra Matts
|
|
* First version.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL
|
|
bDLTTGlyphOut( pTOD )
|
|
TO_DATA *pTOD; /* All that we need to know */
|
|
{
|
|
|
|
/*
|
|
* Calling the HGLYPH mapping function to convert the HGLYPH into
|
|
* a byte to send to the printer. If successful, then simply update
|
|
* the value stored in the TO_DATA passed in, and call off to the
|
|
* normal function. Otherwise, some heavy work is required: the
|
|
* bitmap for this glyph must be obtained then BitBlt'd to the
|
|
* page bitmap image.
|
|
*/
|
|
|
|
int iByte; /* Mapping from download code */
|
|
|
|
BOOL bRet; /* Returned from EngBitBlt */
|
|
|
|
UD_PDEV *pUDPDev; /* For clipping region access */
|
|
|
|
RECTL rclDest; /* Where to blt the glyph */
|
|
POINTL ptlSrc; /* Top left of source bitmap */
|
|
SURFOBJ *pso;
|
|
SURFOBJ *psoGlyph; /* Leads to our bitmap */
|
|
HSURF hbm; /* Engine's handle to our bitmap */
|
|
|
|
GLYPHPOS *pgp; /* For convenience/speed of access */
|
|
GLYPHBITS *pgb; /* Details about this glyph */
|
|
|
|
|
|
|
|
if( (iByte = iTTHG2Index( pTOD )) >= 0 )
|
|
{
|
|
/* Easy: the glyph has been downloaded! */
|
|
pTOD->pgp->hg = (HGLYPH)iByte;
|
|
|
|
return bTTRealGlyphOut( pTOD ); /* Normal course of events */
|
|
}
|
|
|
|
/*
|
|
* Some serious work goes on here. The GLYPHPOS structure has
|
|
* a pointer to the GLYPHDEF structure which contains a pointer to
|
|
* the actual bits of the image. So we have the bits, but need
|
|
* to create a SURFOBJ that the engine will understand.
|
|
*/
|
|
|
|
pso = ((UD_PDEV *)(pTOD->pPDev->pUDPDev))->pso; /* The page bitmap */
|
|
|
|
pgp = pTOD->pgp;
|
|
pgb = pgp->pgdf->pgb; /* Intimate details of this glyph */
|
|
|
|
if( pgb->sizlBitmap.cx == 0 )
|
|
return TRUE; /* Nothing to do e.g. a space! */
|
|
|
|
|
|
rclDest.left = pgp->ptl.x + pgb->ptlOrigin.x;
|
|
rclDest.right = rclDest.left + pgb->sizlBitmap.cx;
|
|
|
|
rclDest.top = pgp->ptl.y + pgb->ptlOrigin.y;
|
|
rclDest.bottom = rclDest.top + pgb->sizlBitmap.cy;
|
|
|
|
ptlSrc.x = 0;
|
|
ptlSrc.y = 0;
|
|
|
|
/*
|
|
* Some verification is in order here, since GDI seems to do funny
|
|
* things with strange fonts. (Well, I guess so: any glyph that
|
|
* is placed to the left of the page boundary is strange!).
|
|
*/
|
|
|
|
if( rclDest.left < 0 )
|
|
{
|
|
/*
|
|
* If the RHS is also hanging over the left, then forget this
|
|
* one! If not, then trim down what we print.
|
|
*/
|
|
|
|
if( rclDest.right <= 0 )
|
|
return TRUE; /* Completely clipped - ignore */
|
|
|
|
/*
|
|
* Well, can now limit the left hand side to what is on the page.
|
|
*/
|
|
|
|
ptlSrc.x -= rclDest.left; /* Double negative -> +ve */
|
|
rclDest.left = 0;
|
|
}
|
|
|
|
pUDPDev = pTOD->pPDev->pUDPDev;
|
|
|
|
|
|
if( rclDest.right > pUDPDev->rcClipRgn.right )
|
|
{
|
|
/* Drops off the RHS, so drop some (or all) of the image */
|
|
|
|
if( rclDest.left >= pUDPDev->rcClipRgn.right )
|
|
return TRUE;
|
|
|
|
|
|
/*
|
|
* Reduce the remaining stuff.
|
|
*/
|
|
|
|
rclDest.right = pUDPDev->rcClipRgn.right;
|
|
|
|
}
|
|
|
|
/*
|
|
* And test the vertical part too!
|
|
*/
|
|
|
|
if( rclDest.top < 0 )
|
|
{
|
|
/* At least part of the top is missing - test the whole lot! */
|
|
|
|
if( rclDest.bottom < 0 )
|
|
return TRUE; /* Nothing shows! */
|
|
|
|
/* Adjust the remainder */
|
|
ptlSrc.y -= rclDest.top;
|
|
rclDest.top = 0;
|
|
|
|
}
|
|
|
|
if( rclDest.bottom > pUDPDev->rcClipRgn.bottom )
|
|
{
|
|
/* Drops off the bottom, so adjust or skip, as needed */
|
|
|
|
if( rclDest.top >= pUDPDev->rcClipRgn.bottom )
|
|
return TRUE; /* All done, as it is missing */
|
|
|
|
rclDest.bottom = pUDPDev->rcClipRgn.bottom;
|
|
}
|
|
|
|
/*
|
|
* We must turn the bitmap data from above into a SURFOBJ for the
|
|
* call to EngBitBlt. This is not difficult, just somewhat messy.
|
|
* First create a bitmap of the data, then use that handle to call
|
|
* EngLockSurface, which returns a SURFOBJ. Then we can unlock
|
|
* and delete the surface when finished.
|
|
*/
|
|
|
|
|
|
hbm = (HSURF)EngCreateBitmap( pgb->sizlBitmap,
|
|
((pgb->sizlBitmap.cx + DWBITS - 1) & ~(DWBITS - 1)) / BBITS,
|
|
(ULONG)BMF_1BPP, BMF_TOPDOWN|BMF_NOZEROINIT, NULL );
|
|
|
|
if( !hbm )
|
|
return FALSE;
|
|
|
|
psoGlyph = EngLockSurface( hbm );
|
|
|
|
/*
|
|
* Initialize the bits.
|
|
* We also need to convert them to DWORD aligned scanlines in the bitmap,
|
|
* as EngBitBlt() does not work for BYTE aligned bitmaps.
|
|
*/
|
|
|
|
vCopyAlign( (BYTE *)psoGlyph->pvBits, pgb->aj,
|
|
pgb->sizlBitmap.cx, pgb->sizlBitmap.cy );
|
|
|
|
/*
|
|
* NOTE: the 0x0000cccc below is stolen from the BitBlt code
|
|
* in the engine. It apparently means SRCCOPY.
|
|
*/
|
|
|
|
bRet = EngBitBlt( pso, psoGlyph, NULL, pTOD->pco, NULL, &rclDest,
|
|
&ptlSrc, NULL, NULL, NULL, 0x00002222 );
|
|
|
|
EngUnlockSurface( psoGlyph );
|
|
EngDeleteSurface( hbm );
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************* Function Header ****************************
|
|
* iTTHG2Index
|
|
* 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 Tue 2 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
iTTHG2Index( 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 = iTTDLGlyph( pPDev, iIndex, pTOD, pgd, &dwMem )) <= 0) )
|
|
{
|
|
/* Bad news - restore this as an available glyph & return */
|
|
|
|
pdm->cAvail++;
|
|
pdm->abAvail[ iIndex / BBITS ] |= 1 << (iIndex & (BBITS - 1));
|
|
|
|
return -1;
|
|
}
|
|
|
|
iIndex = GetCharCode (pTOD->pgp->hg, pPDev);
|
|
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 ***************************
|
|
* iTTDLGlyph
|
|
* Download the glyph table for the glyph passed to us.
|
|
*
|
|
* RETURNS:
|
|
* Character width; < 1 is an error.
|
|
*
|
|
* HISTORY:
|
|
* 09:40 on Tue 2 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
iTTDLGlyph( pPDev, iIndex, pTOD, pgd, pdwMem )
|
|
PDEV *pPDev;
|
|
int iIndex;
|
|
TO_DATA *pTOD; /* Which glyph this is! */
|
|
GLYPHDATA *pgd; /* Details of the glyph */
|
|
DWORD *pdwMem; /* Add the amount of memory used to this */
|
|
{
|
|
/*
|
|
* Two basic steps: first is to generate the header structure
|
|
* and send that off, then send the actual glyph table. The only
|
|
* complication happens if the download data exceeds 32,767 bytes
|
|
* of glyph image. This is unlikely to happen, but we should
|
|
* be prepared for it.
|
|
*/
|
|
|
|
int cbLines; /* Bytes per scan line (sent to printer) */
|
|
int cbTotal; /* Total number of bytes to send */
|
|
int cbSend; /* If size > 32767; send in chunks */
|
|
USHORT GlyphLen; /* number of bytes in glyph */
|
|
BYTE *GlyphMem; /* location of glyph in tt file */
|
|
|
|
GLYPHBITS *pgb; /* Speedier access */
|
|
GLYPHPOS *pGlyphPos;
|
|
|
|
TTCH_HEADER ttCharH; /* true type character header */
|
|
USHORT checkSum = 0;
|
|
USHORT charCode;
|
|
|
|
UD_PDEV * pUDPDev; /* For WriteSpoolBuf() */
|
|
FONTMAP *pFM; /* The FONTMAP structure */
|
|
|
|
pGlyphPos = pTOD->pgp;
|
|
pUDPDev = pPDev->pUDPDev;
|
|
pFM = pTOD->pfm;
|
|
|
|
ZeroMemory( &ttCharH, sizeof( ttCharH ) ); /* Safe initial values */
|
|
|
|
if (pFM->bBound)
|
|
{
|
|
charCode = GetCharCode (pGlyphPos->hg, pPDev);
|
|
if (charCode == INVALID_GLYPH)
|
|
{
|
|
#if DBG
|
|
DbgPrint ("GetCharCode returning INVALID_GLYPH %x \n", pGlyphPos->hg);
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
// hack for single quote and double quote
|
|
if (charCode == LEFT_DOUBLE_QUOTE)
|
|
charCode = PCL_LEFT_DOUBLE_QUOTE;
|
|
|
|
if (charCode == RIGHT_DOUBLE_QUOTE)
|
|
charCode = PCL_RIGHT_DOUBLE_QUOTE;
|
|
|
|
if (charCode == LEFT_SINGLE_QUOTE)
|
|
charCode = PCL_LEFT_SINGLE_QUOTE;
|
|
|
|
if (charCode == RIGHT_SINGLE_QUOTE)
|
|
charCode = PCL_RIGHT_SINGLE_QUOTE;
|
|
|
|
if (charCode == ELLIPSIS)
|
|
charCode = PCL_ELLIPSIS;
|
|
|
|
if (charCode == TRADEMARK)
|
|
charCode = PCL_TRADEMARK;
|
|
|
|
if (charCode == EM_DASH)
|
|
charCode = PCL_EM_DASH;
|
|
|
|
if (charCode == EN_DASH)
|
|
charCode = PCL_EN_DASH;
|
|
|
|
}
|
|
else
|
|
return -1;
|
|
|
|
GlyphLen = GetGlyphInfo (pUDPDev, pGlyphPos, &GlyphMem);
|
|
|
|
ttCharH.bFormat = PCL_FM_TT;
|
|
ttCharH.bContinuation = 0;
|
|
ttCharH.bDescSize = 2;
|
|
ttCharH.bClass = PCL_FM_TT;
|
|
ttCharH.wCharDataSize = GlyphLen + 2* sizeof (USHORT);
|
|
ttCharH.wGlyphID = (WORD)pGlyphPos->hg;
|
|
|
|
SWAB (ttCharH.wGlyphID);
|
|
SWAB (ttCharH.wCharDataSize);
|
|
|
|
|
|
cbTotal = sizeof (ttCharH) + GlyphLen + sizeof (checkSum);
|
|
|
|
|
|
pgb = pgd->gdf.pgb;
|
|
|
|
/*
|
|
* Calculate some sizes of bitmaps: coming from GDI, going to printer.
|
|
*/
|
|
|
|
// cbLines = (chh.wChWidth + BBITS - 1) / BBITS;
|
|
// cbTotal = sizeof( chh ) + cbLines * pgb->sizlBitmap.cy;
|
|
|
|
/*
|
|
* Presume that data is less than the maximum, and so can be
|
|
* sent in one hit. Then loop on any remaining data.
|
|
*/
|
|
|
|
|
|
cbSend = min( cbTotal, 32767 );
|
|
|
|
/*
|
|
* sent the character header and glyph data to the printer
|
|
*/
|
|
WriteChannel( pUDPDev, CMD_SET_CHAR_CODE, charCode );
|
|
WriteChannel( pUDPDev, CMD_SEND_CHAR_DCPT, cbSend );
|
|
|
|
if( WriteSpoolBuf( pUDPDev, (BYTE *)&ttCharH, sizeof( ttCharH ) ) !=
|
|
sizeof( ttCharH ))
|
|
return 0;
|
|
|
|
/* Send the actual TT Glyph data */
|
|
if( WriteSpoolBuf( pUDPDev, GlyphMem, GlyphLen ) != GlyphLen)
|
|
return 0;
|
|
|
|
checkSum = CalcCheckSum ((BYTE *)&ttCharH.wCharDataSize,
|
|
sizeof (ttCharH.wCharDataSize));
|
|
checkSum += CalcCheckSum ((BYTE *)&ttCharH.wGlyphID, sizeof (ttCharH.wGlyphID));
|
|
|
|
checkSum += CalcCheckSum (GlyphMem, GlyphLen);
|
|
|
|
checkSum = (~checkSum + 1) & 0x00ff;
|
|
SWAB (checkSum);
|
|
|
|
if( WriteSpoolBuf( pUDPDev, (BYTE *)&checkSum, sizeof (checkSum) ) !=
|
|
sizeof (checkSum) )
|
|
return 0;
|
|
|
|
/* Sent some, so reduce byte count to compensate */
|
|
cbSend -= sizeof( ttCharH );
|
|
cbTotal -= sizeof( ttCharH );
|
|
|
|
cbTotal -= cbSend; /* Adjust for about to send data */
|
|
|
|
// if( cbTotal > 0 )
|
|
// {
|
|
//#if DBG
|
|
// DbgPrint( "Rasdd!iDLGlyph: cbTotal != 0: NEEDS SENDING LOOP\n" );
|
|
//#endif
|
|
// return 0;
|
|
// }
|
|
|
|
// *pdwMem += cbLines * pgb->sizlBitmap.cy; /* Bytes used, roughly */
|
|
|
|
// return (SWAB( chh.wDeltaX ) + 3) >> 2; /* PCL is in quarter dots! */
|
|
|
|
return 1;
|
|
}
|
|
|
|
/******************************** Function Header ***************************
|
|
* GetCharCode
|
|
* Function to retrieve the character code from the glyph id.
|
|
*
|
|
* RETURNS:
|
|
* The character code; < 1 is an error.
|
|
*
|
|
* HISTORY:
|
|
* 09:40 on Tue 2 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
****************************************************************************/
|
|
int GetCharCode (hglyph, pPDev)
|
|
HGLYPH hglyph;
|
|
PDEV *pPDev;
|
|
{
|
|
GLYPHLIST *pGlyphList;
|
|
int iI = 0;
|
|
WCHAR wcLastChar;
|
|
PIFIMETRICS pIFIMet;
|
|
UD_PDEV *pUDPDev;
|
|
BOOL found = FALSE;
|
|
|
|
pUDPDev = pPDev->pUDPDev;
|
|
pGlyphList = (GLYPHLIST*)pUDPDev->pFM->pGlyphList;
|
|
|
|
/*
|
|
* The glyphList may have deleted previously if alot of
|
|
* different fonts are being downloaded.
|
|
* So, it has to be re-created.
|
|
*/
|
|
if (pGlyphList == NULL)
|
|
bMakeGlyphList (pPDev, pGlyphList, pUDPDev->pFM->pTTFile);
|
|
|
|
pIFIMet = (PIFIMETRICS)pUDPDev->pFM->pIFIMet;
|
|
wcLastChar = pIFIMet->wcLastChar;
|
|
if (pIFIMet->wcLastChar > 0xff)
|
|
wcLastChar = MAX_CHAR;
|
|
|
|
while (!found && iI < wcLastChar)
|
|
{
|
|
if (pGlyphList[iI].GlyphId == hglyph)
|
|
found = TRUE;
|
|
iI++;
|
|
|
|
}
|
|
|
|
if (!found)
|
|
return -1;
|
|
return iI-1;
|
|
}
|
|
|
|
/******************************** Function Header ***************************
|
|
* GetGlyphId
|
|
* Function to retrieve the glyph id from the character code.
|
|
*
|
|
* RETURNS:
|
|
* Glyph Id; < 1 is an error.
|
|
*
|
|
* HISTORY:
|
|
* 09:40 on Tue 2 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
****************************************************************************/
|
|
USHORT GetGlyphId (charCode, pPDev)
|
|
USHORT charCode;
|
|
PDEV *pPDev;
|
|
{
|
|
GLYPHLIST *pGlyphList;
|
|
PIFIMETRICS pIFIMet;
|
|
WCHAR wcLastChar;
|
|
UD_PDEV *pUDPDev;
|
|
|
|
pUDPDev = pPDev->pUDPDev;
|
|
pGlyphList = (GLYPHLIST*)pUDPDev->pFM->pGlyphList;
|
|
|
|
if (pGlyphList == NULL)
|
|
bMakeGlyphList (pPDev, pGlyphList, pUDPDev->pFM->pTTFile);
|
|
|
|
pIFIMet = (PIFIMETRICS)pUDPDev->pFM->pIFIMet;
|
|
wcLastChar = pIFIMet->wcLastChar;
|
|
if (pIFIMet->wcLastChar > 0xff)
|
|
wcLastChar = MAX_CHAR;
|
|
|
|
if (charCode < wcLastChar)
|
|
return pGlyphList[charCode].GlyphId;
|
|
/*
|
|
* character code is not within the allowable range
|
|
*/
|
|
return 0xffff;
|
|
}
|
|
|
|
/************************** Function Header **********************************
|
|
* bTTRealGlyphOut
|
|
* Print this glyph on the printer, at the given position. Unlike
|
|
* bPSGlyphOut, the data is actually spooled for output now, since this
|
|
* function is used for things like LaserJets, i.e. page printers.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE
|
|
*
|
|
* HISTORY:
|
|
* 11:23 on Tue 2 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL
|
|
bTTRealGlyphOut( pTOD )
|
|
register TO_DATA *pTOD;
|
|
{
|
|
/*
|
|
* All we need to do is set the Y position, then call bOutputGlyph
|
|
* to do the actual work.
|
|
*/
|
|
|
|
int iX, iY; /* Calculate real position */
|
|
|
|
UD_PDEV *pUDPDev;
|
|
|
|
|
|
pUDPDev = pTOD->pPDev->pUDPDev;
|
|
|
|
iX = pTOD->pgp->ptl.x + pUDPDev->rcClipRgn.left;
|
|
iY = pTOD->pgp->ptl.y + pUDPDev->rcClipRgn.top;
|
|
|
|
YMoveto( pUDPDev, iY, MV_GRAPHICS | MV_USEREL );
|
|
|
|
|
|
return bTTOutputGlyph( pTOD->pPDev, pTOD->pgp->hg,
|
|
pTOD->pfm->pvntrle, pTOD->pfm, iX );
|
|
|
|
}
|
|
|
|
/*************************** Function Header *******************************
|
|
* bTTOutputGlyph
|
|
* Send printer commands to print the glyph passed in. Basically
|
|
* we do the translation from ANSI to the printer's representation,
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE, FALSE being a failure of SpoolBufWrite()
|
|
*
|
|
* HISTORY
|
|
* 14:05 on Tue 02 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOL
|
|
bTTOutputGlyph(
|
|
PDEV *pPDev,
|
|
HGLYPH hg, /* HGLYPH of interest */
|
|
NT_RLE *pntrle, /* Access to data to send to printer */
|
|
FONTMAP *pFM, /* Private details for this font */
|
|
int iXIn) /* X position at which the glyph is desired */
|
|
{
|
|
|
|
BOOL bRet; /* Returned to caller */
|
|
int iLen; /* Length of string */
|
|
int iIndex; /* Index from glyph to width table */
|
|
BYTE *pb; /* Determining length for above */
|
|
|
|
UHG uhg; /* Various flavours of HGLYPH contents */
|
|
|
|
UD_PDEV *pUDPDev; /* For convenience */
|
|
|
|
BYTE bData;
|
|
|
|
|
|
pUDPDev = pPDev->pUDPDev;
|
|
|
|
/*
|
|
* Set the cursor to the desired X position for this glyph. NOTE
|
|
* that we should only use RELATIVE move commands in here, since
|
|
* the LaserJet family rotates the COORDINATE AXES when text is
|
|
* being rotated by multiples of 90 degrees. Using relative moves
|
|
* means we can avoid trying to figure out where the printer thinks
|
|
* the print positiion is located. It's almost guaranteed to be
|
|
* different to what we think it is!
|
|
*/
|
|
|
|
|
|
// sandram - change code to be absolute for now. Can enhance to
|
|
// move relative later. It's alot of work to get the width of
|
|
// each true type glyph
|
|
|
|
/* if( pUDPDev->fMode & PF_ROTATE )
|
|
XMoveto( pUDPDev, iXIn, MV_GRAPHICS | MV_USEREL );
|
|
else
|
|
XMoveto( pUDPDev, iXIn, MV_GRAPHICS | MV_USEREL | MV_FINE );
|
|
|
|
*/
|
|
|
|
if( pUDPDev->fMode & PF_ROTATE )
|
|
XMoveto( pUDPDev, iXIn, MV_GRAPHICS );
|
|
else
|
|
XMoveto( pUDPDev, iXIn, MV_GRAPHICS | MV_FINE );
|
|
|
|
|
|
|
|
|
|
bRet = FALSE; /* Default case */
|
|
|
|
|
|
uhg.hg = hg; /* Lets us look at it however we want */
|
|
|
|
iLen = 1;
|
|
bData = (BYTE)hg;
|
|
|
|
bRet = WriteSpoolBuf( pUDPDev, &bData, sizeof( bData ) ) == sizeof( bData );
|
|
bRet = TRUE;
|
|
|
|
iIndex = (int)hg;
|
|
|
|
/*
|
|
* 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 )
|
|
{
|
|
/* Output may have succeeded, so update the position */
|
|
|
|
int iXInc;
|
|
|
|
|
|
if( pFM )
|
|
{
|
|
if( pFM->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 = 1;//*(pFM->psWidth + iIndex) * pUDPDev->ixgRes / 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->fFlags & FM_SCALABLE )
|
|
{
|
|
/* Need to transform the value to current size */
|
|
iXInc = lMulFloatLong(&pUDPDev->ctl.eXScale,iXInc);
|
|
}
|
|
|
|
/* Adjust our position for what was printed. */
|
|
|
|
switch( pUDPDev->ctl.iRotate )
|
|
{
|
|
case 2: /* 180 degrees, right to left */
|
|
iXInc = -iXInc;
|
|
|
|
/* FALL THROUGH */
|
|
|
|
case 0: /* Normal direction */
|
|
/* XMoveto( pUDPDev, iXInc,
|
|
MV_RELATIVE | MV_GRAPHICS | MV_UPDATE );
|
|
*/
|
|
break;
|
|
|
|
case 1: /* 90 degrees UP */
|
|
iXInc = -iXInc;
|
|
|
|
/* FALL THROUGH */
|
|
|
|
case 3: /* 270 degrees DOWN */
|
|
YMoveto( pUDPDev, iXInc,
|
|
MV_RELATIVE | MV_GRAPHICS | MV_UPDATE );
|
|
break;
|
|
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/*************************** Function Header *******************************
|
|
* GetGlyphInfo
|
|
* Function to get the glyph data for a particular glyph.
|
|
* The glyph id is passed in as a parameter and the
|
|
* glyph data is kept in the loca table in the True Type file.
|
|
*
|
|
* RETURNS:
|
|
* The number of bytes in the Glyph data table.
|
|
*
|
|
* HISTORY
|
|
* 14:05 on Tue 02 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
USHORT GetGlyphInfo (pUDPDev, pGlyphPos, GlyphMem)
|
|
UD_PDEV *pUDPDev;
|
|
GLYPHPOS *pGlyphPos;
|
|
BYTE **GlyphMem;
|
|
{
|
|
ULONG ulGlyphTable;
|
|
ULONG ulLength;
|
|
ULONG ulLocaTable;
|
|
BYTE *pTrueTypeFile;
|
|
ULONG offset;
|
|
|
|
USHORT GlyphLength;
|
|
ULONG ul;
|
|
|
|
|
|
ulGlyphTable = (pUDPDev->pFM)->ulGlyphTable;
|
|
ulLength = (pUDPDev->pFM)->ulGlyphTabLength;
|
|
pTrueTypeFile = (pUDPDev->pFM)->pTTFile;
|
|
ulLocaTable = (pUDPDev->pFM)->ulLocaTable;
|
|
|
|
pTrueTypeFile += ulLocaTable;
|
|
if (pUDPDev->pFM->indexToLoc == SHORT_OFFSET)
|
|
{
|
|
USHORT *usOffset,
|
|
ui, uj;
|
|
|
|
usOffset = (USHORT *) pTrueTypeFile + pGlyphPos->hg;
|
|
ui = usOffset[0];
|
|
SWAB (ui);
|
|
uj = usOffset[1];
|
|
GlyphLength = (SWAB (uj) - ui) << 1;
|
|
ul = ui;
|
|
*GlyphMem = (BYTE *)((BYTE *)(pUDPDev->pFM)->pTTFile + ulGlyphTable) + (ul << 1);
|
|
|
|
}
|
|
else /* LONG_OFFSET */
|
|
{
|
|
ULONG *ulOffset,
|
|
uj;
|
|
|
|
ulOffset = (ULONG *) pTrueTypeFile + pGlyphPos->hg;
|
|
ul = ulOffset[0];
|
|
SWAL (ul);
|
|
uj = ulOffset[1];
|
|
GlyphLength = (USHORT)(SWAL (uj) - ul);
|
|
*GlyphMem = (BYTE *)((BYTE *)(pUDPDev->pFM)->pTTFile + ulGlyphTable) + ul;
|
|
}
|
|
|
|
return GlyphLength;
|
|
|
|
}
|
|
|
|
|
|
/*************************** Function Header *******************************
|
|
* bReadInTable
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE
|
|
*
|
|
* HISTORY
|
|
* 14:05 on Tue 02 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
BOOL bReadInTable (pTT, pvTableDir, tag, Table, iSize)
|
|
void *pTT;
|
|
void *pvTableDir;
|
|
char *tag;
|
|
void *Table;
|
|
int iSize;
|
|
{
|
|
BYTE *pbTmp;
|
|
ULONG *pulTmp;
|
|
ULONG *ulOffset;
|
|
|
|
pbTmp = pvTableDir;
|
|
pulTmp = pvTableDir;
|
|
while (!bTagCompare (pbTmp, tag, 4))
|
|
{
|
|
pbTmp += TABLE_DIR_ENTRY;
|
|
pulTmp += 4;
|
|
}
|
|
/*
|
|
* Found the directory for the table. Now need to
|
|
* read the actual bits at the offset specified in
|
|
* the table directory.
|
|
*/
|
|
pbTmp +=8;
|
|
ulOffset = (ULONG *)pbTmp;
|
|
pbTmp = pTT;
|
|
pbTmp += *ulOffset;
|
|
memcpy (Table, pbTmp, iSize);
|
|
return TRUE;
|
|
}
|
|
|
|
/*************************** Function Header *******************************
|
|
* bMakeGlyphList
|
|
* Reads in Glyph id information from the True Type file
|
|
* and creates a linked list of glyph ids and corresponding
|
|
* character codes.
|
|
* Currently support Microsoft Windows Encoding only.
|
|
* Refer to True Type Specification for more information.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE, FALSE means there was not a Windows format
|
|
* mapping table (i.e. Mac format)
|
|
*
|
|
* HISTORY
|
|
* 14:05 on Tue 02 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
BOOL bMakeGlyphList (pPDev, pGlyphList, pTT)
|
|
PDEV *pPDev;
|
|
GLYPHLIST *pGlyphList;
|
|
void *pTT;
|
|
{
|
|
int iI;
|
|
ULONG ulOffset;
|
|
BYTE *pbTmp;
|
|
USHORT *usFormat;
|
|
USHORT segCount; /* Number of segments in table */
|
|
USHORT TTFileSegments; /* Number of segments actually parsed -
|
|
in case segCount is really large */
|
|
|
|
GLYPH_MAP_TABLE mapTable;
|
|
CMAP_TABLE cmapTable;
|
|
PIFIMETRICS pIFIMet ;
|
|
UD_PDEV *pUDPDev;
|
|
|
|
USHORT *pGlyphIdArray;
|
|
USHORT *pRangeOffset;
|
|
USHORT startCode[MAX_SEGMENTS];
|
|
USHORT endCode[MAX_SEGMENTS];
|
|
SHORT idDelta[MAX_SEGMENTS];
|
|
USHORT idRangeOffset[MAX_SEGMENTS];
|
|
|
|
|
|
ULONG ulTmp;
|
|
int iJ;
|
|
USHORT usMaxChar;
|
|
BOOL bFound = FALSE;
|
|
|
|
|
|
FillMemory (&endCode, sizeof (endCode), 0x00);
|
|
pUDPDev = pPDev->pUDPDev; /* For our convenience */
|
|
|
|
pIFIMet = (PIFIMETRICS)(pUDPDev->pFM)->pIFIMet;
|
|
|
|
if (pIFIMet->wcLastChar > 0xff)
|
|
usMaxChar = MAX_CHAR;
|
|
|
|
if( !(pGlyphList = HeapAlloc( pPDev->hheap, HEAP_ZERO_MEMORY,
|
|
(usMaxChar*sizeof(GLYPHLIST)) )) )
|
|
{
|
|
#if DBG
|
|
DbgPrint ("Heap Alloc failed - bMakeGlyphList\n");
|
|
#endif
|
|
return 0;
|
|
}
|
|
FillMemory (pGlyphList, usMaxChar*sizeof(GLYPHLIST), 0xff);
|
|
pUDPDev->pFM->pGlyphList = pGlyphList;
|
|
|
|
/*
|
|
* The cmap table contains the Character to Glyph Index
|
|
* mapping table.
|
|
*
|
|
*/
|
|
ulOffset = pUDPDev->pFM->pGlyphData->offset;
|
|
pbTmp = pTT;
|
|
|
|
/*
|
|
* Get the encoding format based on the format id
|
|
* Windows uses Platform ID 3
|
|
* Encoding ID = 1 means format 4
|
|
*/
|
|
cmapTable = pUDPDev->pFM->pGlyphData->cmapTable;
|
|
SWAB (cmapTable.nTables);
|
|
for (iI = 0; iI < cmapTable.nTables; iI++)
|
|
{
|
|
SWAB (cmapTable.encodingTable[iI].PlatformID);
|
|
SWAB (cmapTable.encodingTable[iI].EncodingID);
|
|
if (cmapTable.encodingTable[iI].PlatformID == PLATFORM_MS)
|
|
{
|
|
switch ( cmapTable.encodingTable[iI].EncodingID)
|
|
{
|
|
case SYMBOL_FONT: /* Symbol font */
|
|
SWAL (cmapTable.encodingTable[iI].offset);
|
|
ulOffset += cmapTable.encodingTable[iI].offset;
|
|
bFound = TRUE;
|
|
break;
|
|
case UNICODE_FONT: /* Unicode font */
|
|
SWAL (cmapTable.encodingTable[iI].offset);
|
|
ulOffset += cmapTable.encodingTable[iI].offset;
|
|
bFound = TRUE;
|
|
break;
|
|
default: /* error - can't handle */
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
}
|
|
if (!bFound)
|
|
return FALSE;
|
|
|
|
pbTmp += ulOffset;
|
|
memcpy (&ulTmp, pbTmp, sizeof (ULONG));
|
|
ulTmp = (0x0000ff00 & ulTmp) >> 8;
|
|
|
|
switch (ulTmp)
|
|
{
|
|
case 4:
|
|
memcpy (&mapTable, pbTmp, sizeof (mapTable));
|
|
SWAB (mapTable.SegCountx2 );
|
|
segCount = mapTable.SegCountx2 / 2;
|
|
TTFileSegments = segCount;
|
|
|
|
if (segCount > MAX_SEGMENTS)
|
|
segCount = MAX_SEGMENTS;
|
|
|
|
pbTmp += 7 * sizeof (USHORT);
|
|
memcpy (&endCode, pbTmp, segCount*sizeof(USHORT));
|
|
|
|
pbTmp += ((TTFileSegments +1) * sizeof (USHORT));
|
|
memcpy (&startCode, pbTmp, segCount*sizeof(USHORT));
|
|
|
|
pbTmp += (TTFileSegments * sizeof (USHORT));
|
|
memcpy (&idDelta, pbTmp, segCount*sizeof(USHORT));
|
|
|
|
pbTmp += (TTFileSegments * sizeof (USHORT));
|
|
memcpy (&idRangeOffset, pbTmp, segCount*sizeof(USHORT));
|
|
pRangeOffset = (USHORT*)pbTmp;
|
|
|
|
pbTmp += (TTFileSegments * sizeof (USHORT));
|
|
|
|
pGlyphIdArray = (USHORT*)pbTmp;
|
|
|
|
for (iI = 0; iI < segCount-1; iI++)
|
|
{
|
|
SWAB (startCode[iI]);
|
|
SWAB (endCode[iI]);
|
|
}
|
|
|
|
for (iI = 0; iI < segCount-1; iI++)
|
|
{
|
|
SWAB (idDelta[iI]);
|
|
SWAB (idRangeOffset[iI]);
|
|
for (iJ = startCode[iI]; iJ <= endCode[iI]; iJ++)
|
|
{
|
|
if (iJ < usMaxChar)
|
|
{
|
|
if (idRangeOffset[iI] == 0)
|
|
pGlyphList[iJ].GlyphId = idDelta[iI] + iJ;
|
|
else
|
|
{
|
|
pGlyphList[iJ].GlyphId =
|
|
*(pGlyphIdArray + (iJ - startCode[iI]) );
|
|
pGlyphList[iJ].GlyphId += idDelta[iI];
|
|
}
|
|
if (pGlyphList[iJ].GlyphId == 0)
|
|
pGlyphList[iJ].GlyphId = INVALID_GLYPH;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*************************** Function Header *******************************
|
|
* CalcTableCheckSum
|
|
*
|
|
* RETURNS:
|
|
* The CheckSum value.
|
|
*
|
|
* HISTORY
|
|
* 14:05 on Tue 02 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
ULONG CalcTableCheckSum (table, length)
|
|
ULONG *table;
|
|
ULONG length;
|
|
{
|
|
ULONG sum = 0L;
|
|
ULONG *EndPtr = table + (int)(((length+3) & ~3) / sizeof(ULONG));
|
|
ULONG ul;
|
|
|
|
while (table < EndPtr)
|
|
{
|
|
ul = *table;
|
|
SWAL (ul);
|
|
sum = sum + ul;
|
|
table++;
|
|
}
|
|
return (sum);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*************************** Function Header *******************************
|
|
* BuildTrueTypeHeader
|
|
*
|
|
* RETURNS:
|
|
* Nothing
|
|
*
|
|
* HISTORY
|
|
* 14:05 on Tue 02 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
void BuildTrueTypeHeader (pTT, trueTypeHeader, iNumTags)
|
|
PVOID pTT;
|
|
TRUETYPEHEADER *trueTypeHeader;
|
|
int iNumTags;
|
|
{
|
|
int num,
|
|
i;
|
|
|
|
memcpy (&trueTypeHeader->version, pTT, sizeof (trueTypeHeader->version));
|
|
trueTypeHeader->numTables = (USHORT)iNumTags;
|
|
|
|
num = iNumTags << 4;
|
|
i = 15;
|
|
while ( (i > 0) && (! (num &0x8000)) )
|
|
{
|
|
num = num << 1;
|
|
i--;
|
|
}
|
|
num = 1 << i;
|
|
trueTypeHeader->searchRange = (USHORT)num;
|
|
|
|
num = iNumTags;
|
|
i = 15;
|
|
while ( (i > 0) && (! (num & 0x8000)) )
|
|
{
|
|
num = num << 1;
|
|
i--;
|
|
}
|
|
trueTypeHeader->entrySelector = i;
|
|
|
|
num = (iNumTags << 4) - trueTypeHeader->searchRange;
|
|
trueTypeHeader->rangeShift = (USHORT)num;
|
|
|
|
SWAB (trueTypeHeader->searchRange);
|
|
SWAB (trueTypeHeader->numTables);
|
|
SWAB (trueTypeHeader->entrySelector);
|
|
SWAB (trueTypeHeader->rangeShift);
|
|
}
|
|
|
|
/*************************** Function Header *******************************
|
|
* CalcCheckSum
|
|
*
|
|
* RETURNS:
|
|
* The CheckSum
|
|
*
|
|
* HISTORY
|
|
* 14:05 on Tue 02 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
USHORT CalcCheckSum (startPtr, length)
|
|
BYTE *startPtr;
|
|
ULONG length;
|
|
{
|
|
USHORT ui, sum = 0;
|
|
|
|
for (ui = 0; ui < length; ui++)
|
|
{
|
|
sum = sum + (USHORT)*startPtr;
|
|
startPtr++;
|
|
}
|
|
return (sum);
|
|
}
|
|
|
|
/*************************** Function Header *******************************
|
|
* GetFontName
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE; modifies FontName
|
|
*
|
|
* HISTORY
|
|
* 14:05 on Tue 02 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
BOOL GetFontName (pPDev, pTT, nameTable, FontName, pvTableDir)
|
|
PDEV *pPDev;
|
|
void *pTT; /* address of True Type file */
|
|
NAME_TABLE nameTable;
|
|
char *FontName;
|
|
TABLEDIR *pvTableDir;
|
|
{
|
|
int iI;
|
|
USHORT StringLen,
|
|
StringOffset;
|
|
ULONG ulOffset;
|
|
BOOL bFound = FALSE;
|
|
BYTE *nameOffset;
|
|
|
|
BYTE *pbTable;
|
|
|
|
pbTable = (BYTE *)pvTableDir;
|
|
while (!bTagCompare (pbTable, "name", 4))
|
|
{
|
|
pbTable = pbTable + 16;
|
|
}
|
|
pbTable = pbTable + 8;
|
|
ulOffset = *(ULONG *)pbTable;
|
|
|
|
/*
|
|
* Currently looking for
|
|
* Platform ID 3 Microsoft format
|
|
* Encoding ID 1 Unicode font
|
|
* Language ID 0x0409 U.S. English
|
|
* Name ID 1 Font Family Name
|
|
* If the font file does not contain this format
|
|
* we return FALSE.
|
|
*/
|
|
SWAB (nameTable.NumOfNameRecords);
|
|
if( !(nameTable.pNameRecord = HeapAlloc( pPDev->hheap, HEAP_ZERO_MEMORY,
|
|
nameTable.NumOfNameRecords* sizeof(NAME_RECORD))) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
nameOffset = (BYTE*)pTT + ulOffset + (3*sizeof(USHORT));
|
|
memcpy (nameTable.pNameRecord, nameOffset, nameTable.NumOfNameRecords*sizeof(NAME_RECORD));
|
|
|
|
iI = 0;
|
|
while (iI < nameTable.NumOfNameRecords && !bFound)
|
|
{
|
|
SWAB (nameTable.pNameRecord[iI].PlatformID);
|
|
SWAB (nameTable.pNameRecord[iI].EncodingID);
|
|
SWAB (nameTable.pNameRecord[iI].LanguageID);
|
|
SWAB (nameTable.pNameRecord[iI].NameID);
|
|
if ((nameTable.pNameRecord[iI].PlatformID == PLATFORM_MS) &&
|
|
(nameTable.pNameRecord[iI].EncodingID == 1))
|
|
{
|
|
if ((nameTable.pNameRecord[iI].LanguageID == 0x0409) &&
|
|
(nameTable.pNameRecord[iI].NameID == FAMILY_NAME))
|
|
{
|
|
StringLen = nameTable.pNameRecord[iI].StringLen;
|
|
StringOffset = nameTable.pNameRecord[iI].StringOffset;
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
iI++;
|
|
}
|
|
|
|
if (!bFound)
|
|
{
|
|
iI = 0;
|
|
bFound = FALSE;
|
|
while (iI < nameTable.NumOfNameRecords && !bFound)
|
|
{
|
|
SWAB (nameTable.pNameRecord[iI].PlatformID);
|
|
SWAB (nameTable.pNameRecord[iI].EncodingID);
|
|
SWAB (nameTable.pNameRecord[iI].LanguageID);
|
|
SWAB (nameTable.pNameRecord[iI].NameID);
|
|
if ((nameTable.pNameRecord[iI].PlatformID == PLATFORM_MS) &&
|
|
(nameTable.pNameRecord[iI].EncodingID == 1))
|
|
{
|
|
if ( nameTable.pNameRecord[iI].NameID == FAMILY_NAME)
|
|
{
|
|
StringLen = nameTable.pNameRecord[iI].StringLen;
|
|
StringOffset = nameTable.pNameRecord[iI].StringOffset;
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
iI++;
|
|
}
|
|
}
|
|
|
|
SWAB (StringLen);
|
|
SWAB (StringOffset);
|
|
SWAB (nameTable.Offset);
|
|
|
|
ulOffset += StringOffset + nameTable.Offset;
|
|
pTT = (BYTE *)pTT + ulOffset;
|
|
if (StringLen / 2 > LEN_FONTNAME)
|
|
StringLen = 2*LEN_FONTNAME;
|
|
NameCpy (FontName, pTT, StringLen);
|
|
|
|
HeapFree( pPDev->hheap, 0, (LPSTR)nameTable.pNameRecord );
|
|
return TRUE;
|
|
}
|
|
|
|
/*************************** Function Header *******************************
|
|
* NameCpy
|
|
*
|
|
* RETURNS:
|
|
* Nothing
|
|
*
|
|
* HISTORY
|
|
* 14:05 on Tue 02 Jan 1996 -by- Sandra Matts
|
|
* initial version
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
void NameCpy (PCLFontName, pUnicodeFontName, StringLen)
|
|
char *PCLFontName;
|
|
void *pUnicodeFontName;
|
|
USHORT StringLen;
|
|
{
|
|
|
|
char *Src,
|
|
*Dst;
|
|
USHORT ui;
|
|
|
|
Src = pUnicodeFontName;
|
|
Dst = PCLFontName;
|
|
StringLen = StringLen /2;
|
|
|
|
for (ui = 0; ui < StringLen; ui++)
|
|
{
|
|
Src++;
|
|
*Dst++ = *Src++;
|
|
}
|
|
|
|
}
|
|
|
|
/************************* Function Header *******************************
|
|
* ConvertHiByteToCharCode
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
void ConvertHiByteToCharCode (charCode, pUnicodeStr, StringLen)
|
|
char *charCode;
|
|
void *pUnicodeStr;
|
|
USHORT StringLen;
|
|
{
|
|
|
|
char *Src,
|
|
*Dst;
|
|
USHORT ui;
|
|
|
|
Src = pUnicodeStr;
|
|
Dst = charCode;
|
|
StringLen = StringLen /2;
|
|
|
|
for (ui = 0; ui < StringLen; ui++)
|
|
{
|
|
if (*(SHORT *)pUnicodeStr == LEFT_DOUBLE_QUOTE)
|
|
*Dst++ = (char)PCL_LEFT_DOUBLE_QUOTE;
|
|
|
|
else if (*(SHORT *)pUnicodeStr == RIGHT_DOUBLE_QUOTE)
|
|
*Dst++ = (char)PCL_RIGHT_DOUBLE_QUOTE;
|
|
|
|
else if (*(SHORT *)pUnicodeStr == LEFT_SINGLE_QUOTE)
|
|
*Dst++ = (char)PCL_LEFT_SINGLE_QUOTE;
|
|
|
|
else if (*(SHORT *)pUnicodeStr == RIGHT_SINGLE_QUOTE)
|
|
*Dst++ = (char)PCL_RIGHT_SINGLE_QUOTE;
|
|
|
|
else if (*(SHORT *)pUnicodeStr == ELLIPSIS)
|
|
*Dst++ = (char)PCL_ELLIPSIS;
|
|
|
|
else if (*(SHORT *)pUnicodeStr == TRADEMARK)
|
|
*Dst++ = (char)PCL_TRADEMARK;
|
|
|
|
else if (*(SHORT *)pUnicodeStr == EM_DASH)
|
|
*Dst++ = (char)PCL_EM_DASH;
|
|
|
|
else if (*(SHORT *)pUnicodeStr == EN_DASH)
|
|
*Dst++ = (char)PCL_EN_DASH;
|
|
|
|
else
|
|
*Dst++ = *Src;
|
|
|
|
Src++;
|
|
(SHORT)pUnicodeStr+=2;
|
|
Src++;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/************************* Function Header *******************************
|
|
* bGetTTPointSize
|
|
* Apply the font transform to obtain the point size for this font.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE, TRUE for success.
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*************************************************************************/
|
|
BOOL bGetTTPointSize( 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;
|
|
IFIMETRICS *pifi;
|
|
|
|
#define pIFI ((IFIMETRICS *)(pfm->pIFIMet))
|
|
|
|
pifi = 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;
|
|
|
|
|
|
#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);
|
|
|
|
#endif
|
|
return TRUE;
|
|
|
|
#undef pIFI
|
|
}
|
|
|
|
/*************************** Function Header *******************************
|
|
* bTTSelScalableFont
|
|
* Sends the font height command to a PCL5 printer
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE, TRUE for success.
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
BOOL bTTSelScalableFont( pUDPDev, pptl, pFM )
|
|
UD_PDEV *pUDPDev; /* Unidrive's PDEV */
|
|
POINTL *pptl; /* New size required */
|
|
FONTMAP *pFM; /* The font of interest */
|
|
{
|
|
|
|
char cmdstr[15];
|
|
char pointSize[6];
|
|
int pointLen;
|
|
char *ptr;
|
|
|
|
pointLen = iFont100toStr (pointSize, pptl->y);
|
|
|
|
cmdstr[0] = 0x1b;
|
|
cmdstr[1] = '(';
|
|
cmdstr[2] = 's';
|
|
ptr = cmdstr + 3;
|
|
memcpy (ptr, &pointSize, pointLen);
|
|
cmdstr[pointLen+3] = 'V';
|
|
|
|
WriteSpoolBuf (pUDPDev, cmdstr, 4+pointLen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/************************* Function Header *******************************
|
|
* GetDefStyle
|
|
*
|
|
*
|
|
* RETURNS:
|
|
* Fills in Style.
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
void GetDefStyle (Style, WidthClass, macStyle)
|
|
USHORT *Style;
|
|
USHORT WidthClass;
|
|
USHORT macStyle;
|
|
{
|
|
int i;
|
|
*Style = DEF_STYLE;
|
|
|
|
switch (WidthClass)
|
|
{
|
|
case 1:
|
|
i = 4;
|
|
break;
|
|
case 2:
|
|
i = 2;
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
i = 1;
|
|
break;
|
|
case 5:
|
|
i = 0;
|
|
break;
|
|
case 6:
|
|
case 7:
|
|
i = 6;
|
|
break;
|
|
case 8:
|
|
case 9:
|
|
i = 7;
|
|
break;
|
|
default:
|
|
i = 0;
|
|
}
|
|
i = i << 2;
|
|
*Style = *Style | i;
|
|
i = (macStyle >> 1) & 0x01;
|
|
*Style = *Style | i;
|
|
|
|
}
|
|
|
|
/************************* Function Header *******************************
|
|
* GetDefStrokeWeight
|
|
*
|
|
*
|
|
* RETURNS:
|
|
* The stroke weight of the font.
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
SBYTE GetDefStrokeWeight (WeightClass, macStyle)
|
|
USHORT WeightClass;
|
|
USHORT macStyle;
|
|
{
|
|
SBYTE strokeWeight;
|
|
int i;
|
|
|
|
strokeWeight = DEF_STROKEWEIGHT;
|
|
i = WeightClass / 100;
|
|
if (WeightClass >= 400)
|
|
strokeWeight = i - 4;
|
|
else
|
|
strokeWeight = i - 6;
|
|
|
|
|
|
return strokeWeight;
|
|
}
|
|
|
|
/************************* Function Header *******************************
|
|
* GetHmtxInfo
|
|
*
|
|
*
|
|
* RETURNS:
|
|
* Fills in hmtxInfo.
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
void GetHmtxInfo (hmtxTable, glyphId, numberOfHMetrics, hmtxInfo)
|
|
BYTE *hmtxTable; /* location of hmtx table in True Type file */
|
|
USHORT glyphId; /* retrieve metrics for this glyph */
|
|
USHORT numberOfHMetrics;
|
|
HMTX_INFO *hmtxInfo;
|
|
{
|
|
HORIZONTALMETRICS *longHorMetric;
|
|
uFWord advanceWidth;
|
|
|
|
longHorMetric = ((HMTXTABLE *)hmtxTable)->longHorMetric;
|
|
|
|
if (glyphId < numberOfHMetrics)
|
|
advanceWidth = longHorMetric[glyphId].advanceWidth;
|
|
else
|
|
advanceWidth = longHorMetric[numberOfHMetrics-1].advanceWidth;
|
|
|
|
|
|
hmtxInfo->advanceWidth = SWAB(advanceWidth);
|
|
|
|
|
|
}
|
|
|
|
|
|
/************************* Function Header *******************************
|
|
* GetTableMem
|
|
* Function to find the location of a specific table in the
|
|
* true type file.
|
|
*
|
|
* RETURNS:
|
|
* A Pointer to the beginning of the table in the
|
|
* true type file.
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*************************************************************************/
|
|
BYTE *GetTableMem (tag, tableDir, pTTFile)
|
|
char *tag; /* True Type table tag */
|
|
TABLEDIR *tableDir;
|
|
void *pTTFile; /* pointer to True Type file */
|
|
{
|
|
BYTE *pbTmp;
|
|
ULONG *ulOffset;
|
|
|
|
pbTmp = (BYTE *)tableDir;
|
|
while (!bTagCompare (pbTmp, tag, 4))
|
|
{
|
|
pbTmp += TABLE_DIR_ENTRY;
|
|
}
|
|
/*
|
|
* Found the directory for the table. Now need to
|
|
* read the actual bits at the offset specified in
|
|
* the table directory.
|
|
*/
|
|
pbTmp +=8;
|
|
ulOffset = (ULONG *)pbTmp;
|
|
pbTmp = pTTFile;
|
|
pbTmp += *ulOffset;
|
|
return pbTmp;
|
|
|
|
}
|
|
|
|
/************************* Function Header *******************************
|
|
* GetXHeight
|
|
* Calculates the XHeight for the font.
|
|
*
|
|
* RETURNS:
|
|
* the XHeight.
|
|
*
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*************************************************************************/
|
|
USHORT GetXHeight (pPDev)
|
|
PDEV *pPDev;
|
|
{
|
|
|
|
return DEF_XHEIGHT;
|
|
}
|
|
|
|
/************************* Function Header *******************************
|
|
* GetCapHeight
|
|
* Calculates the CapHeight for the font.
|
|
*
|
|
* RETURNS:
|
|
* The CapHeight.
|
|
*
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*************************************************************************/
|
|
USHORT GetCapHeight (pPDev)
|
|
PDEV *pPDev;
|
|
{
|
|
return DEF_CAPHEIGHT;
|
|
}
|
|
|
|
/************************* Function Header *******************************
|
|
* GetDefPitch
|
|
* Calculates the pitch for the font. Uses the hmtx table
|
|
* to get the information.
|
|
*
|
|
* RETURNS:
|
|
* Nothing. Modifies Pitch.
|
|
*
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*************************************************************************/
|
|
BOOL GetDefPitch (Pitch, pPDev, hheaTable, tableDir)
|
|
USHORT *Pitch; /* The pitch is returned */
|
|
PDEV *pPDev;
|
|
HHEA_TABLE hheaTable;
|
|
TABLEDIR *tableDir;
|
|
{
|
|
HMTX_INFO HmtxInfo;
|
|
USHORT glyphId;
|
|
BYTE *hmtxTable;
|
|
void *pTTFile;
|
|
UD_PDEV *pUDPDev;
|
|
|
|
pUDPDev = pPDev->pUDPDev; /* For our convenience */
|
|
pTTFile = pUDPDev->pFM->pTTFile;
|
|
glyphId = GetGlyphId (0x0020, pPDev);
|
|
if (glyphId == INVALID_GLYPH)
|
|
return FALSE;
|
|
|
|
hmtxTable = GetTableMem (TABLEHMTX, tableDir, pTTFile);
|
|
|
|
/* pick a typical glyph to use - Windows 95 driver uses 3 */
|
|
glyphId = 3;
|
|
GetHmtxInfo (hmtxTable, glyphId, hheaTable.numberOfHMetrics,
|
|
&HmtxInfo);
|
|
|
|
*Pitch = HmtxInfo.advanceWidth;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
/************************* Function Header *******************************
|
|
* GetPCLTInfo
|
|
* Fills in the True Type header with information from the
|
|
* PCLT table in the True Type file. If the PCLT table does
|
|
* not exist (it's optional), then a good set of defaults
|
|
* are used. The defaults come from the Windows 95 driver.
|
|
*
|
|
* RETURNS:
|
|
* Nothing. Modifies ttheader.
|
|
*
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
void GetPCLTInfo (pPDev, ttheader, pcltTable, existPCLTTable, OS2Table, headTable, postTable, hheaTable, tableDir)
|
|
PDEV *pPDev;
|
|
TT_HEADER *ttheader; /* font header */
|
|
PCLT_TABLE pcltTable;
|
|
BOOL existPCLTTable; /* True if PCLT table is in True Type file */
|
|
OS2_TABLE OS2Table;
|
|
HEAD_TABLE headTable;
|
|
POST_TABLE postTable;
|
|
HHEA_TABLE hheaTable;
|
|
TABLEDIR *tableDir;
|
|
{
|
|
|
|
SWAL (pcltTable.Version);
|
|
|
|
/*
|
|
* If there is a PCLT table and it's version is
|
|
* later than 1.0, we can use it.
|
|
*/
|
|
if (existPCLTTable && (pcltTable.Version >= 0x10000L))
|
|
{
|
|
SWAB (pcltTable.Style);
|
|
ttheader->bStyleMSB = (BYTE)(pcltTable.Style >> 8);
|
|
ttheader->wSymSet = pcltTable.SymbolSet;
|
|
|
|
ttheader->wPitch = pcltTable.Pitch;
|
|
ttheader->wXHeight = pcltTable.xHeight;
|
|
|
|
ttheader->sbWidthType = pcltTable.WidthType;
|
|
ttheader->bStyleLSB = (BYTE)pcltTable.Style & 0x0ff;
|
|
|
|
ttheader->sbStrokeWeight = pcltTable.StrokeWeight;
|
|
|
|
ttheader->usCapHeight = pcltTable.CapHeight;
|
|
ttheader->ulFontNum = pcltTable.FontNumber;
|
|
|
|
ttheader->bTypefaceLSB = (BYTE) ((pcltTable.TypeFamily & 0xff00) >> 8);
|
|
ttheader->bTypefaceMSB = (BYTE) pcltTable.TypeFamily & 0x00ff;
|
|
|
|
ttheader->bSerifStyle = pcltTable.SerifStyle;
|
|
}
|
|
else
|
|
{
|
|
USHORT Style;
|
|
USHORT TypeFamily;
|
|
USHORT Pitch;
|
|
BOOL bRet;
|
|
|
|
GetDefStyle (&Style, OS2Table.usWidthClass, headTable.macStyle);
|
|
|
|
ttheader->bStyleMSB = (BYTE)(Style >> 8);
|
|
ttheader->bStyleLSB = (BYTE)(Style & 0x0ff);
|
|
|
|
ttheader->ulFontNum = DEF_FONTNUMBER;
|
|
ttheader->sbWidthType = DEF_WIDTHTYPE;
|
|
ttheader->bSerifStyle = DEF_SERIFSTYLE;
|
|
TypeFamily = DEF_TYPEFACE;
|
|
|
|
ttheader->bTypefaceLSB = (BYTE) (TypeFamily & 0x0ff);
|
|
ttheader->bTypefaceMSB = (BYTE) (TypeFamily >> 8);
|
|
|
|
ttheader->wSymSet = 0;
|
|
|
|
bRet = GetDefPitch ( &Pitch, pPDev, hheaTable, tableDir );
|
|
if (bRet == FALSE)
|
|
ttheader->wPitch = 0;
|
|
else
|
|
ttheader->wPitch = SWAB (Pitch);
|
|
|
|
ttheader->wXHeight = GetXHeight (pPDev);
|
|
|
|
ttheader->sbStrokeWeight = GetDefStrokeWeight (
|
|
SWAB (OS2Table.usWeightClass),
|
|
SWAB (headTable.macStyle) );
|
|
|
|
ttheader->usCapHeight = GetCapHeight (pPDev);
|
|
}
|
|
|
|
}
|
|
|
|
/************************* Function Header *******************************
|
|
* Free GlyphLists
|
|
* Deletes memory associated with the FONTMAP list. This is only
|
|
* called if there are many different fonts being used in one
|
|
* single document.
|
|
*
|
|
* RETURNS:
|
|
* Nothing.
|
|
*
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*************************************************************************/
|
|
void FreeGlyphLists (pPDev)
|
|
PDEV *pPDev;
|
|
{
|
|
|
|
GLYPHLIST *pGlyphList;
|
|
int iI = 0;
|
|
UD_PDEV *pUDPDev = pPDev->pUDPDev;
|
|
DL_MAP_LIST *pFontList = pUDPDev->pvDLMap;
|
|
|
|
while (pFontList != NULL)
|
|
{
|
|
|
|
for (iI = 0; iI < pFontList->cEntries; iI++)
|
|
{
|
|
pGlyphList = pFontList->adlm[iI].fm.pGlyphList;
|
|
if (pGlyphList != NULL)
|
|
HeapFree (pPDev->hheap, 0, (LPSTR)pGlyphList);
|
|
pFontList->adlm[iI].fm.pGlyphList = NULL;
|
|
}
|
|
pFontList = pFontList->pDMLNext;
|
|
}
|
|
|
|
}
|
|
|
|
/************************* Function Header *******************************
|
|
* CopyGlyphData
|
|
* Pull out information about the location of the cmap table
|
|
* in the true type file and store it into the FONTMAP
|
|
* structure. We need this information in case we have
|
|
* to reconstruct the glyph list.
|
|
*
|
|
* RETURNS:
|
|
* Nothing. Modifies pFM.
|
|
*
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*************************************************************************/
|
|
BOOL CopyGlyphData (pPDev, cmapTable, pTT, pvTableDir)
|
|
PDEV *pPDev;
|
|
CMAP_TABLE cmapTable;
|
|
void *pTT;
|
|
void *pvTableDir;
|
|
{
|
|
GLYPH_DATA *pGlyphData;
|
|
ULONG ulOffset;
|
|
UD_PDEV *pUDPDev;
|
|
|
|
pUDPDev = pPDev->pUDPDev; /* For our convenience */
|
|
|
|
if( !(pGlyphData = HeapAlloc( pPDev->hheap, HEAP_ZERO_MEMORY,
|
|
sizeof (GLYPH_DATA))) )
|
|
{
|
|
#if DBG
|
|
DbgPrint ("Heap Alloc failed - CopyGlyphData\n");
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
pUDPDev->pFM->pGlyphData = pGlyphData;
|
|
|
|
|
|
while (!bTagCompare (pvTableDir, TABLECMAP, 4))
|
|
{
|
|
pvTableDir = (ULONG *) pvTableDir + 4;
|
|
}
|
|
pvTableDir = (ULONG *)pvTableDir + 2;
|
|
ulOffset = *(ULONG *)pvTableDir;
|
|
|
|
pUDPDev->pFM->pGlyphData->offset = ulOffset;
|
|
|
|
pUDPDev->pFM->pGlyphData->cmapTable.Version = cmapTable.Version;
|
|
pUDPDev->pFM->pGlyphData->cmapTable.nTables = cmapTable.nTables;
|
|
memcpy (pUDPDev->pFM->pGlyphData->cmapTable.encodingTable, cmapTable.encodingTable, sizeof (cmapTable.encodingTable));
|
|
return TRUE;
|
|
}
|
|
|
|
/************************* Function Header *******************************
|
|
* SetFontFlags
|
|
* Sets the various font flags that describe information
|
|
* about the font.
|
|
*
|
|
* RETURNS:
|
|
* Nothing. Modifies pFM.
|
|
*
|
|
*
|
|
* HISTORY
|
|
* 14:35 on Wed 28 Feb 1996 -by- Sandra Matts
|
|
* First version
|
|
*
|
|
*************************************************************************/
|
|
void SetFontFlags (pFM, pIFI)
|
|
FONTMAP *pFM;
|
|
IFIMETRICS *pIFI;
|
|
{
|
|
pFM->fFlags |= FM_TRUE_TYPE;
|
|
|
|
if (pIFI->fsSelection & FM_SEL_BOLD)
|
|
pFM->fFlags |= FM_BOLD;
|
|
else if (pIFI->fsSelection & FM_SEL_ITALIC)
|
|
pFM->fFlags |= FM_ITALIC;
|
|
// default is regular if none are set.
|
|
else
|
|
pFM->fFlags |= FM_REGULAR;
|
|
|
|
}
|