Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1854 lines
50 KiB

/*++
Copyright (c) 1996 - 1999 Microsoft Corporation
Module Name:
newfont.c
Abstract:
Implementation of the functions to use new font format.
Environment:
Windows NT Unidrv driver
Revision History:
02/21/97 -eigos-
Support Double byte font
01/24/97 -eigos-
Filled in functionality
01/14/97 -ganeshp-
Created
--*/
#include "font.h"
//
//
//
const BYTE aubAnsi[256] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
//
// Macro definition
//
#define DW_MASK (DWBITS - 1)
//
// Internal function prototype
//
BOOL
BExtractGTT(
PUNI_GLYPHSETDATA pGTT,
WCHAR wchFirst,
WCHAR wchLast,
FD_GLYPHSET *pFD_GLYPHSET,
PDWORD pdwFD_GLYPHSETSize);
BOOL
BExtractGTTwithPredefGTT(
IN PUNI_GLYPHSETDATA pPreDefGTT,
IN PUNI_GLYPHSETDATA pMiniDefGTT,
IN WCHAR wchFirst,
IN WCHAR wchLast,
OUT FD_GLYPHSET **ppFD_GLYPHSET,
OUT PMAPTABLE *pMapTable,
IN PDWORD pdwFD_GLYPHSETSize);
SHORT
SGetWidth(
PWIDTHTABLE pWidthTable,
HGLYPH hg);
BYTE ubGetAnsi(
WCHAR,
INT,
PWCHAR,
PBYTE);
DWORD
DwCheckTrans(
PGLYPHRUN pMiniGlyphRun,
PMAPTABLE pMiniMapTable,
DWORD dwMiniGlyphRunCount,
WORD wUnicode);
WCHAR
WchGetNextUnicode(
PWCHAR pwchUnicode,
PDWORD pdwUnicodeBits,
INT iNumOfHandle);
int __cdecl Comp(const void *elem1, const void *elem2);
//
//
// Functions
//
//
VOID*
PVGetUCFD_GLYPHSET(
PDEV *pPDev,
FONTMAP *pFM
)
/*++
Routine Description:
Arguments:
pPDev Pointer to PDEV
Return Value:
TRUE for success and FALSE for failure
Note:
01/14/97 -ganeshp-
Created it.
--*/
{
PFONTMAP_DEV pFMDev;
PVOID pvFD_GLYPHSET = NULL;
DWORD dwFD_GLYPHSETSize;
//
// Paremeter validation
//
ASSERT(pFM != NULL);
pFMDev = pFM->pSubFM;
pvFD_GLYPHSET = NULL;
if (pFMDev->pvNTGlyph)
{
#if ENABLE_GTT_COMBINE
RES_ELEM ResElem;
if (((PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph)->lPredefinedID !=
CC_NOPRECNV)
{
if (BGetWinRes( &(pPDev->WinResData),
((PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph)->lPredefinedID,
RC_GTT,
&ResElem))
{
pFMDev->pvPredefGTT = ResElem.pvResData;
BExtractGTTwithPredefGTT(pFMDev->pvPredefGTT,
pFMDev->pvNTGlyph,
pFM->wFirstChar,
pFM->wLastChar,
pvFD_GLYPHSET,
(PMAPTABLE*)&pFMDev->pvMapTable,
&dwFD_GLYPHSETSize);
}
else
{
pFMDev->pvPredefGTT = NULL;
ERR(("UniFont!PVGetUCFD_GLYPHSET: pvNTGTT is no loaded.\n"));
}
}
#endif
//
// First, try to get Far East Stock FD_GLYPHSET.
//
#if ENABLE_STOCKGLYPHSET
if (!BGetStockGlyphset( pPDev, &pvFD_GLYPHSET, (SHORT)pFMDev->sCTTid))
{
if (!BExtractGTT((PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph,
pFM->wFirstChar,
pFM->wLastChar,
(FD_GLYPHSET*)NULL,
(PDWORD)&dwFD_GLYPHSETSize) ||
!(pvFD_GLYPHSET = MemAlloc(dwFD_GLYPHSETSize)) ||
!BExtractGTT((PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph,
pFM->wFirstChar,
pFM->wLastChar,
(FD_GLYPHSET*)pvFD_GLYPHSET,
(PDWORD)&dwFD_GLYPHSETSize))
{
if (pvFD_GLYPHSET)
{
MemFree(pvFD_GLYPHSET);
pvFD_GLYPHSET = NULL;
ERR(("UniFont!PVGetUCFD_GLYPHSET failed\n"));
}
}
}
#else
if (!BExtractGTT((PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph,
pFM->wFirstChar,
pFM->wLastChar,
(FD_GLYPHSET*)NULL,
(PDWORD)&dwFD_GLYPHSETSize) ||
!(pvFD_GLYPHSET = MemAlloc(dwFD_GLYPHSETSize)) ||
!BExtractGTT((PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph,
pFM->wFirstChar,
pFM->wLastChar,
(FD_GLYPHSET*)pvFD_GLYPHSET,
(PDWORD)&dwFD_GLYPHSETSize))
{
if (pvFD_GLYPHSET)
{
MemFree(pvFD_GLYPHSET);
pvFD_GLYPHSET = NULL;
ERR(("UniFont!PVGetUCFD_GLYPHSET failed\n"));
}
}
#endif
}
else
{
ERR(("UniFont!PVGetUCFD_GLYPHSET: pvNTGTT is no loaded.\n"));
}
pFMDev->pUCTree = pvFD_GLYPHSET;
return pvFD_GLYPHSET;
}
VOID *
PVUCKernPair(
PDEV *pPDev,
FONTMAP *pFM
)
/*++
Routine Description:
Arguments:
pPDev Pointer to PDEV
Return Value:
TRUE for success and FALSE for failure
Note:
01/14/97 -ganeshp-
Created it.
--*/
{
PFONTMAP_DEV pFMDev;
PKERNDATA pKerningData;
PUNIFM_HDR pUFM;
PVOID pvKernPair = NULL;
//
// Paremeter validation
//
ASSERT(pFM != NULL);
pFMDev = pFM->pSubFM;
pUFM = pFMDev->pvFontRes;
if (pFM->flFlags & FM_KERNRES)
{
pvKernPair = pFMDev->pUCKernTree;
}
else
if (pUFM && pUFM->loKernPair)
{
pKerningData = GET_KERNDATA(pUFM);
pFMDev->pUCKernTree = pKerningData->KernPair;
pFM->flFlags |= FM_KERNRES;
}
return pvKernPair;
}
BOOL
BGetNewFontInfo(
FONTMAP *pFM,
BYTE *pRes)
/*++
Routine Description:
Arguments:
pfm Pointer to FONTMAP
pRes Pointer to UFM resource
Return Value:
TRUE for success and FALSE for failure
Note:
01/14/97 -ganeshp-
Created it.
--*/
{
PUNIFM_HDR pUFM;
PUNIDRVINFO pUnidrvInfo;
PIFIMETRICS pIFI;
PKERNDATA pKerningData;
PFONTMAP_DEV pFMDev;
//
// Paremeter validation
//
ASSERT(pFM != NULL || pRes != NULL);
//
// Get UFM data
//
pFMDev = pFM->pSubFM;
pFMDev->pvFontRes = pRes;
pUFM = (PUNIFM_HDR)pRes;
if (pUFM == NULL ||
pUFM->loIFIMetrics == 0)
{
ERR(("UniFont!BGetNewFontInfo failed: Invalid FONTMAP.pUFMFontRes\n"));
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
//
// Get data pointer of UFM
//
pUnidrvInfo = GET_UNIDRVINFO(pUFM);
//
// Fill out FONTMAP members
//
if (0 != pUFM->loIFIMetrics % sizeof(PVOID))
{
DWORD dwSize;
pIFI = GET_IFIMETRICS(pUFM);
if (NULL == pIFI)
{
return FALSE;
}
dwSize = ((IFIMETRICS UNALIGNED *)(pIFI))->cjThis;
if (pFM->pIFIMet = MemAlloc(dwSize))
{
CopyMemory(pFM->pIFIMet, pIFI, dwSize);
pIFI = pFM->pIFIMet;
pFM->flFlags &= ~FM_IFIRES;
}
else
return FALSE;
}
else
{
pIFI = GET_IFIMETRICS(pUFM);
pFM->pIFIMet = pIFI;
pFM->flFlags = FM_IFIRES;
}
if (pUnidrvInfo->SelectFont.dwCount && pUnidrvInfo->SelectFont.loOffset)
{
pFMDev->cmdFontSel.FInv.dwCount =
pUnidrvInfo->SelectFont.dwCount;
pFMDev->cmdFontSel.FInv.pubCommand =
GET_SELECT_CMD(pUnidrvInfo);
pFM->flFlags |= FM_FINVOC | FM_FONTCMD;
}
if (pUnidrvInfo->UnSelectFont.dwCount && pUnidrvInfo->UnSelectFont.loOffset)
{
pFMDev->cmdFontDesel.FInv.dwCount =
pUnidrvInfo->UnSelectFont.dwCount;
pFMDev->cmdFontDesel.FInv.pubCommand =
GET_UNSELECT_CMD(pUnidrvInfo);
pFM->flFlags |= FM_FINVOC | FM_FONTCMD;
}
if (pUFM->loExtTextMetric)
{
pFMDev->pETM = GET_EXTTEXTMETRIC(pUFM);
}
if (pUFM->loWidthTable)
{
pFMDev->W.pWidthTable = GET_WIDTHTABLE(pUFM);
pFM->flFlags |= FM_WIDTHRES;
}
if (pUFM->loKernPair)
{
pKerningData = GET_KERNDATA(pUFM);
pFMDev->pUCKernTree = pKerningData->KernPair;
pFM->flFlags |= FM_KERNRES;
}
pFMDev->wDevFontType = pUnidrvInfo->wType;
pFMDev->ulCodepage = pUFM->ulDefaultCodepage;
pFM->wFirstChar = pIFI->wcFirstChar;
pFM->wLastChar = pIFI->wcLastChar;
pFM->wXRes = pUnidrvInfo->wXRes;
pFM->wYRes = pUnidrvInfo->wYRes;
pFMDev->sYAdjust = pUnidrvInfo->sYAdjust;
pFMDev->sYMoved = pUnidrvInfo->sYMoved;
pFMDev->sCTTid = (SHORT)pUFM->lGlyphSetDataRCID;
pFMDev->fCaps = pUnidrvInfo->fCaps;
return TRUE;
}
INT
IGetUFMGlyphWidth(
PDEV *pPDev,
FONTMAP *pFM,
HGLYPH hg
)
/*++
Routine Description:
Arguments:
pFM Pointer to FONTMAP
Return Value:
Width
Note:
01/14/97 -ganeshp-
Created it.
--*/
{
return IGetUFMGlyphWidthJr(&(pPDev->ptGrxRes), pFM, hg);
}
INT
IGetUFMGlyphWidthJr(
POINT *pptGrxRes,
FONTMAP *pFM,
HGLYPH hg
)
/*++
Routine Description:
Arguments:
pFM Pointer to FONTMAP
Return Value:
Width
Note:
01/14/97 -ganeshp-
Created it.
--*/
{
TRANSDATA *pTrans;
MAPTABLE *pMapTable;
FONTMAP_DEV *pFMDev;
INT iGlyphWidth;
//
// UNIDRV returns 1 for the first glyph handle in FD_GLYPHSET.
// However, GDI could pass zero in hg.
// We need to handle this GDI error properly.
//
if (NULL == pFM || NULL == pptGrxRes || 0 == hg)
{
return 0;
}
pFMDev = pFM->pSubFM;
if ((pFM->flFlags & FM_WIDTHRES) &&
(iGlyphWidth = SGetWidth(pFMDev->W.pWidthTable, hg)))
{
iGlyphWidth = iGlyphWidth * pptGrxRes->x / pFM->wXRes;
}
else
{
pMapTable = GET_MAPTABLE(pFMDev->pvNTGlyph);
pTrans = pMapTable->Trans;
if (IS_DBCSCHARSET(((IFIMETRICS*)pFM->pIFIMet)->jWinCharSet))
{
if (pTrans[hg - 1].ubType & MTYPE_DOUBLE)
{
iGlyphWidth = (INT)((PIFIMETRICS)pFM->pIFIMet)->fwdMaxCharInc;
//VERBOSE(("(2)MTYPE_DOUBLE:Char=0x%x%x, ",
// pTrans[hg-1].uCode.ubPairs[0],
// pTrans[hg-1].uCode.ubPairs[1]));
}
else
{
iGlyphWidth = (INT)((PIFIMETRICS)pFM->pIFIMet)->fwdAveCharWidth;
//VERBOSE(("(2)MTYPE_SINGLE:Char=%d, ",
// pTrans[hg-1].uCode.ubCode));
}
}
else
{
iGlyphWidth = (INT)((PIFIMETRICS)pFM->pIFIMet)->fwdMaxCharInc;
}
}
//VERBOSE(("Width=%d\n",iGlyphWidth));
return iGlyphWidth;
}
BOOL
BGTTOutputGlyph(
TO_DATA *pTod)
/*++
Routine Description:
Same as BRLEOutputGlyph in textout.c. Should use GTT data instead of
RLE.
Arguments:
pTod - a pointer to TEXTOUT DATA (TO_DATA) structure
Return Value:
TRUE for success and FALSE for failure
Note:
02/14/97 -eigos-
Created it.
--*/
{
FONTPDEV *pFontPDev;
IFIMETRICS *pIFIMetrics;
PUNI_GLYPHSETDATA pGlyphSetData;
PUNI_CODEPAGEINFO pCodePageInfo;
PMAPTABLE pMapTable;
COMMAND *pCmd;
PTRANSDATA pTrans;
PFONTMAP_DEV pFMDev;
PDEV *pPDev;
HGLYPH hg;
FONTMAP *pFM;
PGLYPHPOS pgp;
POINTL ptlRem;
PBYTE pString;
DWORD dwSize, cGlyphs;
INT iX, iY, iXInc, iYInc;
BOOL bRet;
BOOL bSetCursorForEachGlyph;
pPDev = pTod->pPDev;
pFontPDev = pPDev->pFontPDev;
pFM = pTod->pfm;
pIFIMetrics = (IFIMETRICS*)pFM->pIFIMet;
pFMDev = pFM->pSubFM;
pGlyphSetData = (PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph;
cGlyphs = pTod->cGlyphsToPrint;
pgp = pTod->pgp;
bSetCursorForEachGlyph = SET_CURSOR_FOR_EACH_GLYPH(pTod->flAccel);
if (!bSetCursorForEachGlyph ||
pFontPDev->flFlags & FDV_DISABLE_POS_OPTIMIZE)
{
//
// If bSetCursorForEachGlyph is not set, send the first character's
// position.
//
// FDV_DISABLE_POS_OPTIMIZE
// If there is rounding error, when scaling width,
// disable x position optimization
//
VSetCursor( pPDev, pgp->ptl.x, pgp->ptl.y, MOVE_ABSOLUTE, &ptlRem);
}
pTod->flFlags |= TODFL_FIRST_GLYPH_POS_SET;
//
// 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!
//
// DCR - should reorganise the move command code to do a better
// job here. Problem is that if we are rotating the bitmap, then MV_FINE
// is NOT a good idea, since it almost undoubtedly move the cursor in
// the WRONG dimension! When we are rotating the bitmap, it is most
// probable that the MV_FINE will move in the Y direction!!!
//
bRet = TRUE;
iX = iY = 0;
if (pGlyphSetData != NULL)
{
while (cGlyphs --)
{
//
// Do nothing. GDI could pass ZERO HGLYPH.
// GTT glyph handle starts from 1. GDI is not supposed to pass 0 in
// HGLYPH.
//
if (0 == pgp->hg)
continue;
hg = pgp->hg;
iX = pgp->ptl.x;
iY = pgp->ptl.y;
//
// Move to the next character's position
//
if (bSetCursorForEachGlyph)
VSetCursor( pPDev, iX, iY, MOVE_ABSOLUTE, &ptlRem);
//
// Minidriver defined glyph conversion
//
pMapTable = GET_MAPTABLE((PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph);
pTrans = pMapTable->Trans;
//
// Send symbol set selection command
//
if ( pFMDev->ulCodepageID != pTrans[hg - 1].ubCodePageID )
{
if (pFMDev->ulCodepageID != -1)
{
pCodePageInfo = GET_CODEPAGEINFO((PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph);
pCodePageInfo += pFMDev->ulCodepageID;
pString = (PBYTE)pCodePageInfo +
pCodePageInfo->UnSelectSymbolSet.loOffset;
dwSize = pCodePageInfo->UnSelectSymbolSet.dwCount;
if (dwSize)
{
WriteSpoolBuf(pPDev, pString, dwSize);
}
}
pFMDev->ulCodepageID = pTrans[hg - 1].ubCodePageID;
pCodePageInfo = GET_CODEPAGEINFO((PUNI_GLYPHSETDATA)pFMDev->pvNTGlyph);
pCodePageInfo += pFMDev->ulCodepageID;
pString = (PBYTE)pCodePageInfo +
pCodePageInfo->SelectSymbolSet.loOffset;
dwSize = pCodePageInfo->SelectSymbolSet.dwCount;
if (dwSize)
{
WriteSpoolBuf(pPDev, pString, dwSize);
}
}
//
// Single/Double byte mode switch
//
if ((pTrans[hg - 1].ubType & MTYPE_SINGLE) &&
!(pFontPDev->flFlags & FDV_SINGLE_BYTE) )
{
if(pCmd = COMMANDPTR(pPDev->pDriverInfo, CMD_SELECTSINGLEBYTEMODE))
{
pFontPDev->flFlags &= ~FDV_DOUBLE_BYTE;
pFontPDev->flFlags |= FDV_SINGLE_BYTE;
WriteChannel( pPDev, pCmd );
}
else
pFontPDev->flFlags |= FDV_SINGLE_BYTE;
}
else
if ((pTrans[hg - 1].ubType & MTYPE_DOUBLE) &&
!(pFontPDev->flFlags & FDV_DOUBLE_BYTE) )
{
if (pCmd = COMMANDPTR(pPDev->pDriverInfo, CMD_SELECTDOUBLEBYTEMODE))
{
pFontPDev->flFlags |= FDV_DOUBLE_BYTE;
pFontPDev->flFlags &= ~FDV_SINGLE_BYTE;
WriteChannel( pPDev, pCmd );
}
else
pFontPDev->flFlags |= FDV_DOUBLE_BYTE;
}
//
// Send string
//
switch(MTYPE_FORMAT_MASK & pTrans[hg - 1].ubType)
{
case MTYPE_DIRECT:
bRet = WriteSpoolBuf(pPDev, &(pTrans[hg - 1].uCode.ubCode), 1) == 1;
break;
case MTYPE_PAIRED:
//
// First, try to use cursor push/pop escapes to
// overlay the 2 characters. If they are not
// available, try the backspace. If it doesn't exist
// either, ignore the second character.
//
pCmd = COMMANDPTR(pPDev->pDriverInfo, CMD_PUSHCURSOR);
pString = pTrans[hg - 1].uCode.ubPairs;
if (pTrans[hg - 1].ubType & (MTYPE_SINGLE|MTYPE_DOUBLE))
{
bRet = WriteSpoolBuf( pPDev, pString, 2 ) == 2;
}
else
{
if ( *(pString + 1) && (pCmd != NULL) )
{
//
// Pushed the position; output ch1, pop position, ch2
//
bRet = WriteSpoolBuf( pPDev, pString, 1 ) == 1;
WriteChannel( pPDev, pCmd );
bRet = WriteSpoolBuf( pPDev, pString + 1, 1 ) == 1;
}
else
{
pCmd = COMMANDPTR(pPDev->pDriverInfo, CMD_BACKSPACE);
bRet = WriteSpoolBuf( pPDev, pString, 1 ) == 1;
if( (*(pString + 1)) && (pFontPDev->flFlags & FDV_BKSP_OK) )
{
WriteChannel( pPDev, pCmd );
bRet = WriteSpoolBuf( pPDev, pString + 1, 1 ) == 1;
}
}
}
break;
case MTYPE_COMPOSE:
pString = (PBYTE)pMapTable + pTrans[hg - 1].uCode.sCode;
bRet = (WriteSpoolBuf(pPDev, pString + 2, *(WORD UNALIGNED *)pString) ==
*(WORD UNALIGNED *)pString);
break;
}
pgp++;
//
// After drawing the character, in the printer, the cursor position
// moves. Update the UNIDRV internal value to reduce the amount of
// command to send.
//
if (bSetCursorForEachGlyph)
{
if( pFM->flFlags & FM_WIDTHRES)
{
if ((iXInc = SGetWidth(pFMDev->W.pWidthTable, hg)))
iXInc = iXInc * pPDev->ptGrxRes.x / pFM->wXRes;
else
iXInc = pIFIMetrics->fwdAveCharWidth;
}
else
{
if (pTrans[hg - 1].ubType & MTYPE_DOUBLE)
iXInc = pIFIMetrics->fwdMaxCharInc;
else
iXInc = pIFIMetrics->fwdAveCharWidth;
}
if (pFM->flFlags & FM_SCALABLE)
{
iXInc = LMulFloatLong(&pFontPDev->ctl.eXScale,iXInc);
}
if (pTod->flAccel & SO_VERTICAL)
{
iYInc = iXInc;
iXInc = 0;
}
else
{
iYInc = 0;
}
VSetCursor( pPDev,
iXInc,
iYInc,
MOVE_RELATIVE|MOVE_UPDATE,
&ptlRem);
}
}
}
else
{
bRet = FALSE;
}
if (bRet && pFM)
{
if (!bSetCursorForEachGlyph)
{
//
// Output may have successed, so update the position.
//
if (pFM->flFlags & FM_WIDTHRES)
{
if (!(iXInc = SGetWidth(pFMDev->W.pWidthTable, hg)))
iXInc = pIFIMetrics->fwdAveCharWidth;
}
else
{
if (pTrans[hg - 1].ubType & MTYPE_DOUBLE)
{
iXInc = pIFIMetrics->fwdMaxCharInc;
}
else
{
iXInc = pIFIMetrics->fwdAveCharWidth;
}
}
if (pFM->flFlags & FM_SCALABLE)
{
//
// Need to transform the value to current size
//
iXInc = LMulFloatLong(&pFontPDev->ctl.eXScale,iXInc);
}
if (pTod->flAccel & SO_VERTICAL)
{
iYInc = iXInc;
iXInc = 0;
}
else
{
iYInc = 0;
}
VSetCursor( pPDev,
(iX + iXInc) - pTod->pgp->ptl.x,
(iY + iYInc) - pTod->pgp->ptl.y,
MOVE_RELATIVE | MOVE_UPDATE,
&ptlRem);
}
}
else
{
bRet = FALSE;
}
return bRet;
}
BOOL
BGTTSelectFont(
PDEV *pPDev,
PFONTMAP pFM,
POINTL *pptl)
{
PFONTMAP_DEV pfmdev;
INT iCmdLength;
PBYTE pbCmd;
pfmdev = pFM->pSubFM;
if ((iCmdLength = (INT)pfmdev->cmdFontSel.FInv.dwCount) &&
(pbCmd = pfmdev->cmdFontSel.FInv.pubCommand))
{
pfmdev->pfnDevSelFont( pPDev, pbCmd, iCmdLength, pptl);
}
//
// Reset uLCodepageID to send codepage selection command.
//
pfmdev->ulCodepageID = (ULONG)-1;
((PFONTPDEV)pPDev->pFontPDev)->flFlags &= ~FDV_DOUBLE_BYTE | FDV_SINGLE_BYTE;
return TRUE;
}
BOOL
BGTTDeselectFont(
PDEV *pPDev,
PFONTMAP pFM)
{
PFONTMAP_DEV pfmdev;
INT iCmdLength;
PBYTE pbCmd;
pfmdev = pFM->pSubFM;
if ((iCmdLength = (INT)pfmdev->cmdFontDesel.FInv.dwCount) &&
(pbCmd = pfmdev->cmdFontDesel.FInv.pubCommand) &&
iCmdLength != WriteSpoolBuf( pPDev, pbCmd, iCmdLength) )
{
return FALSE;
}
return TRUE;
}
//
//
// Internal functions
//
//
BOOL
BExtractGTT(
PUNI_GLYPHSETDATA pGTT,
WCHAR wchFirst,
WCHAR wchLast,
FD_GLYPHSET *pFD_GLYPHSET,
PDWORD pdwFD_GLYPHSETSize)
/*++
Routine Description:
Create FD_GLYPHSET from GLYPHRUN in GTT.
Arguments:
pGTT - GTT file resource
pFD_GLYPHSET - a buffer to be filled out
pdwFD_GLYPHSETSize - a pointer to the size of FD_GLYPHSET
Return Value:
TRUE for success and FALSE for failure
Note:
--*/
{
PGLYPHRUN pGlyphRun;
HGLYPH GlyphHandle, *pGlyphHandle;
DWORD dwI, dwGlyphNum;
WORD wJ;
//
// parameter validation
//
ASSERT(pGTT != NULL);
if (pFD_GLYPHSET == NULL)
{
//
// pFD_GLYPHSET == NULL case
// return the necessary amount of memory
//
pGlyphRun = GET_GLYPHRUN(pGTT);
dwGlyphNum = 0;
for (dwI = 0; dwI < pGTT->dwRunCount; dwI ++, pGlyphRun ++)
{
dwGlyphNum += pGlyphRun->wGlyphCount;
}
*pdwFD_GLYPHSETSize = sizeof(FD_GLYPHSET) +
(pGTT->dwRunCount - 1) * sizeof(WCRUN) +
dwGlyphNum * sizeof(HGLYPH);
}
else
{
//
// pFD_GLYPHSET != NULL case
// Fill out pFD_GLYPHSET
//
pFD_GLYPHSET->cjThis = *pdwFD_GLYPHSETSize;
pFD_GLYPHSET->flAccel = 0;
pFD_GLYPHSET->cGlyphsSupported = 0;
pFD_GLYPHSET->cRuns = pGTT->dwRunCount;
pGlyphHandle = (HGLYPH*)( (PBYTE)pFD_GLYPHSET +
sizeof(FD_GLYPHSET) +
sizeof(WCRUN) * (pGTT->dwRunCount-1) );
pGlyphRun = GET_GLYPHRUN(pGTT);
dwGlyphNum = 0;
//
// IMPORTANT!!!: Glyph handle in FD_GLYPHSET starts from 1 for GTT.
//
GlyphHandle = 1;
for (dwI = 0; dwI < pGTT->dwRunCount; dwI ++, pGlyphRun ++)
{
dwGlyphNum += pGlyphRun->wGlyphCount;
pFD_GLYPHSET->awcrun[dwI].cGlyphs = pGlyphRun->wGlyphCount;
pFD_GLYPHSET->awcrun[dwI].wcLow = pGlyphRun->wcLow;
pFD_GLYPHSET->awcrun[dwI].phg = pGlyphHandle;
for (wJ = 0; wJ < pGlyphRun->wGlyphCount; wJ ++,
pGlyphHandle ++,
GlyphHandle ++)
{
*pGlyphHandle = GlyphHandle;
}
}
pFD_GLYPHSET->cGlyphsSupported = dwGlyphNum;
}
return TRUE;
}
SHORT
SGetWidth(
PWIDTHTABLE pWidthTable,
HGLYPH hg)
{
// Because of a problem in at least one very common font resource DLL (HPCFONT.DLL)
// already out and about, it's safer and easier to access this table in an unaligned
// memory location than to try move it to align it.
PWIDTHRUN pWidthRun = pWidthTable->WidthRun;
SHORT UNALIGNED *psWidth;
DWORD dwRunCount = 0;
while ( ( hg < (ULONG)(*((SHORT UNALIGNED *)&(pWidthRun->wStartGlyph)) ) ||
(ULONG)( *((SHORT UNALIGNED *)&(pWidthRun->wStartGlyph)) )
+ ( *((SHORT UNALIGNED *)&(pWidthRun->wGlyphCount)) ) <= hg ) &&
dwRunCount < ( *((DWORD UNALIGNED *)&(pWidthTable->dwRunNum)) ) )
{
pWidthRun ++;
dwRunCount ++;
}
if (dwRunCount == ( *((SHORT UNALIGNED *)&(pWidthTable->dwRunNum)) ))
{
return 0;
}
else
{
DWORD dwOffset = *( (DWORD UNALIGNED *) (&(pWidthRun->loCharWidthOffset)) );
psWidth = ((SHORT UNALIGNED *)( (PBYTE)pWidthTable + dwOffset ));
return psWidth[hg - ( *((SHORT UNALIGNED *)&(pWidthRun->wStartGlyph)) )];
}
}
PUNI_GLYPHSETDATA
PNTGTT1To1(
IN DWORD dwCodePage,
IN BOOL bSymbolCharSet,
IN INT iFirstChar,
IN INT iLastChar)
/*++
Routine Description:
Generates a simple mapping format for the GTT stuff. This is
typically used for a printer with a 1:1 mapping to the Windows
character set.
Arguments:
iFirst: The lowest glyph in the range.
iLast: The last glyph in the range (inclusive)
Return Value:
Address of GTT structure allocated from heap; NULL on failure.
Note:
11-27-96: Created it -ganeshp-
--*/
{
PUNI_CODEPAGEINFO pCodePageInfo;
PGLYPHRUN pGlyphRun, pGlyphRunOrg;
TRANSDATA *pTrans;
PMAPTABLE pMapTable;
USHORT usAnsiCodePage, usOEMCodePage;
INT iNumOfHandle, iNumOfRuns, iTotalGlyphSetDataSize, iNumOfUnsupportChar;
INT iI, iJ, iK, iIndex;
WCHAR awchUnicode[256];
struct {
WORD wID;
WCHAR Unicode;
} UnicodeDst[256];
WCHAR wchChar, wchCurrent, wchTemp;
PBYTE pbBase;
ASSERT(iFirstChar == 0x20 && iLastChar == 0xFF);
iNumOfUnsupportChar = 0;
iNumOfHandle = iLastChar - iFirstChar + 1;
if (iNumOfHandle > 256)
{
ERR(("UniFont!NTGTT1To1 failed:iNumOfHandle > 256.\n"));
return NULL;
}
if (dwCodePage == 0)
{
dwCodePage = 1252;
}
#ifndef WINNT_40 // NT 5.0
if( -1 == (iNumOfHandle = EngMultiByteToWideChar(dwCodePage,
awchUnicode,
(INT)(iNumOfHandle * sizeof(WCHAR)),
(PCH)aubAnsi+iFirstChar,
(INT)iNumOfHandle)))
{
ERR(("UniFont!NTGTT1To1:EngMultiByteToWideChar failed\n"));
return NULL;
}
#else
EngMultiByteToUnicodeN(awchUnicode, iNumOfHandle * sizeof(WCHAR), NULL, (PBYTE)aubAnsi+iFirstChar, iNumOfHandle);
//
// Disable new symbol set character range on NT4 (F020 to F0FF)
//
bSymbolCharSet = FALSE;
#endif // WINNT_40
wchCurrent = 0;
iNumOfRuns = 0;
for (iI = 0; iI < iNumOfHandle; iI ++)
{
UnicodeDst[iI].wID = iI+iFirstChar;
UnicodeDst[iI].Unicode = awchUnicode[iI];
}
qsort(UnicodeDst, iNumOfHandle, sizeof(WCHAR)+sizeof(WORD), Comp);
for( iI = 0; iI < iNumOfHandle; iI ++ )
{
wchTemp = UnicodeDst[iI].Unicode;
if (wchTemp == EURO_CUR_SYMBOL || wchTemp == 0xFFFF)
{
iNumOfUnsupportChar ++;
UnicodeDst[iI].Unicode = 0;
continue;
}
else
if (wchTemp == wchCurrent + 1)
{
wchCurrent ++;
continue;
}
wchCurrent = wchTemp;
iNumOfRuns ++;
}
//
// Create GLYPHRUN
//
if (bSymbolCharSet)
{
iNumOfRuns ++;
}
if( !(pGlyphRunOrg = pGlyphRun =
(PGLYPHRUN)MemAlloc( iNumOfRuns * sizeof(GLYPHRUN) )) )
{
ERR(("UniFont!NTGTT1To1:MemAlloc failed\n"));
return NULL;
}
wchCurrent = 0;
for (iI = 0; iI < iNumOfHandle; iI ++)
{
wchTemp = UnicodeDst[iI].Unicode;
if (wchTemp == 0)
{
continue;
}
else
if (wchTemp == wchCurrent + 1)
{
pGlyphRun->wGlyphCount++;
wchCurrent ++;
}
else
{
if (wchCurrent != 0)
pGlyphRun ++;
wchCurrent =
pGlyphRun->wcLow = wchTemp;
pGlyphRun->wGlyphCount = 1;
}
}
if (bSymbolCharSet)
{
pGlyphRun++;
pGlyphRun->wcLow = SYMBOL_START;
pGlyphRun->wGlyphCount = NUM_OF_SYMBOL;
}
//
// Calculate total size of this file.
//
iNumOfHandle -= iNumOfUnsupportChar;
iTotalGlyphSetDataSize = sizeof(UNI_GLYPHSETDATA) +
sizeof(UNI_CODEPAGEINFO) +
iNumOfRuns * sizeof( GLYPHRUN ) +
sizeof(MAPTABLE) +
(iNumOfHandle - 1) * sizeof(TRANSDATA);
if (bSymbolCharSet)
{
iTotalGlyphSetDataSize += sizeof(TRANSDATA) * NUM_OF_SYMBOL;
}
//
// Allocate memory and set header, copy GLYPHRUN, CODEPAGEINFO
//
if( !(pbBase = MemAlloc( iTotalGlyphSetDataSize )) )
{
MemFree(pGlyphRunOrg);
return NULL;
}
((PUNI_GLYPHSETDATA)pbBase)->dwVersion = UNI_GLYPHSETDATA_VERSION_1_0;
((PUNI_GLYPHSETDATA)pbBase)->dwFlags = 0;
((PUNI_GLYPHSETDATA)pbBase)->lPredefinedID = CC_NOPRECNV;
((PUNI_GLYPHSETDATA)pbBase)->dwGlyphCount = 0;
((PUNI_GLYPHSETDATA)pbBase)->dwCodePageCount = 1;
((PUNI_GLYPHSETDATA)pbBase)->dwRunCount = iNumOfRuns;
((PUNI_GLYPHSETDATA)pbBase)->dwSize = iTotalGlyphSetDataSize;
((PUNI_GLYPHSETDATA)pbBase)->loRunOffset = sizeof(UNI_GLYPHSETDATA);
((PUNI_GLYPHSETDATA)pbBase)->loCodePageOffset =
sizeof(UNI_GLYPHSETDATA) +
sizeof(GLYPHRUN) * iNumOfRuns;
((PUNI_GLYPHSETDATA)pbBase)->loMapTableOffset =
sizeof(UNI_GLYPHSETDATA) +
sizeof(GLYPHRUN) * iNumOfRuns +
sizeof(UNI_CODEPAGEINFO);
CopyMemory(pbBase + sizeof(UNI_GLYPHSETDATA),
pGlyphRunOrg,
sizeof(GLYPHRUN) * iNumOfRuns);
//
// CodePageInfo
//
pCodePageInfo = (PUNI_CODEPAGEINFO)(pbBase + ((PUNI_GLYPHSETDATA)pbBase)->loCodePageOffset);
pCodePageInfo->dwCodePage = dwCodePage;
pCodePageInfo->SelectSymbolSet.dwCount = 0;
pCodePageInfo->UnSelectSymbolSet.dwCount = 0;
pCodePageInfo->SelectSymbolSet.loOffset = 0;
pCodePageInfo->UnSelectSymbolSet.loOffset = 0;
//
// MapTable
//
pMapTable = (PMAPTABLE)(pbBase +
((PUNI_GLYPHSETDATA)pbBase)->loMapTableOffset);
pMapTable->dwSize = sizeof(MAPTABLE) +
(iNumOfHandle - 1) * sizeof(TRANSDATA);
pMapTable->dwGlyphNum = iNumOfHandle;
pTrans = pMapTable->Trans;
iIndex = 0;
iK = 0;
pGlyphRun = pGlyphRunOrg;
if (bSymbolCharSet)
{
for( iI = 0; iI < iNumOfRuns; iI ++, pGlyphRun ++)
{
if (pGlyphRun->wcLow == SYMBOL_START)
{
for (iJ = SYMBOL_START; iJ <= SYMBOL_END; iJ ++)
{
pTrans[iIndex].ubCodePageID = 0;
pTrans[iIndex].ubType = MTYPE_DIRECT;
pTrans[iIndex].uCode.ubCode = (BYTE)iJ;
iIndex++;
}
}
else
{
for( iJ = 0; iJ < pGlyphRun->wGlyphCount; iJ ++)
{
while (iK < 256 && UnicodeDst[iK].Unicode == 0)
{
iK++;
}
if (iK < 256)
{
pTrans[iIndex].ubCodePageID = 0;
pTrans[iIndex].ubType = MTYPE_DIRECT;
pTrans[iIndex].uCode.ubCode = (BYTE)UnicodeDst[iK++].wID;
iIndex++;
}
}
}
}
}
else
{
for( iI = 0; iI < iNumOfHandle; iI ++)
{
while (iK < 256 && UnicodeDst[iK].Unicode == 0)
{
iK++;
}
if (iK < 256)
{
pTrans[iIndex].ubCodePageID = 0;
pTrans[iIndex].ubType = MTYPE_DIRECT;
pTrans[iIndex].uCode.ubCode = (BYTE)UnicodeDst[iK++].wID;
iIndex++;
}
}
}
MemFree(pGlyphRunOrg);
VDBGDUMPGTT((PUNI_GLYPHSETDATA)pbBase);
return (PUNI_GLYPHSETDATA)pbBase;
}
BOOL
BExtractGTTwithPredefGTT(
IN PUNI_GLYPHSETDATA pPreDefGTT,
IN PUNI_GLYPHSETDATA pMiniDefGTT,
IN WCHAR wchFirst,
IN WCHAR wchLast,
OUT FD_GLYPHSET **ppFD_GLYPHSET,
OUT MAPTABLE **ppMapTable,
IN PDWORD pdwFD_GLYPHSETSize)
{
PGLYPHRUN pPreDefGlyphRun, pMiniDefGlyphRun;
PMAPTABLE pMiniMapTable;
PTRANSDATA pMiniDefTrans, pPreDefTrans;
PTRANSDATA pSrcTrans, pDstTrans, pNewTrans, pTrans;
WCRUN* pWCRun;
HGLYPH *pHGlyph;
DWORD dwGlyphNum, dwMapTableSize, dwRunCount, dwIndex, dwI;
DWORD dwAddGlyphNum, dwSubGlyphNum, dwType;
WORD wJ;
WCHAR wcLow, wcHigh;
BOOL bInRun;
//
// FD_GLYPHSET creation.
//
// Additonal case:
// case 1: the begining of predef run
// Change wcLow and add cGlyphs in WCRUN.
// Change cGlyphsSupported in FD_GLYPHSET.
// case 2: the end of predef run
// Change add cGlyphs in WCRUN.
// Change cGlyphsSupported in FD_GLYPHSET.
// case 3: not in the predef run
// Add new WCRUN
// Change cGlyphsSupported in FD_GLYPHSET.
//
// Disable case:
// case 1: the begining of predef run
// Change wcLow and cGlyphs in WCRUN.
// Change cGlyphsSupported in FD_GLYPHSET.
// case 2: in the middle of predef run
// Divide this run into two different run.
// Change cGlyphsSupported in FD_GLYPHSET.
// case 3: the end of predef run
// Change cGlyphs in WCRUN.
// Change cGlyphsSupported in FD_GLYPHSET.
//
// Replace case:
// Do nothing.
//
ASSERT(pPreDefGTT != NULL && pMiniDefGTT);
//
// Count glyph number in predefined GTT.
//
dwGlyphNum = 0;
pPreDefGlyphRun = GET_GLYPHRUN(pPreDefGTT);
for (dwI = 0; dwI < pPreDefGTT->dwRunCount; dwI ++, pPreDefGlyphRun ++)
{
dwGlyphNum += pPreDefGlyphRun->wGlyphCount;
}
pPreDefGlyphRun = GET_GLYPHRUN(pPreDefGTT);
pMiniDefGlyphRun = GET_GLYPHRUN(pMiniDefGTT);
pMiniMapTable = GET_MAPTABLE(pMiniDefGTT);
dwIndex = 0;
dwAddGlyphNum = 0;
dwSubGlyphNum = 0;
//
// Count a total glyph number and glyph run number.
//
for (dwI = 0; dwI < pMiniDefGTT->dwRunCount; dwI ++, pMiniDefGlyphRun ++)
{
wcHigh = pMiniDefGlyphRun->wcLow + pMiniDefGlyphRun->wGlyphCount;
for (wJ = pMiniDefGlyphRun->wcLow; wJ < wcHigh; wJ ++, dwIndex ++)
{
switch (pMiniMapTable->Trans[dwIndex].ubType & MTYPE_PREDEFIN_MASK)
{
case MTYPE_ADD:
dwAddGlyphNum ++;
break;
case MTYPE_DISABLE:
dwSubGlyphNum ++;
break;
case MTYPE_REPLACE:
default:
break;
}
}
}
dwGlyphNum += dwAddGlyphNum - dwSubGlyphNum;
//
// Create MAPTABLE
//
// Memory allocation
// Creation
//
// ----------------
// Predefined MAPPTABLE (1 -> n glyph handle)
// Minidriver's MTYPE_DISABLE is already removed.
// ----------------
// Minidriver additional MAPTABLE
// (n + 1 -> n + m) glyph handle
// Even if some glyphs could be merged into Predefined MAPTABLE, we
// separate them with minidriver's additional glyphs for a convenience.
// ----------------
//
dwMapTableSize = sizeof(MAPTABLE) + sizeof(TRANSDATA) * (dwGlyphNum - 1);
if((*ppMapTable = MemAlloc(dwMapTableSize)) == NULL)
{
return FALSE;
}
//
// Fill in MAPTABLE
//
(*ppMapTable)->dwSize = dwMapTableSize;
(*ppMapTable)->dwGlyphNum = dwGlyphNum;
pPreDefGlyphRun = GET_GLYPHRUN(pPreDefGTT);
pMiniDefGlyphRun = GET_GLYPHRUN(pMiniDefGTT);
pMiniMapTable = GET_MAPTABLE(pMiniDefGTT);
pPreDefTrans = (GET_MAPTABLE(pPreDefGTT))->Trans;
pMiniDefTrans = pMiniMapTable->Trans;
pTrans = (*ppMapTable)->Trans;
pNewTrans = (*ppMapTable)->Trans + dwGlyphNum - dwAddGlyphNum;
dwIndex = 0;
dwRunCount = 0;
for (dwI = 0; dwI < pPreDefGlyphRun->wGlyphCount; dwI ++)
{
wcHigh = pPreDefGlyphRun->wcLow + pPreDefGlyphRun->wGlyphCount;
bInRun = FALSE;
for (wJ = pPreDefGlyphRun->wcLow; wJ < wcHigh; wJ ++)
{
dwType = DwCheckTrans(pMiniDefGlyphRun,
pMiniMapTable,
pMiniDefGTT->dwRunCount,
wJ);
if ( (dwType == 0) || (dwType == MTYPE_REPLACE) )
{
if (!bInRun)
{
dwRunCount ++;
bInRun = TRUE;
}
if (!dwType )
{
pSrcTrans = pPreDefTrans;
pDstTrans = pTrans;
}
else
if (dwType == MTYPE_REPLACE)
{
pSrcTrans = pMiniDefTrans;
pDstTrans = pTrans;
}
pDstTrans->ubCodePageID = pSrcTrans->ubCodePageID;
pDstTrans->ubType = pSrcTrans->ubType;
switch(pSrcTrans->ubType & MTYPE_FORMAT_MASK)
{
case MTYPE_COMPOSE:
pDstTrans->uCode.ubCode = pSrcTrans->uCode.ubCode;
break;
case MTYPE_DIRECT:
pDstTrans->uCode.ubPairs[0] = pSrcTrans->uCode.ubPairs[0];
pDstTrans->uCode.ubPairs[1] = pSrcTrans->uCode.ubPairs[1];
break;
case MTYPE_PAIRED:
pDstTrans->uCode.sCode = pSrcTrans->uCode.sCode;
break;
}
pSrcTrans ++;
pDstTrans ++;
}
else
if (dwType == MTYPE_DISABLE)
{
pPreDefTrans ++;
if (bInRun && wJ != wcHigh - 1)
{
dwRunCount ++;
bInRun = FALSE;
}
}
}
}
for (dwI = 0; dwI < pMiniDefGlyphRun->wGlyphCount; dwI ++)
{
wcHigh = pMiniDefGlyphRun->wcLow + pMiniDefGlyphRun->wGlyphCount;
bInRun = FALSE;
for (wJ = pMiniDefGlyphRun->wcLow; wJ < wcHigh; wJ ++, pMiniDefTrans ++)
{
if (pMiniDefTrans->ubType & MTYPE_ADD)
{
pNewTrans->ubCodePageID = pMiniDefTrans->ubCodePageID;
pNewTrans->ubType = pMiniDefTrans->ubType;
switch (pNewTrans->ubType & MTYPE_FORMAT_MASK)
{
case MTYPE_COMPOSE:
pNewTrans->uCode.ubCode = pMiniDefTrans->uCode.ubCode;
break;
case MTYPE_DIRECT:
pNewTrans->uCode.ubPairs[0] = pMiniDefTrans->uCode.ubPairs[0];
pNewTrans->uCode.ubPairs[1] = pMiniDefTrans->uCode.ubPairs[1];
break;
case MTYPE_PAIRED:
pNewTrans->uCode.sCode = pMiniDefTrans->uCode.sCode;
break;
}
pNewTrans ++;
if (!bInRun)
{
dwRunCount ++;
bInRun = TRUE;
}
}
else
{
if (bInRun)
{
bInRun = FALSE;
}
}
}
}
//
// Crate FD_GLYPHSET
//
// Memory allocation with dwGlyphNum and dwRunCount.
//
// -----------------
// Predefined FD_GLYPHSET
// -----------------
// Minidriver additional glyph run
// ----------------
//
//
// Now we know the number of run. Allocate memory for FD_GLYPHSET.
//
*pdwFD_GLYPHSETSize = sizeof(FD_GLYPHSET) +
sizeof(WCRUN) * dwRunCount +
sizeof(HGLYPH) * dwGlyphNum;
if((*ppFD_GLYPHSET = (FD_GLYPHSET*)MemAlloc(*pdwFD_GLYPHSETSize)) == NULL)
{
MemFree(*ppMapTable);
return FALSE;
}
(*ppFD_GLYPHSET)->cjThis = *pdwFD_GLYPHSETSize;
(*ppFD_GLYPHSET)->cGlyphsSupported = *pdwFD_GLYPHSETSize;
(*ppFD_GLYPHSET)->cRuns = dwRunCount;
pWCRun = (*ppFD_GLYPHSET)->awcrun;
pHGlyph = (HGLYPH*)((PBYTE)*ppFD_GLYPHSET +
sizeof(FD_GLYPHSET) +
sizeof(WCRUN) * dwRunCount);
pPreDefGlyphRun = GET_GLYPHRUN(pPreDefGTT);
pMiniDefGlyphRun = GET_GLYPHRUN(pMiniDefGTT);
pMiniDefTrans = pMiniMapTable->Trans;
for (dwI = 1; dwI <= dwGlyphNum; dwI ++, *pHGlyph)
{
*pHGlyph = dwI;
}
pHGlyph = (HGLYPH*)((PBYTE)*ppFD_GLYPHSET +
sizeof(FD_GLYPHSET) +
sizeof(WCRUN) * dwRunCount);
for (dwI = 0; dwI < pPreDefGlyphRun->wGlyphCount; dwI ++)
{
pWCRun->wcLow = wcLow
= pPreDefGlyphRun->wcLow;
wcHigh = wcLow + pPreDefGlyphRun->wGlyphCount;
bInRun = FALSE;
for (wJ = pPreDefGlyphRun->wcLow; wJ < wcHigh; wJ ++)
{
if (MTYPE_DISABLE == DwCheckTrans(pMiniDefGlyphRun,
pMiniMapTable,
pMiniDefGTT->dwRunCount,
wJ))
{
if (bInRun)
{
pWCRun->cGlyphs = wJ - wcLow + 1;
pWCRun->phg = pHGlyph;
pHGlyph += pWCRun->cGlyphs;
pWCRun ++;
bInRun = FALSE;
}
}
else
{
if (!bInRun)
{
pWCRun->wcLow = wcLow
= wJ;
wcHigh = wcLow + pPreDefGlyphRun->wGlyphCount;
bInRun = TRUE;
}
}
}
pWCRun->cGlyphs = wcHigh - wcLow;
pWCRun->phg = pHGlyph;
pWCRun ++;
}
bInRun = FALSE;
for (dwI = 0; dwI < pMiniDefGlyphRun->wGlyphCount; dwI ++)
{
for (wJ = pMiniDefGlyphRun->wcLow; wJ < wcHigh; wJ ++, pMiniDefTrans ++)
{
if (pMiniDefTrans->ubType & MTYPE_ADD)
{
if (!bInRun)
{
pWCRun->wcLow = wcLow = wJ;
bInRun = TRUE;
}
}
else
{
if (bInRun)
{
pWCRun->cGlyphs = wJ - wcLow + 1;
pWCRun->phg = pHGlyph;
pHGlyph += pWCRun->cGlyphs;
bInRun = FALSE;
}
}
}
}
return TRUE;
}
DWORD
DwCheckTrans(
PGLYPHRUN pMiniGlyphRun,
PMAPTABLE pMiniMapTable,
DWORD dwMiniGlyphRunCount,
WORD wUnicode)
{
DWORD dwI;
WORD wIndex;
for (dwI = 0; dwI < dwMiniGlyphRunCount; dwI ++, pMiniGlyphRun ++)
{
if (wUnicode < pMiniGlyphRun->wcLow)
{
continue;
}
if (wUnicode < pMiniGlyphRun->wcLow + pMiniGlyphRun->wGlyphCount)
{
wIndex = wUnicode - pMiniGlyphRun->wcLow;
return pMiniMapTable->Trans[wIndex].ubType & MTYPE_PREDEFIN_MASK;
}
else
{
return 0;
}
}
return 0;
}
int __cdecl Comp(const void *elem1, const void *elem2)
{
//struct {
// WORD wID;
// WCHAR Unicode;
//} UnicodeDst[256];
//
// Compare Unicode in this data structure
//
return *((PWORD)elem1+1) - *((PWORD)elem2+1);
}