Author: tkreuzer
Date: Sun Mar 4 19:08:47 2012
New Revision: 56006
URL:
http://svn.reactos.org/svn/reactos?rev=56006&view=rev
Log:
[WIN32K]
- Calculate font name hash in GreHfontCreate
- Partly implement LFONT_ppfe, which finds a matching PFE for an LFONT
- Implement PFE_ulPenalty, that calculates a penalty value from a PFE based on a LOGFONT
- Implement HASHBUCKET_ppfeFindBestMatch, that finds the best matching PFE from within a
HASHBUCKET
- Implement PFT_ppfeFindBestMatch, that finds the best matching PFE from a PFT
- Rename PFT_pffFindFont to PFT_pffFindFontByFile
- Use bitfields instead of BOOLs in RFONT structure
- Add a name hash value to the LFONT structure
- Add a FONTSUBSTITUTE structure that will be used for font substitutions
Modified:
branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/font/fontrsrc.c
branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/font/lfont.c
branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/include/font.h
Modified: branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/font/fontrsrc.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/subsyst…
==============================================================================
--- branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/font/fontrsrc.c [iso-8859-1]
(original)
+++ branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/font/fontrsrc.c [iso-8859-1]
Sun Mar 4 19:08:47 2012
@@ -7,12 +7,19 @@
#include <win32k.h>
#include <include/font.h>
-
-#define NDEBUG
-#include <debug.h>
+DBG_DEFAULT_CHANNEL(GdiFont);
PFT gpftPublic;
ULONG gulHashBucketId = 0;
+
+static
+PFONTSUBSTITUTE
+GetFontSubstitute(PWSTR pwszFace)
+{
+ // HACK
+ WARN("GetFontSubstitute is unimplemented.\n");
+ return NULL;
+}
VOID
NTAPI
@@ -34,8 +41,8 @@
}
-static
ULONG
+NTAPI
CalculateNameHash(PWSTR pwszName)
{
ULONG iHash = 0;
@@ -121,7 +128,7 @@
if (!ppfel)
{
- DPRINT1("PFE not found!\n");
+ ERR("PFE not found!\n");
ASSERT(FALSE);
}
@@ -138,6 +145,185 @@
/* Free the PFELINK */
ExFreePoolWithTag(ppfel, GDITAG_PFE_LINK);
+}
+
+BYTE
+NTAPI
+GreGetDefaultCharset()
+{
+ USHORT usACP, usOEM;
+
+ RtlGetDefaultCodePage(&usACP, &usOEM);
+ WARN("GreGetDefaultCharset is unimplemented.\n");
+
+ // HACK!
+ return ANSI_CHARSET;
+}
+
+ULONG
+NTAPI
+PFE_ulPenalty(
+ PPFE ppfe,
+ LOGFONTW *plfw,
+ ULONG ulMargin)
+{
+ PIFIMETRICS pifi = ppfe->pifi;
+ ULONG i, ulPenalty = 0;
+ PBYTE pjCharSets;
+ BYTE jCharSet;
+
+ jCharSet = plfw->lfCharSet;
+ if (jCharSet == DEFAULT_CHARSET)
+ {
+ /* Get the default charset */
+ jCharSet = GreGetDefaultCharset();
+ }
+
+ /* Check charsets */
+ if (pifi->dpCharSets)
+ {
+ /* Get a pointer to the charset array */
+ pjCharSets = (PBYTE)pifi + pifi->dpCharSets;
+
+ /* Loop charsets, until the requeste one is found */
+ for (i = 0; pjCharSets[i] != jCharSet; i++)
+ {
+ /* Check if this is the last charset */
+ if ((i == 15) || (pjCharSets[i] == DEFAULT_CHARSET))
+ {
+ /* Charset wasn't found, add penalty */
+ ulPenalty += PENALTY_CharSet;
+ if (ulPenalty > ulMargin) return ulPenalty;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Otherwise check if the win charset matches */
+ if (pifi->jWinCharSet != jCharSet)
+ {
+ /* Charset doesn't match, add penalty */
+ ulPenalty += PENALTY_CharSet;
+ if (ulPenalty > ulMargin) return ulPenalty;
+ }
+ }
+
+
+ /* There are contrary claims about the font mapper behaviour towards
+ different lfOutPrecision values between MS LOGFONT structure docs
+ and the font mapper article. */
+ if ((plfw->lfOutPrecision == OUT_DEVICE_PRECIS) &&
+ ((ppfe->flPFE & PFE_DEVICEFONT) == 0))
+ {
+ ulPenalty += PENALTY_OutputPrecision;
+ }
+
+ /* Check if pitch matches */
+ if (((plfw->lfPitchAndFamily & 0x0f) == FIXED_PITCH) &&
+ (pifi->jWinPitchAndFamily & 0x0f) != FIXED_PITCH)
+ {
+ ulPenalty += PENALTY_FixedPitch;
+ if (ulPenalty > ulMargin) return ulPenalty;
+ }
+ else if (((plfw->lfPitchAndFamily & 0x0f) == VARIABLE_PITCH) &&
+ (pifi->jWinPitchAndFamily & 0x0f) != VARIABLE_PITCH)
+ {
+ ulPenalty += PENALTY_PitchVariable;
+ if (ulPenalty > ulMargin) return ulPenalty;
+ }
+
+
+ if ((plfw->lfPitchAndFamily & 0xf0) != FF_DONTCARE)
+ {
+ if ((pifi->jWinPitchAndFamily & 0xf0) == FF_DONTCARE)
+ {
+ ulPenalty += PENALTY_FamilyUnknown;
+ }
+ else if ((plfw->lfPitchAndFamily & 0xf0) != (pifi->jWinPitchAndFamily
& 0xf0))
+ {
+ ulPenalty += PENALTY_Family;
+ }
+ }
+
+// PENALTY_HeightSmaller 150
+// PENALTY_HeightBiggerDifference 150
+// PENALTY_FamilyUnlikely 50
+// PENALTY_Width 50
+// PENALTY_SizeSynth 50
+// PENALTY_Aspect 30
+// PENALTY_IntSizeSynth 20
+// PENALTY_UnevenSizeSynth 4
+
+ if (!plfw->lfItalic && (pifi->fsSelection & FM_SEL_ITALIC))
+ {
+ ulPenalty += PENALTY_Italic;
+ }
+
+ if ((plfw->lfOutPrecision == OUT_TT_ONLY_PRECIS) &&
+ !(pifi->flInfo & FM_INFO_TECH_TRUETYPE))
+ {
+ ulPenalty += 500000; // more then can be accounted for
+ }
+
+ if ((plfw->lfOutPrecision == OUT_TT_PRECIS) &&
+ !(pifi->flInfo & FM_INFO_TECH_TRUETYPE))
+ {
+ ulPenalty += PENALTY_NotTrueType;
+ }
+
+
+ ulPenalty += (abs(plfw->lfWeight - pifi->usWinWeight) / 10) * PENALTY_Weight;
+
+ if (!plfw->lfUnderline && (pifi->fsSelection & FM_SEL_UNDERSCORE))
+ {
+ ulPenalty += PENALTY_Underline;
+ }
+
+ if (!plfw->lfStrikeOut && (pifi->fsSelection & FM_SEL_STRIKEOUT))
+ {
+ ulPenalty += PENALTY_StrikeOut;
+ }
+
+// PENALTY_VectorHeightSmaller 2
+// PENALTY_DeviceFavor 2
+// PENALTY_ItalicSim 1
+
+ if (((plfw->lfPitchAndFamily & 0x0f) == DEFAULT_PITCH) &&
+ (pifi->jWinPitchAndFamily & 0x0f) != FIXED_PITCH)
+ {
+ ulPenalty += PENALTY_DefaultPitchFixed;
+ }
+
+// PENALTY_SmallPenalty 1
+// PENALTY_VectorHeightBigger 1
+ return ulPenalty;
+}
+
+
+static
+PPFE
+HASHBUCKET_ppfeFindBestMatch(
+ PHASHBUCKET pbkt,
+ LOGFONTW *plf,
+ ULONG *pulPenalty)
+{
+ PPFELINK ppfel;
+ ULONG ulPenalty, ulBestMatch = *pulPenalty;
+ PPFE ppfeBestMatch;
+
+ /* Loop all PFELINKs */
+ for (ppfel = pbkt->ppfelEnumHead; ppfel; ppfel = ppfel->ppfelNext)
+ {
+ ulPenalty = PFE_ulPenalty(ppfel->ppfe, plf, ulBestMatch);
+ if (ulPenalty < ulBestMatch)
+ {
+ ppfeBestMatch = ppfel->ppfe;
+ ulBestMatch = ulPenalty;
+ }
+ }
+
+ return ppfeBestMatch;
}
static
@@ -218,6 +404,7 @@
return pbkt;
}
+
static
VOID
FONTHASH_vInsertPFE(
@@ -303,9 +490,69 @@
return FALSE;
}
+PPFE
+NTAPI
+PFT_ppfeFindBestMatch(
+ _In_ PPFT ppft,
+ _In_ PWSTR pwszCapName,
+ _In_ ULONG iHashValue,
+ _In_ LOGFONTW *plf,
+ _Inout_ PULONG pulPenalty)
+{
+ PHASHBUCKET pbkt;
+ ULONG ulPenalty = *pulPenalty;
+ PFONTSUBSTITUTE pfs = NULL;
+ PPFE ppfe;
+
+ /* Acquire PFT lock for reading */
+ EngAcquireSemaphoreShared(ppft->hsem);
+
+ /* Try to find a HASHBUCKET by the face name */
+ pbkt = FONTHASH_pbktFindBucketByName(ppft->pfhFace, pwszCapName, iHashValue);
+
+ /* Check if we found the face name */
+ if (!pbkt)
+ {
+ /* Check if there is a font substitute */
+ pfs = GetFontSubstitute(pwszCapName);
+ if (pfs)
+ {
+ /* Try again with the substitute name */
+ pbkt = FONTHASH_pbktFindBucketByName(ppft->pfhFace,
+ pfs->awcCapSubstName,
+ pfs->iHashValue);
+ }
+ }
+
+ if (pbkt)
+ {
+ ppfe = HASHBUCKET_ppfeFindBestMatch(pbkt, plf, &ulPenalty);
+ if (pfs) ulPenalty += PENALTY_FaceNameSubst;
+
+ }
+ else
+ {
+ TRACE("Font with face name '%ls' was not found!\n",
pwszCapName);
+ ulPenalty = PENALTY_FaceName;
+ }
+
+
+ if (ulPenalty >= PENALTY_FaceName)
+ {
+ }
+
+ /* Release PFT lock */
+ EngReleaseSemaphore(ppft->hsem);
+
+ *pulPenalty = ulPenalty;
+ return ppfe;
+}
+
+
+
static
PPFF
-PFT_pffFindFont(
+PFT_pffFindFontByFile(
PFT *ppft,
PWSTR pwszFiles,
ULONG cwc,
@@ -407,7 +654,7 @@
iFileNameHash = CalculateNameHash(pwszFiles);
/* Try to find the font in the font table */
- ppff = PFT_pffFindFont(ppft, pwszFiles, cwc, cFiles, iFileNameHash);
+ ppff = PFT_pffFindFontByFile(ppft, pwszFiles, cwc, cFiles, iFileNameHash);
/* Did we find the font? */
if (ppff)
@@ -424,7 +671,7 @@
ppff = EngLoadFontFileFD(pwszFiles, cwc, cFiles, pdv, ulCheckSum);
if (!ppff)
{
- DPRINT1("Failed to load font with font driver\n");
+ ERR("Failed to load font with font driver\n");
return 0;
}
Modified: branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/font/lfont.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/subsyst…
==============================================================================
--- branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/font/lfont.c [iso-8859-1]
(original)
+++ branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/font/lfont.c [iso-8859-1] Sun
Mar 4 19:08:47 2012
@@ -18,6 +18,81 @@
ASSERT(FALSE);
return 0;
}
+
+PPFE
+NTAPI
+LFONT_ppfe(PLFONT plfnt)
+{
+ PPFEOBJ ppfeobj;
+ PPFE ppfe, ppfeSave;
+ HGDIOBJ hPFE;
+ ULONG ulPenalty;
+
+ /* Check if the font has a PFE associated */
+ hPFE = plfnt->hPFE;
+ if (hPFE)
+ {
+ /* Try to lock the PFE */
+ ppfeobj = (PVOID)GDIOBJ_ReferenceObjectByHandle(hPFE, 0x0c);
+
+ /* If we succeeded, the font is still there and we can use it */
+ if (ppfeobj) return ppfeobj->ppfe;
+
+ /* The previous font is not loaded anymore, reset the handle */
+ InterlockedCompareExchangePointer((PVOID*)&plfnt->hPFE, hPFE, NULL);
+ }
+
+ ulPenalty = PENALTY_Max;
+#if 0
+ /* Search the private font table */
+ pti = PsGetCurrentThreadWin32Thread();
+ ppfe = PFT_ppfeFindBestMatch(pti->ppftPrivate,
+ plfnt->awchFace,
+ plfnt->iNameHash,
+ &plfnt->elfexw.elfEnumLogfontEx.elfLogFont,
+ &ulPenalty);
+#else
+ ppfe = 0;
+#endif
+ /* Check if we got an exact match */
+ if (ulPenalty != 0)
+ {
+ /* Not an exact match, save this PFE */
+ ppfeSave = ppfe;
+
+ /* Try to find a better match in the global table */
+ ppfe = PFT_ppfeFindBestMatch(&gpftPublic,
+ plfnt->awchFace,
+ plfnt->iNameHash,
+ &plfnt->elfexw.elfEnumLogfontEx.elfLogFont,
+ &ulPenalty);
+
+ /* If we didn't find a better one, use the old one */
+ if (!ppfe) ppfe = ppfeSave;
+ }
+
+ /* Check if we got an exact match now */
+ if (ulPenalty == 0)
+ {
+ __debugbreak();
+ // should create a PFEOBJ and save it
+ }
+
+ ASSERT(ppfe);
+ return ppfe;
+}
+
+PRFONT
+NTAPI
+LFONT_prfntFindRFONT(
+ IN PLFONT plfnt)
+{
+
+ __debugbreak();
+
+ return NULL;
+}
+
HFONT
NTAPI
@@ -51,6 +126,9 @@
UpcaseString(plfnt->awchFace,
pelfw->elfEnumLogfontEx.elfLogFont.lfFaceName,
LF_FACESIZE);
+
+ /* Calculate the name hash value */
+ plfnt->iNameHash = CalculateNameHash(plfnt->awchFace);
/* Set client data */
GDIOBJ_vSetObjectAttr(&plfnt->baseobj, pvCliData);
Modified: branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/include/font.h
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/subsyst…
==============================================================================
--- branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/include/font.h [iso-8859-1]
(original)
+++ branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/include/font.h [iso-8859-1]
Sun Mar 4 19:08:47 2012
@@ -1,9 +1,17 @@
#pragma once
+// FIXME: duplicated from ntoskrnl, should got to NDK or something
+#define InterlockedIncrementUL(Addend) \
+ (ULONG)InterlockedIncrement((PLONG)(Addend))
+
+#define InterlockedDecrementUL(Addend) \
+ (ULONG)InterlockedDecrement((PLONG)(Addend))
+
#define LFONT_GetObject FontGetObject
#define ENGAPI
+#define PENALTY_Max 127979
#define PENALTY_CharSet 65000
#define PENALTY_OutputPrecision 19000
#define PENALTY_FixedPitch 15000
@@ -38,6 +46,14 @@
extern PEPROCESS gpepCSRSS;
+typedef struct _FONTSUBSTITUTE
+{
+ WCHAR awcSubstName[LF_FACESIZE];
+ WCHAR awcCapSubstName[LF_FACESIZE];
+ ULONG iHashValue;
+} FONTSUBSTITUTE, *PFONTSUBSTITUTE;
+
+
typedef struct _POINTEF
{
FLOATOBJ x;
@@ -46,11 +62,24 @@
typedef struct _RFONT *PRFONT;
+typedef enum _FLPFE
+{
+ PFE_DEVICEFONT = 0x0001,
+ PFE_DEADSTATE = 0x0002,
+ PFE_REMOTEFONT = 0x0004,
+ PFE_EUDC = 0x0008,
+ PFE_SBCS_SYSTEM = 0x0010,
+ PFE_UFIMATCH = 0x0020,
+ PFE_MEMORYFONT = 0x0040,
+ PFE_DBCS_FONT = 0x0080,
+ PFE_VERT_FACE = 0x0100,
+} FLPFE;
+
typedef struct _PFE
{
struct _PFF * pPFF;
ULONG_PTR iFont;
- FLONG flPFE;
+ FLPFE flPFE;
FD_GLYPHSET *pfdg;
ULONG_PTR idfdg;
IFIMETRICS * pifi;
@@ -71,6 +100,12 @@
ULONG cPfdgRef;
ULONG aiFamilyName[1];
} PFE, *PPFE;
+
+typedef struct _PFEOBJ
+{
+ BASEOBJECT baseobj;
+ PPFE ppfe;
+} PFEOBJ, *PPFEOBJ;
typedef struct _PFF
{
@@ -215,11 +250,14 @@
ULONG iGraphicsMode;
ULONG ulOrientation;
ULONG cBitsPerPel;
- BOOL bVertical;
- BOOL bDeviceFont;
- BOOL bIsSystemFont;
- BOOL bNeededPaths;
- BOOL bFilledEudcArray;
+ struct
+ {
+ ULONG bVertical:1;
+ ULONG bDeviceFont:1;
+ ULONG bIsSystemFont:1;
+ ULONG bNeededPaths:1;
+ ULONG bFilledEudcArray:1;
+ };
FD_XFORM fdx;
@@ -278,6 +316,7 @@
FLONG fl;
PPDEVOBJ ppdev;
HGDIOBJ hPFE;
+ ULONG iNameHash;
WCHAR awchFace[LF_FACESIZE];
ENUMLOGFONTEXDVW elfexw;
} LFONT, *PLFONT;
@@ -332,6 +371,27 @@
ULONG acFaceNameGlyphs[8];
} ESTROBJ, *PESTROBJ;
+extern PRFONT gprfntSystemTT;
+extern PFT gpftPublic;
+
+FORCEINLINE
+PLFONT
+LFONT_ShareLockFont(HFONT hfont)
+{
+ return (PLFONT)GDIOBJ_ReferenceObjectByHandle(hfont, GDIObjType_LFONT_TYPE);
+}
+
+FORCEINLINE
+VOID
+LFONT_ShareUnlockFont(PLFONT plfnt)
+{
+ GDIOBJ_vDereferenceObject(&plfnt->baseobj);
+}
+
+PPFE
+NTAPI
+LFONT_ppfe(PLFONT plfnt);
+
VOID
NTAPI
UpcaseString(
@@ -339,24 +399,24 @@
IN PWSTR pwszSource,
IN ULONG cwc);
-FORCEINLINE
-PLFONT
-LFONT_ShareLockFont(HFONT hfont)
-{
- return (PLFONT)GDIOBJ_ReferenceObjectByHandle(hfont, GDIObjType_LFONT_TYPE);
-}
-
-FORCEINLINE
-VOID
-LFONT_ShareUnlockFont(PLFONT plfnt)
-{
- GDIOBJ_vDereferenceObject(&plfnt->baseobj);
-}
+ULONG
+NTAPI
+CalculateNameHash(
+ PWSTR pwszName);
BOOL
NTAPI
PFT_bInit(
PFT *ppft);
+
+PPFE
+NTAPI
+PFT_ppfeFindBestMatch(
+ _In_ PPFT ppft,
+ _In_ PWSTR pwszCapName,
+ _In_ ULONG iHashValue,
+ _In_ LOGFONTW *plf,
+ _Inout_ PULONG pulPenalty);
VOID
NTAPI
@@ -423,3 +483,8 @@
INT cwc,
LPSIZE psize,
UINT flOpts);
+
+PRFONT
+NTAPI
+RFONT_AllocRFONT(void);
+