Ziqing Hui : mlang: Implement IMLangFontLink2_MapFont, IMLangFontLink2_ReleaseFont and IMLangFontLink2_ResetFont.
Alexandre Julliard
julliard at winehq.org
Mon Nov 27 15:05:39 CST 2017
Module: wine
Branch: master
Commit: 98d35d97c7ed00474a54e2a5c264d7d3f2032520
URL: http://source.winehq.org/git/wine.git/?a=commit;h=98d35d97c7ed00474a54e2a5c264d7d3f2032520
Author: Ziqing Hui <zhui at codeweavers.com>
Date: Mon Nov 27 19:46:36 2017 +0800
mlang: Implement IMLangFontLink2_MapFont, IMLangFontLink2_ReleaseFont and IMLangFontLink2_ResetFont.
Signed-off-by: Ziqing Hui <zhui at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/mlang/mlang.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 156 insertions(+), 7 deletions(-)
diff --git a/dlls/mlang/mlang.c b/dlls/mlang/mlang.c
index 47f9d98..7de6cc7 100644
--- a/dlls/mlang/mlang.c
+++ b/dlls/mlang/mlang.c
@@ -40,6 +40,7 @@
#include "wine/unicode.h"
#include "wine/debug.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(mlang);
@@ -525,6 +526,24 @@ static const struct mlang_data
"Courier","Arial" } /* FIXME */
};
+struct font_list
+{
+ struct list list_entry;
+ HFONT base_font;
+ HFONT font;
+ UINT charset;
+};
+
+static struct list font_cache = LIST_INIT(font_cache);
+static CRITICAL_SECTION font_cache_critical;
+static CRITICAL_SECTION_DEBUG font_cache_critical_debug =
+{
+ 0, 0, &font_cache_critical,
+ { &font_cache_critical_debug.ProcessLocksList, &font_cache_critical_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": font_cache_critical") }
+};
+static CRITICAL_SECTION font_cache_critical = { &font_cache_critical_debug, -1, 0, 0, 0, 0 };
+
static void fill_cp_info(const struct mlang_data *ml_data, UINT index, MIMECPINFO *mime_cp_info);
static LONG dll_count;
@@ -1312,6 +1331,119 @@ HRESULT WINAPI Rfc1766ToLcidA(LCID *lcid, LPCSTR rfc1766A)
return Rfc1766ToLcidW(lcid, rfc1766W);
}
+static HRESULT map_font(HDC hdc, DWORD codepages, HFONT src_font, HFONT *dst_font)
+{
+ struct font_list *font_list_entry;
+ CHARSETINFO charset_info;
+ HFONT new_font, old_font;
+ LOGFONTW font_attr;
+ DWORD mask, Csb[2];
+ BOOL found_cached;
+ UINT charset;
+ BOOL ret;
+ UINT i;
+
+ if (hdc == NULL || src_font == NULL) return E_FAIL;
+
+ for (i = 0; i < 32; i++)
+ {
+ mask = (DWORD)(1 << i);
+ if (codepages & mask)
+ {
+ Csb[0] = mask;
+ Csb[1] = 0x0;
+ ret = TranslateCharsetInfo(Csb, &charset_info, TCI_SRCFONTSIG);
+ if (!ret) continue;
+
+ /* use cached font if possible */
+ found_cached = FALSE;
+ EnterCriticalSection(&font_cache_critical);
+ LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
+ {
+ if (font_list_entry->charset == charset_info.ciCharset &&
+ font_list_entry->base_font == src_font)
+ {
+ if (dst_font != NULL)
+ *dst_font = font_list_entry->font;
+ found_cached = TRUE;
+ }
+ }
+ LeaveCriticalSection(&font_cache_critical);
+ if (found_cached) return S_OK;
+
+ GetObjectW(src_font, sizeof(font_attr), &font_attr);
+ font_attr.lfCharSet = (BYTE)charset_info.ciCharset;
+ font_attr.lfWidth = 0;
+ font_attr.lfFaceName[0] = 0;
+ new_font = CreateFontIndirectW(&font_attr);
+ if (new_font == NULL) continue;
+
+ old_font = SelectObject(hdc, new_font);
+ charset = GetTextCharset(hdc);
+ SelectObject(hdc, old_font);
+ if (charset == charset_info.ciCharset)
+ {
+ font_list_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_list_entry));
+ if (font_list_entry == NULL) return E_OUTOFMEMORY;
+
+ font_list_entry->base_font = src_font;
+ font_list_entry->font = new_font;
+ font_list_entry->charset = charset;
+
+ EnterCriticalSection(&font_cache_critical);
+ list_add_tail(&font_cache, &font_list_entry->list_entry);
+ LeaveCriticalSection(&font_cache_critical);
+
+ if (dst_font != NULL)
+ *dst_font = new_font;
+ return S_OK;
+ }
+ }
+ }
+
+ return E_FAIL;
+}
+
+static HRESULT release_font(HFONT font)
+{
+ struct font_list *font_list_entry;
+ HRESULT hr;
+
+ hr = E_FAIL;
+ EnterCriticalSection(&font_cache_critical);
+ LIST_FOR_EACH_ENTRY(font_list_entry, &font_cache, struct font_list, list_entry)
+ {
+ if (font_list_entry->font == font)
+ {
+ list_remove(&font_list_entry->list_entry);
+ DeleteObject(font);
+ HeapFree(GetProcessHeap(), 0, font_list_entry);
+ hr = S_OK;
+ break;
+ }
+ }
+ LeaveCriticalSection(&font_cache_critical);
+
+ return hr;
+}
+
+static HRESULT clear_font_cache(void)
+{
+ struct font_list *font_list_entry;
+ struct font_list *font_list_entry2;
+
+ EnterCriticalSection(&font_cache_critical);
+ LIST_FOR_EACH_ENTRY_SAFE(font_list_entry, font_list_entry2, &font_cache, struct font_list, list_entry)
+ {
+ list_remove(&font_list_entry->list_entry);
+ DeleteObject(font_list_entry->font);
+ HeapFree(GetProcessHeap(), 0, font_list_entry);
+ }
+ LeaveCriticalSection(&font_cache_critical);
+
+ return S_OK;
+}
+
/******************************************************************************
* MLANG ClassFactory
*/
@@ -2499,7 +2631,7 @@ static ULONG WINAPI fnIMultiLanguage3_Release( IMultiLanguage3* iface )
TRACE("(%p)->(%d)\n", This, ref);
if (ref == 0)
{
- HeapFree(GetProcessHeap(), 0, This);
+ HeapFree(GetProcessHeap(), 0, This);
UnlockModule();
}
@@ -3351,21 +3483,38 @@ static HRESULT WINAPI fnIMLangFontLink2_GetFontCodePages(IMLangFontLink2 *iface,
static HRESULT WINAPI fnIMLangFontLink2_ReleaseFont(IMLangFontLink2* This,
HFONT hFont)
{
- FIXME("(%p)->%p\n",This, hFont);
- return E_NOTIMPL;
+ TRACE("(%p)->%p\n",This, hFont);
+
+ return release_font(hFont);
}
static HRESULT WINAPI fnIMLangFontLink2_ResetFontMapping(IMLangFontLink2* This)
{
- FIXME("(%p)->\n",This);
- return E_NOTIMPL;
+ TRACE("(%p)\n",This);
+
+ return clear_font_cache();
}
static HRESULT WINAPI fnIMLangFontLink2_MapFont(IMLangFontLink2* This,
HDC hDC, DWORD dwCodePages, WCHAR chSrc, HFONT *pFont)
{
- FIXME("(%p)->%p %i %s %p\n",This, hDC, dwCodePages, debugstr_wn(&chSrc,1), pFont);
- return E_NOTIMPL;
+ HFONT old_font;
+
+ TRACE("(%p)->%p %08x %04x %p\n",This, hDC, dwCodePages, chSrc, pFont);
+
+ if (!hDC) return E_FAIL;
+
+ if (dwCodePages != 0)
+ {
+ old_font = GetCurrentObject(hDC, OBJ_FONT);
+ return map_font(hDC, dwCodePages, old_font, pFont);
+ }
+ else
+ {
+ if (pFont == NULL) return E_INVALIDARG;
+ FIXME("the situation where dwCodepages is set to zero is not implemented\n");
+ return E_FAIL;
+ }
}
static HRESULT WINAPI fnIMLangFontLink2_GetFontUnicodeRanges(IMLangFontLink2* This,
More information about the wine-cvs
mailing list