Author: tkreuzer Date: Sat Aug 6 11:10:42 2011 New Revision: 53099
URL: http://svn.reactos.org/svn/reactos?rev=53099&view=rev Log: [GDI FONT DRIVER] - Implement font hash handling (adding fonts only atm) - Don't link win32k to ftfd.dll anymore - Dereference logical font, when deleting a DC
Modified: branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/CMakeLists.txt 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 branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/objects/dclife.c branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/objects/path.c
Modified: branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/subsyste... ============================================================================== --- branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/CMakeLists.txt [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/CMakeLists.txt [iso-8859-1] Sat Aug 6 11:10:42 2011 @@ -203,7 +203,7 @@ dxguid libcntpr)
-add_importlibs(win32k ntoskrnl hal ftfd) +add_importlibs(win32k ntoskrnl hal) add_pch(win32k pch.h) add_cd_file(TARGET win32k DESTINATION reactos/system32 FOR all) add_importlib_target(win32k.spec)
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] Sat Aug 6 11:10:42 2011 @@ -12,30 +12,265 @@ #include <debug.h>
PFT gpftPublic; -static LIST_ENTRY glePrivatePFFList = {&glePrivatePFFList, &glePrivatePFFList}; -static LIST_ENTRY glePublicPFFList = {&glePublicPFFList, &glePublicPFFList}; +ULONG gulHashBucketId = 0; + +VOID +NTAPI +UpcaseString( + OUT PWSTR pwszDest, + IN PWSTR pwszSource, + IN ULONG cwc) +{ + WCHAR wc; + + while (--cwc) + { + wc = *pwszSource++; + if (wc == 0) break; + *pwszDest++ = RtlUpcaseUnicodeChar(wc); + } + + *pwszDest = 0; +} + + +static +ULONG +CalculateNameHash(PWSTR pwszName) +{ + ULONG iHash = 0; + WCHAR wc; + + while ((wc = *pwszName++) != 0) + { + iHash = _rotl(iHash, 7); + iHash += wc; + } + + return iHash; +} + + +static +PHASHBUCKET +HASHBUCKET_Allocate(void) +{ + PHASHBUCKET pbkt; + + + pbkt = ExAllocatePoolWithTag(PagedPool, + sizeof(HASHBUCKET), + GDITAG_PFE_HASHBUCKET); + if (!pbkt) return NULL; + + RtlZeroMemory(pbkt, sizeof(HASHBUCKET)); + pbkt->ulTime = InterlockedIncrement((LONG*)gulHashBucketId); + + return pbkt; +}
static BOOL -PFF_bCompareFiles( - PPFF ppff, - ULONG cFiles, - PFONTFILEVIEW apffv[]) -{ - ULONG i; - - /* Check if number of files matches */ - if (ppff->cFiles != cFiles) return FALSE; - - /* Loop all files */ - for (i = 0; i < cFiles; i++) - { - /* Check if the files match */ - if (apffv[i] != ppff->apffv[i]) return FALSE; - } +HASHBUCKET_bLinkPFE( + IN PHASHBUCKET pbkt, + IN PPFE ppfe) +{ + PPFELINK ppfel; + + ppfel = ExAllocatePoolWithTag(PagedPool, sizeof(PFELINK), GDITAG_PFE_LINK); + if (!ppfel) + { + return FALSE; + } + + ppfel->ppfe = ppfe; + + ppfel->ppfelNext = pbkt->ppfelEnumHead; + pbkt->ppfelEnumHead = ppfel; + if (!ppfel->ppfelNext) pbkt->ppfelEnumTail = ppfel;
return TRUE; } + +static +VOID +HASHBUCKET_vUnlinkPFE( + IN PHASHBUCKET pbkt, + IN PPFE ppfe) +{ + PPFELINK ppfel, ppfelPrev; + + /* List must not be empty */ + ASSERT(pbkt->ppfelEnumHead); + ASSERT(pbkt->ppfelEnumTail); + + /* First check the list head */ + ppfel = pbkt->ppfelEnumHead; + if (ppfel->ppfe == ppfe) + { + pbkt->ppfelEnumHead = ppfel->ppfelNext; + ppfelPrev = NULL; + } + else + { + /* Loop through the rest of the list */ + while (TRUE) + { + ppfelPrev = ppfel; + ppfel = ppfel->ppfelNext; + + if (!ppfel) + { + DPRINT1("PFE not found!\n"); + ASSERT(FALSE); + } + + if (ppfel && (ppfel->ppfe == ppfe)) + { + ppfelPrev->ppfelNext = ppfel->ppfelNext; + break; + } + } + } + + /* Check list tail */ + if (ppfel == pbkt->ppfelEnumTail) pbkt->ppfelEnumTail = ppfelPrev; + + /* Free the PFELINK */ + ExFreePoolWithTag(ppfel, GDITAG_PFE_LINK); +} + +static +PFONTHASH +FONTHASH_Allocate( + FONT_HASH_TYPE fht, + ULONG cBuckets) +{ + PFONTHASH pfh; + + pfh = ExAllocatePoolWithTag(PagedPool, + sizeof(FONTHASH) + cBuckets * sizeof(PVOID), + GDITAG_PFE_HASHTABLE); + + if (!pfh) return NULL; + + pfh->id = 'HSAH'; + pfh->fht = fht; + pfh->cBuckets = cBuckets; + pfh->cUsed = 0; + pfh->cCollisions = 0; + pfh->pbktFirst = NULL; + pfh->pbktLast = NULL; + RtlZeroMemory(pfh->apbkt, cBuckets * sizeof(PVOID)); + + return pfh; +} + + +static +VOID +FONTHASH_vInsertBucket( + PFONTHASH pfh, + PHASHBUCKET pbkt, + ULONG iHashValue) +{ + ULONG iHashIndex = iHashValue % pfh->cBuckets; + + pbkt->iHashValue = iHashValue; + + /* Insert the bucket into the list */ + pbkt->pbktPrev = pfh->pbktLast; + pbkt->pbktNext = NULL; + pfh->pbktLast = pbkt; + if (!pfh->pbktFirst) pfh->pbktFirst = pbkt; + + /* Insert the bucket into the slot */ + pbkt->pbktCollision = pfh->apbkt[iHashIndex]; + pfh->apbkt[iHashIndex] = pbkt; + + /* Update counter */ + if (pbkt->pbktCollision) pfh->cCollisions++; + else pfh->cUsed++; +} + + + +static +PHASHBUCKET +FONTHASH_pbktFindBucketByName( + PFONTHASH pfh, + PWSTR pwszCapName, + ULONG iHashValue) +{ + ULONG iHashIndex = iHashValue % pfh->cBuckets; + PHASHBUCKET pbkt; + + /* Loop all colliding hash buckets */ + for (pbkt = pfh->apbkt[iHashIndex]; pbkt; pbkt = pbkt->pbktCollision) + { + /* Quick check */ + if (pbkt->iHashValue != iHashValue) continue; + + /* Compare the font name */ + if (wcsncmp(pbkt->u.wcCapName, pwszCapName, LF_FACESIZE) == 0) break; + } + + return pbkt; +} + +static +VOID +FONTHASH_vInsertPFE( + PFONTHASH pfh, + PPFE ppfe) +{ + PIFIMETRICS pifi = ppfe->pifi; + PWSTR pwszName; + WCHAR awcCapName[LF_FACESIZE]; + ULONG iHashValue; + PHASHBUCKET pbkt; + + + if (pfh->fht == FHT_UFI) + { + ASSERT(FALSE); + } + else + { + if (pfh->fht == FHT_FACE) + pwszName = (PWSTR)((PUCHAR)pifi + pifi->dpwszFaceName); + else + pwszName = (PWSTR)((PUCHAR)pifi + pifi->dpwszFamilyName); + + UpcaseString(awcCapName, pwszName, LF_FACESIZE); + iHashValue = CalculateNameHash(awcCapName); + + pbkt = FONTHASH_pbktFindBucketByName(pfh, awcCapName, iHashValue); + } + + if (!pbkt) + { + pbkt = HASHBUCKET_Allocate(); + + if (!pbkt) + { + ASSERT(FALSE); + } + + RtlCopyMemory(pbkt->u.wcCapName, awcCapName, sizeof(awcCapName)); + + FONTHASH_vInsertBucket(pfh, pbkt, iHashValue); + } + + /* Finally add the PFE to the HASHBUCKET */ + if (!HASHBUCKET_bLinkPFE(pbkt, ppfe)) + { + ASSERT(FALSE); + } + + +} +
BOOL NTAPI @@ -46,9 +281,26 @@ RtlZeroMemory(ppft, sizeof(PFT));
ppft->hsem = EngCreateSemaphore(); - if (!ppft->hsem) return FALSE; + if (!ppft->hsem) goto failed; + + ppft->cBuckets = MAX_FONT_LIST; + + ppft->pfhFace = FONTHASH_Allocate(FHT_FACE, MAX_FONT_LIST); + if (!ppft->pfhFace) goto failed; + + ppft->pfhFamily = FONTHASH_Allocate(FHT_FAMILY, MAX_FONT_LIST); + if (!ppft->pfhFace) goto failed; + + ppft->pfhUFI = FONTHASH_Allocate(FHT_UFI, MAX_FONT_LIST); + if (!ppft->pfhFace) goto failed;
return TRUE; + +failed: + // FIXME: cleanup + ASSERT(FALSE); + + return FALSE; }
static @@ -60,11 +312,11 @@ ULONG cFiles, ULONG iFileNameHash) { - ULONG iListIndex = iFileNameHash % MAX_FONT_LIST; + ULONG iListIndex = iFileNameHash % ppft->cBuckets; PPFF ppff = NULL;
- /* Acquire PFT lock */ - EngAcquireSemaphore(ppft->hsem); + /* Acquire PFT lock for reading */ + EngAcquireSemaphoreShared(ppft->hsem);
/* Loop all PFFs in the slot */ for (ppff = ppft->apPFF[iListIndex]; ppff; ppff = ppff->pPFFNext) @@ -82,28 +334,6 @@ return ppff; }
-static -VOID -PFT_vInsertPFE( - PPFT ppft, - PPFE ppfe) -{ - UCHAR ajWinChatSet[2] = {0, DEFAULT_CHARSET}; - UCHAR *pjCharSets; - PIFIMETRICS pifi = ppfe->pifi; - - if (pifi->dpCharSets) - { - pjCharSets = (PUCHAR)pifi + pifi->dpCharSets; - } - else - { - ajWinChatSet[0] = pifi->jWinCharSet; - pjCharSets = ajWinChatSet; - } - - -}
static VOID @@ -112,7 +342,7 @@ PPFF ppff, ULONG iFileNameHash) { - ULONG i, iListIndex = iFileNameHash % MAX_FONT_LIST; + ULONG i, iHashIndex = iFileNameHash % ppft->cBuckets;
ppff->iFileNameHash = iFileNameHash;
@@ -121,34 +351,23 @@
/* Insert the font file into the hash bucket */ ppff->pPFFPrev = NULL; - ppff->pPFFNext = ppft->apPFF[iListIndex]; - ppft->apPFF[iListIndex] = ppff; + ppff->pPFFNext = ppft->apPFF[iHashIndex]; + ppft->apPFF[iHashIndex] = ppff; + + ppft->cFiles++;
/* Loop all PFE's */ for (i = 0; i < ppff->cFonts; i++) { - PFT_vInsertPFE(ppft, &ppff->apfe[i]); + FONTHASH_vInsertPFE(ppft->pfhFace, &ppff->apfe[i]); + FONTHASH_vInsertPFE(ppft->pfhFamily, &ppff->apfe[i]); + //FONTHASH_vInsertPFE(ppft->pfhUFI, &ppff->apfe[i]); }
/* Release PFT lock */ EngReleaseSemaphore(ppft->hsem); }
-static -ULONG -CalculateNameHash(PWSTR pwszName) -{ - ULONG iHash = 0; - WCHAR wc; - - while ((wc = *pwszName++) != 0) - { - iHash = _rotl(iHash, 7); - iHash += wc; - } - - return iHash; -}
@@ -232,7 +451,6 @@ ULONG cjSize; DESIGNVECTOR dv; INT iRes = 0; - ULONG i;
/* Check parameters */ if (cFiles == 0 || cFiles > FD_MAX_FILES || @@ -261,10 +479,7 @@ }
/* Convert the string to upper case */ - for (i = 0; i < cwc; i++) - { - pwszUpcase[i] = RtlUpcaseUnicodeChar(pwszFiles[i]); - } + UpcaseString(pwszUpcase, pwszFiles, cwc);
/* Check if we have a DESIGNVECTOR */ if (pdv)
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] Sat Aug 6 11:10:42 2011 @@ -47,6 +47,11 @@ plfnt->fl = fl; plfnt->elfexw = *pelfw;
+ /* Upcase the font name */ + UpcaseString(plfnt->awchFace, + pelfw->elfEnumLogfontEx.elfLogFont.lfFaceName, + LF_FACESIZE); + /* 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] Sat Aug 6 11:10:42 2011 @@ -97,43 +97,50 @@ ULONG cFonts; void *pPvtDataHead; PFONTFILEVIEW apffv[FD_MAX_FILES]; - PFE apfe[1]; + PFE apfe[]; } PFF, *PPFF;
+typedef struct _PFELINK +{ + struct _PFELINK *ppfelNext; + PPFE ppfe; +} PFELINK, *PPFELINK; + typedef struct _HASHBUCKET { struct _HASHBUCKET *pbktCollision; - // PFELINK *ppfelEnumHead; - // PFELINK *ppfelEnumTail; + PFELINK *ppfelEnumHead; + PFELINK *ppfelEnumTail; ULONG cTrueType; + ULONG iHashValue; FLONG fl; struct _HASHBUCKET * pbktPrev; struct _HASHBUCKET * pbktNext; ULONG ulTime; union { - WCHAR wcCapName[1]; + WCHAR wcCapName[LF_FACESIZE]; // LF_FULLFACESIZE? dynamic? UNIVERSAL_FONT_ID ufi; } u; } HASHBUCKET, *PHASHBUCKET;
typedef enum _FONT_HASH_TYPE { + FHT_FACE = 0, FHT_FAMILY = 1, - FHT_FACE, - FHT_UFI, + FHT_UFI = 2, } FONT_HASH_TYPE;
-typedef struct +typedef struct _FONTHASH { DWORD id; FONT_HASH_TYPE fht; ULONG cBuckets; ULONG cUsed; ULONG cCollisions; - HASHBUCKET * pbktFirst; - HASHBUCKET * pbktLast; - HASHBUCKET * apbkt[]; + PHASHBUCKET pbktFirst; + PHASHBUCKET pbktLast; + PHASHBUCKET apbkt[]; } FONTHASH, *PFONTHASH;
#define MAX_FONT_LIST 100 @@ -150,7 +157,7 @@ HSEMAPHORE hsem; } PFT, *PPFT;
-typedef struct +typedef struct _RFONTLINK { PRFONT prfntPrev; PRFONT prfntNext; @@ -325,6 +332,13 @@ ULONG acFaceNameGlyphs[8]; } ESTROBJ, *PESTROBJ;
+VOID +NTAPI +UpcaseString( + OUT PWSTR pwszDest, + IN PWSTR pwszSource, + IN ULONG cwc); + FORCEINLINE PLFONT LFONT_ShareLockFont(HFONT hfont) @@ -398,3 +412,8 @@
#define DbgDefaultChannel 0x0 + +VOID +NTAPI +EngAcquireSemaphoreShared( + IN HSEMAPHORE hsem);
Modified: branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/objects/dclife.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/subsyste... ============================================================================== --- branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/objects/dclife.c [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/objects/dclife.c [iso-8859-1] Sat Aug 6 11:10:42 2011 @@ -358,6 +358,8 @@ DC_vSelectLineBrush(pdc, NULL); DC_vSelectPalette(pdc, NULL);
+ GDIOBJ_vDereferenceObject((PVOID)pdc->dclevel.plfnt); + /* Cleanup the dc brushes */ EBRUSHOBJ_vCleanup(&pdc->eboFill); EBRUSHOBJ_vCleanup(&pdc->eboLine);
Modified: branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/objects/path.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/subsyste... ============================================================================== --- branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/objects/path.c [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/subsystems/win32/win32k/objects/path.c [iso-8859-1] Sat Aug 6 11:10:42 2011 @@ -2061,6 +2061,8 @@ GLYPHMETRICS gm; DWORD dwSize; void *outline; + + __debugbreak(); #if 0 dwSize = ftGdiGetGlyphOutline( dc, str[idx],