Initial version of a gdi font driver for bitmap fonts (.fon / .fnt). It starts to work, but not yet correctly. Glyphs are truncated. Developed on Windows XP.

svn path=/trunk/; revision=39849
This commit is contained in:
Timo Kreuzer 2009-03-03 02:42:00 +00:00
parent eff51218fb
commit f1aeddb982
7 changed files with 1357 additions and 0 deletions

View file

@ -4,6 +4,9 @@
<directory name="displays">
<xi:include href="displays/directory.rbuild" />
</directory>
<directory name="font">
<xi:include href="font/directory.rbuild" />
</directory>
<directory name="miniport">
<xi:include href="miniport/directory.rbuild" />
</directory>

View file

@ -0,0 +1,359 @@
/*
* 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 <stdarg.h>
#include <windef.h>
#include <wingdi.h>
#include <winddi.h>
#if defined(_M_IX86) || defined(_M_AMD64)
/* on x86 and x64, unaligned access is allowed, byteorder is LE */
#define GETVAL(x) (x)
#else
// FIXME: BE
#define GETVAL(x) \
sizeof(x) == 1 ? (x) : \
sizeof(x) == 2 ? (((PCHAR)&(x))[0] + (((PCHAR)&(x))[1] << 8)) : \
(((PCHAR)&(x))[0] + (((PCHAR)&(x))[1] << 8) + (((PCHAR)&(x))[2] << 16) + \
(((PCHAR)&(x))[3] << 24))
#endif
#define FDM_MASK \
FDM_TYPE_CONST_BEARINGS | FDM_TYPE_ZERO_BEARINGS | \
FDM_TYPE_CHAR_INC_EQUAL_BM_BASE | FDM_TYPE_MAXEXT_EQUAL_BM_SIDE | \
FDM_TYPE_BM_SIDE_CONST
#define FM_INFO_MASK \
FM_INFO_TECH_BITMAP | FM_INFO_1BPP | FM_INFO_INTEGER_WIDTH | \
FM_INFO_RETURNS_BITMAPS | FM_INFO_RIGHT_HANDED | FM_INFO_INTEGRAL_SCALING |\
FM_INFO_90DEGREE_ROTATIONS | FM_INFO_OPTICALLY_FIXED_PITCH | FM_INFO_NONNEGATIVE_AC
#define FLOATL_1 0x3f800000
#define TAG_PDEV 'veDP'
#define TAG_GLYPHSET 'GlSt'
#define TAG_IFIMETRICS 'Ifim'
#define TAG_FONTINFO 'Font'
/** FON / FNT specific types **************************************************/
#define IMAGE_DOS_MAGIC 0x594D // FIXME: hack hack hack
#include <pshpack1.h>
typedef struct
{
WORD offset;
WORD length;
WORD flags;
WORD id;
WORD handle;
WORD usage;
} NE_NAMEINFO, *PNE_NAMEINFO;
#define NE_RSCTYPE_FONT 0x8008
#define NE_RSCTYPE_FONTDIR 0x8007
typedef struct
{
WORD type_id;
WORD count;
DWORD resloader;
NE_NAMEINFO nameinfo[1];
} NE_TYPEINFO, *PNE_TYPEINFO;
typedef struct
{
WORD size_shift;
NE_TYPEINFO typeinfo[1];
} NE_RESTABLE, *PNE_RESTABLE;
// Values of dfFlags:
#define DFF_FIXED 0x0001
#define DFF_PROPORTIONAL 0x0002
#define DFF_ABCFIXED 0x0004
#define DFF_ABCPROPORTIONAL 0x0008
#define DFF_1COLOR 0x0010
#define DFF_16COLOR 0x0020
#define DFF_256COLOR 0x0040
#define DFF_RGBCOLOR 0x0080
// see http://msdn.microsoft.com/en-us/library/ms648014(VS.85).aspx
typedef struct _FONTDIRENTRY
{
WORD dfVersion;
DWORD dfSize;
char dfCopyright[60];
WORD dfType;
WORD dfPoints;
WORD dfVertRes;
WORD dfHorizRes;
WORD dfAscent;
WORD dfInternalLeading;
WORD dfExternalLeading;
BYTE dfItalic;
BYTE dfUnderline;
BYTE dfStrikeOut;
WORD dfWeight;
BYTE dfCharSet;
WORD dfPixWidth;
WORD dfPixHeight;
BYTE dfPitchAndFamily;
WORD dfAvgWidth;
WORD dfMaxWidth;
BYTE dfFirstChar;
BYTE dfLastChar;
BYTE dfDefaultChar;
BYTE dfBreakChar;
WORD dfWidthBytes;
DWORD dfDevice;
DWORD dfFace;
DWORD dfReserved;
char szDeviceName[1];
char szFaceName[1];
} FONTDIRENTRY, *PFONTDIRENTRY;
typedef struct _DIRENTRY
{
WORD fontOrdinal;
FONTDIRENTRY fde;
} DIRENTRY, *PDIRENTRY;
typedef struct _FONTGROUPHDR
{
WORD NumberOfFonts;
DIRENTRY ade[1];
} FONTGROUPHDR, *PFONTGROUPHDR;
typedef struct
{
WORD dfVersion;
DWORD dfSize;
CHAR dfCopyright[60];
WORD dfType;
WORD dfPoints;
WORD dfVertRes;
WORD dfHorizRes;
WORD dfAscent;
WORD dfInternalLeading;
WORD dfExternalLeading;
BYTE dfItalic;
BYTE dfUnderline;
BYTE dfStrikeOut;
WORD dfWeight;
BYTE dfCharSet;
WORD dfPixWidth;
WORD dfPixHeight;
BYTE dfPitchAndFamily;
WORD dfAvgWidth;
WORD dfMaxWidth;
BYTE dfFirstChar;
BYTE dfLastChar;
BYTE dfDefaultChar;
BYTE dfBreakChar;
WORD dfWidthBytes;
DWORD dfDevice;
DWORD dfFace;
DWORD dfBitsPointer;
DWORD dfBitsOffset;
BYTE dfReserved;
/* Version 3.00: */
DWORD dfFlags;
WORD dfAspace;
WORD dfBspace;
WORD dfCspace;
DWORD dfColorPointer;
DWORD dfReserved1[4];
BYTE dfCharTable[1];
} FONTINFO16, *LPFONTINFO16, *PFONTINFO16;
typedef struct
{
WORD geWidth;
WORD geOffset;
} GLYPHENTRY20, *PGLYPHENTRY20;
typedef struct
{
WORD geWidth;
DWORD geOffset;
} GLYPHENTRY30, *PGLYPHENTRY30;
typedef union
{
GLYPHENTRY20 ge20;
GLYPHENTRY30 ge30;
} GLYPHENTRY, *PGLYPHENTRY;
#include <poppack.h>
/** Driver specific types *****************************************************/
typedef enum
{
FONTTYPE_FON,
FONTTYPE_FNT,
} FONTTYPE;
typedef struct
{
PFONTDIRENTRY pFontDirEntry;
PFONTINFO16 pFontInfo;
PBYTE pCharTable;
ULONG cjEntrySize;
ULONG ulVersion;
PCHAR pszFaceName;
PCHAR pszCopyright;
ULONG cGlyphs;
CHAR chFirstChar;
CHAR chLastChar;
WCHAR wcFirstChar;
WCHAR wcLastChar;
WCHAR wcDefaultChar;
WCHAR wcBreakChar;
WORD wPixHeight;
WORD wPixWidth;
WORD wWidthBytes;
WORD wA;
WORD wB;
WORD wC;
WORD wAscent;
WORD wDescent;
FLONG flInfo;
} DRVFACE, *PDRVFACE;
typedef struct
{
PVOID pvView;
ULONG_PTR iFile;
PFONTGROUPHDR pFontDir;
FONTTYPE ulFontType;
ULONG cNumFaces;
DRVFACE aface[1];
} DRVFONT, *PDRVFONT;
//"Bold Italic Underline Strikeout"
#define MAX_STYLESIZE 35
typedef struct
{
IFIMETRICS ifim;
BYTE ajCharSet[16];
WCHAR wszFamilyName[LF_FACESIZE];
WCHAR wszFaceName[LF_FACESIZE];
WCHAR wszStyleName[MAX_STYLESIZE];
} DRVIFIMETRICS, *PDRVIFIMETRICS;
/** Function prototypes *******************************************************/
ULONG
DbgPrint(IN PCHAR Format, IN ...);
static __inline__
void
DbgBreakPoint(void)
{
asm volatile ("int $3");
}
DHPDEV
APIENTRY
BmfdEnablePDEV(
IN DEVMODEW *pdm,
IN LPWSTR pwszLogAddress,
IN ULONG cPat,
OUT HSURF *phsurfPatterns,
IN ULONG cjCaps,
OUT ULONG *pdevcaps,
IN ULONG cjDevInfo,
OUT DEVINFO *pdi,
IN HDEV hdev,
IN LPWSTR pwszDeviceName,
IN HANDLE hDriver);
VOID
APIENTRY
BmfdCompletePDEV(
IN DHPDEV dhpdev,
IN HDEV hdev);
VOID
APIENTRY
BmfdDisablePDEV(
IN DHPDEV dhpdev);
ULONG_PTR
APIENTRY
BmfdLoadFontFile(
ULONG cFiles,
ULONG_PTR *piFile,
PVOID *ppvView,
ULONG *pcjView,
DESIGNVECTOR *pdv,
ULONG ulLangID,
ULONG ulFastCheckSum);
BOOL
APIENTRY
BmfdUnloadFontFile(
IN ULONG_PTR iFile);
LONG
APIENTRY
BmfdQueryFontFile(
ULONG_PTR iFile,
ULONG ulMode,
ULONG cjBuf,
ULONG *pulBuf);
LONG
APIENTRY
BmfdQueryFontCaps(
ULONG culCaps,
ULONG *pulCaps);
PVOID
APIENTRY
BmfdQueryFontTree(
DHPDEV dhpdev,
ULONG_PTR iFile,
ULONG iFace,
ULONG iMode,
ULONG_PTR *pid);
PIFIMETRICS
APIENTRY
BmfdQueryFont(
IN DHPDEV dhpdev,
IN ULONG_PTR iFile,
IN ULONG iFace,
IN ULONG_PTR *pid);
VOID
APIENTRY
BmfdFree(
PVOID pv,
ULONG_PTR id);
PFD_GLYPHATTR
APIENTRY
BmfdQueryGlyphAttrs(
FONTOBJ *pfo,
ULONG iMode);
LONG
APIENTRY
BmfdQueryFontData(
DHPDEV dhpdev,
FONTOBJ *pfo,
ULONG iMode,
HGLYPH hg,
OUT GLYPHDATA *pgd,
PVOID pv,
ULONG cjSize);

View file

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="bmfd" type="kernelmodedriver" entrypoint="FonfdEnableDriver@12" installbase="system32" installname="bmfd.dll" crt="static">
<library>win32k</library>
<library>libcntpr</library>
<file>enable.c</file>
<file>font.c</file>
<file>glyph.c</file>
</module>

View file

@ -0,0 +1,104 @@
/*
* 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 DRVFN gadrvfn[] =
{
{INDEX_DrvEnablePDEV, (PFN)BmfdEnablePDEV},
{INDEX_DrvCompletePDEV, (PFN)BmfdCompletePDEV},
{INDEX_DrvDisablePDEV, (PFN)BmfdDisablePDEV},
{INDEX_DrvLoadFontFile, (PFN)BmfdLoadFontFile},
{INDEX_DrvUnloadFontFile, (PFN)BmfdUnloadFontFile},
{INDEX_DrvQueryFontFile, (PFN)BmfdQueryFontFile},
{INDEX_DrvQueryFontCaps, (PFN)BmfdQueryFontCaps},
{INDEX_DrvQueryFontTree, (PFN)BmfdQueryFontTree},
{INDEX_DrvQueryFont, (PFN)BmfdQueryFont},
{INDEX_DrvFree, (PFN)BmfdFree},
{INDEX_DrvQueryGlyphAttrs, (PFN)BmfdQueryGlyphAttrs},
{INDEX_DrvQueryFontData, (PFN)BmfdQueryFontData},
};
ULONG
DbgPrint(IN PCHAR Format, IN ...)
{
va_list args;
va_start(args, Format);
EngDebugPrint("Bmfd: ", (PCHAR)Format, args);
va_end(args);
return 0;
}
BOOL
APIENTRY
BmfdEnableDriver(
ULONG iEngineVersion,
ULONG cj,
PDRVENABLEDATA pded)
{
DbgPrint("BmfdEnableDriver()\n");
/* Check parameter */
if (cj < sizeof(DRVENABLEDATA))
{
return FALSE;
}
/* Fill DRVENABLEDATA */
pded->c = sizeof(gadrvfn) / sizeof(DRVFN);
pded->pdrvfn = gadrvfn;
pded->iDriverVersion = DDI_DRIVER_VERSION_NT5;
/* Success */
return TRUE;
}
DHPDEV
APIENTRY
BmfdEnablePDEV(
IN DEVMODEW *pdm,
IN LPWSTR pwszLogAddress,
IN ULONG cPat,
OUT HSURF *phsurfPatterns,
IN ULONG cjCaps,
OUT ULONG *pdevcaps,
IN ULONG cjDevInfo,
OUT DEVINFO *pdi,
IN HDEV hdev,
IN LPWSTR pwszDeviceName,
IN HANDLE hDriver)
{
DbgPrint("BmfdEnablePDEV(hdev=%p)\n", hdev);
/* Return a dummy DHPDEV */
return (PVOID)1;
}
VOID
APIENTRY
BmfdCompletePDEV(
IN DHPDEV dhpdev,
IN HDEV hdev)
{
DbgPrint("BmfdCompletePDEV()\n");
/* Nothing to do */
}
VOID
APIENTRY
BmfdDisablePDEV(
IN DHPDEV dhpdev)
{
DbgPrint("BmfdDisablePDEV()\n");
/* Nothing to do */
}

View file

@ -0,0 +1,682 @@
/*
* 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(
PDRVFACE 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 = pface->pFontInfo->dfCharTable;
pface->cjEntrySize = sizeof(GLYPHENTRY30);
}
else
{
dfFlags = DFF_1COLOR;
pface->wA = 0;
pface->wB = 0;
pface->wC = 0;
pface->pCharTable = &pface->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;
PDRVFONT pfont = 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(DRVFONT) + (count-1) * sizeof(DRVFACE);
pfont = EngAllocMem(0, cjLength, TAG_FONTINFO);
if (!pfont)
{
DbgPrint("Not enough memory: %ld\n", cjLength);
return NULL;
}
pfont->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(pfont);
return NULL;
}
/* Validate FONTINFO and fill face info */
if (!FillFaceInfo(&pfont->aface[i], pFontInfo))
{
DbgPrint("pFontInfo is invalid: 0x%p\n", pFontInfo);
EngFreeMem(pfont);
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 pfont;
}
/** Public Interface **********************************************************/
ULONG_PTR
APIENTRY
BmfdLoadFontFile(
ULONG cFiles,
ULONG_PTR *piFile,
PVOID *ppvView,
ULONG *pcjView,
DESIGNVECTOR *pdv,
ULONG ulLangID,
ULONG ulFastCheckSum)
{
PDRVFONT pfont = NULL;
PVOID pvView;
ULONG cjView;
DbgPrint("BmfdLoadFontFile()\n");
DbgBreakPoint();
/* 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 */
pfont = ParseFonFile(pvView, cjView);
if (!pfont)
{
/* Could be a .fnt file */
pfont = ParseFntFile(pvView, cjView);
}
/* Check whether we succeeded finding a font */
if (!pfont)
{
DbgPrint("No font data found\n");
/* Unmap the file */
EngUnmapFontFileFD(*piFile);
/* Failure! */
return HFF_INVALID;
}
pfont->iFile = *piFile;
pfont->pvView = pvView;
/* Success, return the pointer to font info structure */
return (ULONG_PTR)pfont;
}
BOOL
APIENTRY
BmfdUnloadFontFile(
IN ULONG_PTR iFile)
{
PDRVFONT pfont = (PDRVFONT)iFile;
DbgPrint("BmfdUnloadFontFile()\n");
/* Free the memory that was allocated for the font */
EngFreeMem(pfont);
/* Unmap the font file */
EngUnmapFontFileFD(pfont->iFile);
return TRUE;
}
LONG
APIENTRY
BmfdQueryFontFile(
ULONG_PTR iFile,
ULONG ulMode,
ULONG cjBuf,
ULONG *pulBuf)
{
PDRVFONT pfont = (PDRVFONT)iFile;
DbgPrint("BmfdQueryFontFile()\n");
// DbgBreakPoint();
switch (ulMode)
{
case QFF_DESCRIPTION:
{
/* We copy the face name of the 1st face */
PCHAR pDesc = pfont->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 pfont->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)
{
PDRVFONT pfont = (PDRVFONT)iFile;
PDRVFACE pface;
ULONG i, j, cjOffset, 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);
DbgBreakPoint();
/* Check parameters, we only support QFT_GLYPHSET */
if (!iFace || iFace > pfont->cNumFaces || iMode != QFT_GLYPHSET)
{
DbgPrint("iFace = %ld, cNumFaces = %ld\n", iFace, pfont->cNumFaces);
return NULL;
}
/* Get a pointer to the face data */
pface = &pfont->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] = (HGLYPH)pface->pCharTable;
/* Walk through all supported chars */
for (i = 1, j = 0; i < cGlyphs; i++)
{
/* Use pointer to glyph entry as hglyph */
cjOffset = (ach[i] - chFirst) * pface->cjEntrySize;
phglyphs[i] = (HGLYPH)pface->pCharTable + cjOffset;
/* 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)
{
PDRVFONT pfont = (PDRVFONT)iFile;
PDRVFACE pface;
PFONTINFO16 pFontInfo;
PIFIMETRICS pifi;
PDRVIFIMETRICS pDrvIM;
PANOSE panose = {0};
DbgPrint("BmfdQueryFont()\n");
// DbgBreakPoint();
/* Validate parameters */
if (iFace > pfont->cNumFaces || !pid)
{
return NULL;
}
pface = &pfont->aface[iFace - 1];
pFontInfo = pface->pFontInfo;
/* Allocate the structure */
pDrvIM = EngAllocMem(FL_ZERO_MEMORY, sizeof(DRVIFIMETRICS), TAG_IFIMETRICS);
if (!pDrvIM)
{
return NULL;
}
/* Return a pointer to free it later */
*pid = (ULONG_PTR)pDrvIM;
/* Fill IFIMETRICS */
pifi = &pDrvIM->ifim;
pifi->cjThis = sizeof(DRVIFIMETRICS);
pifi->cjIfiExtra = 0;
pifi->dpwszFamilyName = FIELD_OFFSET(DRVIFIMETRICS, wszFamilyName);
pifi->dpwszStyleName = FIELD_OFFSET(DRVIFIMETRICS, wszFamilyName);
pifi->dpwszFaceName = FIELD_OFFSET(DRVIFIMETRICS, wszFaceName);
pifi->dpwszUniqueName = FIELD_OFFSET(DRVIFIMETRICS, 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 */
pDrvIM->ajCharSet[0] = pifi->jWinCharSet;
pDrvIM->ajCharSet[1] = DEFAULT_CHARSET;
if (pface->flInfo & FM_INFO_CONSTANT_WIDTH)
pifi->jWinPitchAndFamily |= FIXED_PITCH;
#if 0
EngMultiByteToUnicodeN(pDrvIM->wszFaceName,
LF_FACESIZE * sizeof(WCHAR),
NULL,
pFontInfo->,
strnlen(pDesc, LF_FACESIZE));
#endif
wcscpy(pDrvIM->wszFaceName, L"Courier-X");
wcscpy(pDrvIM->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(pDrvIM->wszStyleName, L"Bold ");
}
else if (pifi->usWinWeight <= FW_LIGHT)
{
wcscat(pDrvIM->wszStyleName, L"Light ");
}
if (pFontInfo->dfItalic)
{
pifi->fsSelection |= FM_SEL_ITALIC;
wcscat(pDrvIM->wszStyleName, L"Italic ");
}
if (pFontInfo->dfUnderline)
{
pifi->fsSelection |= FM_SEL_UNDERSCORE;
wcscat(pDrvIM->wszStyleName, L"Underscore ");
}
if (pFontInfo->dfStrikeOut)
{
pifi->fsSelection |= FM_SEL_STRIKEOUT;
wcscat(pDrvIM->wszStyleName, L"Strikeout ");
}
return pifi;
}
VOID
APIENTRY
BmfdFree(
PVOID pv,
ULONG_PTR id)
{
DbgPrint("BmfdFree()\n");
if (id)
{
EngFreeMem((PVOID)id);
}
}

View file

@ -0,0 +1,192 @@
/*
* 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
VOID
FillFDDM(
PFD_DEVICEMETRICS pfddm,
PFONTINFO16 pFontInfo)
{
/* Fill FD_DEVICEMETRICS */
pfddm->flRealizedType = FDM_MASK;
pfddm->pteBase.x = FLOATL_1;
pfddm->pteBase.y = 0;
pfddm->pteSide.x = 0;
pfddm->pteSide.y = FLOATL_1;
pfddm->ptlUnderline1.x = 0;
pfddm->ptlUnderline1.y = 1;
pfddm->ptlStrikeout.x = 0;
pfddm->ptlStrikeout.y = -4;
pfddm->ptlULThickness.x = 0;
pfddm->ptlULThickness.y = 1;
pfddm->ptlSOThickness.x = 0;
pfddm->ptlSOThickness.y = 1;
pfddm->lD = GETVAL(pFontInfo->dfPixWidth);
pfddm->cxMax = GETVAL(pFontInfo->dfMaxWidth);
pfddm->cyMax = GETVAL(pFontInfo->dfPixHeight);
pfddm->cjGlyphMax = pfddm->cyMax * ((pfddm->cxMax + 7) / 8);
pfddm->fxMaxAscender = GETVAL(pFontInfo->dfAscent) << 4;
pfddm->fxMaxDescender = (pfddm->cyMax << 4) - pfddm->fxMaxAscender;
pfddm->lMinA = 0;
pfddm->lMinC = 0;
pfddm->lMinD = 0;
/* NOTE: fdxQuantized and NonLinear... stay unchanged */
}
/** Public Interface **********************************************************/
PFD_GLYPHATTR
APIENTRY
BmfdQueryGlyphAttrs(
FONTOBJ *pfo,
ULONG iMode)
{
DbgPrint("BmfdQueryGlyphAttrs()\n");
/* We don't support FO_ATTR_MODE_ROTATE */
return NULL;
}
LONG
APIENTRY
BmfdQueryFontData(
DHPDEV dhpdev,
FONTOBJ *pfo,
ULONG iMode,
HGLYPH hg,
OUT GLYPHDATA *pgd,
PVOID pv,
ULONG cjSize)
{
PDRVFONT pfont = (PDRVFONT)pfo->iFile;
PDRVFACE pface = &pfont->aface[pfo->iFace - 1];
PGLYPHENTRY pge = (PGLYPHENTRY)hg;
ULONG ulGlyphOffset, ulWidthBytes, ulPixWidth, ulPixHeight, x, y, cjRow;
DbgPrint("BmfdQueryFontData(pfo=%p, iMode=%ld, hg=%p, pgd=%p, pv=%p, cjSize=%ld)\n",
pfo, iMode, hg, pgd, pv, cjSize);
// DbgBreakPoint();
switch (iMode)
{
case QFD_GLYPHANDBITMAP: /* 1 */
{
GLYPHBITS *pgb = pv;
BYTE j, *pjGlyphBits;
// DbgPrint("QFD_GLYPHANDBITMAP, hg=%p, pgd=%p, pv=%p, cjSize=%d\n",
// hg, pgd, pv, cjSize);
if (!hg)
{
DbgPrint("no glyph handle given!\n");
return FD_ERROR;
}
/* Get the bitmap offset depending on file version */
if (pface->ulVersion >= 0x300)
{
ulPixWidth = GETVAL(pge->ge20.geWidth);
ulGlyphOffset = GETVAL(pge->ge30.geOffset);
}
else
{
ulPixWidth = GETVAL(pge->ge30.geWidth);
ulGlyphOffset = GETVAL(pge->ge20.geOffset);
}
ulPixHeight = pface->wPixHeight;
/* Calculate number of bytes per row for gdi */
cjRow = (ulPixWidth + 7) / 8; // FIXME: other bpp values
if (pgd)
{
/* Fill GLYPHDATA structure */
pgd->gdf.pgb = pgb;
pgd->hg = hg;
pgd->fxD = (pface->wA + ulPixWidth + pface->wC) << 4;
pgd->fxA = pface->wA << 4;
pgd->fxAB = (pface->wA + ulPixWidth) << 4;
pgd->fxInkTop = pface->wAscent << 4;
pgd->fxInkBottom = - (pface->wDescent << 4);
pgd->rclInk.top = - pface->wAscent;
pgd->rclInk.bottom = pface->wDescent ;
pgd->rclInk.left = pface->wA;
pgd->rclInk.right = pface->wA + ulPixWidth;
pgd->ptqD.x.LowPart = 0;
pgd->ptqD.x.HighPart = pgd->fxD;
pgd->ptqD.y.LowPart = 0;
pgd->ptqD.y.HighPart = 0;
}
if (pgb)
{
// DbgBreakPoint();
/* Verify that the buffer is big enough */
if (cjSize < ulPixHeight * cjRow)
{
DbgPrint("Buffer too small (%ld), %ld,%ld\n",
cjSize, ulPixWidth, ulPixHeight);
return FD_ERROR;
}
/* Fill GLYPHBITS structure */
pgb->ptlOrigin.x = pface->wA;
pgb->ptlOrigin.y = - pface->wAscent;
pgb->sizlBitmap.cx = ulPixWidth;
pgb->sizlBitmap.cy = ulPixHeight;
/* Copy the bitmap bits */
pjGlyphBits = (PBYTE)pface->pFontInfo + ulGlyphOffset;
ulWidthBytes = pface->wWidthBytes;
for (y = 0; y < ulPixHeight; y++)
{
for (x = 0; x < cjRow; x++)
{
j = pjGlyphBits[x * ulPixHeight + y];
pgb->aj[y * cjRow + x] = j;
}
}
DbgPrint("iFace=%ld, ulGlyphOffset=%lx, ulPixHeight=%ld, cjRow=%ld\n",
pfo->iFace, ulGlyphOffset, ulPixHeight, cjRow);
DbgBreakPoint();
}
/* Return the size of the bitmap buffer */
return ulPixHeight * cjRow;
}
case QFD_MAXEXTENTS: /* 3 */
{
if (pv)
{
if (cjSize < sizeof(FD_DEVICEMETRICS))
{
/* Not enough space, fail */
return FD_ERROR;
}
/* Fill the PFD_DEVICEMETRICS structure */
FillFDDM((PFD_DEVICEMETRICS)pv, pface->pFontInfo);
}
/* Return the size of the structure */
return sizeof(FD_DEVICEMETRICS);
}
/* we support nothing else */
default:
return FD_ERROR;
}
return FD_ERROR;
}

View file

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<!DOCTYPE group SYSTEM "../../tools/rbuild/project.dtd">
<group xmlns:xi="http://www.w3.org/2001/XInclude">
<directory name="bmfd">
<xi:include href="bmfd/bmfd.rbuild" />
</directory>
</group>