diff --git a/reactos/drivers/video/directory.rbuild b/reactos/drivers/video/directory.rbuild index 753c95c941c..03036110e78 100644 --- a/reactos/drivers/video/directory.rbuild +++ b/reactos/drivers/video/directory.rbuild @@ -4,6 +4,9 @@ + + + diff --git a/reactos/drivers/video/font/bmfd/bmfd.h b/reactos/drivers/video/font/bmfd/bmfd.h new file mode 100644 index 00000000000..dd03bba8ad4 --- /dev/null +++ b/reactos/drivers/video/font/bmfd/bmfd.h @@ -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 +#include +#include +#include + +#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 +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 + + +/** 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); + diff --git a/reactos/drivers/video/font/bmfd/bmfd.rbuild b/reactos/drivers/video/font/bmfd/bmfd.rbuild new file mode 100644 index 00000000000..21b6f6b22c0 --- /dev/null +++ b/reactos/drivers/video/font/bmfd/bmfd.rbuild @@ -0,0 +1,9 @@ + + + + win32k + libcntpr + enable.c + font.c + glyph.c + diff --git a/reactos/drivers/video/font/bmfd/enable.c b/reactos/drivers/video/font/bmfd/enable.c new file mode 100644 index 00000000000..4c6fa0413d9 --- /dev/null +++ b/reactos/drivers/video/font/bmfd/enable.c @@ -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 */ +} diff --git a/reactos/drivers/video/font/bmfd/font.c b/reactos/drivers/video/font/bmfd/font.c new file mode 100644 index 00000000000..0680b2c0f2b --- /dev/null +++ b/reactos/drivers/video/font/bmfd/font.c @@ -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); + } +} + + + diff --git a/reactos/drivers/video/font/bmfd/glyph.c b/reactos/drivers/video/font/bmfd/glyph.c new file mode 100644 index 00000000000..f47e34fe901 --- /dev/null +++ b/reactos/drivers/video/font/bmfd/glyph.c @@ -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; +} diff --git a/reactos/drivers/video/font/directory.rbuild b/reactos/drivers/video/font/directory.rbuild new file mode 100644 index 00000000000..1d59fcfc573 --- /dev/null +++ b/reactos/drivers/video/font/directory.rbuild @@ -0,0 +1,8 @@ + + + + + + + +