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/subsystems/win32/win32k/CMakeLists.txt?rev=53099&r1=53098&r2=53099&view=diff
==============================================================================
--- 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/subsystems/win32/win32k/font/fontrsrc.c?rev=53099&r1=53098&r2=53099&view=diff
==============================================================================
--- 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/subsystems/win32/win32k/font/lfont.c?rev=53099&r1=53098&r2=53099&view=diff
==============================================================================
--- 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/subsystems/win32/win32k/include/font.h?rev=53099&r1=53098&r2=53099&view=diff
==============================================================================
--- 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/subsystems/win32/win32k/objects/dclife.c?rev=53099&r1=53098&r2=53099&view=diff
==============================================================================
--- 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/subsystems/win32/win32k/objects/path.c?rev=53099&r1=53098&r2=53099&view=diff
==============================================================================
--- 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],


Reply via email to