Nikolay Sivov : dwrite: Use file mapping for local file stream.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Nov 26 14:13:54 CST 2014
Module: wine
Branch: master
Commit: 416527a6adb62ff446960226a9e4127d5e1ffcfd
URL: http://source.winehq.org/git/wine.git/?a=commit;h=416527a6adb62ff446960226a9e4127d5e1ffcfd
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Wed Nov 26 08:59:04 2014 +0300
dwrite: Use file mapping for local file stream.
---
dlls/dwrite/font.c | 58 +++++++++++++++++++++++++-----------------------
dlls/dwrite/tests/font.c | 16 ++++++++-----
2 files changed, 41 insertions(+), 33 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index cef4a27..76f3e3e 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -2042,7 +2042,8 @@ struct dwrite_localfontfilestream
LONG ref;
struct local_cached_stream *entry;
- HANDLE handle;
+ const void *file_ptr;
+ UINT64 size;
};
struct dwrite_localfontfileloader {
@@ -2100,8 +2101,7 @@ static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
TRACE("(%p)->(%d)\n", This, ref);
if (!ref) {
- if (This->handle != INVALID_HANDLE_VALUE)
- CloseHandle(This->handle);
+ UnmapViewOfFile(This->file_ptr);
release_cached_stream(This->entry);
heap_free(This);
}
@@ -2112,26 +2112,18 @@ static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
{
struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
- LARGE_INTEGER distance;
- DWORD bytes = fragment_size;
- DWORD read;
TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
*fragment_context = NULL;
- distance.QuadPart = offset;
- if (!SetFilePointerEx(This->handle, distance, NULL, FILE_BEGIN))
- return E_FAIL;
- *fragment_start = *fragment_context = heap_alloc(bytes);
- if (!*fragment_context)
- return E_FAIL;
- if (!ReadFile(This->handle, *fragment_context, bytes, &read, NULL))
- {
- heap_free(*fragment_context);
+
+ if ((offset >= This->size - 1) || (fragment_size > This->size - offset)) {
+ *fragment_start = NULL;
return E_FAIL;
}
+ *fragment_start = (char*)This->file_ptr + offset;
return S_OK;
}
@@ -2139,16 +2131,13 @@ static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
{
struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
TRACE("(%p)->(%p)\n", This, fragment_context);
- heap_free(fragment_context);
}
static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
{
struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
- LARGE_INTEGER li;
- TRACE("(%p)->(%p)\n",This, size);
- GetFileSizeEx(This->handle, &li);
- *size = li.QuadPart;
+ TRACE("(%p)->(%p)\n", This, size);
+ *size = This->size;
return S_OK;
}
@@ -2177,15 +2166,17 @@ static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
localfontfilestream_GetLastWriteTime
};
-static HRESULT create_localfontfilestream(HANDLE handle, struct local_cached_stream *entry, IDWriteFontFileStream** iface)
+static HRESULT create_localfontfilestream(const void *file_ptr, UINT64 size, struct local_cached_stream *entry, IDWriteFontFileStream** iface)
{
struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
if (!This)
return E_OUTOFMEMORY;
- This->ref = 1;
- This->handle = handle;
This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
+ This->ref = 1;
+
+ This->file_ptr = file_ptr;
+ This->size = size;
This->entry = entry;
*iface = &This->IDWriteFontFileStream_iface;
@@ -2244,11 +2235,12 @@ static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFi
const struct local_refkey *refkey = key;
struct local_cached_stream *stream;
IDWriteFontFileStream *filestream;
- HANDLE handle;
+ HANDLE file, mapping;
+ LARGE_INTEGER size;
+ void *file_ptr;
HRESULT hr;
TRACE("(%p)->(%p, %i, %p)\n", This, key, key_size, ret);
-
TRACE("name: %s\n", debugstr_w(refkey->name));
/* search cache first */
@@ -2262,18 +2254,27 @@ static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFi
*ret = NULL;
- handle = CreateFileW(refkey->name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ file = CreateFileW(refkey->name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file == INVALID_HANDLE_VALUE)
+ return E_FAIL;
- if (handle == INVALID_HANDLE_VALUE)
+ GetFileSizeEx(file, &size);
+ mapping = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
+ CloseHandle(file);
+ if (!mapping)
return E_FAIL;
+ file_ptr = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
+ CloseHandle(mapping);
+
stream = heap_alloc(sizeof(*stream));
if (!stream)
return E_OUTOFMEMORY;
stream->key = heap_alloc(key_size);
if (!stream->key) {
+ UnmapViewOfFile(file_ptr);
heap_free(stream);
return E_OUTOFMEMORY;
}
@@ -2281,8 +2282,9 @@ static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFi
stream->key_size = key_size;
memcpy(stream->key, key, key_size);
- hr = create_localfontfilestream(handle, stream, &filestream);
+ hr = create_localfontfilestream(file_ptr, size.QuadPart, stream, &filestream);
if (FAILED(hr)) {
+ UnmapViewOfFile(file_ptr);
heap_free(stream->key);
heap_free(stream);
return hr;
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 8143120..221a5d3 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -2497,16 +2497,14 @@ static void test_ReadFileFragment(void)
fragment = (void*)0xdeadbeef;
context = (void*)0xdeadbeef;
hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize+1, &context);
-todo_wine {
ok(hr == E_FAIL, "got 0x%08x\n", hr);
ok(context == NULL, "got %p\n", context);
ok(fragment == NULL, "got %p\n", fragment);
-}
+
fragment = (void*)0xdeadbeef;
context = (void*)0xdeadbeef;
hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize, &context);
ok(hr == S_OK, "got 0x%08x\n", hr);
-todo_wine
ok(context == NULL, "got %p\n", context);
ok(fragment != NULL, "got %p\n", fragment);
@@ -2514,13 +2512,21 @@ todo_wine
context2 = (void*)0xdeadbeef;
hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment2, 0, filesize, &context2);
ok(hr == S_OK, "got 0x%08x\n", hr);
-todo_wine {
ok(context2 == NULL, "got %p\n", context2);
ok(fragment == fragment2, "got %p, %p\n", fragment, fragment2);
-}
+
IDWriteFontFileStream_ReleaseFileFragment(stream, context);
IDWriteFontFileStream_ReleaseFileFragment(stream, context2);
+ /* fragment is released, try again */
+ fragment = (void*)0xdeadbeef;
+ context = (void*)0xdeadbeef;
+ hr = IDWriteFontFileStream_ReadFileFragment(stream, &fragment, 0, filesize, &context);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(context == NULL, "got %p\n", context);
+ ok(fragment == fragment2, "got %p, %p\n", fragment, fragment2);
+ IDWriteFontFileStream_ReleaseFileFragment(stream, context);
+
IDWriteFontFileStream_Release(stream);
IDWriteLocalFontFileLoader_Release(localloader);
IDWriteFactory_Release(factory);
More information about the wine-cvs
mailing list