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/subsyste... ============================================================================== --- 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/subsyste... ============================================================================== --- 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/subsyste... ============================================================================== --- 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); +