mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
689 lines
18 KiB
C
689 lines
18 KiB
C
/*
|
|
* PROJECT: ReactOS win32 subsystem
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* PURPOSE: GDI font driver for bitmap fonts
|
|
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
|
*/
|
|
|
|
#include "bmfd.h"
|
|
|
|
static
|
|
BOOLEAN
|
|
IsValidPtr(
|
|
PVOID p,
|
|
ULONG cjSize,
|
|
PVOID pStart,
|
|
PVOID pEnd,
|
|
ULONG cjAlign)
|
|
{
|
|
if ((ULONG_PTR)p < (ULONG_PTR)pStart ||
|
|
(ULONG_PTR)p + cjSize >= (ULONG_PTR)pEnd ||
|
|
(ULONG_PTR)p & (cjAlign -1))
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
FillFaceInfo(
|
|
PBMFD_FACE pface,
|
|
PFONTINFO16 pFontInfo)
|
|
{
|
|
CHAR ansi[4];
|
|
WCHAR unicode[4];
|
|
ULONG written;
|
|
DWORD dfFlags;
|
|
|
|
pface->pFontInfo = pFontInfo;
|
|
pface->ulVersion = GETVAL(pFontInfo->dfVersion);
|
|
pface->cGlyphs = pFontInfo->dfLastChar - pFontInfo->dfFirstChar + 1;
|
|
|
|
/* Convert chars to unicode */
|
|
ansi[0] = pFontInfo->dfFirstChar;
|
|
ansi[1] = pFontInfo->dfLastChar;
|
|
ansi[2] = pFontInfo->dfFirstChar + pFontInfo->dfDefaultChar;
|
|
ansi[3] = pFontInfo->dfFirstChar + pFontInfo->dfBreakChar;
|
|
EngMultiByteToUnicodeN(unicode, 4 * sizeof(WCHAR), &written, ansi, 4);
|
|
pface->wcFirstChar = unicode[0];
|
|
pface->wcLastChar = unicode[1];
|
|
pface->wcDefaultChar = unicode[2];
|
|
pface->wcBreakChar = unicode[3];
|
|
|
|
/* Copy some values */
|
|
pface->wPixHeight = GETVAL(pFontInfo->dfPixHeight);
|
|
pface->wPixWidth = GETVAL(pFontInfo->dfPixWidth);
|
|
pface->wWidthBytes = GETVAL(pFontInfo->dfWidthBytes);
|
|
pface->wAscent = GETVAL(pFontInfo->dfAscent);
|
|
pface->wDescent = pface->wPixHeight - pface->wAscent;
|
|
|
|
/* Some version specific members */
|
|
if (pface->ulVersion >= 0x300)
|
|
{
|
|
dfFlags = GETVAL(pFontInfo->dfFlags);
|
|
pface->wA = GETVAL(pFontInfo->dfAspace);
|
|
pface->wB = GETVAL(pFontInfo->dfBspace);
|
|
pface->wC = GETVAL(pFontInfo->dfCspace);
|
|
pface->pCharTable = pFontInfo->dfCharTable;
|
|
pface->cjEntrySize = sizeof(GLYPHENTRY30);
|
|
}
|
|
else
|
|
{
|
|
dfFlags = DFF_1COLOR;
|
|
pface->wA = 0;
|
|
pface->wB = 0;
|
|
pface->wC = 0;
|
|
pface->pCharTable = &pFontInfo->dfReserved + 1;
|
|
pface->cjEntrySize = sizeof(GLYPHENTRY20);
|
|
}
|
|
|
|
pface->flInfo = FM_INFO_MASK;
|
|
|
|
/* If dfWidth is non-null, we have a fixed width font */
|
|
if (dfFlags & DFF_FIXED || pface->wPixWidth)
|
|
pface->flInfo |= FM_INFO_CONSTANT_WIDTH;
|
|
|
|
/* Initialize color depth flags */
|
|
if (dfFlags & DFF_1COLOR)
|
|
pface->flInfo |= FM_INFO_1BPP;
|
|
else if (dfFlags & DFF_16COLOR)
|
|
pface->flInfo |= FM_INFO_4BPP;
|
|
else if (dfFlags & DFF_256COLOR)
|
|
pface->flInfo |= FM_INFO_8BPP;
|
|
else if (dfFlags & DFF_RGBCOLOR)
|
|
pface->flInfo |= FM_INFO_24BPP;
|
|
|
|
// TODO: walk through all glyphs and veryfy them and calculate max values
|
|
|
|
// FIXME: After this point, the whole font data should be verified!
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
PVOID
|
|
ParseFntFile(
|
|
PVOID pvView,
|
|
ULONG cjView)
|
|
{
|
|
/* unimplemented */
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static
|
|
PVOID
|
|
ParseFonFile(
|
|
PVOID pvView,
|
|
ULONG cjView)
|
|
{
|
|
PIMAGE_DOS_HEADER pDosHeader = pvView;
|
|
PIMAGE_OS2_HEADER pOs2Header;
|
|
PNE_RESTABLE pResTable;
|
|
PNE_TYPEINFO pTInfo;
|
|
PFONTINFO16 pFontInfo;
|
|
PCHAR pStart, pEnd;
|
|
PBMFD_FILE pfile = NULL;
|
|
WORD wShift;
|
|
ULONG i, cjOffset, cjLength;
|
|
ULONG type_id, count;
|
|
|
|
/* Initial margins for valid pointers */
|
|
pStart = pvView;
|
|
pEnd = pStart + cjView;
|
|
|
|
/* Check for image dos header */
|
|
if (GETVAL(pDosHeader->e_magic) != IMAGE_DOS_MAGIC)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/* Get pointer to OS2 header and veryfy it is valid */
|
|
pOs2Header = (PVOID)((PCHAR)pDosHeader + GETVAL(pDosHeader->e_lfanew));
|
|
pStart += sizeof(IMAGE_DOS_HEADER);
|
|
if (!IsValidPtr(pOs2Header, sizeof(IMAGE_OS2_HEADER), pStart, pEnd, 4))
|
|
{
|
|
DbgPrint("e_lfanew is invalid: 0x%lx\n", pDosHeader->e_lfanew);
|
|
return NULL;
|
|
}
|
|
|
|
/* Get pointer to resource table and verify it is valid */
|
|
pResTable = (PVOID)((PCHAR)pOs2Header + GETVAL(pOs2Header->ne_rsrctab));
|
|
pStart = (PCHAR)pOs2Header;
|
|
if (!IsValidPtr(pResTable, sizeof(NE_RESTABLE), pStart, pEnd, 1))
|
|
{
|
|
DbgPrint("pTInfo is invalid: 0x%p\n", pResTable);
|
|
return NULL;
|
|
}
|
|
|
|
wShift = GETVAL(pResTable->size_shift);
|
|
pTInfo = pResTable->typeinfo;
|
|
type_id = GETVAL(pTInfo->type_id);
|
|
|
|
/* Loop the resource table to find a font resource */
|
|
while (type_id)
|
|
{
|
|
/* Get number of nameinfo entries */
|
|
count = GETVAL(pTInfo->count);
|
|
|
|
/* Look for a font resource */
|
|
if (type_id == NE_RSCTYPE_FONT && count > 0)
|
|
{
|
|
DbgPrint("Found NE_RSCTYPE_FONT\n");
|
|
|
|
/* Allocate an info structure for this font and all faces */
|
|
cjLength = sizeof(BMFD_FILE) + (count-1) * sizeof(BMFD_FACE);
|
|
pfile = EngAllocMem(0, cjLength, TAG_FONTINFO);
|
|
if (!pfile)
|
|
{
|
|
DbgPrint("Not enough memory: %ld\n", cjLength);
|
|
return NULL;
|
|
}
|
|
|
|
pfile->cNumFaces = count;
|
|
|
|
/* Fill all face info structures */
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
cjOffset = GETVAL(pTInfo->nameinfo[i].offset) << wShift;
|
|
cjLength = GETVAL(pTInfo->nameinfo[i].length) << wShift;
|
|
pFontInfo = (PVOID)((PCHAR)pDosHeader + cjOffset);
|
|
|
|
if (!IsValidPtr(pFontInfo, cjLength, pStart, pEnd, 1))
|
|
{
|
|
DbgPrint("pFontInfo is invalid: 0x%p\n", pFontInfo);
|
|
EngFreeMem(pfile);
|
|
return NULL;
|
|
}
|
|
|
|
/* Validate FONTINFO and fill face info */
|
|
if (!FillFaceInfo(&pfile->aface[i], pFontInfo))
|
|
{
|
|
DbgPrint("pFontInfo is invalid: 0x%p\n", pFontInfo);
|
|
EngFreeMem(pfile);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* Break out of the loop */
|
|
break;
|
|
}
|
|
|
|
/* Following pointers must be bigger than this */
|
|
pStart = (PCHAR)pTInfo;
|
|
|
|
/* Goto next entry in resource table */
|
|
pTInfo = (PVOID)&pTInfo->nameinfo[count];
|
|
|
|
/* Verify that the new pTInfo pointer is valid */
|
|
if (!IsValidPtr(pTInfo, sizeof(NE_TYPEINFO), pStart, pEnd, 1))
|
|
{
|
|
DbgPrint("pTInfo is invalid: 0x%p\n", pTInfo);
|
|
return NULL;
|
|
}
|
|
|
|
type_id = GETVAL(pTInfo->type_id);
|
|
}
|
|
|
|
return pfile;
|
|
}
|
|
|
|
/** Public Interface **********************************************************/
|
|
|
|
ULONG_PTR
|
|
APIENTRY
|
|
BmfdLoadFontFile(
|
|
ULONG cFiles,
|
|
ULONG_PTR *piFile,
|
|
PVOID *ppvView,
|
|
ULONG *pcjView,
|
|
DESIGNVECTOR *pdv,
|
|
ULONG ulLangID,
|
|
ULONG ulFastCheckSum)
|
|
{
|
|
PBMFD_FILE pfile = NULL;
|
|
PVOID pvView;
|
|
ULONG cjView;
|
|
|
|
DbgPrint("BmfdLoadFontFile()\n");
|
|
__debugbreak();
|
|
|
|
/* Check parameters */
|
|
if (cFiles != 1)
|
|
{
|
|
DbgPrint("Only 1 File is allowed, got %ld!\n", cFiles);
|
|
return HFF_INVALID;
|
|
}
|
|
|
|
/* Map the font file */
|
|
if (!EngMapFontFileFD(*piFile, (PULONG*)&pvView, &cjView))
|
|
{
|
|
DbgPrint("Could not map font file!\n", cFiles);
|
|
return HFF_INVALID;
|
|
}
|
|
|
|
DbgPrint("mapped font file to %p, site if %ld\n", pvView, cjView);
|
|
|
|
/* Try to parse a .fon file */
|
|
pfile = ParseFonFile(pvView, cjView);
|
|
|
|
if (!pfile)
|
|
{
|
|
/* Could be a .fnt file */
|
|
pfile = ParseFntFile(pvView, cjView);
|
|
}
|
|
|
|
/* Check whether we succeeded finding a font */
|
|
if (!pfile)
|
|
{
|
|
DbgPrint("No font data found\n");
|
|
|
|
/* Unmap the file */
|
|
EngUnmapFontFileFD(*piFile);
|
|
|
|
/* Failure! */
|
|
return HFF_INVALID;
|
|
}
|
|
|
|
pfile->iFile = *piFile;
|
|
pfile->pvView = pvView;
|
|
|
|
/* Success, return the pointer to font info structure */
|
|
return (ULONG_PTR)pfile;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
BmfdUnloadFontFile(
|
|
IN ULONG_PTR iFile)
|
|
{
|
|
PBMFD_FILE pfile = (PBMFD_FILE)iFile;
|
|
|
|
DbgPrint("BmfdUnloadFontFile()\n");
|
|
|
|
/* Unmap the font file */
|
|
EngUnmapFontFileFD(pfile->iFile);
|
|
|
|
/* Free the memory that was allocated for the font */
|
|
EngFreeMem(pfile);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
BmfdQueryFontFile(
|
|
ULONG_PTR iFile,
|
|
ULONG ulMode,
|
|
ULONG cjBuf,
|
|
ULONG *pulBuf)
|
|
{
|
|
PBMFD_FILE pfile = (PBMFD_FILE)iFile;
|
|
|
|
DbgPrint("BmfdQueryFontFile()\n");
|
|
// __debugbreak();
|
|
|
|
switch (ulMode)
|
|
{
|
|
case QFF_DESCRIPTION:
|
|
{
|
|
/* We copy the face name of the 1st face */
|
|
PCHAR pDesc = pfile->aface[0].pszFaceName;
|
|
ULONG cOutSize;
|
|
if (pulBuf)
|
|
{
|
|
EngMultiByteToUnicodeN((LPWSTR)pulBuf,
|
|
cjBuf,
|
|
&cOutSize,
|
|
pDesc,
|
|
strnlen(pDesc, LF_FACESIZE));
|
|
}
|
|
else
|
|
{
|
|
cOutSize = (strnlen(pDesc, LF_FACESIZE) + 1) * sizeof(WCHAR);
|
|
}
|
|
return cOutSize;
|
|
}
|
|
|
|
case QFF_NUMFACES:
|
|
/* return the number of faces in the file */
|
|
return pfile->cNumFaces;
|
|
|
|
default:
|
|
return FD_ERROR;
|
|
}
|
|
}
|
|
|
|
LONG
|
|
APIENTRY
|
|
BmfdQueryFontCaps(
|
|
ULONG culCaps,
|
|
ULONG *pulCaps)
|
|
{
|
|
DbgPrint("BmfdQueryFontCaps()\n");
|
|
|
|
/* We need room for 2 ULONGs */
|
|
if (culCaps < 2)
|
|
{
|
|
return FD_ERROR;
|
|
}
|
|
|
|
/* We only support 1 bpp */
|
|
pulCaps[0] = 2;
|
|
pulCaps[1] = QC_1BIT;
|
|
|
|
return 2;
|
|
}
|
|
|
|
|
|
PVOID
|
|
APIENTRY
|
|
BmfdQueryFontTree(
|
|
DHPDEV dhpdev,
|
|
ULONG_PTR iFile,
|
|
ULONG iFace,
|
|
ULONG iMode,
|
|
ULONG_PTR *pid)
|
|
{
|
|
PBMFD_FILE pfile = (PBMFD_FILE)iFile;
|
|
PBMFD_FACE pface;
|
|
ULONG i, j, cjSize, cGlyphs, cRuns;
|
|
CHAR ch, chFirst, ach[256];
|
|
WCHAR wc, awc[256];
|
|
PFD_GLYPHSET pGlyphSet;
|
|
WCRUN *pwcrun;
|
|
HGLYPH * phglyphs;
|
|
|
|
DbgPrint("DrvQueryFontTree(iMode=%ld)\n", iMode);
|
|
// __debugbreak();
|
|
|
|
/* Check parameters, we only support QFT_GLYPHSET */
|
|
if (!iFace || iFace > pfile->cNumFaces || iMode != QFT_GLYPHSET)
|
|
{
|
|
DbgPrint("iFace = %ld, cNumFaces = %ld\n", iFace, pfile->cNumFaces);
|
|
return NULL;
|
|
}
|
|
|
|
/* Get a pointer to the face data */
|
|
pface = &pfile->aface[iFace - 1];
|
|
|
|
/* Get the number of characters in the face */
|
|
cGlyphs = pface->cGlyphs;
|
|
|
|
chFirst = pface->pFontInfo->dfFirstChar;
|
|
|
|
/* Build array of supported chars */
|
|
for (i = 0; i < cGlyphs; i++)
|
|
{
|
|
ach[i] = chFirst + i;
|
|
}
|
|
|
|
/* Convert the chars to unicode */
|
|
EngMultiByteToUnicodeN(awc, sizeof(awc), NULL, ach, cGlyphs);
|
|
|
|
/* Sort both arrays in wchar order */
|
|
for (i = 0; i < cGlyphs - 1; i++)
|
|
{
|
|
wc = awc[i];
|
|
for (j = i + 1; j < cGlyphs; j++)
|
|
{
|
|
if (awc[j] < wc)
|
|
{
|
|
awc[i] = awc[j];
|
|
awc[j] = wc;
|
|
wc = awc[i];
|
|
ch = ach[i];
|
|
ach[i] = ach[j];
|
|
ach[j] = ch;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Find number of WCRUNs */
|
|
cRuns = 1;
|
|
for (i = 1; i < cGlyphs; i++)
|
|
{
|
|
if (awc[i] != awc[i - 1] + 1)
|
|
{
|
|
cRuns++;
|
|
}
|
|
}
|
|
|
|
/* Calculate FD_GLYPHSET size */
|
|
cjSize = sizeof(FD_GLYPHSET)
|
|
+ (cRuns - 1) * sizeof(WCRUN)
|
|
+ cGlyphs * sizeof(HGLYPH);
|
|
|
|
/* Allocate the FD_GLYPHSET structure */
|
|
pGlyphSet = EngAllocMem(0, cjSize, TAG_GLYPHSET);
|
|
if (!pGlyphSet)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/* Initialize FD_GLYPHSET */
|
|
pGlyphSet->cjThis = cjSize;
|
|
pGlyphSet->flAccel = 0;
|
|
pGlyphSet->cGlyphsSupported = cGlyphs;
|
|
pGlyphSet->cRuns = cRuns;
|
|
|
|
/* Initialize 1st WCRUN */
|
|
pwcrun = pGlyphSet->awcrun;
|
|
phglyphs = (PHGLYPH)&pGlyphSet->awcrun[cRuns];
|
|
pwcrun[0].wcLow = awc[0];
|
|
pwcrun[0].cGlyphs = 1;
|
|
pwcrun[0].phg = phglyphs;
|
|
phglyphs[0] = 0;
|
|
|
|
/* Walk through all supported chars */
|
|
for (i = 1, j = 0; i < cGlyphs; i++)
|
|
{
|
|
/* Use offset to glyph entry as hglyph */
|
|
phglyphs[i] = (ach[i] - chFirst) * pface->cjEntrySize;
|
|
|
|
/* Check whether we can append the wchar to a run */
|
|
if (awc[i] == awc[i - 1] + 1)
|
|
{
|
|
/* Append to current WCRUN */
|
|
pwcrun[j].cGlyphs++;
|
|
}
|
|
else
|
|
{
|
|
/* Add a new WCRUN */
|
|
j++;
|
|
pwcrun[j].wcLow = awc[i];
|
|
pwcrun[j].cGlyphs = 1;
|
|
pwcrun[j].phg = &phglyphs[i];
|
|
}
|
|
}
|
|
|
|
/* Set *pid to the allocated structure for use in BmfdFree */
|
|
*pid = (ULONG_PTR)pGlyphSet;
|
|
|
|
return pGlyphSet;
|
|
}
|
|
|
|
PIFIMETRICS
|
|
APIENTRY
|
|
BmfdQueryFont(
|
|
IN DHPDEV dhpdev,
|
|
IN ULONG_PTR iFile,
|
|
IN ULONG iFace,
|
|
IN ULONG_PTR *pid)
|
|
{
|
|
PBMFD_FILE pfile = (PBMFD_FILE)iFile;
|
|
PBMFD_FACE pface;
|
|
PFONTINFO16 pFontInfo;
|
|
PIFIMETRICS pifi;
|
|
PBMFD_IFIMETRICS pifiX;
|
|
PANOSE panose = {0};
|
|
|
|
DbgPrint("BmfdQueryFont()\n");
|
|
// __debugbreak();
|
|
|
|
/* Validate parameters */
|
|
if (iFace > pfile->cNumFaces || !pid)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pface = &pfile->aface[iFace - 1];
|
|
pFontInfo = pface->pFontInfo;
|
|
|
|
/* Allocate the structure */
|
|
pifiX = EngAllocMem(FL_ZERO_MEMORY, sizeof(BMFD_IFIMETRICS), TAG_IFIMETRICS);
|
|
if (!pifiX)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/* Return a pointer to free it later */
|
|
*pid = (ULONG_PTR)pifiX;
|
|
|
|
/* Fill IFIMETRICS */
|
|
pifi = &pifiX->ifim;
|
|
pifi->cjThis = sizeof(BMFD_IFIMETRICS);
|
|
pifi->cjIfiExtra = 0;
|
|
pifi->dpwszFamilyName = FIELD_OFFSET(BMFD_IFIMETRICS, wszFamilyName);
|
|
pifi->dpwszStyleName = FIELD_OFFSET(BMFD_IFIMETRICS, wszFamilyName);
|
|
pifi->dpwszFaceName = FIELD_OFFSET(BMFD_IFIMETRICS, wszFaceName);
|
|
pifi->dpwszUniqueName = FIELD_OFFSET(BMFD_IFIMETRICS, wszFaceName);
|
|
pifi->dpFontSim = 0;
|
|
pifi->lEmbedId = 0;
|
|
pifi->lItalicAngle = 0;
|
|
pifi->lCharBias = 0;
|
|
pifi->dpCharSets = 0;
|
|
pifi->jWinCharSet = pFontInfo->dfCharSet;
|
|
pifi->jWinPitchAndFamily = pFontInfo->dfPitchAndFamily;
|
|
pifi->usWinWeight = GETVAL(pFontInfo->dfWeight);
|
|
pifi->flInfo = pface->flInfo;
|
|
pifi->fsSelection = 0;
|
|
pifi->fsType = 0;
|
|
pifi->fwdUnitsPerEm = GETVAL(pFontInfo->dfPixHeight);
|
|
pifi->fwdLowestPPEm = 0;
|
|
pifi->fwdWinAscender = GETVAL(pFontInfo->dfAscent);
|
|
pifi->fwdWinDescender = pifi->fwdUnitsPerEm - pifi->fwdWinAscender;
|
|
pifi->fwdMacAscender = pifi->fwdWinAscender;
|
|
pifi->fwdMacDescender = - pifi->fwdWinDescender;
|
|
pifi->fwdMacLineGap = 0;
|
|
pifi->fwdTypoAscender = pifi->fwdWinAscender;
|
|
pifi->fwdTypoDescender = - pifi->fwdWinDescender;
|
|
pifi->fwdTypoLineGap = 0;
|
|
pifi->fwdAveCharWidth = GETVAL(pFontInfo->dfAvgWidth);
|
|
pifi->fwdMaxCharInc = GETVAL(pFontInfo->dfMaxWidth);
|
|
pifi->fwdCapHeight = pifi->fwdUnitsPerEm / 2;
|
|
pifi->fwdXHeight = pifi->fwdUnitsPerEm / 4;
|
|
pifi->fwdSubscriptXSize = 0;
|
|
pifi->fwdSubscriptYSize = 0;
|
|
pifi->fwdSubscriptXOffset = 0;
|
|
pifi->fwdSubscriptYOffset = 0;
|
|
pifi->fwdSuperscriptXSize = 0;
|
|
pifi->fwdSuperscriptYSize = 0;
|
|
pifi->fwdSuperscriptXOffset = 0;
|
|
pifi->fwdSuperscriptYOffset = 0;
|
|
pifi->fwdUnderscoreSize = 01;
|
|
pifi->fwdUnderscorePosition = -1;
|
|
pifi->fwdStrikeoutSize = 1;
|
|
pifi->fwdStrikeoutPosition = pifi->fwdXHeight + 1;
|
|
pifi->chFirstChar = pFontInfo->dfFirstChar;
|
|
pifi->chLastChar = pFontInfo->dfLastChar;
|
|
pifi->chDefaultChar = pFontInfo->dfFirstChar + pFontInfo->dfDefaultChar;
|
|
pifi->chBreakChar = pFontInfo->dfFirstChar + pFontInfo->dfBreakChar;
|
|
pifi->wcFirstChar = pface->wcFirstChar;
|
|
pifi->wcLastChar = pface->wcLastChar;
|
|
pifi->wcDefaultChar = pface->wcDefaultChar;
|
|
pifi->wcBreakChar = pface->wcBreakChar;
|
|
pifi->ptlBaseline.x = 1;
|
|
pifi->ptlBaseline.y = 0;
|
|
pifi->ptlAspect.x = pFontInfo->dfVertRes; // CHECKME
|
|
pifi->ptlAspect.y = pFontInfo->dfHorizRes;
|
|
pifi->ptlCaret.x = 0;
|
|
pifi->ptlCaret.y = 1;
|
|
pifi->rclFontBox.left = 0;
|
|
pifi->rclFontBox.right = pifi->fwdAveCharWidth;
|
|
pifi->rclFontBox.top = pifi->fwdWinAscender;
|
|
pifi->rclFontBox.bottom = - pifi->fwdWinDescender;
|
|
*(DWORD*)&pifi->achVendId = 0x30303030; // FIXME
|
|
pifi->cKerningPairs = 0;
|
|
pifi->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN;
|
|
pifi->panose = panose;
|
|
|
|
/* Set char sets */
|
|
pifiX->ajCharSet[0] = pifi->jWinCharSet;
|
|
pifiX->ajCharSet[1] = DEFAULT_CHARSET;
|
|
|
|
if (pface->flInfo & FM_INFO_CONSTANT_WIDTH)
|
|
pifi->jWinPitchAndFamily |= FIXED_PITCH;
|
|
|
|
#if 0
|
|
EngMultiByteToUnicodeN(pifiX->wszFaceName,
|
|
LF_FACESIZE * sizeof(WCHAR),
|
|
NULL,
|
|
pFontInfo->,
|
|
strnlen(pDesc, LF_FACESIZE));
|
|
#endif
|
|
wcscpy(pifiX->wszFaceName, L"Courier-X");
|
|
wcscpy(pifiX->wszFamilyName, L"Courier-X");
|
|
|
|
/* Initialize font weight style flags and string */
|
|
if (pifi->usWinWeight == FW_REGULAR)
|
|
{
|
|
// pifi->fsSelection |= FM_SEL_REGULAR;
|
|
}
|
|
else if (pifi->usWinWeight > FW_SEMIBOLD)
|
|
{
|
|
pifi->fsSelection |= FM_SEL_BOLD;
|
|
wcscat(pifiX->wszStyleName, L"Bold ");
|
|
}
|
|
else if (pifi->usWinWeight <= FW_LIGHT)
|
|
{
|
|
wcscat(pifiX->wszStyleName, L"Light ");
|
|
}
|
|
|
|
if (pFontInfo->dfItalic)
|
|
{
|
|
pifi->fsSelection |= FM_SEL_ITALIC;
|
|
wcscat(pifiX->wszStyleName, L"Italic ");
|
|
}
|
|
|
|
if (pFontInfo->dfUnderline)
|
|
{
|
|
pifi->fsSelection |= FM_SEL_UNDERSCORE;
|
|
wcscat(pifiX->wszStyleName, L"Underscore ");
|
|
}
|
|
|
|
if (pFontInfo->dfStrikeOut)
|
|
{
|
|
pifi->fsSelection |= FM_SEL_STRIKEOUT;
|
|
wcscat(pifiX->wszStyleName, L"Strikeout ");
|
|
}
|
|
|
|
return pifi;
|
|
}
|
|
|
|
|
|
VOID
|
|
APIENTRY
|
|
BmfdFree(
|
|
PVOID pv,
|
|
ULONG_PTR id)
|
|
{
|
|
DbgPrint("BmfdFree()\n");
|
|
if (id)
|
|
{
|
|
EngFreeMem((PVOID)id);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
APIENTRY
|
|
BmfdDestroyFont(
|
|
IN FONTOBJ *pfo)
|
|
{
|
|
/* Free the font realization info */
|
|
EngFreeMem(pfo->pvProducer);
|
|
pfo->pvProducer = NULL;
|
|
}
|