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
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);
|
|
}
|