dwrite: Reuse local file stream instances.
This commit is contained in:
parent
53fb0cc711
commit
8b769332e2
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
|
|
||||||
|
#include "wine/list.h"
|
||||||
#include "dwrite_private.h"
|
#include "dwrite_private.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
|
WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
|
||||||
|
@ -1975,12 +1976,20 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
|
/* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
|
||||||
|
struct local_cached_stream
|
||||||
|
{
|
||||||
|
struct list entry;
|
||||||
|
IDWriteFontFileStream *stream;
|
||||||
|
void *key;
|
||||||
|
UINT32 key_size;
|
||||||
|
};
|
||||||
|
|
||||||
struct dwrite_localfontfilestream
|
struct dwrite_localfontfilestream
|
||||||
{
|
{
|
||||||
IDWriteFontFileStream IDWriteFontFileStream_iface;
|
IDWriteFontFileStream IDWriteFontFileStream_iface;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
|
|
||||||
|
struct local_cached_stream *entry;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1993,6 +2002,8 @@ struct local_refkey
|
||||||
struct dwrite_localfontfileloader {
|
struct dwrite_localfontfileloader {
|
||||||
IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
|
IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
|
|
||||||
|
struct list streams;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
|
static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
|
||||||
|
@ -2028,6 +2039,13 @@ static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void release_cached_stream(struct local_cached_stream *stream)
|
||||||
|
{
|
||||||
|
list_remove(&stream->entry);
|
||||||
|
heap_free(stream->key);
|
||||||
|
heap_free(stream);
|
||||||
|
}
|
||||||
|
|
||||||
static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
|
static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
|
||||||
{
|
{
|
||||||
struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
|
struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
|
||||||
|
@ -2035,10 +2053,10 @@ static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
|
||||||
|
|
||||||
TRACE("(%p)->(%d)\n", This, ref);
|
TRACE("(%p)->(%d)\n", This, ref);
|
||||||
|
|
||||||
if (!ref)
|
if (!ref) {
|
||||||
{
|
|
||||||
if (This->handle != INVALID_HANDLE_VALUE)
|
if (This->handle != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle(This->handle);
|
CloseHandle(This->handle);
|
||||||
|
release_cached_stream(This->entry);
|
||||||
heap_free(This);
|
heap_free(This);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2107,7 +2125,7 @@ static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
|
||||||
localfontfilestream_GetLastWriteTime
|
localfontfilestream_GetLastWriteTime
|
||||||
};
|
};
|
||||||
|
|
||||||
static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream** iface)
|
static HRESULT create_localfontfilestream(HANDLE handle, struct local_cached_stream *entry, IDWriteFontFileStream** iface)
|
||||||
{
|
{
|
||||||
struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
|
struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
|
||||||
if (!This)
|
if (!This)
|
||||||
|
@ -2116,6 +2134,7 @@ static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream**
|
||||||
This->ref = 1;
|
This->ref = 1;
|
||||||
This->handle = handle;
|
This->handle = handle;
|
||||||
This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
|
This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
|
||||||
|
This->entry = entry;
|
||||||
|
|
||||||
*iface = &This->IDWriteFontFileStream_iface;
|
*iface = &This->IDWriteFontFileStream_iface;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -2153,28 +2172,76 @@ static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *ifac
|
||||||
|
|
||||||
TRACE("(%p)->(%d)\n", This, ref);
|
TRACE("(%p)->(%d)\n", This, ref);
|
||||||
|
|
||||||
if (!ref)
|
if (!ref) {
|
||||||
|
struct local_cached_stream *stream, *stream2;
|
||||||
|
|
||||||
|
/* This will detach all entries from cache. Entries are released together with streams,
|
||||||
|
so stream controls its lifetime. */
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(stream, stream2, &This->streams, struct local_cached_stream, entry)
|
||||||
|
list_init(&stream->entry);
|
||||||
|
|
||||||
heap_free(This);
|
heap_free(This);
|
||||||
|
}
|
||||||
|
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *key, UINT32 key_size, IDWriteFontFileStream **fontFileStream)
|
static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *key, UINT32 key_size, IDWriteFontFileStream **ret)
|
||||||
{
|
{
|
||||||
struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
|
struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
|
||||||
const struct local_refkey *refkey = key;
|
const struct local_refkey *refkey = key;
|
||||||
|
struct local_cached_stream *stream;
|
||||||
|
IDWriteFontFileStream *filestream;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
TRACE("(%p)->(%p, %i, %p)\n", This, key, key_size, fontFileStream);
|
TRACE("(%p)->(%p, %i, %p)\n", This, key, key_size, ret);
|
||||||
|
|
||||||
TRACE("name: %s\n", debugstr_w(refkey->name));
|
TRACE("name: %s\n", debugstr_w(refkey->name));
|
||||||
|
|
||||||
|
/* search cache first */
|
||||||
|
LIST_FOR_EACH_ENTRY(stream, &This->streams, struct local_cached_stream, entry) {
|
||||||
|
if (key_size == stream->key_size && !memcmp(stream->key, key, key_size)) {
|
||||||
|
*ret = stream->stream;
|
||||||
|
IDWriteFontFileStream_AddRef(*ret);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret = NULL;
|
||||||
|
|
||||||
handle = CreateFileW(refkey->name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
handle = CreateFileW(refkey->name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
return create_localfontfilestream(handle, fontFileStream);
|
stream = heap_alloc(sizeof(*stream));
|
||||||
|
if (!stream)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
stream->key = heap_alloc(key_size);
|
||||||
|
if (!stream->key) {
|
||||||
|
heap_free(stream);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->key_size = key_size;
|
||||||
|
memcpy(stream->key, key, key_size);
|
||||||
|
|
||||||
|
hr = create_localfontfilestream(handle, stream, &filestream);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
heap_free(stream->key);
|
||||||
|
heap_free(stream);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->stream = filestream;
|
||||||
|
list_add_head(&This->streams, &stream->entry);
|
||||||
|
|
||||||
|
*ret = stream->stream;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
|
static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
|
||||||
|
@ -2229,8 +2296,9 @@ HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
|
||||||
if (!This)
|
if (!This)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
This->ref = 1;
|
|
||||||
This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
|
This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
|
||||||
|
This->ref = 1;
|
||||||
|
list_init(&This->streams);
|
||||||
|
|
||||||
*iface = &This->IDWriteLocalFontFileLoader_iface;
|
*iface = &This->IDWriteLocalFontFileLoader_iface;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -2355,6 +2355,56 @@ if (0) { /* crashes on native */
|
||||||
IDWriteFactory_Release(factory);
|
IDWriteFactory_Release(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_CreateStreamFromKey(void)
|
||||||
|
{
|
||||||
|
IDWriteLocalFontFileLoader *localloader;
|
||||||
|
IDWriteFontFileStream *stream, *stream2;
|
||||||
|
IDWriteFontFileLoader *loader;
|
||||||
|
IDWriteFactory *factory;
|
||||||
|
IDWriteFontFile *file;
|
||||||
|
void *key;
|
||||||
|
UINT32 size;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
factory = create_factory();
|
||||||
|
|
||||||
|
create_testfontfile(test_fontfile);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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_CreateStreamFromKey(localloader, key, size, &stream);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
EXPECT_REF(stream, 1);
|
||||||
|
|
||||||
|
hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream2);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
ok(stream == stream2, "got %p, %p\n", stream, stream2);
|
||||||
|
EXPECT_REF(stream, 2);
|
||||||
|
IDWriteFontFileStream_Release(stream);
|
||||||
|
IDWriteFontFileStream_Release(stream2);
|
||||||
|
|
||||||
|
hr = IDWriteLocalFontFileLoader_CreateStreamFromKey(localloader, key, size, &stream);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
EXPECT_REF(stream, 1);
|
||||||
|
IDWriteFontFileStream_Release(stream);
|
||||||
|
|
||||||
|
IDWriteLocalFontFileLoader_Release(localloader);
|
||||||
|
IDWriteFactory_Release(factory);
|
||||||
|
DeleteFileW(test_fontfile);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(font)
|
START_TEST(font)
|
||||||
{
|
{
|
||||||
IDWriteFactory *factory;
|
IDWriteFactory *factory;
|
||||||
|
@ -2386,6 +2436,7 @@ START_TEST(font)
|
||||||
test_GetFaceNames();
|
test_GetFaceNames();
|
||||||
test_TryGetFontTable();
|
test_TryGetFontTable();
|
||||||
test_ConvertFontToLOGFONT();
|
test_ConvertFontToLOGFONT();
|
||||||
|
test_CreateStreamFromKey();
|
||||||
|
|
||||||
IDWriteFactory_Release(factory);
|
IDWriteFactory_Release(factory);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue