Nikolay Sivov : dwrite: Keep a single instance of system font collection.

Alexandre Julliard julliard at winehq.org
Tue Oct 23 13:37:18 CDT 2012


Module: wine
Branch: master
Commit: a291a7adf8f92e97e3bb9365008b0fc28d17a773
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a291a7adf8f92e97e3bb9365008b0fc28d17a773

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sun Oct 21 23:20:42 2012 -0400

dwrite: Keep a single instance of system font collection.

---

 dlls/dwrite/dwrite_private.h |    3 +-
 dlls/dwrite/font.c           |   97 +++++++++++++++++++++--------------------
 dlls/dwrite/main.c           |    5 ++-
 dlls/dwrite/tests/font.c     |   12 +++++-
 4 files changed, 67 insertions(+), 50 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 4cb0e3b..e9d927a 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -74,4 +74,5 @@ extern HRESULT create_textlayout(const WCHAR*,UINT32,IDWriteTextLayout**) DECLSP
 extern HRESULT create_gdiinterop(IDWriteGdiInterop**) DECLSPEC_HIDDEN;
 extern HRESULT create_localizedstrings(IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
 extern HRESULT add_localizedstring(IDWriteLocalizedStrings*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN;
-extern HRESULT create_system_fontcollection(IDWriteFontCollection**) DECLSPEC_HIDDEN;
+extern HRESULT get_system_fontcollection(IDWriteFontCollection**) DECLSPEC_HIDDEN;
+extern void release_system_fontcollection(void) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index ff4a345..60aa7db 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -129,13 +129,14 @@ typedef struct
 
 struct dwrite_fontcollection {
     IDWriteFontCollection IDWriteFontCollection_iface;
-    LONG ref;
 
     WCHAR **families;
     UINT32 count;
     int alloc;
 };
 
+static IDWriteFontCollection *system_collection;
+
 struct dwrite_fontfamily {
     IDWriteFontFamily IDWriteFontFamily_iface;
     LONG ref;
@@ -645,32 +646,14 @@ static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection
     return E_NOINTERFACE;
 }
 
-static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface)
+static ULONG WINAPI dwritesysfontcollection_AddRef(IDWriteFontCollection *iface)
 {
-    struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
-    ULONG ref = InterlockedIncrement(&This->ref);
-    TRACE("(%p)->(%d)\n", This, ref);
-    return ref;
+    return 2;
 }
 
-static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
+static ULONG WINAPI dwritesysfontcollection_Release(IDWriteFontCollection *iface)
 {
-    struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
-    ULONG ref = InterlockedDecrement(&This->ref);
-
-    TRACE("(%p)->(%d)\n", This, ref);
-
-    if (!ref)
-    {
-        int i;
-
-        for (i = 0; i < This->count; i++)
-            heap_free(This->families[i]);
-        heap_free(This->families);
-        heap_free(This);
-    }
-
-    return ref;
+    return 1;
 }
 
 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
@@ -715,10 +698,10 @@ static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollec
     return E_NOTIMPL;
 }
 
-static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
+static const IDWriteFontCollectionVtbl systemfontcollectionvtbl = {
     dwritefontcollection_QueryInterface,
-    dwritefontcollection_AddRef,
-    dwritefontcollection_Release,
+    dwritesysfontcollection_AddRef,
+    dwritesysfontcollection_Release,
     dwritefontcollection_GetFontFamilyCount,
     dwritefontcollection_GetFontFamily,
     dwritefontcollection_FindFamilyName,
@@ -749,35 +732,55 @@ static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm
     return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
 }
 
-HRESULT create_system_fontcollection(IDWriteFontCollection **collection)
+static void release_font_collection(IDWriteFontCollection *iface)
 {
-    struct dwrite_fontcollection *This;
-    LOGFONTW lf;
-    HDC hdc;
+    struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
+    int i;
 
-    *collection = NULL;
+    for (i = 0; i < This->count; i++)
+        heap_free(This->families[i]);
+    heap_free(This->families);
+    heap_free(This);
+}
 
-    This = heap_alloc(sizeof(struct dwrite_fontcollection));
-    if (!This) return E_OUTOFMEMORY;
+void release_system_fontcollection(void)
+{
+    release_font_collection(system_collection);
+}
 
-    This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
-    This->ref = 1;
+HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
+{
+    if (!system_collection)
+    {
+        struct dwrite_fontcollection *This;
+        LOGFONTW lf;
+        HDC hdc;
 
-    This->alloc = 50;
-    This->count = 0;
-    This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
+        *collection = NULL;
 
-    TRACE("building system font collection:\n");
+        This = heap_alloc(sizeof(struct dwrite_fontcollection));
+        if (!This) return E_OUTOFMEMORY;
 
-    hdc = CreateCompatibleDC(0);
-    memset(&lf, 0, sizeof(lf));
-    lf.lfCharSet = DEFAULT_CHARSET;
-    lf.lfPitchAndFamily = DEFAULT_PITCH;
-    lf.lfFaceName[0] = 0;
-    EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
-    DeleteDC(hdc);
+        This->IDWriteFontCollection_iface.lpVtbl = &systemfontcollectionvtbl;
+        This->alloc = 50;
+        This->count = 0;
+        This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
+
+        TRACE("building system font collection:\n");
+
+        hdc = CreateCompatibleDC(0);
+        memset(&lf, 0, sizeof(lf));
+        lf.lfCharSet = DEFAULT_CHARSET;
+        lf.lfPitchAndFamily = DEFAULT_PITCH;
+        lf.lfFaceName[0] = 0;
+        EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
+        DeleteDC(hdc);
+
+        if (InterlockedCompareExchangePointer((void**)&system_collection, &This->IDWriteFontCollection_iface, NULL))
+            release_font_collection(&This->IDWriteFontCollection_iface);
+    }
 
-    *collection = &This->IDWriteFontCollection_iface;
+    *collection = system_collection;
 
     return S_OK;
 }
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 4605008..ea1bbce 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -43,6 +43,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
     case DLL_PROCESS_ATTACH:
         DisableThreadLibraryCalls( hinstDLL );
         break;
+    case DLL_PROCESS_DETACH:
+        release_system_fontcollection();
+        break;
     }
     return TRUE;
 }
@@ -389,7 +392,7 @@ static HRESULT WINAPI dwritefactory_GetSystemFontCollection(IDWriteFactory *ifac
     if (check_for_updates)
         FIXME("checking for system font updates not implemented\n");
 
-    return create_system_fontcollection(collection);
+    return get_system_fontcollection(collection);
 }
 
 static HRESULT WINAPI dwritefactory_CreateCustomFontCollection(IDWriteFactory *iface,
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 07d3e7d..423c876 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -525,7 +525,7 @@ todo_wine
 
 static void test_system_fontcollection(void)
 {
-    IDWriteFontCollection *collection;
+    IDWriteFontCollection *collection, *coll2;
     HRESULT hr;
     UINT32 i;
     BOOL ret;
@@ -533,6 +533,16 @@ static void test_system_fontcollection(void)
     hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, FALSE);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
+    IDWriteFontCollection_Release(coll2);
+
+    hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, TRUE);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
+    IDWriteFontCollection_Release(coll2);
+
     i = IDWriteFontCollection_GetFontFamilyCount(collection);
     ok(i, "got %u\n", i);
 




More information about the wine-cvs mailing list