Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
a0c8f066
Commit
a0c8f066
authored
Nov 22, 2018
by
Nikolay Sivov
Committed by
Alexandre Julliard
Nov 22, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dwrite: Add support for memory font resources in CreateFontFaceFromHdc().
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
5d31184d
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
261 additions
and
10 deletions
+261
-10
gdiinterop.c
dlls/dwrite/gdiinterop.c
+197
-3
font.c
dlls/dwrite/tests/font.c
+64
-7
No files found.
dlls/dwrite/gdiinterop.c
View file @
a0c8f066
...
...
@@ -2,7 +2,7 @@
* GDI Interop
*
* Copyright 2011 Huw Davies
* Copyright 2012, 2014-201
6
Nikolay Sivov for CodeWeavers
* Copyright 2012, 2014-201
8
Nikolay Sivov for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -54,10 +54,17 @@ struct rendertarget {
struct
gdiinterop
{
IDWriteGdiInterop1
IDWriteGdiInterop1_iface
;
IDWriteFontFileLoader
IDWriteFontFileLoader_iface
;
LONG
ref
;
IDWriteFactory5
*
factory
;
};
struct
memresource_stream
{
IDWriteFontFileStream
IDWriteFontFileStream_iface
;
LONG
ref
;
DWORD
key
;
};
static
inline
int
get_dib_stride
(
int
width
,
int
bpp
)
{
return
((
width
*
bpp
+
31
)
>>
3
)
&
~
3
;
...
...
@@ -111,6 +118,16 @@ static inline struct gdiinterop *impl_from_IDWriteGdiInterop1(IDWriteGdiInterop1
return
CONTAINING_RECORD
(
iface
,
struct
gdiinterop
,
IDWriteGdiInterop1_iface
);
}
static
inline
struct
gdiinterop
*
impl_from_IDWriteFontFileLoader
(
IDWriteFontFileLoader
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
gdiinterop
,
IDWriteFontFileLoader_iface
);
}
static
inline
struct
memresource_stream
*
impl_from_IDWriteFontFileStream
(
IDWriteFontFileStream
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
memresource_stream
,
IDWriteFontFileStream_iface
);
}
static
HRESULT
WINAPI
rendertarget_sink_QueryInterface
(
ID2D1SimplifiedGeometrySink
*
iface
,
REFIID
riid
,
void
**
obj
)
{
if
(
IsEqualIID
(
riid
,
&
IID_ID2D1SimplifiedGeometrySink
)
||
...
...
@@ -637,6 +654,7 @@ static ULONG WINAPI gdiinterop_Release(IDWriteGdiInterop1 *iface)
TRACE
(
"(%p)->(%d)
\n
"
,
This
,
ref
);
if
(
!
ref
)
{
IDWriteFactory5_UnregisterFontFileLoader
(
This
->
factory
,
&
This
->
IDWriteFontFileLoader_iface
);
factory_detach_gdiinterop
(
This
->
factory
,
iface
);
heap_free
(
This
);
}
...
...
@@ -728,6 +746,7 @@ struct font_fileinfo {
/* Undocumented gdi32 exports, used to access actually selected font information */
extern
BOOL
WINAPI
GetFontRealizationInfo
(
HDC
hdc
,
struct
font_realization_info
*
info
);
extern
BOOL
WINAPI
GetFontFileInfo
(
DWORD
instance_id
,
DWORD
unknown
,
struct
font_fileinfo
*
info
,
SIZE_T
size
,
SIZE_T
*
needed
);
extern
BOOL
WINAPI
GetFontFileData
(
DWORD
instance_id
,
DWORD
unknown
,
UINT64
offset
,
void
*
buff
,
DWORD
buff_size
);
static
HRESULT
WINAPI
gdiinterop_CreateFontFaceFromHdc
(
IDWriteGdiInterop1
*
iface
,
HDC
hdc
,
IDWriteFontFace
**
fontface
)
...
...
@@ -773,8 +792,12 @@ static HRESULT WINAPI gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop1 *iface
return
E_FAIL
;
}
hr
=
IDWriteFactory5_CreateFontFileReference
(
This
->
factory
,
fileinfo
->
path
,
&
fileinfo
->
writetime
,
&
file
);
if
(
*
fileinfo
->
path
)
hr
=
IDWriteFactory5_CreateFontFileReference
(
This
->
factory
,
fileinfo
->
path
,
&
fileinfo
->
writetime
,
&
file
);
else
hr
=
IDWriteFactory5_CreateCustomFontFileReference
(
This
->
factory
,
&
info
.
instance_id
,
sizeof
(
info
.
instance_id
),
&
This
->
IDWriteFontFileLoader_iface
,
&
file
);
heap_free
(
fileinfo
);
if
(
FAILED
(
hr
))
return
hr
;
...
...
@@ -897,6 +920,175 @@ static const struct IDWriteGdiInterop1Vtbl gdiinteropvtbl = {
gdiinterop1_GetMatchingFontsByLOGFONT
};
static
HRESULT
WINAPI
memresourcestream_QueryInterface
(
IDWriteFontFileStream
*
iface
,
REFIID
riid
,
void
**
out
)
{
struct
memresource_stream
*
This
=
impl_from_IDWriteFontFileStream
(
iface
);
TRACE
(
"(%p)->(%s %p)
\n
"
,
This
,
debugstr_guid
(
riid
),
out
);
if
(
IsEqualIID
(
&
IID_IDWriteFontFileStream
,
riid
)
||
IsEqualIID
(
&
IID_IUnknown
,
riid
))
{
*
out
=
iface
;
IDWriteFontFileStream_AddRef
(
iface
);
return
S_OK
;
}
*
out
=
NULL
;
WARN
(
"Unsupported interface %s.
\n
"
,
debugstr_guid
(
riid
));
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
memresourcestream_AddRef
(
IDWriteFontFileStream
*
iface
)
{
struct
memresource_stream
*
This
=
impl_from_IDWriteFontFileStream
(
iface
);
ULONG
ref
=
InterlockedIncrement
(
&
This
->
ref
);
TRACE
(
"(%p)->(%d)
\n
"
,
This
,
ref
);
return
ref
;
}
static
ULONG
WINAPI
memresourcestream_Release
(
IDWriteFontFileStream
*
iface
)
{
struct
memresource_stream
*
This
=
impl_from_IDWriteFontFileStream
(
iface
);
ULONG
ref
=
InterlockedDecrement
(
&
This
->
ref
);
TRACE
(
"(%p)->(%d)
\n
"
,
This
,
ref
);
if
(
!
ref
)
heap_free
(
This
);
return
ref
;
}
static
HRESULT
WINAPI
memresourcestream_ReadFileFragment
(
IDWriteFontFileStream
*
iface
,
void
const
**
fragment_start
,
UINT64
offset
,
UINT64
fragment_size
,
void
**
fragment_context
)
{
struct
memresource_stream
*
This
=
impl_from_IDWriteFontFileStream
(
iface
);
struct
font_fileinfo
fileinfo
;
void
*
fragment
;
TRACE
(
"(%p)->(%p %s %s %p)
\n
"
,
This
,
fragment_start
,
wine_dbgstr_longlong
(
offset
),
wine_dbgstr_longlong
(
fragment_size
),
fragment_context
);
*
fragment_context
=
NULL
;
*
fragment_start
=
NULL
;
if
(
!
GetFontFileInfo
(
This
->
key
,
0
,
&
fileinfo
,
sizeof
(
fileinfo
),
NULL
))
return
E_INVALIDARG
;
if
((
offset
>=
fileinfo
.
size
.
QuadPart
-
1
)
||
(
fragment_size
>
fileinfo
.
size
.
QuadPart
-
offset
))
return
E_INVALIDARG
;
if
(
!
(
fragment
=
heap_alloc
(
fragment_size
)))
return
E_OUTOFMEMORY
;
if
(
!
GetFontFileData
(
This
->
key
,
0
,
offset
,
fragment
,
fragment_size
))
return
E_FAIL
;
*
fragment_start
=
*
fragment_context
=
fragment
;
return
S_OK
;
}
static
void
WINAPI
memresourcestream_ReleaseFileFragment
(
IDWriteFontFileStream
*
iface
,
void
*
fragment_context
)
{
struct
memresource_stream
*
This
=
impl_from_IDWriteFontFileStream
(
iface
);
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
fragment_context
);
heap_free
(
fragment_context
);
}
static
HRESULT
WINAPI
memresourcestream_GetFileSize
(
IDWriteFontFileStream
*
iface
,
UINT64
*
size
)
{
struct
memresource_stream
*
This
=
impl_from_IDWriteFontFileStream
(
iface
);
struct
font_fileinfo
fileinfo
;
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
size
);
if
(
!
GetFontFileInfo
(
This
->
key
,
0
,
&
fileinfo
,
sizeof
(
fileinfo
),
NULL
))
return
E_INVALIDARG
;
*
size
=
fileinfo
.
size
.
QuadPart
;
return
S_OK
;
}
static
HRESULT
WINAPI
memresourcestream_GetLastWriteTime
(
IDWriteFontFileStream
*
iface
,
UINT64
*
last_writetime
)
{
struct
memresource_stream
*
This
=
impl_from_IDWriteFontFileStream
(
iface
);
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
last_writetime
);
return
E_NOTIMPL
;
}
static
const
struct
IDWriteFontFileStreamVtbl
memresourcestreamvtbl
=
{
memresourcestream_QueryInterface
,
memresourcestream_AddRef
,
memresourcestream_Release
,
memresourcestream_ReadFileFragment
,
memresourcestream_ReleaseFileFragment
,
memresourcestream_GetFileSize
,
memresourcestream_GetLastWriteTime
,
};
static
HRESULT
WINAPI
memresourceloader_QueryInterface
(
IDWriteFontFileLoader
*
iface
,
REFIID
riid
,
void
**
out
)
{
struct
gdiinterop
*
This
=
impl_from_IDWriteFontFileLoader
(
iface
);
TRACE
(
"(%p)->(%s %p)
\n
"
,
This
,
debugstr_guid
(
riid
),
out
);
if
(
IsEqualIID
(
&
IID_IDWriteFontFileLoader
,
riid
)
||
IsEqualIID
(
&
IID_IUnknown
,
riid
))
{
*
out
=
iface
;
IDWriteFontFileLoader_AddRef
(
iface
);
return
S_OK
;
}
*
out
=
NULL
;
WARN
(
"Unsupported interface %s.
\n
"
,
debugstr_guid
(
riid
));
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
memresourceloader_AddRef
(
IDWriteFontFileLoader
*
iface
)
{
return
2
;
}
static
ULONG
WINAPI
memresourceloader_Release
(
IDWriteFontFileLoader
*
iface
)
{
return
1
;
}
static
HRESULT
WINAPI
memresourceloader_CreateStreamFromKey
(
IDWriteFontFileLoader
*
iface
,
void
const
*
key
,
UINT32
key_size
,
IDWriteFontFileStream
**
ret
)
{
struct
gdiinterop
*
This
=
impl_from_IDWriteFontFileLoader
(
iface
);
struct
memresource_stream
*
stream
;
TRACE
(
"(%p)->(%p %u %p)
\n
"
,
This
,
key
,
key_size
,
ret
);
*
ret
=
NULL
;
if
(
!
key
||
key_size
!=
sizeof
(
DWORD
))
return
E_INVALIDARG
;
if
(
!
(
stream
=
heap_alloc
(
sizeof
(
*
stream
))))
return
E_OUTOFMEMORY
;
stream
->
IDWriteFontFileStream_iface
.
lpVtbl
=
&
memresourcestreamvtbl
;
stream
->
ref
=
1
;
memcpy
(
&
stream
->
key
,
key
,
sizeof
(
stream
->
key
));
*
ret
=
&
stream
->
IDWriteFontFileStream_iface
;
return
S_OK
;
}
static
const
struct
IDWriteFontFileLoaderVtbl
memresourceloadervtbl
=
{
memresourceloader_QueryInterface
,
memresourceloader_AddRef
,
memresourceloader_Release
,
memresourceloader_CreateStreamFromKey
,
};
HRESULT
create_gdiinterop
(
IDWriteFactory5
*
factory
,
IDWriteGdiInterop1
**
ret
)
{
struct
gdiinterop
*
interop
;
...
...
@@ -907,8 +1099,10 @@ HRESULT create_gdiinterop(IDWriteFactory5 *factory, IDWriteGdiInterop1 **ret)
return
E_OUTOFMEMORY
;
interop
->
IDWriteGdiInterop1_iface
.
lpVtbl
=
&
gdiinteropvtbl
;
interop
->
IDWriteFontFileLoader_iface
.
lpVtbl
=
&
memresourceloadervtbl
;
interop
->
ref
=
1
;
IDWriteFactory5_AddRef
(
interop
->
factory
=
factory
);
IDWriteFactory5_RegisterFontFileLoader
(
factory
,
&
interop
->
IDWriteFontFileLoader_iface
);
*
ret
=
&
interop
->
IDWriteGdiInterop1_iface
;
return
S_OK
;
...
...
dlls/dwrite/tests/font.c
View file @
a0c8f066
/*
* Font related tests
*
* Copyright 2012, 2014-201
7
Nikolay Sivov for CodeWeavers
* Copyright 2012, 2014-201
8
Nikolay Sivov for CodeWeavers
* Copyright 2014 Aric Stewart for CodeWeavers
*
* This library is free software; you can redistribute it and/or
...
...
@@ -122,6 +122,8 @@ static void _expect_ref_broken(IUnknown* obj, ULONG ref, ULONG brokenref, int li
ok_
(
__FILE__
,
line
)(
rc
==
ref
||
broken
(
rc
==
brokenref
),
"expected refcount %d, got %d
\n
"
,
ref
,
rc
);
}
static
BOOL
(
WINAPI
*
pGetFontRealizationInfo
)(
HDC
hdc
,
void
*
);
static
const
WCHAR
test_fontfile
[]
=
{
'w'
,
'i'
,
'n'
,
'e'
,
'_'
,
't'
,
'e'
,
's'
,
't'
,
'_'
,
'f'
,
'o'
,
'n'
,
't'
,
'.'
,
't'
,
't'
,
'f'
,
0
};
static
const
WCHAR
tahomaW
[]
=
{
'T'
,
'a'
,
'h'
,
'o'
,
'm'
,
'a'
,
0
};
static
const
WCHAR
arialW
[]
=
{
'A'
,
'r'
,
'i'
,
'a'
,
'l'
,
0
};
...
...
@@ -3735,10 +3737,22 @@ static void *map_font_file(const WCHAR *filename, DWORD *file_size)
return
ptr
;
}
struct
font_realization_info
{
DWORD
size
;
DWORD
flags
;
DWORD
cache_num
;
DWORD
instance_id
;
DWORD
unk
;
WORD
face_index
;
WORD
simulations
;
};
static
void
test_CreateFontFaceFromHdc
(
void
)
{
IDWriteFontFileStream
*
stream
,
*
stream2
;
void
*
font_data
,
*
fragment_context
;
struct
font_realization_info
info
;
const
void
*
refkey
,
*
fragment
;
IDWriteFontFileLoader
*
loader
;
DWORD
data_size
,
num_fonts
;
...
...
@@ -3748,10 +3762,10 @@ static void test_CreateFontFaceFromHdc(void)
UINT64
size
,
writetime
;
IDWriteFontFile
*
file
;
HFONT
hfont
,
oldhfont
;
UINT32
count
,
dummy
;
LOGFONTW
logfont
;
HANDLE
resource
;
IUnknown
*
unk
;
UINT32
count
;
LOGFONTA
lf
;
WCHAR
*
path
;
HRESULT
hr
;
...
...
@@ -3761,6 +3775,8 @@ static void test_CreateFontFaceFromHdc(void)
factory
=
create_factory
();
pGetFontRealizationInfo
=
(
void
*
)
GetProcAddress
(
GetModuleHandleA
(
"gdi32"
),
"GetFontRealizationInfo"
);
interop
=
NULL
;
hr
=
IDWriteFactory_GetGdiInterop
(
factory
,
&
interop
);
ok
(
hr
==
S_OK
,
"got 0x%08x
\n
"
,
hr
);
...
...
@@ -3789,7 +3805,23 @@ static void test_CreateFontFaceFromHdc(void)
fontface
=
NULL
;
hr
=
IDWriteGdiInterop_CreateFontFaceFromHdc
(
interop
,
hdc
,
&
fontface
);
ok
(
hr
==
S_OK
,
"got 0x%08x
\n
"
,
hr
);
ok
(
hr
==
S_OK
,
"Failed to create font face, hr %#x.
\n
"
,
hr
);
count
=
1
;
hr
=
IDWriteFontFace_GetFiles
(
fontface
,
&
count
,
&
file
);
ok
(
hr
==
S_OK
,
"Failed to get font files, hr %#x.
\n
"
,
hr
);
hr
=
IDWriteFontFile_GetLoader
(
file
,
&
loader
);
ok
(
hr
==
S_OK
,
"Failed to get file loader, hr %#x.
\n
"
,
hr
);
hr
=
IDWriteFontFileLoader_QueryInterface
(
loader
,
&
IID_IDWriteLocalFontFileLoader
,
(
void
**
)
&
unk
);
ok
(
hr
==
S_OK
||
broken
(
hr
==
E_NOINTERFACE
)
/* Vista */
,
"Expected local loader, hr %#x.
\n
"
,
hr
);
if
(
unk
)
IUnknown_Release
(
unk
);
IDWriteFontFileLoader_Release
(
loader
);
IDWriteFontFile_Release
(
file
);
IDWriteFontFace_Release
(
fontface
);
DeleteObject
(
SelectObject
(
hdc
,
oldhfont
));
...
...
@@ -3828,11 +3860,8 @@ static void test_CreateFontFaceFromHdc(void)
oldhfont
=
SelectObject
(
hdc
,
hfont
);
hr
=
IDWriteGdiInterop_CreateFontFaceFromHdc
(
interop
,
hdc
,
&
fontface
);
todo_wine
ok
(
hr
==
S_OK
,
"Failed to create fontface, hr %#x.
\n
"
,
hr
);
if
(
fontface
)
{
count
=
1
;
hr
=
IDWriteFontFace_GetFiles
(
fontface
,
&
count
,
&
file
);
ok
(
hr
==
S_OK
,
"Failed to get font files, hr %#x.
\n
"
,
hr
);
...
...
@@ -3854,6 +3883,17 @@ if (fontface)
ok
(
hr
==
S_OK
,
"Failed to get ref key, hr %#x.
\n
"
,
hr
);
ok
(
count
>
0
,
"Unexpected key length %u.
\n
"
,
count
);
if
(
pGetFontRealizationInfo
)
{
info
.
size
=
sizeof
(
info
);
ret
=
pGetFontRealizationInfo
(
hdc
,
&
info
);
ok
(
ret
,
"Failed to get realization info.
\n
"
);
ok
(
count
==
sizeof
(
info
.
instance_id
),
"Unexpected key size.
\n
"
);
ok
(
*
(
DWORD
*
)
refkey
==
info
.
instance_id
,
"Unexpected stream key.
\n
"
);
}
else
win_skip
(
"GetFontRealizationInfo() is not available.
\n
"
);
hr
=
IDWriteFontFileLoader_CreateStreamFromKey
(
loader
,
refkey
,
count
,
&
stream
);
ok
(
hr
==
S_OK
,
"Failed to create file stream, hr %#x.
\n
"
,
hr
);
...
...
@@ -3862,6 +3902,17 @@ if (fontface)
ok
(
stream2
!=
stream
,
"Unexpected stream instance.
\n
"
);
IDWriteFontFileStream_Release
(
stream2
);
dummy
=
1
;
hr
=
IDWriteFontFileLoader_CreateStreamFromKey
(
loader
,
&
dummy
,
count
,
&
stream2
);
ok
(
hr
==
S_OK
,
"Failed to create file stream, hr %#x.
\n
"
,
hr
);
writetime
=
1
;
hr
=
IDWriteFontFileStream_GetLastWriteTime
(
stream2
,
&
writetime
);
ok
(
hr
==
E_NOTIMPL
,
"Unexpected hr %#x.
\n
"
,
hr
);
ok
(
writetime
==
1
,
"Unexpected write time.
\n
"
);
IDWriteFontFileStream_Release
(
stream2
);
hr
=
IDWriteFontFileStream_GetFileSize
(
stream
,
&
size
);
ok
(
hr
==
S_OK
,
"Failed to get stream size, hr %#x.
\n
"
,
hr
);
ok
(
size
==
data_size
,
"Unexpected stream size.
\n
"
);
...
...
@@ -3876,13 +3927,19 @@ if (fontface)
ok
(
fragment
==
fragment_context
,
"Unexpected data pointer %p, context %p.
\n
"
,
fragment
,
fragment_context
);
IDWriteFontFileStream_ReleaseFileFragment
(
stream
,
fragment_context
);
hr
=
IDWriteFontFileStream_ReadFileFragment
(
stream
,
&
fragment
,
0
,
size
+
1
,
&
fragment_context
);
ok
(
FAILED
(
hr
),
"Unexpected hr %#x.
\n
"
,
hr
);
hr
=
IDWriteFontFileStream_ReadFileFragment
(
stream
,
&
fragment
,
size
-
1
,
size
/
2
,
&
fragment_context
);
ok
(
FAILED
(
hr
),
"Unexpected hr %#x.
\n
"
,
hr
);
IDWriteFontFileStream_Release
(
stream
);
IDWriteFontFileLoader_Release
(
loader
);
IDWriteFontFile_Release
(
file
);
IDWriteFontFace_Release
(
fontface
);
}
ret
=
RemoveFontMemResourceEx
(
resource
);
ok
(
ret
,
"Failed to remove memory resource font, %d.
\n
"
,
GetLastError
());
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment