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/subsyst…
==============================================================================
--- 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/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]
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/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] 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/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]
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/subsyst…
==============================================================================
--- 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/subsyst…
==============================================================================
--- 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],