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.
1072 lines
34 KiB
1072 lines
34 KiB
/******************************* MODULE HEADER *******************************
|
|
* uddjfont.c
|
|
* Functions associated with generating the font permutations allowed
|
|
* for HP DeskJet and similar printers. Based on the win 3.1 code.
|
|
*
|
|
*
|
|
* Copyright (C) 1993 Microsoft Corporation.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include <stddef.h>
|
|
#include <windows.h>
|
|
#include <winddi.h>
|
|
|
|
#include <winres.h>
|
|
#include <libproto.h>
|
|
|
|
#include "win30def.h"
|
|
#include "udmindrv.h"
|
|
#include "udpfm.h"
|
|
#include "uddevice.h"
|
|
#include "udresrc.h"
|
|
#include "pdev.h"
|
|
#include "udresid.h"
|
|
#include "stretch.h"
|
|
#include "udrender.h"
|
|
#include "udfnprot.h"
|
|
#include "raslib.h"
|
|
#include "ntres.h"
|
|
#include "kmfntrd.h" /* FI_MEM definition */
|
|
#include "fontinst.h" /* Font layout in the file */
|
|
|
|
#include <udproto.h> /* Lib functions for GPC lookup */
|
|
|
|
#include <memory.h>
|
|
#include <string.h>
|
|
|
|
#include <fnenabl.h>
|
|
#include <ntrle.h> /* RLE glyph encoding stuff */
|
|
|
|
#include "djfont.h"
|
|
#include "rasdd.h"
|
|
|
|
|
|
/*
|
|
* Local function prototypes.
|
|
*/
|
|
|
|
BOOL bDJ_DuplicateFont( HANDLE, FONTMAP *, FONTMAP *, char *,
|
|
CONST DUPSTRUCT *, WORD );
|
|
|
|
//Comment it out for no Debugging Info
|
|
//#define PRINT_INFO1 1
|
|
|
|
#if PRINT_INFO
|
|
|
|
typedef VOID (*VPRINT) (char*,...);
|
|
|
|
|
|
VOID
|
|
vPrintIFIMETRICS(
|
|
IFIMETRICS *pifi,
|
|
VPRINT vPrint
|
|
);
|
|
|
|
#endif
|
|
|
|
/*
|
|
* The following maps the wPrivateData in DRIVERINFO to the variations
|
|
* of font types allowed.
|
|
*/
|
|
|
|
static CONST DSMAP dsmap[] =
|
|
{
|
|
{ 0, { NORMAL_SIZE, NORMAL_SIZE, NORMAL_FACE } },
|
|
{ DOUBLE_PITCH, { HALF_SIZE, NORMAL_SIZE, NORMAL_FACE } },
|
|
{ HALF_PITCH, { DOUBLE_SIZE, NORMAL_SIZE, NORMAL_FACE } },
|
|
{ HALF_HEIGHT , { NORMAL_SIZE, HALF_SIZE, NORMAL_FACE } },
|
|
{ HALF_PITCH | HALF_HEIGHT, { DOUBLE_SIZE, HALF_SIZE, NORMAL_FACE } },
|
|
{ DOUBLE_PITCH | HALF_HEIGHT, { HALF_SIZE, HALF_SIZE, NORMAL_FACE } },
|
|
{ MAKE_BOLD, { NORMAL_SIZE, NORMAL_SIZE, BOLD_FACE } },
|
|
{ DOUBLE_PITCH | MAKE_BOLD, { HALF_SIZE, NORMAL_SIZE, BOLD_FACE } },
|
|
{ HALF_PITCH | MAKE_BOLD, { DOUBLE_SIZE, NORMAL_SIZE, BOLD_FACE } },
|
|
{ HALF_HEIGHT | MAKE_BOLD, { NORMAL_SIZE, HALF_SIZE, BOLD_FACE } },
|
|
{ DOUBLE_PITCH | HALF_HEIGHT | MAKE_BOLD,
|
|
{ HALF_SIZE, HALF_SIZE, BOLD_FACE } },
|
|
{ HALF_PITCH | HALF_HEIGHT | MAKE_BOLD,
|
|
{ DOUBLE_SIZE, HALF_SIZE, BOLD_FACE } },
|
|
};
|
|
|
|
#define NUM_VARIATIONS (sizeof( dsmap ) / sizeof( dsmap[ 0 ] ))
|
|
|
|
|
|
/***************************** Function Header *****************************
|
|
* cDJPermutations
|
|
* Returns the maximum number of permutations available for a DeskJet
|
|
* font. This is a worst case value, as a given font may not allow
|
|
* all variations.
|
|
* NOTE that this function is provided to allow future expansion of
|
|
* this style, where there may be several methods of enumeration,
|
|
* and the main part of rasdd would call the appropriate device function.
|
|
*
|
|
* RETURNS:
|
|
* Number of permutations, 1 being the lowest return value.
|
|
*
|
|
* HISTORY:
|
|
* 11:04 on Tue 20 Jul 1993 -by- Lindsay Harris [lindsayh]
|
|
* First version, borrowed from Win 3.1
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
cDJPermutations()
|
|
{
|
|
return NUM_VARIATIONS;
|
|
}
|
|
|
|
|
|
/******************************** Function Header ***************************
|
|
* iDJPermute
|
|
* Function to generate the basic FONTMAP data for variations on the
|
|
* the font passed in. It is presumed that the FONTMAP passed in is
|
|
* the base font, and we fill in from there.
|
|
*
|
|
* RETURNS:
|
|
* Total number of fonts added (INCLUDING THE BASE FONT). 0 is legitimate.
|
|
*
|
|
* HISTORY:
|
|
* 13:33 on Wed 28 Jul 1993 -by- Lindsay Harris [lindsayh]
|
|
* Based on Win 3.1 Unidrive code.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int
|
|
iDJPermute( pPDev, pfm )
|
|
PDEV *pPDev;
|
|
FONTMAP *pfm; /* The base FONTMAP data */
|
|
{
|
|
int iNum; /* Number of fonts we generated */
|
|
int iIndex; /* Loop index! */
|
|
|
|
WORD wPermFlags; /* Variations supported by this font */
|
|
|
|
CD *pcd; /* Manipulate selection string */
|
|
FONTMAP *pfmBase; /* Remember the one passed in */
|
|
|
|
char achEscPrefix[MAX_STRING_LENGTH];
|
|
|
|
#if PRINT_INFO1
|
|
WCHAR * pwch;
|
|
IFIMETRICS *pifi;
|
|
#endif
|
|
|
|
|
|
|
|
pfmBase = pfm;
|
|
iNum = 0;
|
|
|
|
|
|
/*
|
|
* The wPrivateData field is used to record the possible variations
|
|
* available with this font. Basically AND it with the wPerm field
|
|
* of the static array at the start of this module, and you get the
|
|
* information about whether this is a usable combination.
|
|
*/
|
|
|
|
wPermFlags = pfmBase->wPrivateData;
|
|
|
|
if( wPermFlags == 0 )
|
|
{
|
|
/* No variations are permitted, so return now. */
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* The font select CD command contains the base selection string
|
|
* for this font. From that we construct the complete string for
|
|
* each variation. So go find it now.
|
|
*/
|
|
|
|
if( pfmBase->pCDSelect == NULL )
|
|
{
|
|
/* No selection string, so this font is in error. */
|
|
#if DBG
|
|
DbgPrint( "rasdd!iDJPermute: Font has null selection string!\n" );
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* The font selection string in the base FONTMAP is only partial.
|
|
* It needs to be completed, based on the variations of the font
|
|
* we are generating. To make life a little easier, we copy the
|
|
* base string into a local (temporary) array, so that we can
|
|
* clobber the one in the base FONTMAP without concern.
|
|
*/
|
|
|
|
pcd = pfm->pCDSelect;
|
|
|
|
|
|
if( strlen( pcd->rgchCmd ) >= sizeof( achEscPrefix ) )
|
|
{
|
|
/* Selection string is too long - reject this font */
|
|
#if DBG
|
|
DbgPrint( "rasdd!iDJPermute: Base selection string too long\n" );
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
CopyMemory( (LPSTR)achEscPrefix, (LPSTR)pcd->rgchCmd, pcd->wLength );
|
|
achEscPrefix[ pcd->wLength ] = '\0';
|
|
|
|
|
|
/*
|
|
* Check through all the variations, and for those that are permitted
|
|
* for this font, call off and perform a partial initalisation of
|
|
* the FONTMAP.
|
|
*/
|
|
|
|
#if PRINT_INFO1
|
|
pifi = (IFIMETRICS *)pfm->pIFIMet;
|
|
pwch = (WCHAR *)((BYTE *)pifi + pifi->dpwszFaceName);
|
|
|
|
if (pifi)
|
|
{
|
|
if(pwch[0] == L'C' && pwch[1] == L'G')
|
|
{
|
|
DbgPrint("\nRasdd!iDJPermute:Doing Pemutations for base font %ws\n",pwch);
|
|
DbgPrint(" Unique Name is %ws\n", (BYTE *)pifi+pifi->dpwszUniqueName);
|
|
DbgPrint(" usWinWeight %d\n" , pifi->usWinWeight );
|
|
DbgPrint(" fwdWinAscender %d\n" , pifi->fwdWinAscender );
|
|
DbgPrint(" fwdWinDescender %d\n" , pifi->fwdWinDescender );
|
|
DbgPrint(" PointSize in Device units is %d\n",
|
|
(pifi->fwdWinDescender + pifi->fwdWinAscender));
|
|
DbgPrint(" Permutations for This font are==>\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
for( iIndex = 0; iIndex < NUM_VARIATIONS; iIndex++ )
|
|
{
|
|
if( (dsmap[ iIndex ].wPerm & wPermFlags) == dsmap[ iIndex ].wPerm )
|
|
{
|
|
|
|
#if PRINT_INFO1
|
|
if(pwch[0] == L'C' && pwch[1] == L'G')
|
|
{
|
|
switch(dsmap[ iIndex ].wPerm)
|
|
{
|
|
case 0:
|
|
DbgPrint(" NO Permutation\n");
|
|
break;
|
|
case HALF_PITCH:
|
|
DbgPrint(" HALF_HEIGHT Permutation\n");
|
|
break;
|
|
case DOUBLE_PITCH:
|
|
DbgPrint(" DOUBLE_PITCH Permutation\n");
|
|
break;
|
|
case HALF_HEIGHT:
|
|
DbgPrint(" HALF_HEIGHT Permutation\n");
|
|
break;
|
|
case MAKE_BOLD:
|
|
DbgPrint(" MAKE_BOLD Permutation\n");
|
|
break;
|
|
case (HALF_PITCH | HALF_HEIGHT):
|
|
DbgPrint(" HALF_PITCH | HALF_HEIGHT Permutation\n");
|
|
break;
|
|
case (DOUBLE_PITCH | HALF_HEIGHT):
|
|
DbgPrint(" DOUBLE_PITCH | HALF_HEIGHT Permutation\n");
|
|
break;
|
|
case (DOUBLE_PITCH | MAKE_BOLD):
|
|
DbgPrint(" DOUBLE_PITCH | MAKE_BOLD Permutation\n");
|
|
break;
|
|
case (HALF_PITCH | MAKE_BOLD):
|
|
DbgPrint(" HALF_PITCH | MAKE_BOLD Permutation\n");
|
|
break;
|
|
case (HALF_HEIGHT | MAKE_BOLD):
|
|
DbgPrint(" HALF_HEIGHT | MAKE_BOLD Permutation\n");
|
|
break;
|
|
case (DOUBLE_PITCH | HALF_HEIGHT | MAKE_BOLD):
|
|
DbgPrint(" DOUBLE_PITCH | HALF_HEIGHT | MAKE_BOLD Permutation\n");
|
|
break;
|
|
case (HALF_PITCH | HALF_HEIGHT | MAKE_BOLD):
|
|
DbgPrint(" HALF_PITCH | HALF_HEIGHT | MAKE_BOLD Permutation\n");
|
|
break;
|
|
default:
|
|
DbgPrint("Not a valid Permutation, value is %x\n",dsmap[ iIndex ].wPerm);
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
if( bDJ_DuplicateFont( pPDev->hheap, pfmBase, pfm,
|
|
achEscPrefix, &dsmap[ iIndex ].ds, wPermFlags ) )
|
|
{
|
|
pfm->jPermuteIndex = (BYTE)iIndex; /* Later regeneration */
|
|
|
|
pfm++;
|
|
iNum++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( iNum > 1 )
|
|
pfmBase->fFlags |= FM_BASE_XPND; /* Mark this as base */
|
|
|
|
return iNum;
|
|
}
|
|
|
|
#if 0
|
|
//-------------------------------*DJ_PermutateSoftFont*------------------------------
|
|
// Action: permutate DeskJet fonts based on the given base SOFT font.
|
|
// Hints for permutation are in the font descriptor which is at the
|
|
// beginning of the download file.
|
|
// Note that the base font does not have the selection escape yet.
|
|
//
|
|
// Return: total # of fonts derived (incl. the base font).
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
short FAR PASCAL DJ_PermutateSoftFont(lpdv, lpfm, lpDLFileName)
|
|
LPDV lpdv;
|
|
LPFONTMAP lpfm; // pointer to the FONTMAP entry of the base font.
|
|
LPSTR lpDLFileName; // download file name
|
|
{
|
|
LPFONTMAP lpBaseFM;
|
|
int count = 0;
|
|
char szFaceName[MAX_STRING_LENGTH];
|
|
char szEscPrefix[MAX_FILE_PATHNAME];
|
|
int hDLFile;
|
|
WORD wPermFlags;
|
|
int i;
|
|
|
|
lpBaseFM = lpfm;
|
|
if (lpBaseFM->iFontType != SOFT_FONT)
|
|
return count;
|
|
|
|
if (!GlobalGetAtomName(lpBaseFM->aFaceName, (LPSTR)szFaceName, sizeof(szFaceName)))
|
|
return count;
|
|
GlobalDeleteAtom(lpBaseFM->aFaceName);
|
|
|
|
// read the download file header to extract the permutation info.
|
|
if (!lpDLFileName ||
|
|
(hDLFile = _lopen(lpDLFileName, OF_READ | OF_SHARE_DENY_WRITE)) < 0)
|
|
return 0;
|
|
|
|
// skip to the beginning of the font descriptor and extract the
|
|
// symbol set value and the typeface number. Also, the permutation
|
|
// flag.
|
|
wPermFlags = DJ_GetPermInfo(hDLFile, (LPSTR)szEscPrefix);
|
|
|
|
// get info on pitch, point size, italic and bold from TEXTMETRIC
|
|
// and compose the escape for the base font and duplicate fonts.
|
|
// Note that the font installer doesn't construct the selection escape.
|
|
|
|
for (i = 0; i < MAX_PERMS; i++)
|
|
if ((gPermOpts[i].wPerm & wPermFlags) == gPermOpts[i].wPerm)
|
|
if (DJ_DuplicateFont(lpdv, lpBaseFM, lpfm, (LPSTR)szFaceName,
|
|
(LPSTR)szEscPrefix, (LPSTR)&gPermOpts[i].ds, count, wPermFlags))
|
|
{
|
|
lpfm++;
|
|
count++;
|
|
}
|
|
|
|
_lclose(hDLFile);
|
|
return count;
|
|
}
|
|
#endif
|
|
|
|
|
|
/**************************** Function Header *******************************
|
|
* bDJ_DuplicateFont
|
|
* Function to generate the variations on a theme version of a base font.
|
|
* Note that we do NOT generate the IFIMETRICS in here. This is done
|
|
* as required, since (for journal playback) the only fonts required
|
|
* will be those used.
|
|
*
|
|
* RETURNS:
|
|
* TRUE/FALSE, TRUE means the duplication happened successfully
|
|
*
|
|
* HISTORY:
|
|
* 14:45 on Wed 28 Jul 1993 -by- Lindsay Harris [lindsayh]
|
|
* First version, based on Win 3.1 function of same name.
|
|
*
|
|
****************************************************************************/
|
|
|
|
BOOL
|
|
bDJ_DuplicateFont( hheap, pfmBase, pfmNew, pchEscPrefix, pds, wBoldFlags )
|
|
HANDLE hheap; /* Access to heap for CD */
|
|
FONTMAP *pfmBase; /* Base FONTMAP for this operation */
|
|
FONTMAP *pfmNew; /* New FONTMAP to be parially set up */
|
|
char *pchEscPrefix; /* The base selection string */
|
|
CONST DUPSTRUCT *pds; /* The variation of interest */
|
|
WORD wBoldFlags; /* The variations allowed this font */
|
|
{
|
|
|
|
|
|
int iIndex; /* End of string as building command */
|
|
int iSize;
|
|
int iPoint100; /* For calculating the font's point size */
|
|
|
|
CD *pCD;
|
|
|
|
char achEscStr[ MAX_STRING_LENGTH ];
|
|
|
|
#define pifiBase ((IFIMETRICS *)(pfmBase->pIFIMet))
|
|
|
|
|
|
|
|
/*
|
|
* Check for some illegal combinations. These are not enumerated.
|
|
*/
|
|
|
|
if( !(pifiBase->flInfo & FM_INFO_CONSTANT_WIDTH) )
|
|
{
|
|
/*
|
|
* A variable pitch font. Check for restrictions.
|
|
*/
|
|
if( pds->width != pds->height || pds->width == DOUBLE_SIZE )
|
|
return FALSE;
|
|
}
|
|
|
|
if( pifiBase->fsSelection & FM_SEL_BOLD )
|
|
{
|
|
/* Only one go at bold - can't embolden a bold font. */
|
|
if( pds->face == BOLD_FACE )
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* OK to proceed - the verification has completed OK. If this is
|
|
* not the first font, then copy the contents of the FONTMAP. And
|
|
* fiddle with a few pointers too!
|
|
*/
|
|
|
|
if( pfmNew != pfmBase )
|
|
{
|
|
*pfmNew = *pfmBase;
|
|
|
|
pfmNew->pIFIMet = NULL; /* Generated as needed */
|
|
|
|
/* Flag as an expansion font. */
|
|
pfmNew->fFlags &= ~(FM_BASE_XPND | FM_MAIN_CTT);
|
|
pfmNew->fFlags |= FM_EXPANDABLE;
|
|
|
|
}
|
|
/*
|
|
* Generate the selection string, then create a Command Descriptor
|
|
* to store it away for future reference.
|
|
*/
|
|
|
|
strcpy( achEscStr, pchEscPrefix );
|
|
iIndex = strlen( achEscStr );
|
|
|
|
/*
|
|
* Fixed pitch fonts are selected using the pitch, so figure it out
|
|
* now if applicable. Note that the printer works to the nearest
|
|
* quarter cpi figure, so calculate the number as 100 times the pitch.
|
|
*/
|
|
|
|
if( pifiBase->flInfo & FM_INFO_CONSTANT_WIDTH )
|
|
{
|
|
int iPitch100; /* Calculate pitch times 100 */
|
|
|
|
/* Note that we ROUND the calculation. */
|
|
iPitch100 = MulDiv( pfmBase->wXRes, 100, pifiBase->fwdAveCharWidth );
|
|
|
|
/*
|
|
* Adjust for whatever scaling we may be applying this time.
|
|
*/
|
|
|
|
if( pds->width == HALF_SIZE )
|
|
{
|
|
iPitch100 *= 2;
|
|
}
|
|
else if( pds->width == DOUBLE_SIZE )
|
|
{
|
|
iPitch100 = (iPitch100 + 1) / 2;
|
|
}
|
|
|
|
achEscStr[ iIndex++ ] = '0'; /* Fixed pitch */
|
|
achEscStr[ iIndex++ ] = 'p';
|
|
|
|
iIndex += iFont100toStr( &achEscStr[ iIndex ], iPitch100 );
|
|
|
|
achEscStr[ iIndex++ ] = 'h';
|
|
}
|
|
else
|
|
{
|
|
/* Proportionally spaced font */
|
|
achEscStr[ iIndex++ ] = '1';
|
|
achEscStr[ iIndex++ ] = 'p';
|
|
|
|
}
|
|
|
|
/*
|
|
* Calculate point size. This is easily derived from the height.
|
|
* NOTE THAT THIS ONLY WORKS FOR BITMAP FONTS!!!!
|
|
*
|
|
* Point size is specified to the nearest 0.25 point, and trailing
|
|
* zeroes (after the decimal point) may be deleted.
|
|
*/
|
|
|
|
iPoint100 = (pifiBase->fwdUnitsPerEm * 7200) / pfmBase->wYRes;
|
|
|
|
if( pds->height == HALF_SIZE )
|
|
{
|
|
iPoint100 /= 2;
|
|
}
|
|
|
|
iPoint100 = ((iPoint100 + 12) / 25) * 25;
|
|
|
|
iIndex += iFont100toStr( &achEscStr[ iIndex ], iPoint100 );
|
|
achEscStr[ iIndex++ ] = 'v';
|
|
|
|
if( (pifiBase->fsSelection & FM_SEL_BOLD) || pds->face == BOLD_FACE )
|
|
achEscStr[ iIndex++ ] = '3';
|
|
else
|
|
achEscStr[ iIndex++ ] = '0';
|
|
|
|
achEscStr[ iIndex++ ] = 'B';
|
|
achEscStr[ iIndex ] = '\0';
|
|
|
|
/*
|
|
* Need to make a CD (Command Descriptor) to select this font. This
|
|
* is a simple type CD, and all it contains is the basic format
|
|
* plus the string just generated.
|
|
*/
|
|
|
|
iSize = iIndex + sizeof( CD ) - 2;
|
|
pCD = pfmNew->pCDSelect = (CD *)HeapAlloc( hheap, 0, iSize );
|
|
if( !pfmNew->pCDSelect )
|
|
{
|
|
return FALSE; /* We've run out of memory! */
|
|
|
|
}
|
|
|
|
pCD->fType = 0;
|
|
pCD->sCount = 0;
|
|
pCD->wLength = iIndex;
|
|
CopyMemory( pCD->rgchCmd, achEscStr, iIndex );
|
|
|
|
pfmNew->pCDDeselect = NULL;
|
|
|
|
/*
|
|
* Remember the fiddling to adjust bold values. All black magic,
|
|
* and I gather mostly produces the wrong value anyway!
|
|
*/
|
|
|
|
if( pds->face == BOLD_FACE )
|
|
{
|
|
if( pds->height == NORMAL_SIZE )
|
|
pfmNew->jAddBold = (wBoldFlags & BASE_BOLD_MASK) >> BASE_BOLD_SHIFT;
|
|
else
|
|
pfmNew->jAddBold = (wBoldFlags & HALF_BOLD_MASK) >> HALF_BOLD_SHIFT;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
#undef pifiBase
|
|
}
|
|
|
|
|
|
|
|
/***************************** Function Header ******************************
|
|
* bDJExpandIFI
|
|
* Called when the user really needs the IFIMETRICS for one of the
|
|
* derived fonts on the DESKJET. Changes relate to the basic variations
|
|
* of change of height or width, or making the font bold.
|
|
*
|
|
* RETURNSL
|
|
* TRUE/FALSE, FALSE being failure to find base font, or alloc memory.
|
|
*
|
|
* HISTORY:
|
|
* 14:31 on Thu 29 Jul 1993 -by- Lindsay Harris [lindsayh]
|
|
* Gotta start somewhere.
|
|
*
|
|
****************************************************************************/
|
|
|
|
BOOL
|
|
bDJExpandIFI( hheap, pfm )
|
|
HANDLE hheap; /* Heap access for new IFIMETRICS structure */
|
|
FONTMAP *pfm; /* The FONTMAP to complete */
|
|
{
|
|
|
|
int iSize; /* Required size of IFIMETRICS structure */
|
|
|
|
int iXRes, iYRes; /* Resolution to change IFIMETRICS */
|
|
|
|
WCHAR *pwchNew; /* New strings data */
|
|
WCHAR *pwchOld; /* Old strings data */
|
|
WCHAR *pwchAttrib; /* Attributes to add to name (only Bold) */
|
|
|
|
CONST DUPSTRUCT *pds; /* Details of how to mangle this version */
|
|
|
|
FONTMAP *pfmBase; /* FONTMAP for base font for this variation. */
|
|
|
|
IFIMETRICS *pifiBase; /* IFIMETRICS of base font */
|
|
IFIMETRICS *pifiNew; /* IFIMETRICS for new font */
|
|
|
|
WCHAR awchPitch[ 32 ]; /* For generating pitch field */
|
|
|
|
#if PRINT_INFO1
|
|
WCHAR * pwch;
|
|
#endif
|
|
|
|
#if PRINT_INFO
|
|
CHAR _dj_print;
|
|
#endif
|
|
|
|
|
|
|
|
|
|
for( pfmBase = pfm; !(pfmBase->fFlags & FM_BASE_XPND); --pfmBase )
|
|
;
|
|
|
|
|
|
pifiBase = pfmBase->pIFIMet;
|
|
|
|
pds = &dsmap[ pfm->jPermuteIndex ].ds;
|
|
|
|
/*
|
|
* The hard part is if we need to change the name of the font.
|
|
* This only happens when the font is to be made bold, OR if
|
|
* it is a fixed pitch font (and thus contains the pitch in the name).
|
|
*/
|
|
|
|
iSize = pifiBase->cjThis;
|
|
|
|
if( pds->face )
|
|
{
|
|
pwchAttrib = L" Bold";
|
|
/* 3 is # fields to amend */
|
|
iSize += 3 * wcslen( pwchAttrib ) * sizeof( WCHAR );
|
|
}
|
|
else
|
|
pwchAttrib = NULL;
|
|
|
|
|
|
if( pifiBase->flInfo & FM_INFO_CONSTANT_WIDTH )
|
|
{
|
|
/* We don't know the exact pitch yet, so assume the largest */
|
|
iSize += 2 * strlen( " XXX pitch" ) * sizeof( WCHAR );
|
|
}
|
|
|
|
pifiNew = (IFIMETRICS *)HeapAlloc( hheap, 0, iSize );
|
|
|
|
if( !pifiNew )
|
|
return FALSE;
|
|
|
|
pfm->fFlags &= ~FM_IFIRES; /* No longer a resource */
|
|
pfm->pIFIMet = pifiNew; /* Now accessable! */
|
|
|
|
*pifiNew = *pifiBase; /* Copy the data, amend as needed */
|
|
|
|
pifiNew->cjThis = iSize;
|
|
|
|
/*
|
|
* Can scale the IFIMETRICS using an existing function that already
|
|
* does this, although we need to fiddle to make this work.
|
|
*/
|
|
|
|
iXRes = pfm->wXRes;
|
|
iYRes = pfm->wYRes;
|
|
|
|
switch( pds->width )
|
|
{
|
|
case HALF_SIZE:
|
|
iXRes /= 2; /* Half size means the metrics shrink by 2 */
|
|
break;
|
|
|
|
case DOUBLE_SIZE:
|
|
iXRes *= 2; /* Double size -> metrics times 2 */
|
|
break;
|
|
}
|
|
|
|
|
|
switch( pds->height )
|
|
{
|
|
case HALF_SIZE:
|
|
iYRes /= 2;
|
|
break;
|
|
|
|
case DOUBLE_SIZE:
|
|
iYRes *= 2;
|
|
break;
|
|
}
|
|
|
|
if( pds->face )
|
|
{
|
|
/* Adjust the widths for being bold */
|
|
pifiNew->fwdAveCharWidth += pfm->jAddBold;
|
|
pifiNew->fwdMaxCharInc += pfm->jAddBold;
|
|
pifiNew->rclFontBox.right += pfm->jAddBold;
|
|
}
|
|
|
|
/* Adjust the IFIMETRICS for the scaling factors we just determined */
|
|
if( !bIFIScale( hheap, pfm, iXRes, iYRes ) )
|
|
{
|
|
HeapFree( hheap, 0, pifiNew );
|
|
pfm->pIFIMet = NULL;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if( pds->face )
|
|
{
|
|
/* A bold font, so add all the bold bits to the IFIMETRICS data */
|
|
pifiNew->usWinWeight = FW_BOLD; /* Set BOLD weight */
|
|
pifiNew->fsSelection |= FM_SEL_BOLD;
|
|
pifiNew->panose.bWeight = PAN_WEIGHT_BOLD;
|
|
}
|
|
|
|
|
|
awchPitch[ 0 ] = L'\0';
|
|
if( pifiBase->flInfo & FM_INFO_CONSTANT_WIDTH )
|
|
{
|
|
/* Fixed pitch font, SO generate the fixed pitch string now */
|
|
iDrvPrintfW( awchPitch, L" %d Pitch",
|
|
pfm->wXRes / pifiNew->fwdAveCharWidth );
|
|
}
|
|
|
|
/*
|
|
* Adjust the string data, as needed.
|
|
*/
|
|
|
|
pwchOld = (WCHAR *)((BYTE *)pifiBase + pifiBase->dpwszFamilyName);
|
|
pwchNew = (WCHAR *)(pifiNew + 1);
|
|
pifiNew->dpwszFamilyName = (BYTE *)pwchNew - (BYTE *)pifiNew;
|
|
|
|
/* Copy family name as is */
|
|
wcscpy( pwchNew, pwchOld ); /* No change */
|
|
pwchNew += wcslen( pwchNew ) + 1; /* How much we copied */
|
|
|
|
pwchOld = (WCHAR *)((BYTE *)pifiBase + pifiBase->dpwszFaceName);
|
|
|
|
pifiNew->dpwszFaceName = (BYTE *)pwchNew - (BYTE*)pifiNew;
|
|
|
|
/* Copy base face name, and append attributes as needed */
|
|
wcscpy( pwchNew, pwchOld ); /* Base face name */
|
|
if( pwchAttrib )
|
|
wcscat( pwchNew, pwchAttrib ); /* The attributes */
|
|
|
|
if( awchPitch[ 0 ] )
|
|
wcscat(pwchNew, awchPitch);
|
|
|
|
pwchOld = (WCHAR *)((BYTE *)pifiBase + pifiBase->dpwszUniqueName);
|
|
pwchNew += wcslen( pwchNew ) + 1;
|
|
pifiNew->dpwszUniqueName = (BYTE *)pwchNew - (BYTE *)pifiNew;
|
|
|
|
wcscpy( pwchNew, pwchOld );
|
|
if( pwchAttrib )
|
|
wcscat( pwchNew, pwchAttrib );
|
|
|
|
if( awchPitch[ 0 ] )
|
|
wcscat( pwchNew, awchPitch );
|
|
|
|
/* Finally, simply the Attributes field */
|
|
pwchNew += wcslen( pwchNew ) + 1;
|
|
pwchOld = (WCHAR *)((BYTE *)pifiBase + pifiBase->dpwszStyleName);
|
|
pifiNew->dpwszStyleName = (BYTE *)pwchNew - (BYTE *)pifiNew;
|
|
|
|
wcscpy( pwchNew, pwchOld );
|
|
if( pwchAttrib )
|
|
wcscat( pwchNew, pwchAttrib );
|
|
|
|
#if DBG
|
|
if( ((BYTE *)(pwchNew + wcslen( pwchNew )) - (BYTE *)pifiNew) >
|
|
(int)pifiNew->cjThis )
|
|
{
|
|
DbgPrint( "rasdd!bDJExpandFont overwrites IFIMETRICS area\n" );
|
|
|
|
HeapFree( hheap, 0, (LPSTR)pifiNew );
|
|
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
if( pwchAttrib )
|
|
{
|
|
/* A BOLD font, so turn on the bold bits */
|
|
pifiNew->fsSelection |= FM_SEL_BOLD;
|
|
pifiNew->panose.bWeight = PAN_WEIGHT_BOLD;
|
|
}
|
|
|
|
/*
|
|
* The width data also needs modifying, PERHAPS. This must happen
|
|
* if any of the following is true:
|
|
* double width font
|
|
* half width font
|
|
* bold version
|
|
* AND
|
|
* proportionally spaced font.
|
|
*/
|
|
|
|
if( !(pifiBase->flInfo & FM_INFO_CONSTANT_WIDTH) )
|
|
{
|
|
/* Is a candidate, so check the other conditions. */
|
|
if( pds->face != NORMAL_FACE || pds->width != NORMAL_SIZE )
|
|
{
|
|
/* Needs fiddling! */
|
|
if( pfmBase->psWidth )
|
|
{
|
|
int cbWidth; /* Bytes needed for width table */
|
|
|
|
cbWidth = sizeof( short ) *
|
|
(pifiBase->chLastChar - pifiBase->chFirstChar + 1);
|
|
|
|
pfm->psWidth = (short *)HeapAlloc( hheap, 0, cbWidth );
|
|
|
|
if( !pfm->psWidth )
|
|
{
|
|
HeapFree( hheap, 0, pifiNew );
|
|
pfm->pIFIMet = NULL;
|
|
|
|
return FALSE;
|
|
}
|
|
cbWidth /= 2; /* Number of iterations */
|
|
|
|
while( --cbWidth >= 0 )
|
|
{
|
|
pfm->psWidth[ cbWidth ] =
|
|
MulDiv( pfmBase->psWidth[ cbWidth ] + pfm->jAddBold,
|
|
iXRes, pfm->wXRes );
|
|
}
|
|
|
|
/* SPECIAL CASE: the BOLD space char width does not change */
|
|
if( pifiBase->chFirstChar <= ' ' )
|
|
{
|
|
cbWidth = ' ' - pifiBase->chFirstChar;
|
|
|
|
pfm->psWidth[ cbWidth ] =
|
|
MulDiv( pfmBase->psWidth[ cbWidth ],
|
|
iXRes, pfm->wXRes );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
DbgPrint( "rasdd!bDJExpandIFI: pfmBase->psWidth == 0 for proportional font\n" );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#if PRINT_INFO1
|
|
#if 0
|
|
pwch = (WCHAR *)((BYTE *)pifiNew + pifiNew->dpwszFaceName);
|
|
//DbgPrint("\nRasdd!bDJExpandIFI:Expanding font,Name is %ws\n",pwch);
|
|
if ( pwch[0] == L'C' && pwch[1] == L'G')
|
|
{
|
|
DbgPrint("\nRasdd!bDJExpandIFI:Dumping Font IFIMETRICS\n");
|
|
DbgPrint(" Face Name is %ws\n", (BYTE *)pifiNew + pifiNew->dpwszFaceName );
|
|
DbgPrint(" Unique Name is %ws\n", (BYTE *)pifiNew + pifiNew->dpwszUniqueName );
|
|
DbgPrint(" usWinWeight %d\n" , pifiNew->usWinWeight );
|
|
DbgPrint(" fwdWinAscender %d\n" , pifiNew->fwdWinAscender );
|
|
DbgPrint(" fwdWinDescender %d\n" , pifiNew->fwdWinDescender );
|
|
DbgPrint(" PointSize in Device units is %d\n"
|
|
, (pifiNew->fwdWinDescender + pifiNew->fwdWinAscender));
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#if PRINT_INFO
|
|
switch( _dj_print )
|
|
{
|
|
case 1:
|
|
DbgPrint( " %ws\n", (BYTE *)pifiNew + pifiNew->dpwszUniqueName );
|
|
break;
|
|
|
|
case 2:
|
|
vPrintIFIMETRICS( pifiNew, (VPRINT)DbgPrint );
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
//-----------------------------*ReadNum*-------------------------------------
|
|
// Action: read an integer from the given file.
|
|
// Adapted from the HP/PCL soft font installer.
|
|
//
|
|
// Return: the next character following the integer.
|
|
//----------------------------------------------------------------------------
|
|
|
|
BYTE NEAR PASCAL ReadNum(hFile, lpNum)
|
|
int hFile;
|
|
LPINT lpNum;
|
|
{
|
|
BYTE ch;
|
|
|
|
*lpNum = 0;
|
|
|
|
// DBCS Alert!!! this piece of code may need to be changed. It seems
|
|
// that we have to read from the file one byte at a time so we don't
|
|
// advance the file pointer too much.
|
|
|
|
while (_lread(hFile,(LPSTR)&ch,1) > 0 && ch >= '0' && ch <= '9')
|
|
{
|
|
*lpNum *= 10;
|
|
*lpNum += (int)ch - (int)'0';
|
|
}
|
|
|
|
if (*lpNum == 0)
|
|
ch = '\0';
|
|
|
|
return (ch);
|
|
}
|
|
|
|
//------------------------*DJ_GetPermInfo*-----------------------------------
|
|
// Action: extract permutation options and the other information (italic?
|
|
// symbol set, typeface) from the DeskJet family soft font download
|
|
// file.
|
|
// Return: the permutation flags.
|
|
//----------------------------------------------------------------------------
|
|
|
|
WORD NEAR PASCAL DJ_GetPermInfo(hDLFile, lpEsc)
|
|
int hDLFile; // handle to the download file
|
|
LPSTR lpEsc; // return: partial selection escape (prefix)
|
|
{
|
|
WORD wPermFlags = 0;
|
|
char esc, tmpc, ch;
|
|
int num, rem, length;
|
|
long lnum;
|
|
char buf[MAX_HEADER];
|
|
LPFD lpfd;
|
|
char tmpbuf[7];
|
|
LPSTR lptmpbuf;
|
|
int i;
|
|
|
|
// DBCS Alert!!! this piece of code may need to be changed. It seems
|
|
// that we have to read from the file one byte at a time so we don't
|
|
// advance the file pointer too much.
|
|
|
|
// search for the font descriptor escape sequence.
|
|
while (_lread(hDLFile, (LPSTR)&esc, 1) > 0)
|
|
if (esc == '\033' &&
|
|
_lread(hDLFile, (LPSTR)&ch, 1) > 0 && ch == ')' &&
|
|
_lread(hDLFile, (LPSTR)&tmpc, 1) > 0 && tmpc == 's' &&
|
|
(tmpc = ReadNum(hDLFile, (LPINT)&num)) && tmpc == 'W')
|
|
{
|
|
// found the escape for defining a font header.
|
|
_lread(hDLFile, (LPSTR)buf, (num > MAX_HEADER ? MAX_HEADER : num));
|
|
lpfd = (LPFD)buf;
|
|
|
|
// Setup the algorithmic flags for use in algFonts
|
|
if (!lpfd->no_half_pitch)
|
|
wPermFlags |= HALF_PITCH;
|
|
if (!lpfd->no_double_pitch)
|
|
wPermFlags |= DOUBLE_PITCH;
|
|
if (!lpfd->no_half_height)
|
|
wPermFlags |= HALF_HEIGHT;
|
|
if (!lpfd->no_bold)
|
|
wPermFlags |= MAKE_BOLD;
|
|
// set up enboldening width change
|
|
if (lpfd->bold_method)
|
|
wPermFlags |= (BASE_BOLD_ADD_2 | HALF_BOLD_ADD_2);
|
|
else
|
|
wPermFlags |= (BASE_BOLD_ADD_1 | HALF_BOLD_ADD_1);
|
|
|
|
// construct the font selection prefix including: the symbol
|
|
// set, italic, and typeface. Ex. "\033(8U\0330s4t"
|
|
i = 0;
|
|
lpEsc[i++] = '\033';
|
|
lpEsc[i++] = '(';
|
|
switch (swab(lpfd->symbol_set))
|
|
{
|
|
case (0*32)+'N'-64: /* ECMA-94 */
|
|
case 529: /* DeskJet8 */
|
|
lpEsc[i++] = '0';
|
|
lpEsc[i++] = 'N';
|
|
break;
|
|
default:
|
|
/* compute escape sequence value field. See PCL
|
|
* Implementor's Guide for formula.
|
|
*/
|
|
num = swab(lpfd->symbol_set) / 32;
|
|
lptmpbuf = tmpbuf;
|
|
length = _itoa(lptmpbuf, num);
|
|
switch (length)
|
|
{
|
|
case 1:
|
|
lpEsc[i++] = ' ';
|
|
lpEsc[i++] = tmpbuf[0];
|
|
break;
|
|
case 2:
|
|
lpEsc[i++] = tmpbuf[0];
|
|
lpEsc[i++] = tmpbuf[1];
|
|
break;
|
|
default:
|
|
/* This should never happen, the escape sequence value
|
|
* field should never be greater than 2 digits.
|
|
* Default to ECMA-94
|
|
*/
|
|
lpEsc[i++] = '0';
|
|
break;
|
|
}
|
|
// Compute the escape sequence termination character
|
|
rem = swab(lpfd->symbol_set) % 32;
|
|
if (length > 2)
|
|
lpEsc[i++] = 'N';
|
|
else
|
|
lpEsc[i++] = (char)(64 + rem);
|
|
break;
|
|
} // switch ...
|
|
|
|
// append italic attribute etc.
|
|
lpEsc[i++] = '\033';
|
|
lpEsc[i++] = '(';
|
|
lpEsc[i++] = 's';
|
|
lpEsc[i++] = lpfd->style == 1 ? '1': '0';
|
|
lpEsc[i++] = 's';
|
|
|
|
// determine typeface.
|
|
i += _itoa((LPSTR)&lpEsc[i], (int)lpfd->typeface);
|
|
lpEsc[i++] = 't';
|
|
lpEsc[i] = '\0';
|
|
|
|
// jump out of the while loop.
|
|
break;
|
|
} // if esc == '\033'...
|
|
|
|
return wPermFlags;
|
|
}
|
|
|
|
//--------------------------------*ConvertFontSizeToStr*------------------------
|
|
// Action: Convert the given font size, pitch or point size which has been
|
|
// multiplied by 100, into the corresponding ASCII string and insert
|
|
// the decimal point in the string if needed. There should be no
|
|
// trailing zeros. If the fractional part is zero, do not insert
|
|
// the decimal point either. For example: 1000 ==> "10",
|
|
// 950 ==> "9.5", and 475 ==> "4.75".
|
|
// Return the length of the final string (not counting the null terminator).
|
|
//-----------------------------------------------------------------------------
|
|
|
|
short FAR PASCAL ConvertFontSizeToStr(size, lpStr)
|
|
short size;
|
|
LPSTR lpStr;
|
|
{
|
|
short count;
|
|
|
|
if (size % 100 == 0)
|
|
count = _itoa(lpStr, size / 100);
|
|
else if (size % 10 == 0)
|
|
{
|
|
count = _itoa(lpStr, size / 10);
|
|
lpStr[count] = lpStr[count - 1];
|
|
lpStr[count - 1] = '.';
|
|
lpStr[++count] = '\0';
|
|
}
|
|
else
|
|
{
|
|
count = _itoa(lpStr, size);
|
|
lpStr[count] = lpStr[count - 1];
|
|
lpStr[count - 1] = lpStr[count - 2];
|
|
lpStr[count - 2] = '.';
|
|
lpStr[++count] = '\0';
|
|
}
|
|
return count;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#if PRINT_INFO
|
|
#include "debugifi.c"
|
|
#endif
|