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.
 
 
 
 
 
 

1880 lines
56 KiB

/*++
Copyright (c) 1996 - 1999 Microsoft Corporation
Module Name:
fmcallbk.c
Abstract:
The font module callback helper functions
Environment:
Windows NT Unidrv driver
Revision History:
03/31/97 -eigos-
Created
--*/
#include "font.h"
#define CALL_OEMOUTPUTCHARSTR(type, count, startpoint) \
if(bCOMInterface) \
{ \
HComOutputCharStr((POEM_PLUGIN_ENTRY)pPDev->pOemEntry, \
&pPDev->devobj, \
(PUNIFONTOBJ)pUFObj, \
(type), \
(count), \
(startpoint)); \
} \
else \
{ \
if (pfnOEMOutputCharStr) \
pfnOEMOutputCharStr(&pPDev->devobj, \
(PUNIFONTOBJ)pUFObj, \
(type), \
(count), \
(startpoint)); \
}
#define GET_CHARWIDTH(width, pfontmap, hg) \
if (pfontmap->flFlags & FM_WIDTHRES) \
{ \
if (!(width = IGetUFMGlyphWidth(pPDev, pfontmap, hg))) \
width = (INT)pIFIMet->fwdAveCharWidth; \
} \
else \
{ \
if (pTrans[hg - 1].ubType & MTYPE_DOUBLE) \
width = pIFIMet->fwdMaxCharInc; \
else \
width = pIFIMet->fwdAveCharWidth; \
} \
if (pfontmap->flFlags & FM_SCALABLE) \
{ \
width = LMulFloatLong(&pFontPDev->ctl.eXScale,width); \
}
//
// Local functions' prototype definition
//
WCHAR
WGHtoUnicode(
DWORD dwNumOfRuns,
PGLYPHRUN pGlyphRun,
HGLYPH hg);
//
// UNIFONTOBJ callback interface
//
BOOL
UNIFONTOBJ_GetInfo(
IN PUNIFONTOBJ pUFObj,
IN DWORD dwInfoID,
IN PVOID pData,
IN DWORD dwDataSize,
OUT PDWORD pcbNeeded)
/*++
Routine Description:
Implementation of UNIFONTOBJ GetInfo function
Please refer to DDK
Arguments:
pUFOBj - a pointer to UNIFONTOBJ
dwInfoID - Function ID
pData - a pointer to data structure according to dwInfoID
dwDataSize - size of pData
pcbNeeded - DWORD buffer to return the necessary size of pData
Return Value:
TRUE if successful, otherwise FALSE.
Note:
--*/
{
PI_UNIFONTOBJ pI_UFObj = (PI_UNIFONTOBJ)pUFObj;
GETINFO_GLYPHSTRING* pGlyphString;
GETINFO_GLYPHBITMAP* pGlyphBitmap;
GETINFO_GLYPHWIDTH* pGlyphWidth;
GETINFO_STDVAR* pStdVar;
PFONTPDEV pFontPDev;
PUNI_GLYPHSETDATA pGlyphData;
PTRANSDATA pTrans, pTransOut, pTransOutStart;
PMAPTABLE pMapTable;
PGLYPHRUN pGlyphRun;
HGLYPH *pHGlyph;
PDLGLYPH *apdlGlyph;
PBYTE pbString, pbOutput;
LONG *plWidth, lBuffSize;
DWORD *pGlyphID, dwI, dwJ;
WCHAR *pUnicode;
DWORD dwNumOfVar, dwCount, dwSVID, dwNumOfRuns, dwBuffSize;
BOOL bRet;
static STDVARIABLE FontStdVariable[FNT_INFO_MAX] = {
SV_PRINTDIRECTION,
SV_GRAYPERCENT,
SV_NEXTFONTID,
SV_NEXTGLYPH,
SV_FONTHEIGHT,
SV_FONTWIDTH,
SV_FONTBOLD,
SV_FONTITALIC,
SV_FONTUNDERLINE,
SV_FONTSTRIKETHRU,
SV_CURRENTFONTID,
SV_TEXTYRES,
SV_TEXTXRES,
SV_FONTMAXWIDTH };
//
// Error check
//
if (!pI_UFObj )
{
ERR(("UNIFONTOBJ_GetInfo(): pUFObj is NULL.\n"));
return FALSE;
}
if (!pData)
//
// pData == NULL case
// Return the necessary buffer size
//
{
bRet = TRUE;
if (!pcbNeeded)
{
ERR(("UNIFONTOBJ_GetInfo(): pData and pcbNeed is NULL.\n"));
bRet = FALSE;
}
else
{
switch (dwInfoID)
{
case UFO_GETINFO_FONTOBJ:
*pcbNeeded = sizeof(GETINFO_FONTOBJ);
break;
case UFO_GETINFO_GLYPHSTRING:
*pcbNeeded = sizeof(GETINFO_GLYPHSTRING);
break;
case UFO_GETINFO_GLYPHBITMAP:
*pcbNeeded = sizeof(GETINFO_GLYPHBITMAP);
break;
case UFO_GETINFO_GLYPHWIDTH:
*pcbNeeded = sizeof(GETINFO_GLYPHWIDTH);
break;
case UFO_GETINFO_MEMORY:
*pcbNeeded = sizeof(GETINFO_MEMORY);
break;
case UFO_GETINFO_STDVARIABLE:
*pcbNeeded = sizeof(GETINFO_STDVAR);
break;
default:
*pcbNeeded = 0;
bRet = FALSE;
VERBOSE(("UNIFONTOBJ_GetInfo(): Invalid dwInfoID.\n"));
break;
}
}
}
else
{
bRet = FALSE;
//
// ERROR CHECK LIST
// (A) Data structure size check
// GETINFO_FONTOBJ
// GETINFO_GLYPHYSTRING
// GETINFO_GLYPHBITMAP
// GETINFO_GLYPHWIDTH
// GETINFO_MEORY
// GETNFO_STDVARIABLE
// (B) Necessary data pointer check
// e.g. pI_UFObj->XXXX
//
switch (dwInfoID)
{
case UFO_GETINFO_FONTOBJ:
//
// Return FONTOBJ data in GETINFO_FONTOBJ
// typedef struct _GETINFO_FONTOBJ {
// DWORD dwSize; // Size of this structure
// FONTOBJ *pFontObj; // Pointer to the FONTOBJ
// } GETINFO_FONTOBJ, *PGETINFO_FONTOBJ;
//
// ERROR CHECK
// (A) and (B)
// (B) pI_UFObj->pFontObj
//
if (((GETINFO_FONTOBJ*)pData)->dwSize != sizeof(GETINFO_FONTOBJ) || !pI_UFObj->pFontObj)
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_FONTOBJ): pData or pUFObj is invalid.\n"));
break;
}
((GETINFO_FONTOBJ*)pData)->pFontObj = pI_UFObj->pFontObj;
bRet = TRUE;
break;
case UFO_GETINFO_GLYPHSTRING:
//
// Return glyph string
//
// typedef struct _GETINFO_GLYPHSTRING {
// DWORD dwSize; // Size of this structure
// DWORD dwCount; // Count of glyphs in pGlyphIn
// DWORD dwTypeIn; // Glyph type of pGlyphIn, TYPE_GLYPHID/TYPE_HANDLE.
// PVOID pGlyphIn; // Pointer to the input glyph string
// DWORD dwTypeOut; // Glyph type of pGlyphOut, TYPE_UNICODE/TYPE_TRANSDATA.
// PVOID pGlyphOut; // Pointer to the output glyph string
// DWORD dwGlyphOutSize; // The size of pGlyphOut buffer
// } GETINFO_GLYPHSTRING, *PGETINFO_GLYPHSTRING;
//
//
// OutputGlyph callback function receives
// 1. GLYPH HANLDE for Device font
// 2. GLYPH ID for TrueType font
//
// In TYPE_GLYPHHANDLE (Device font)
// Out TYPE_UNICODE
// TYPE_TRANSDATA
//
// In TYPE_GLYPHID (TrueType font)
// Out TYPE_UNICODE
// Out TYPE_GLYPHHANDLE
//
// <Special case for TYPE_GLYPHHANDLE -> TYPE_TRANSDATA conversion>
// TRANSDATA could have MTYPE_COMPOSE so that UNIDRV doesn't know the size of output buffer.
// At the first call, a minidriver sets 0 to dwGlyphOutSize.
// Then UNIDRV returns necessary buffer size in dwGlyphOutSize.
// At the second call, a minidriver allocates memory, set the pointer of it to pGlyphOut,
// and set the size to dwGlyphOutSize.
//
//
pGlyphString = pData;
dwCount = pGlyphString->dwCount;
if (!dwCount)
{
//
// No operation is necessary.
//
break;
}
//
// ERROR CHECK (A)
// pGlyphString
//
if ( !pGlyphString->pGlyphIn ||
pGlyphString->dwTypeOut != TYPE_TRANSDATA &&
!pGlyphString->pGlyphOut )
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_FONTOBJ): pData is invalid.\n"));
break;
}
//
// Now we support type size of GETINFO_GLYPHSTRING.
// This is a bug backward compatibility.
// Before beta 3 GETINFO_GLYPHSTRING didn't have dwGlyphOutSize.
// Now we have new data structure but don't change the name of
// structure.
//
if (!(
(pGlyphString->dwSize == sizeof(GETINFO_GLYPHSTRING)) ||
(pGlyphString->dwSize == sizeof(GETINFO_GLYPHSTRING) - sizeof(DWORD))
)
)
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_FONTOBJ): pData is invalid.\n"));
break;
}
//
// ERROR CHECK (B)
// pI_UFObj->pFontMap
// pI_UFObj->pPDev
//
if (!pI_UFObj->pFontMap || !pI_UFObj->pPDev)
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_FONTOBJ): pUFObj is invalid.\n"));
break;
}
switch(pGlyphString->dwTypeIn)
{
case TYPE_GLYPHHANDLE:
//
// Device font case
//
if ( pI_UFObj->pFontMap->dwFontType == FMTYPE_DEVICE )
{
pHGlyph = pGlyphString->pGlyphIn;
pGlyphData = ((PFONTMAP_DEV)pI_UFObj->pFontMap->pSubFM)->pvNTGlyph;
dwNumOfRuns = pGlyphData->dwRunCount;
switch(pGlyphString->dwTypeOut)
{
case TYPE_UNICODE:
pUnicode = pGlyphString->pGlyphOut;
pGlyphRun = GET_GLYPHRUN(pGlyphData);
while (dwCount--)
{
*pUnicode++ = WGHtoUnicode(dwNumOfRuns,
pGlyphRun,
*pHGlyph++);
}
bRet = TRUE;
break;
case TYPE_TRANSDATA:
pTransOutStart = pTransOut = pGlyphString->pGlyphOut;
pMapTable = GET_MAPTABLE(pGlyphData);
pTrans = pMapTable->Trans;
dwBuffSize = pGlyphString->dwGlyphOutSize;
//
// New version of GETINFO_GLYPYSTRING
//
if ( pGlyphString->dwSize == sizeof(GETINFO_GLYPHSTRING) )
{
if (0 == dwBuffSize)
{
while (dwCount --)
{
if (!(pTrans[*pHGlyph - 1].ubType & MTYPE_COMPOSE))
{
dwBuffSize += sizeof(TRANSDATA);
}
else
{
pbString = (PBYTE)pMapTable + pTrans[*pHGlyph - 1].uCode.sCode;
dwBuffSize += sizeof(TRANSDATA) + *(PWORD)pbString + sizeof(WORD);
}
pHGlyph++;
}
pGlyphString->dwGlyphOutSize = dwBuffSize;
}
else
{
//
// Initialize the MTYPE_COMPOSE buffer
//
pbOutput = (PBYTE)pTransOutStart + dwCount * sizeof(TRANSDATA);
lBuffSize = dwBuffSize - dwCount * sizeof(TRANSDATA);
if (lBuffSize < 0 || NULL == pTransOut)
{
break;
}
else
{
bRet = TRUE;
while (dwCount --)
{
*pTransOut = pTrans[*pHGlyph - 1];
if (pTrans[*pHGlyph - 1].ubType & MTYPE_COMPOSE)
{
pbString = (PBYTE)pMapTable + pTrans[*pHGlyph - 1].uCode.sCode;
if (lBuffSize >= *(PWORD)pbString)
{
pTransOut->uCode.sCode = (SHORT)(pbOutput - (PBYTE)pTransOutStart);
CopyMemory(pbOutput, pbString, *(PWORD)pbString + sizeof(WORD));
pbOutput += *(PWORD)pbString + sizeof(WORD);
lBuffSize -= *(PWORD)pbString + sizeof(WORD);
}
else
{
bRet = FALSE;
break;
}
}
pTransOut ++;
pHGlyph ++;
}
}
}
}
//
// New version of GETINFO_GLYPYSTRING
//
else if ( pGlyphString->dwSize == sizeof(GETINFO_GLYPHSTRING) - sizeof(DWORD) )
{
pTransOut = pGlyphString->pGlyphOut;
pMapTable = GET_MAPTABLE(pGlyphData);
pTrans = pMapTable->Trans;
while (dwCount --)
{
*pTransOut++ = pTrans[*pHGlyph++ - 1];
}
bRet = TRUE;
}
break;
default:
break;
}
}
break;
case TYPE_GLYPHID:
//
// TrueType font case
//
pGlyphID = (PDWORD)pGlyphString->pGlyphIn;
apdlGlyph = pI_UFObj->apdlGlyph;
if (!apdlGlyph)
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_GLYPHSTRING): pUFObj is not correct.\n"));
break;
}
if (pI_UFObj->pFontMap->dwFontType == FMTYPE_TTOEM)
{
switch (pGlyphString->dwTypeOut)
{
case TYPE_UNICODE:
pUnicode = pGlyphString->pGlyphOut;
while (dwCount--)
{
*pUnicode = 0;
for (dwI = 0; dwI < pI_UFObj->dwNumInGlyphTbl; dwI++, apdlGlyph++)
{
if ((*apdlGlyph)->wDLGlyphID == (0x0ffff & *pGlyphID))
{
*pUnicode = (*apdlGlyph)->wchUnicode;
break;
}
}
pGlyphID ++;
pUnicode ++;
}
bRet = TRUE;
break;
case TYPE_GLYPHHANDLE:
pHGlyph = pGlyphString->pGlyphOut;
while (dwCount--)
{
*pHGlyph = 0;
for (dwI = 0; dwI < pI_UFObj->dwNumInGlyphTbl; dwI++, apdlGlyph++)
{
if ((*apdlGlyph)->wDLGlyphID == (0x0ffff & *pGlyphID))
{
*pHGlyph = (*apdlGlyph)->hTTGlyph;
break;
}
}
pGlyphID ++;
pHGlyph ++;
}
bRet = TRUE;
break;
}
}
break;
}
break;
case UFO_GETINFO_GLYPHBITMAP:
//
// Return Glyph Bitmap
//
// typedef struct _GETINFO_GLYPHBITMAP {
// DWORD dwSize; // Size of this structure
// HGLYPH hGlyph; // Glyph hangle passed in OEMDownloadCharGlyph
// GLYPHDATA *pGlyphData; // Pointer to the GLYPHDATA data structure
// } GETINFO_GLYPHBITMAP, *PGETINFO_GLYPHBITMAP;
//
pGlyphBitmap = pData;
//
// Error check (A) and (B)
// (B) pI_UFObj->pFontObj
//
if (!pI_UFObj->pFontObj || pGlyphBitmap->dwSize != sizeof(GETINFO_GLYPHBITMAP))
break;
if (FONTOBJ_cGetGlyphs(pI_UFObj->pFontObj,
FO_GLYPHBITS,
1,
&pGlyphBitmap->hGlyph,
&pGlyphBitmap->pGlyphData) )
{
bRet = TRUE;
}
break;
case UFO_GETINFO_GLYPHWIDTH:
//
// Return glyph width.
//
// typedef struct _GETINFO_GLYPHWIDTH {
// DWORD dwSize; // Size of this structure
// DWORD dwType; // Type of glyph stirng in pGlyph, TYPE_GLYPHHANDLE/GLYPHID.
// DWORD dwCount; // Count of glyph in pGlyph
// PVOID pGlyph; // Pointer to a glyph string
// PLONG plWidth; // Pointer to the buffer of width table.
// // Minidriver has to prepare this.
// } GETINFO_GLYPHWIDTH, *PGETINFO_GLYPHWIDTH;
//
pGlyphWidth = pData;
//
// Error check (A)
//
if ((pGlyphWidth->dwSize != sizeof(GETINFO_GLYPHWIDTH))||
!(plWidth = pGlyphWidth->plWidth) ||
!(pGlyphID = pGlyphWidth->pGlyph) )
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_GLYPHWIDTH): pData is not correct.\n"));
break;
}
//
// Error check (B)
// pI_UFObj->pPDev
// pI_UFObj->pFontObj
//
if (!pI_UFObj->pPDev)
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_GLYPHWIDTH): pUFObj is not correct.\n"));
break;
}
switch(pGlyphWidth->dwType)
{
case TYPE_GLYPHID:
if (pUFObj->dwFlags & UFOFLAG_TTFONT)
{
HGLYPH hGlyph;
if (!pI_UFObj->pFontObj)
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_GLYPHWIDTH): UNIDRV needs FONTOBJ. This must be white text case!\n"));
break;
}
for (dwI = 0, pGlyphID = pGlyphWidth->pGlyph;
dwI < pGlyphWidth->dwCount;
dwI ++, pGlyphID ++, plWidth++)
{
apdlGlyph = pI_UFObj->apdlGlyph;
for (dwJ = 0;
dwJ < pI_UFObj->dwNumInGlyphTbl;
dwJ++ , apdlGlyph++)
{
if ((*apdlGlyph)->wDLGlyphID == (0x0ffff & *pGlyphID))
{
hGlyph = (*apdlGlyph)->hTTGlyph;
break;
}
}
*plWidth= DwGetTTGlyphWidth(pI_UFObj->pPDev->pFontPDev,
pI_UFObj->pFontObj,
hGlyph);
}
bRet = TRUE;
}
break;
case TYPE_GLYPHHANDLE:
if (!(pUFObj->dwFlags & UFOFLAG_TTFONT))
{
for (dwI = 0,pHGlyph = pGlyphWidth->pGlyph;
dwI < pGlyphWidth->dwCount;
dwI ++, pHGlyph++, plWidth++)
{
*plWidth = IGetUFMGlyphWidthJr(&pI_UFObj->ptGrxRes,
pI_UFObj->pFontMap,
*pHGlyph);
}
bRet = TRUE;
}
break;
}
break;
case UFO_GETINFO_MEMORY:
//
// Retuen available memory on the printer.
//
// typedef struct _GETINFO_MEMORY {
// DWORD dwSize;
// DWORD dwRemainingMemory;
// } GETINFO_MEMORY, PGETINFO_MEMROY;
//
// Error check (A)
//
if (((GETINFO_MEMORY*)pData)->dwSize != sizeof(GETINFO_MEMORY))
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_MEMORY): pData is not correct.\n"));
break;
}
//
// Error check (B)
// pI_UFObj->pPDev
// pI_UFObj->pPDev->pFontPDev
//
if (!pI_UFObj->pPDev || !(pFontPDev = pI_UFObj->pPDev->pFontPDev))
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_MEMORY): pUFObj is not correct.\n"));
break;
}
((GETINFO_MEMORY*)pData)->dwRemainingMemory = pFontPDev->dwFontMem;
bRet = TRUE;
break;
case UFO_GETINFO_STDVARIABLE:
//
// Return standard variables
//
//typedef struct _GETINFO_STDVAR {
// DWORD dwSize;
// DWORD dwNumOfVariable;
// struct {
// DWORD dwStdVarID;
// LONG lStdVariable;
// } StdVar[1];
//} GETINFO_STDVAR, *PGETINFO_STDVAR;
//
//
// FNT_INFO_PRINTDIRINCCDEGREES 0 // PrintDirInCCDegrees
// FNT_INFO_GRAYPERCENTAGE 1 // GrayPercentage
// FNT_INFO_NEXTFONTID 2 // NextfontID
// FNT_INFO_NEXTGLYPH 3 // NextGlyph
// FNT_INFO_FONTHEIGHT 4 // FontHeight
// FNT_INFO_FONTWIDTH 5 // FontWidth
// FNT_INFO_FONTBOLD 6 // FontBold
// FNT_INFO_FONTITALIC 7 // FontItalic
// FNT_INFO_FONTUNDERLINE 8 // FontUnderline
// FNT_INFO_FONTSTRIKETHRU 9 // FontStrikeThru
// FNT_INFO_CURRENTFONTID 10 // Current
// FNT_INFO_TEXTYRES 11 // TextYRes
// FNT_INFO_TEXTXRES 12 // TextXRes
// FNT_INFO_FONTMAXWIDTH 13 // FontMaxWidth
//
pStdVar = pData;
//
// Error check (A)
//
if ( (pStdVar->dwSize != sizeof(GETINFO_STDVAR) +
((dwNumOfVar = pStdVar->dwNumOfVariable) - 1) * 2 * sizeof(DWORD))
)
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETIFNO_STDVARIABLE): pData is incorrect.\n"));
break;
}
//
// Error check (B)
// pI_UFObj->pPDev
//
if (!pI_UFObj->pPDev)
{
ERR(("UNIFONTOBJ_GetInfo(UFO_GETINFO_STDVARIABLE): pUFObj is not correct.\n"));
break;
}
bRet = TRUE;
while (dwNumOfVar--)
{
dwSVID =
FontStdVariable[pStdVar->StdVar[dwNumOfVar].dwStdVarID];
if (dwSVID > SV_MAX)
{
bRet = FALSE;
ERR(("UFONTOBJ_GetInfo(UFO_GETIFNO_STDVARIABLE): pData is incorrect.\n"));
break;
}
pStdVar->StdVar[dwNumOfVar].lStdVariable = *(pI_UFObj->pPDev->arStdPtrs[dwSVID]);
}
break;
default:
VERBOSE(("UNIFONTOBJ_GetInfo(): Invalid dwInfoID.\n"));
break;
}
}
return bRet;
}
//
// Font module FONTMAP functions
//
DWORD
DwOutputGlyphCallback(
TO_DATA *pTod)
/*++
Routine Description:
Implementation of OEM OutpuotGlyphCallback calling routine for FONTMAP dispatch routine
Arguments:
pTod - a pointer to TO_DATA.
Return Value:
The number of glyph printed.
Note:
--*/
{
PFN_OEMOutputCharStr pfnOEMOutputCharStr;
PI_UNIFONTOBJ pUFObj;
IFIMETRICS *pIFIMet;
PFONTPDEV pFontPDev;
PDEV *pPDev;
PUNI_GLYPHSETDATA pGlyphData;
PTRANSDATA pTrans;
PMAPTABLE pMapTable;
COMMAND *pCmd, *pCmdSingle, *pCmdDouble;
FONTMAP *pFontMap;
GLYPHPOS *pgp;
PDLGLYPH pdlGlyph;
POINTL ptlRem;
DWORD dwI, dwCount;
PDWORD pdwGlyph, pdwGlyphStart;
INT iXInc, iYInc;
BOOL bSetCursorForEachGlyph, bPrint, bNewFontSelect, bCOMInterface;
bCOMInterface = FALSE;
pPDev = pTod->pPDev;
ASSERT(pPDev)
pFontPDev = pPDev->pFontPDev;
ASSERT(pFontPDev)
pFontMap = pTod->pfm;
pUFObj = (PI_UNIFONTOBJ)pFontPDev->pUFObj;
ASSERT(pFontMap && pUFObj)
pIFIMet = pFontMap->pIFIMet;
ASSERT(pIFIMet)
pfnOEMOutputCharStr = NULL;
if ( pPDev->pOemHookInfo &&
(pPDev->pOemHookInfo[EP_OEMOutputCharStr].pfnHook))
{
FIX_DEVOBJ(pPDev, EP_OEMOutputCharStr);
if( pPDev->pOemEntry && ((POEM_PLUGIN_ENTRY)pPDev->pOemEntry)->pIntfOem )
{
bCOMInterface = TRUE;
}
else
{
pfnOEMOutputCharStr = (PFN_OEMOutputCharStr)pPDev->pOemHookInfo[EP_OEMOutputCharStr].pfnHook;
}
}
else if (pPDev->ePersonality != kPCLXL)
{
ERR(("DwOutputGlyphCallback: OEMOutputCharStr callback is not supported by a minidriver."));
return 0;
}
//
// Error exit
//
if (pFontMap->flFlags & FM_IFIVER40 || pUFObj->pGlyph == NULL)
{
ERR(("DwOutputGlyphCallback: pUFObj->pGlyph is NULL."));
return 0;
}
//
// OEMOutputCharStr passes two type of glyph string.
// TYPE_GLYPHID for TrueType font
// TYPE_GLYPHHANDLE for Device font
//
bSetCursorForEachGlyph = SET_CURSOR_FOR_EACH_GLYPH(pTod->flAccel);
pdwGlyphStart =
pdwGlyph = (PDWORD)pUFObj->pGlyph;
pgp = pTod->pgp;
pUFObj->pFontMap = pFontMap;
if (pUFObj->dwFlags & UFOFLAG_TTFONT)
{
DWORD dwCurrGlyphIndex = pTod->dwCurrGlyph;
PFONTMAP_TTOEM pFMOEM = (PFONTMAP_TTOEM) pFontMap->pSubFM;
DL_MAP *pdm = pFMOEM->u.pvDLData;
ASSERT(pTod->apdlGlyph);
if (bSetCursorForEachGlyph)
{
for (dwI = 0;
dwI < pTod->cGlyphsToPrint;
dwI++, pgp++, dwCurrGlyphIndex++)
{
pdlGlyph = pTod->apdlGlyph[dwCurrGlyphIndex];
if (!pdlGlyph)
{
//
// pFM->pfnDownloadGlyph could fail by some reason.
// Eventually apdlGlyph is not initialized by download.c
//
ERR(("DwOutputGlyphCallback: pTod->apdlGlyph[dwCurrGlyphIndex] is NULL."));
continue;
}
if (GLYPH_IN_NEW_SOFTFONT(pFontPDev, pdm, pdlGlyph))
{
//
// Need to select the new softfont.
// We do this by setting pfm->ulDLIndex
// to new softfontid.
//
pUFObj->ulFontID =
pFontMap->ulDLIndex = pdlGlyph->wDLFontId;
BNewFont(pPDev, pTod->iFace, pFontMap, 0);
}
VSetCursor( pPDev, pgp->ptl.x, pgp->ptl.y, MOVE_ABSOLUTE, &ptlRem);
HANDLE_VECTORPROCS(pPDev, VMOutputCharStr, ((PDEVOBJ)pPDev,
(PUNIFONTOBJ)pUFObj,
TYPE_GLYPHID,
1,
&(pdlGlyph->wDLGlyphID)))
else
CALL_OEMOUTPUTCHARSTR(TYPE_GLYPHID, 1, &(pdlGlyph->wDLGlyphID));
//
// Update position
//
VSetCursor( pPDev,
pdlGlyph->wWidth,
0,
MOVE_RELATIVE|MOVE_UPDATE,
&ptlRem);
}
}
else
{
VSetCursor( pPDev, pgp->ptl.x, pgp->ptl.y, MOVE_ABSOLUTE, &ptlRem);
dwI = 0;
dwCount = 0;
bNewFontSelect = FALSE;
do
{
for (; dwI < pTod->cGlyphsToPrint; pdwGlyph++, dwCount++, pgp++, dwI++, dwCurrGlyphIndex++)
{
pdlGlyph = pTod->apdlGlyph[dwCurrGlyphIndex];
if (0 == pgp->hg)
{
//
// 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.
continue;
}
if (!pdlGlyph)
{
//
// pFM->pfnDownloadGlyph could fail by some reason.
// Eventually apdlGlyph is not initialized by download.c
//
ERR(("DwOutputGlyphCallback: pTod->apdlGlyph[dwCurrGlyphIndex++] is NULL."));
continue;
}
*pdwGlyph = pdlGlyph->wDLGlyphID;
if (GLYPH_IN_NEW_SOFTFONT(pFontPDev, pdm, pdlGlyph))
{
//
// Need to select the new softfont.
// We do this by setting pfm->ulDLIndex
// to new softfontid.
//
pFontMap->ulDLIndex = pdlGlyph->wDLFontId;
bNewFontSelect = TRUE;
break;
}
}
if (dwCount > 0)
{
HANDLE_VECTORPROCS(pPDev, VMOutputCharStr, ((PDEVOBJ)pPDev,
(PUNIFONTOBJ)pUFObj,
TYPE_GLYPHID,
dwCount,
pdwGlyphStart))
else
CALL_OEMOUTPUTCHARSTR(TYPE_GLYPHID, dwCount, pdwGlyphStart);
//
// Update position
//
pgp --;
VSetCursor( pPDev,
pgp->ptl.x + pdlGlyph->wWidth,
pgp->ptl.y,
MOVE_ABSOLUTE|MOVE_UPDATE,
&ptlRem);
dwCount = 0;
}
if (bNewFontSelect)
{
dwCount = 1;
*pdwGlyphStart = *pdwGlyph;
pdwGlyph = pdwGlyphStart + 1;
pUFObj->ulFontID = pFontMap->ulDLIndex;
BNewFont(pPDev, pTod->iFace, pFontMap, 0);
bNewFontSelect = FALSE;
}
} while (dwCount > 0);
}
pgp --;
if (NULL != pdlGlyph)
{
iXInc = pdlGlyph->wWidth;
}
else
{
iXInc = 0;
}
}
else // Device Font
{
pGlyphData = ((PFONTMAP_DEV)pFontMap->pSubFM)->pvNTGlyph;
pMapTable = GET_MAPTABLE(pGlyphData);
pTrans = pMapTable->Trans;
pCmdSingle = COMMANDPTR(pPDev->pDriverInfo, CMD_SELECTSINGLEBYTEMODE);
pCmdDouble = COMMANDPTR(pPDev->pDriverInfo, CMD_SELECTDOUBLEBYTEMODE);
if (bSetCursorForEachGlyph)
{
for (dwI = 0; dwI < pTod->cGlyphsToPrint; dwI ++, pgp ++)
{
//
// 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 (0 == pgp->hg)
{
continue;
}
VSetCursor( pPDev, pgp->ptl.x, pgp->ptl.y, MOVE_ABSOLUTE, &ptlRem);
if (
(pCmdSingle) &&
(pTrans[pgp->hg - 1].ubType & MTYPE_SINGLE) &&
!(pFontPDev->flFlags & FDV_SINGLE_BYTE)
)
{
WriteChannel( pPDev, pCmdSingle );
pFontPDev->flFlags |= FDV_SINGLE_BYTE;
pFontPDev->flFlags &= ~FDV_DOUBLE_BYTE;
}
else
if (
(pCmdDouble) &&
(pTrans[pgp->hg - 1].ubType & MTYPE_DOUBLE) &&
!(pFontPDev->flFlags & FDV_DOUBLE_BYTE)
)
{
WriteChannel( pPDev, pCmdDouble );
pFontPDev->flFlags |= FDV_DOUBLE_BYTE;
pFontPDev->flFlags &= ~FDV_SINGLE_BYTE;
}
HANDLE_VECTORPROCS(pPDev, VMOutputCharStr, ((PDEVOBJ)pPDev,
(PUNIFONTOBJ)pUFObj,
TYPE_GLYPHHANDLE,
1,
&(pgp->hg)))
else
CALL_OEMOUTPUTCHARSTR(TYPE_GLYPHHANDLE, 1, &(pgp->hg));
//
// Update position
//
GET_CHARWIDTH(iXInc, pFontMap, pgp->hg);
VSetCursor( pPDev,
iXInc,
0,
MOVE_RELATIVE|MOVE_UPDATE,
&ptlRem);
}
}
else // Default Placement
{
bPrint = FALSE;
dwCount = 0;
VSetCursor( pPDev, pgp->ptl.x, pgp->ptl.y, MOVE_ABSOLUTE, &ptlRem);
for (dwI = 0; dwI < pTod->cGlyphsToPrint; dwI ++, pgp ++, pdwGlyph ++, dwCount++)
{
*pdwGlyph = pgp->hg;
//
// Single/Double byte mode switch
//
if (pCmdSingle &&
(pTrans[*pdwGlyph - 1].ubType & MTYPE_SINGLE) &&
!(pFontPDev->flFlags & FDV_SINGLE_BYTE) )
{
pFontPDev->flFlags &= ~FDV_DOUBLE_BYTE;
pFontPDev->flFlags |= FDV_SINGLE_BYTE;
pCmd = pCmdSingle;
bPrint = TRUE;
}
else
if (pCmdDouble &&
(pTrans[*pdwGlyph - 1].ubType & MTYPE_DOUBLE) &&
!(pFontPDev->flFlags & FDV_DOUBLE_BYTE) )
{
pFontPDev->flFlags |= FDV_DOUBLE_BYTE;
pFontPDev->flFlags &= ~FDV_SINGLE_BYTE;
pCmd = pCmdDouble;
bPrint = TRUE;
}
if (bPrint)
{
if (dwI != 0)
{
HANDLE_VECTORPROCS(pPDev, VMOutputCharStr, ((PDEVOBJ)pPDev,
(PUNIFONTOBJ)pUFObj,
TYPE_GLYPHHANDLE,
dwCount,
pdwGlyphStart))
else
CALL_OEMOUTPUTCHARSTR(TYPE_GLYPHHANDLE, dwCount, pdwGlyphStart);
//
// Update position
//
GET_CHARWIDTH(iXInc, pFontMap, pgp->hg);
VSetCursor( pPDev,
iXInc,
0,
MOVE_RELATIVE|MOVE_UPDATE,
&ptlRem);
dwCount = 0;
pdwGlyphStart = pdwGlyph;
}
WriteChannel(pPDev, pCmd);
bPrint = FALSE;
}
}
HANDLE_VECTORPROCS(pPDev, VMOutputCharStr, ((PDEVOBJ)pPDev,
(PUNIFONTOBJ)pUFObj,
TYPE_GLYPHHANDLE,
dwCount,
pdwGlyphStart))
else
CALL_OEMOUTPUTCHARSTR(TYPE_GLYPHHANDLE, dwCount, pdwGlyphStart);
}
//
// Output may have successed, so update the position.
//
pgp --;
GET_CHARWIDTH(iXInc, pFontMap, pgp->hg);
VSetCursor( pPDev,
pgp->ptl.x + iXInc,
pgp->ptl.y,
MOVE_ABSOLUTE|MOVE_UPDATE,
&ptlRem);
}
return pTod->cGlyphsToPrint;
}
BOOL
BFontCmdCallback(
PDEV *pdev,
PFONTMAP pFM,
POINTL *pptl,
BOOL bSelect)
/*++
Routine Description:
Implementation of OEM SendFontCmd calling sub routine for FONTMAP dispatch routine
Arguments:
pdev - a pointer to PDEV
pFM - a pointer to FONTMAP
pptl - a pointer to POINTL which has the height and with of font
bSelect - Boolean to send selection/deselection command
Return Value:
TRUE if successful, otherwise FALSE.
Note:
--*/
{
PFN_OEMSendFontCmd pfnOEMSendFontCmd;
FONTPDEV *pFontPDev;
PFONTMAP_DEV pfmdev;
FINVOCATION FInv;
ASSERT(pdev && pFM);
if (pdev->pOemHookInfo &&
(pfnOEMSendFontCmd = (PFN_OEMSendFontCmd)pdev->pOemHookInfo[EP_OEMSendFontCmd].pfnHook) ||
(pdev->ePersonality == kPCLXL))
{
pFontPDev = pdev->pFontPDev;
pFontPDev->flFlags &= ~FDV_DOUBLE_BYTE | FDV_SINGLE_BYTE;
if (pFM->dwFontType == FMTYPE_DEVICE)
{
pfmdev = pFM->pSubFM;
pfmdev->ulCodepageID = (ULONG)-1;
pFontPDev->pUFObj->pFontMap = pFM;
if (pFM->flFlags & FM_IFIVER40)
{
if (bSelect)
{
FInv.dwCount = pfmdev->cmdFontSel.pCD->wLength;
FInv.pubCommand = pfmdev->cmdFontSel.pCD->rgchCmd;
}
else
{
FInv.dwCount = pfmdev->cmdFontDesel.pCD->wLength;
FInv.pubCommand = pfmdev->cmdFontDesel.pCD->rgchCmd;
}
}
else
{
if (bSelect)
{
FInv.dwCount = pfmdev->cmdFontSel.FInv.dwCount;
FInv.pubCommand = pfmdev->cmdFontSel.FInv.pubCommand;
}
else
{
FInv.dwCount = pfmdev->cmdFontDesel.FInv.dwCount;
FInv.pubCommand = pfmdev->cmdFontDesel.FInv.pubCommand;
}
}
}
else
if (pFM->dwFontType == FMTYPE_TTOEM)
{
//
// Initialize UNIFONTOBJ
//
pFontPDev->pUFObj->ulFontID = pFM->ulDLIndex;
pFontPDev->pUFObj->pFontMap = pFM;
//
// Initialize FInv
//
FInv.dwCount = sizeof(ULONG);
FInv.pubCommand = (PBYTE)&(pFontPDev->pUFObj->ulFontID);
}
HANDLE_VECTORPROCS(pdev, VMSendFontCmd, ((PDEVOBJ)pdev,
(PUNIFONTOBJ)pFontPDev->pUFObj,
&FInv))
else
{
FIX_DEVOBJ(pdev, EP_OEMSendFontCmd);
if (pdev->pOemEntry)
{
if(((POEM_PLUGIN_ENTRY)pdev->pOemEntry)->pIntfOem ) // OEM plug in uses COM and function is implemented.
{
HRESULT hr ;
hr = HComSendFontCmd((POEM_PLUGIN_ENTRY)pdev->pOemEntry,
&pdev->devobj, (PUNIFONTOBJ)pFontPDev->pUFObj,
&FInv);
if(SUCCEEDED(hr))
; // cool !
}
else
{
if (NULL != pfnOEMSendFontCmd)
{
pfnOEMSendFontCmd(&pdev->devobj,
(PUNIFONTOBJ)pFontPDev->pUFObj,
&FInv);
}
}
}
}
}
return TRUE;
}
BOOL
BSelectFontCallback(
PDEV *pdev,
PFONTMAP pFM,
POINTL *pptl)
/*++
Routine Description:
Implementation of OEM SendFontCMd calling routine for FONTMAP dispatch routine
Arguments:
pTod - a pointer to TO_DATA.
Return Value:
The number of glyph printed.
Note:
--*/
{
return BFontCmdCallback(pdev, pFM, pptl, TRUE);
}
BOOL
BDeselectFontCallback(
PDEV *pdev,
PFONTMAP pFM)
/*++
Routine Description:
Implementation of OEM SendFontCmd calling routine for FONTMAP dispatch routine
Arguments:
pTod - a pointer to TO_DATA.
Return Value:
The number of glyph printed.
Note:
--*/
{
return BFontCmdCallback(pdev, pFM, NULL, FALSE);
}
DWORD
DwDLHeaderOEMCallback(
PDEV *pPDev,
PFONTMAP pFM)
/*++
Routine Description:
Implementation of OEM SendFontCmd calling routine for FONTMAP dispatch routine
Arguments:
pPDev - a pointer to PDEV
pFM - a pointer to FONTMAP
Return Value:
Note:
--*/
{
PFN_OEMDownloadFontHeader pfnOEMDownloadFontHeader;
PFONTPDEV pFontPDev;
DWORD dwMem = 0;
//
// Should not be NULL
//
ASSERT(pPDev && pFM);
pFontPDev = pPDev->pFontPDev;
pfnOEMDownloadFontHeader = NULL;
if ( pPDev->pOemHookInfo &&
(pfnOEMDownloadFontHeader = (PFN_OEMDownloadFontHeader)
pPDev->pOemHookInfo[EP_OEMDownloadFontHeader].pfnHook) ||
(pPDev->ePersonality == kPCLXL))
{
HRESULT hr ;
if (pFontPDev->pUFObj == NULL)
{
//
// This should not happen. pUFObj must be initialized.
//
ERR(("DwDLHeaderOEMCallback: pFontPDev->pUFObj is NULL"));
return 0;
}
pFontPDev->pUFObj->pFontMap = pFM;
pFontPDev->pUFObj->ulFontID = pFM->ulDLIndex;
BUpdateStandardVar(pPDev, pFM, 0, 0, STD_STD | STD_NFID);
WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_SETFONTID));
HANDLE_VECTORPROCS(pPDev, VMDownloadFontHeader, ((PDEVOBJ)pPDev,
(PUNIFONTOBJ)pFontPDev->pUFObj,
&dwMem))
else
{
FIX_DEVOBJ(pPDev, EP_OEMDownloadFontHeader);
if (pPDev->pOemEntry)
{
if(((POEM_PLUGIN_ENTRY)pPDev->pOemEntry)->pIntfOem ) // OEM plug in uses COM and function is implemented.
{
hr = HComDownloadFontHeader((POEM_PLUGIN_ENTRY)pPDev->pOemEntry,
&pPDev->devobj, (PUNIFONTOBJ)pFontPDev->pUFObj, &dwMem);
if(SUCCEEDED(hr))
; // cool !
}
else if (pfnOEMDownloadFontHeader)
{
dwMem = pfnOEMDownloadFontHeader(&pPDev->devobj,
(PUNIFONTOBJ)pFontPDev->pUFObj);
}
}
}
}
return dwMem;
}
DWORD
DwDLGlyphOEMCallback(
PDEV *pPDev,
PFONTMAP pFM,
HGLYPH hGlyph,
WORD wDLGlyphId,
WORD *pwWidth)
/*++
Routine Description:
Implementation of OEM SendFontCmd calling routine for FONTMAP dispatch routine
Arguments:
pPDev - a pointer to PDEV
pFM - a pointer to FONTMAP
Return Value:
Note:
--*/
{
PFN_OEMDownloadCharGlyph pfnOEMDownloadCharGlyph;
PI_UNIFONTOBJ pUFObj;
PFONTPDEV pFontPDev;
DL_MAP *pdm;
DWORD dwMem;
INT iWide;
//
// There values have to be non-NULL.
//
ASSERT(pPDev && pFM);
dwMem = 0;
iWide = 0;
pFontPDev = pPDev->pFontPDev;
pUFObj = pFontPDev->pUFObj;
pdm = ((PFONTMAP_TTOEM)pFM->pSubFM)->u.pvDLData;
pfnOEMDownloadCharGlyph = NULL;
//
// There values have to be non-NULL.
//
ASSERT(pFontPDev && pUFObj && pdm);
if ( pPDev->pOemHookInfo &&
(pfnOEMDownloadCharGlyph = (PFN_OEMDownloadCharGlyph)
pPDev->pOemHookInfo[EP_OEMDownloadCharGlyph].pfnHook) ||
(pPDev->ePersonality == kPCLXL))
{
HRESULT hr ;
if (!(PFDV->flFlags & FDV_SET_FONTID))
{
pFM->ulDLIndex = pdm->wCurrFontId;
BUpdateStandardVar(pPDev, pFM, 0, 0, STD_STD | STD_NFID);
WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_SETFONTID));
PFDV->flFlags |= FDV_SET_FONTID;
}
BUpdateStandardVar(pPDev, pFM, wDLGlyphId, 0, STD_GL);
WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_SETCHARCODE));
pUFObj->pFontMap = pFM;
pUFObj->ulFontID = pFM->ulDLIndex;
HANDLE_VECTORPROCS(pPDev, VMDownloadCharGlyph, ((PDEVOBJ)pPDev,
(PUNIFONTOBJ)pFontPDev->pUFObj,
hGlyph,
(PDWORD)&iWide,
&dwMem))
else
{
FIX_DEVOBJ(pPDev, EP_OEMDownloadCharGlyph);
if (pPDev->pOemEntry)
{
if(((POEM_PLUGIN_ENTRY)pPDev->pOemEntry)->pIntfOem ) // OEM plug in uses COM and function is implemented.
{
hr = HComDownloadCharGlyph((POEM_PLUGIN_ENTRY)pPDev->pOemEntry,
&pPDev->devobj,
(PUNIFONTOBJ)pFontPDev->pUFObj,
hGlyph,
(PDWORD)&iWide, &dwMem);
if(SUCCEEDED(hr))
; // cool !
}
else if (pfnOEMDownloadCharGlyph)
{
dwMem = pfnOEMDownloadCharGlyph(&pPDev->devobj,
(PUNIFONTOBJ)pFontPDev->pUFObj,
hGlyph,
(PDWORD)&iWide);
}
}
}
((PFONTMAP_TTOEM)pFM->pSubFM)->dwDLSize += dwMem;
*pwWidth = (WORD)iWide;
}
return dwMem;
}
BOOL
BCheckCondOEMCallback(
PDEV *pPDev,
FONTOBJ *pfo,
STROBJ *pso,
IFIMETRICS *pifi
)
/*++
Routine Description:
Implementation of CheckConditon for FONTMAP dispatch routine
Arguments:
pPDev - a pointer to PDEV
pfo - a pointer to FONTOBJ
pso - a pointer to STROBJ
pifi - a pointer to IFIMETRICS
Return Value:
Note:
--*/
{
PFONTPDEV pFontPDev;
PI_UNIFONTOBJ pUFObj;
ASSERT(pPDev);
pFontPDev = pPDev->pFontPDev;
pUFObj = pFontPDev->pUFObj;
if (pUFObj->dwFlags & UFOFLAG_TTFONT)
return TRUE;
else
return FALSE;
}
BOOL
BSelectTrueTypeOutline(
PDEV *pPDev,
PFONTMAP pFM,
POINTL *pptl)
{
BOOL bRet = FALSE;
if( pFM->flFlags & FM_SOFTFONT )
{
if (BUpdateStandardVar(pPDev, pFM, 0, 0, STD_STD | STD_CFID ) &&
BFontCmdCallback(pPDev, pFM, pptl, TRUE) )
bRet = TRUE;
}
return bRet;
}
BOOL
BDeselectTrueTypeOutline(
PDEV *pPDev,
PFONTMAP pFM)
{
BOOL bRet = FALSE;
DWORD dwFlags;
PFONTPDEV pFontPDev = pPDev->pFontPDev;
PFONTMAP_TTOEM pFMOEM = (PFONTMAP_TTOEM) pFM->pSubFM;
//
// Deselect case. We need to reinitialize UFObj
//
dwFlags = ((PI_UNIFONTOBJ)pFontPDev->pUFObj)->dwFlags;
((PI_UNIFONTOBJ)pFontPDev->pUFObj)->dwFlags = pFMOEM->dwFlags;
if( pFM->flFlags & FM_SOFTFONT )
{
if (BUpdateStandardVar(pPDev, pFM, 0, 0, STD_STD | STD_CFID ) &&
BFontCmdCallback(pPDev, pFM, NULL, 0) )
bRet = TRUE;
}
//
// Restore the current dwFlags in UFOBJ
//
((PI_UNIFONTOBJ)pFontPDev->pUFObj)->dwFlags = dwFlags;
return bRet;
}
BOOL
BOEMFreePFMCallback(
PFONTMAP pfm)
/*++
Routine Description:
Implementation of PFM Free function for FONTMAP dispatch routine
Arguments:
pFM - a pointer to FONTMAP
Return Value:
Note:
--*/
{
ASSERT(pfm);
if (pfm)
{
if (pfm->pIFIMet)
MemFree(pfm->pIFIMet);
MemFree(pfm);
return TRUE;
}
else
return FALSE;
}
PFONTMAP
PfmInitPFMOEMCallback(
PDEV *pPDev,
FONTOBJ *pfo)
/*++
Routine Description:
Implementation of PfmInit for FONTMAP dispatch routine
Arguments:
pPDev - a pointer to PDEV
pfo - a pointer to FONTOBJ
Return Value:
A pointer to FONTMAP
Note:
--*/
{
PFONTPDEV pFontPDev;
PFONTMAP pfm;
DWORD dwSize;
ASSERT(pPDev && pfo);
pFontPDev = pPDev->pFontPDev;
dwSize = sizeof(FONTMAP) + sizeof(FONTMAP_TTOEM);
if (pfm = MemAlloc(dwSize))
{
PFONTMAP_TTOEM pFMOEM;
ZeroMemory(pfm, dwSize);
pfm->dwSignature = FONTMAP_ID;
pfm->dwSize = sizeof(FONTMAP);
pfm->dwFontType = FMTYPE_TTOEM;
pfm->pSubFM = (PVOID)(pfm+1);
pfm->wFirstChar = 0;
pfm->wLastChar = 0xffff;
pfm->wXRes = (WORD)pPDev->ptGrxRes.x;
pfm->wYRes = (WORD)pPDev->ptGrxRes.y;
pfm->pIFIMet = pFontPDev->pIFI;
pfm->ulDLIndex = (ULONG)-1;
if (!(pFontPDev->flFlags & FDV_ALIGN_BASELINE) )
{
pfm->syAdj = ((IFIMETRICS*)pfm->pIFIMet)->fwdWinAscender;
}
if (pPDev->pOemHookInfo &&
pPDev->pOemHookInfo[EP_OEMOutputCharStr].pfnHook ||
(pPDev->ePersonality == kPCLXL)
)
pfm->pfnGlyphOut = DwOutputGlyphCallback;
else
pfm->pfnGlyphOut = DwTrueTypeBMPGlyphOut;
if (pPDev->ePersonality == kPCLXL)
{
pfm->pfnSelectFont = BSelectTrueTypeOutline;
pfm->pfnDeSelectFont = BDeselectTrueTypeOutline;
}
else
if (pFontPDev->pUFObj->dwFlags & UFOFLAG_TTDOWNLOAD_TTOUTLINE)
{
pfm->pfnSelectFont = BSelectTrueTypeOutline;
pfm->pfnDeSelectFont = BDeselectTrueTypeOutline;
}
else
if (pFontPDev->pUFObj->dwFlags & UFOFLAG_TTDOWNLOAD_BITMAP)
{
pfm->pfnSelectFont = BSelectTrueTypeBMP;
pfm->pfnDeSelectFont = BDeselectTrueTypeBMP;
}
pfm->pfnDownloadFontHeader = DwDLHeaderOEMCallback;
pfm->pfnDownloadGlyph = DwDLGlyphOEMCallback;
pfm->pfnCheckCondition = BCheckCondOEMCallback;
pfm->pfnFreePFM = BOEMFreePFMCallback;
pFMOEM = (PFONTMAP_TTOEM) pfm->pSubFM;
pFMOEM->dwFlags = ((PI_UNIFONTOBJ)pFontPDev->pUFObj)->dwFlags;
pFMOEM->flFontType = pfo->flFontType;
if (pFontPDev->pUFObj->dwFlags & UFOFLAG_TTDOWNLOAD_TTOUTLINE)
{
if (pfo->flFontType & FO_SIM_BOLD)
pFontPDev->pUFObj->dwFlags |= UFOFLAG_TTOUTLINE_BOLD_SIM;
if (pfo->flFontType & FO_SIM_ITALIC)
pFontPDev->pUFObj->dwFlags |= UFOFLAG_TTOUTLINE_ITALIC_SIM;
if (NULL != pFontPDev->pIFI &&
'@' == *((PBYTE)pFontPDev->pIFI + pFontPDev->pIFI->dpwszFamilyName))
{
pFontPDev->pUFObj->dwFlags |= UFOFLAG_TTOUTLINE_VERTICAL;
}
}
}
else
{
ERR(("PfmInitPFMOEMCallback: MemAlloc failed.\n"));
}
return pfm;
}
//
// Misc functions
//
VOID
VUFObjFree(
IN FONTPDEV* pFontPDev)
/*++
Routine Description:
UFObj(UNIFONTOBJ) memory free function
Arguments:
pFontPDev - a pointer to FONTPDEV.
Return Value:
Note:
--*/
{
PI_UNIFONTOBJ pUFObj = pFontPDev->pUFObj;
ASSERT(pFontPDev);
pUFObj = pFontPDev->pUFObj;
if (pUFObj && pUFObj->pGlyph)
MemFree(pUFObj->pGlyph);
pFontPDev->pUFObj = NULL;
}
WCHAR
WGHtoUnicode(
DWORD dwNumOfRuns,
PGLYPHRUN pGlyphRun,
HGLYPH hg)
/*++
Routine Description:
Character coversion function from HGLYPH to Unicode.
Arguments:
dwNumOfRuns - number of run in pGlyphRun
pGlyphRun - a pointer to glyph run
hd - HGLYPH
Return Value:
Unicode character
Note:
--*/
{
DWORD dwI;
HGLYPH hCurrent = 1;
WCHAR wchChar = 0;
ASSERT(pGlyphRun);
for( dwI = 0; dwI < dwNumOfRuns; dwI ++, pGlyphRun ++)
{
if (hCurrent <= hg && hg < hCurrent + pGlyphRun->wGlyphCount)
{
wchChar = (WCHAR)(pGlyphRun->wcLow + hg - hCurrent);
break;
}
hCurrent += pGlyphRun->wGlyphCount;
}
return wchChar;
}