diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index d1c42ce0a80..3b1d2833d29 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -108,6 +108,7 @@ extern HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface) DE extern HRESULT create_fontface(DWRITE_FONT_FACE_TYPE,UINT32,IDWriteFontFile* const*,UINT32,DWRITE_FONT_SIMULATIONS,IDWriteFontFace2**) DECLSPEC_HIDDEN; extern HRESULT create_font_collection(IDWriteFactory*,IDWriteFontFileEnumerator*,BOOL,IDWriteFontCollection**) DECLSPEC_HIDDEN; extern BOOL is_system_collection(IDWriteFontCollection*) DECLSPEC_HIDDEN; +extern HRESULT get_local_refkey(const WCHAR*,const FILETIME*,void**,UINT32*) DECLSPEC_HIDDEN; /* Opentype font table functions */ extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,UINT32*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,BOOL*) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 8bb39fabdef..a83baa7e7fa 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -1984,6 +1984,12 @@ struct dwrite_localfontfilestream HANDLE handle; }; +struct local_refkey +{ + FILETIME writetime; + WCHAR name[1]; +}; + struct dwrite_localfontfileloader { IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface; LONG ref; @@ -2153,16 +2159,16 @@ static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *ifac return ref; } -static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream) +static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *key, UINT32 key_size, IDWriteFontFileStream **fontFileStream) { - HANDLE handle; struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface); - const WCHAR *name = (const WCHAR*)fontFileReferenceKey; + const struct local_refkey *refkey = key; + HANDLE handle; - TRACE("(%p)->(%p, %i, %p)\n",This, fontFileReferenceKey, fontFileReferenceKeySize, fontFileStream); + TRACE("(%p)->(%p, %i, %p)\n", This, key, key_size, fontFileStream); - TRACE("name: %s\n",debugstr_w(name)); - handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, + TRACE("name: %s\n", debugstr_w(refkey->name)); + handle = CreateFileW(refkey->name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (handle == INVALID_HANDLE_VALUE) @@ -2174,26 +2180,37 @@ static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFi static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length) { struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface); - TRACE("(%p)->(%p, %i, %p)\n",This, key, key_size, length); - *length = key_size; + const struct local_refkey *refkey = key; + + TRACE("(%p)->(%p, %i, %p)\n", This, key, key_size, length); + + *length = strlenW(refkey->name); return S_OK; } static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length) { struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface); - TRACE("(%p)->(%p, %i, %p, %i)\n",This, key, key_size, path, length); - if (length < key_size) + const struct local_refkey *refkey = key; + + TRACE("(%p)->(%p, %i, %p, %i)\n", This, key, key_size, path, length); + + if (length < strlenW(refkey->name)) return E_INVALIDARG; - lstrcpynW((WCHAR*)key, path, key_size); + + strcpyW(path, refkey->name); return S_OK; } static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime) { struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface); - FIXME("(%p)->(%p, %i, %p):stub\n",This, key, key_size, writetime); - return E_NOTIMPL; + const struct local_refkey *refkey = key; + + TRACE("(%p)->(%p, %i, %p)\n", This, key, key_size, writetime); + + *writetime = refkey->writetime; + return S_OK; } static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = { @@ -2218,3 +2235,31 @@ HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface) *iface = &This->IDWriteLocalFontFileLoader_iface; return S_OK; } + +HRESULT get_local_refkey(const WCHAR *path, const FILETIME *writetime, void **key, UINT32 *size) +{ + struct local_refkey *refkey; + + *size = FIELD_OFFSET(struct local_refkey, name) + (strlenW(path)+1)*sizeof(WCHAR); + *key = NULL; + + refkey = heap_alloc(*size); + if (!refkey) + return E_OUTOFMEMORY; + + if (writetime) + refkey->writetime = *writetime; + else { + WIN32_FILE_ATTRIBUTE_DATA info; + + if (GetFileAttributesExW(path, GetFileExInfoStandard, &info)) + refkey->writetime = info.ftLastWriteTime; + else + memset(&refkey->writetime, 0, sizeof(refkey->writetime)); + } + strcpyW(refkey->name, path); + + *key = refkey; + + return S_OK; +} diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 2868c3b9ae3..1292086b122 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -686,8 +686,11 @@ static HRESULT WINAPI dwritefactory_UnregisterFontCollectionLoader(IDWriteFactor static HRESULT WINAPI dwritefactory_CreateFontFileReference(IDWriteFactory *iface, WCHAR const *path, FILETIME const *writetime, IDWriteFontFile **font_file) { - HRESULT hr; struct dwritefactory *This = impl_from_IDWriteFactory(iface); + UINT32 key_size; + HRESULT hr; + void *key; + TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(path), writetime, font_file); if (!This->localfontfileloader) @@ -696,7 +699,16 @@ static HRESULT WINAPI dwritefactory_CreateFontFileReference(IDWriteFactory *ifac if (FAILED(hr)) return hr; } - return create_font_file((IDWriteFontFileLoader*)This->localfontfileloader, path, sizeof(WCHAR) * (strlenW(path)+1), font_file); + + /* get a reference key used by local loader */ + hr = get_local_refkey(path, writetime, &key, &key_size); + if (FAILED(hr)) + return hr; + + hr = create_font_file((IDWriteFontFileLoader*)This->localfontfileloader, key, key_size, font_file); + heap_free(key); + + return hr; } static HRESULT WINAPI dwritefactory_CreateCustomFontFileReference(IDWriteFactory *iface, diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 60d0d440568..1fdb8d07f1d 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -2218,15 +2218,26 @@ static void test_GetFaceNames(void) IDWriteFactory_Release(factory); } +struct local_refkey +{ + FILETIME writetime; + WCHAR name[1]; +}; + static void test_TryGetFontTable(void) { + IDWriteLocalFontFileLoader *localloader; + WIN32_FILE_ATTRIBUTE_DATA info; + const struct local_refkey *key; + IDWriteFontFileLoader *loader; const void *table, *table2; IDWriteFontFace *fontface; void *context, *context2; IDWriteFactory *factory; IDWriteFontFile *file; - BOOL exists; - UINT32 size; + WCHAR buffW[MAX_PATH]; + BOOL exists, ret; + UINT32 size, len; HRESULT hr; create_testfontfile(test_fontfile); @@ -2236,6 +2247,30 @@ static void test_TryGetFontTable(void) hr = IDWriteFactory_CreateFontFileReference(factory, test_fontfile, NULL, &file); ok(hr == S_OK, "got 0x%08x\n",hr); + key = NULL; + size = 0; + hr = IDWriteFontFile_GetReferenceKey(file, (const void**)&key, &size); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(size != 0, "got %u\n", size); + + ret = GetFileAttributesExW(test_fontfile, GetFileExInfoStandard, &info); + ok(ret, "got %d\n", ret); + ok(!memcmp(&info.ftLastWriteTime, &key->writetime, sizeof(key->writetime)), "got wrong write time\n"); + + hr = IDWriteFontFile_GetLoader(file, &loader); + ok(hr == S_OK, "got 0x%08x\n", hr); + IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteLocalFontFileLoader, (void**)&localloader); + IDWriteFontFileLoader_Release(loader); + + hr = IDWriteLocalFontFileLoader_GetFilePathLengthFromKey(localloader, key, size, &len); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(lstrlenW(key->name) == len, "path length %d\n", len); + + hr = IDWriteLocalFontFileLoader_GetFilePathFromKey(localloader, key, size, buffW, sizeof(buffW)/sizeof(WCHAR)); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(buffW, key->name), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(key->name)); + IDWriteLocalFontFileLoader_Release(localloader); + hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, 0, &fontface); ok(hr == S_OK, "got 0x%08x\n",hr);