Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
December 2020
- 68 participants
- 931 messages
[PATCH 5/7] mf/topoloader: Make sure MF_TOPONODE_STREAMID is set for all outputs.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mf/tests/mf.c | 131 ++++++++++++++++++++++++++++++++++++++++++++-
dlls/mf/topology.c | 29 ++++++++++
2 files changed, 158 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 4d4c6283be8..c36a76d83bb 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -1622,8 +1622,11 @@ static void init_source_node(IMFMediaType *mediatype, IMFMediaSource *source, IM
hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr);
- hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
- ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ if (source)
+ {
+ hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ }
IMFStreamDescriptor_Release(sd);
}
@@ -2121,6 +2124,129 @@ todo_wine {
ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
}
+static void test_topology_loader_evr(void)
+{
+ IMFTopologyNode *node, *source_node, *evr_node;
+ IMFTopology *topology, *full_topology;
+ IMFMediaTypeHandler *handler;
+ unsigned int i, count, value;
+ IMFStreamSink *stream_sink;
+ IMFMediaType *media_type;
+ IMFActivate *activate;
+ IMFTopoLoader *loader;
+ IMFMediaSink *sink;
+ WORD node_count;
+ HWND window;
+ HRESULT hr;
+
+ hr = CoInitialize(NULL);
+ ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
+
+ hr = MFCreateTopoLoader(&loader);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ /* Source node. */
+ hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &source_node);
+ ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
+
+ hr = MFCreateMediaType(&media_type);
+ ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
+
+ hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ init_source_node(media_type, NULL, source_node);
+
+ /* EVR sink node. */
+ window = create_window();
+
+ hr = MFCreateVideoRendererActivate(window, &activate);
+ ok(hr == S_OK, "Failed to create activate object, hr %#x.\n", hr);
+
+ hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &evr_node);
+ ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
+
+ hr = IMFTopologyNode_SetObject(evr_node, (IUnknown *)stream_sink);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ IMFMediaTypeHandler_Release(handler);
+
+ IMFStreamSink_Release(stream_sink);
+ IMFMediaSink_Release(sink);
+
+ hr = MFCreateTopology(&topology);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFTopology_AddNode(topology, source_node);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFTopology_AddNode(topology, evr_node);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFTopologyNode_ConnectOutput(source_node, 0, evr_node, 0);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFTopologyNode_SetUINT32(evr_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_DIRECT);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFTopologyNode_GetCount(evr_node, &count);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(count == 1, "Unexpected attribute count %u.\n", count);
+
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFTopology_GetNodeCount(full_topology, &node_count);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+todo_wine
+ ok(node_count == 3, "Unexpected node count %u.\n", node_count);
+
+ for (i = 0; i < node_count; ++i)
+ {
+ MF_TOPOLOGY_TYPE node_type;
+
+ hr = IMFTopology_GetNode(full_topology, i, &node);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFTopologyNode_GetNodeType(node, &node_type);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ if (node_type == MF_TOPOLOGY_OUTPUT_NODE)
+ {
+ value = 1;
+ hr = IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_STREAMID, &value);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(!value, "Unexpected stream id %u.\n", value);
+ }
+ }
+
+ IMFTopology_Release(full_topology);
+
+ IMFTopoLoader_Release(loader);
+
+ IMFTopologyNode_Release(source_node);
+ IMFTopologyNode_Release(evr_node);
+ IMFTopology_Release(topology);
+ IMFMediaType_Release(media_type);
+ DestroyWindow(window);
+
+ CoUninitialize();
+}
+
static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IMFShutdown) ||
@@ -4859,6 +4985,7 @@ START_TEST(mf)
test_topology();
test_topology_tee_node();
test_topology_loader();
+ test_topology_loader_evr();
test_MFGetService();
test_sequencer_source();
test_media_session();
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index 77baa1128c4..6f73bb859cd 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -2364,6 +2364,32 @@ static HRESULT topology_loader_resolve_nodes(struct topoloader_context *context,
return hr;
}
+static void topology_loader_resolve_complete(struct topoloader_context *context)
+{
+ MF_TOPOLOGY_TYPE node_type;
+ IMFTopologyNode *node;
+ WORD i, node_count;
+
+ IMFTopology_GetNodeCount(context->output_topology, &node_count);
+
+ for (i = 0; i < node_count; ++i)
+ {
+ if (SUCCEEDED(IMFTopology_GetNode(context->output_topology, i, &node)))
+ {
+ IMFTopologyNode_GetNodeType(node, &node_type);
+
+ if (node_type == MF_TOPOLOGY_OUTPUT_NODE)
+ {
+ /* Make sure MF_TOPONODE_STREAMID is set for all outputs. */
+ if (FAILED(IMFTopologyNode_GetItem(node, &MF_TOPONODE_STREAMID, NULL)))
+ IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_STREAMID, 0);
+ }
+
+ IMFTopologyNode_Release(node);
+ }
+ }
+}
+
static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *input_topology,
IMFTopology **ret_topology, IMFTopology *current_topology)
{
@@ -2451,6 +2477,9 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in
break;
}
+ if (SUCCEEDED(hr))
+ topology_loader_resolve_complete(&context);
+
*ret_topology = output_topology;
return hr;
--
2.29.2
Dec. 1, 2020
[PATCH 4/7] mf/topoloader: Set MF_TOPONODE_TRANSFORM_OBJECTID for created transforms when CLSID is available.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mf/tests/mf.c | 6 ++++++
dlls/mf/topology.c | 13 +++++++++----
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index d7d7fdfa60e..4d4c6283be8 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -2045,6 +2045,9 @@ todo_wine {
ok(value == 1, "Unexpected value.\n");
}
+ hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
+ ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
+
hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform);
ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#x.\n", hr);
IUnknown_Release(node_object);
@@ -2068,6 +2071,9 @@ todo_wine {
ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#x.\n", hr);
ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
+ hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
+ ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
+
hr = IMFTopologyNode_GetObject(mft_node, &node_object);
ok(hr == S_OK, "Failed to get object of transform node, hr %#x.\n", hr);
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index efa28e9f457..77baa1128c4 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -1996,7 +1996,7 @@ struct transform_output_type
{
IMFMediaType *type;
IMFTransform *transform;
- const GUID *category;
+ IMFActivate *activate;
};
struct connect_context
@@ -2054,7 +2054,7 @@ static HRESULT topology_loader_enumerate_output_types(const GUID *category, IMFM
unsigned int output_count = 0;
output_type.transform = transform;
- output_type.category = category;
+ output_type.activate = activates[i];
while (SUCCEEDED(IMFTransform_GetOutputAvailableType(transform, 0, output_count++, &output_type.type)))
{
hr = connect_func(&output_type, context);
@@ -2079,17 +2079,22 @@ static HRESULT topology_loader_create_transform(const struct transform_output_ty
IMFTopologyNode **node)
{
HRESULT hr;
+ GUID guid;
if (FAILED(hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, node)))
return hr;
IMFTopologyNode_SetObject(*node, (IUnknown *)output_type->transform);
- if (IsEqualGUID(output_type->category, &MFT_CATEGORY_AUDIO_DECODER) ||
- IsEqualGUID(output_type->category, &MFT_CATEGORY_VIDEO_DECODER))
+
+ if (SUCCEEDED(IMFActivate_GetGUID(output_type->activate, &MF_TRANSFORM_CATEGORY_Attribute, &guid)) &&
+ (IsEqualGUID(&guid, &MFT_CATEGORY_AUDIO_DECODER) || IsEqualGUID(&guid, &MFT_CATEGORY_VIDEO_DECODER)))
{
IMFTopologyNode_SetUINT32(*node, &MF_TOPONODE_DECODER, 1);
}
+ if (SUCCEEDED(IMFActivate_GetGUID(output_type->activate, &MFT_TRANSFORM_CLSID_Attribute, &guid)))
+ IMFTopologyNode_SetGUID(*node, &MF_TOPONODE_TRANSFORM_OBJECTID, &guid);
+
return hr;
}
--
2.29.2
Dec. 1, 2020
[PATCH 3/7] mf/topoloader: Set MF_TOPONODE_DECODER for the decoders.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mf/tests/mf.c | 10 ++++++++--
dlls/mf/topology.c | 27 ++++++++++++++++++++++-----
2 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 20e3e8713c6..d7d7fdfa60e 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -1740,7 +1740,6 @@ static void test_topology_loader(void)
{
/* PCM -> PCM, different bps. */
&MFMediaType_Audio,
- /* Source type */
{
{
{ &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
@@ -1751,7 +1750,6 @@ static void test_topology_loader(void)
{ &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
}
},
- /* Sink type */
{
{
{ &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
@@ -2039,6 +2037,14 @@ todo_wine {
hr = IMFTopologyNode_GetObject(mft_node, &node_object);
ok(hr == S_OK, "Failed to get object of transform node, hr %#x.\n", hr);
+ if (test->flags & LOADER_EXPECTED_DECODER)
+ {
+ value = 0;
+ hr = IMFTopologyNode_GetUINT32(mft_node, &MF_TOPONODE_DECODER, &value);
+ ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
+ ok(value == 1, "Unexpected value.\n");
+ }
+
hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform);
ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#x.\n", hr);
IUnknown_Release(node_object);
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index 7001a33f088..efa28e9f457 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -1996,6 +1996,7 @@ struct transform_output_type
{
IMFMediaType *type;
IMFTransform *transform;
+ const GUID *category;
};
struct connect_context
@@ -2053,6 +2054,7 @@ static HRESULT topology_loader_enumerate_output_types(const GUID *category, IMFM
unsigned int output_count = 0;
output_type.transform = transform;
+ output_type.category = category;
while (SUCCEEDED(IMFTransform_GetOutputAvailableType(transform, 0, output_count++, &output_type.type)))
{
hr = connect_func(&output_type, context);
@@ -2073,6 +2075,24 @@ static HRESULT topology_loader_enumerate_output_types(const GUID *category, IMFM
return hr;
}
+static HRESULT topology_loader_create_transform(const struct transform_output_type *output_type,
+ IMFTopologyNode **node)
+{
+ HRESULT hr;
+
+ if (FAILED(hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, node)))
+ return hr;
+
+ IMFTopologyNode_SetObject(*node, (IUnknown *)output_type->transform);
+ if (IsEqualGUID(output_type->category, &MFT_CATEGORY_AUDIO_DECODER) ||
+ IsEqualGUID(output_type->category, &MFT_CATEGORY_VIDEO_DECODER))
+ {
+ IMFTopologyNode_SetUINT32(*node, &MF_TOPONODE_DECODER, 1);
+ }
+
+ return hr;
+}
+
static HRESULT connect_to_sink(struct transform_output_type *output_type, struct connect_context *context)
{
IMFTopologyNode *node;
@@ -2081,10 +2101,9 @@ static HRESULT connect_to_sink(struct transform_output_type *output_type, struct
if (FAILED(IMFMediaTypeHandler_IsMediaTypeSupported(context->sink_handler, output_type->type, NULL)))
return MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION;
- if (FAILED(hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node)))
+ if (FAILED(hr = topology_loader_create_transform(output_type, &node)))
return hr;
- IMFTopologyNode_SetObject(node, (IUnknown *)output_type->transform);
IMFTopology_AddNode(context->context->output_topology, node);
IMFTopologyNode_ConnectOutput(context->upstream_node, 0, node, 0);
IMFTopologyNode_ConnectOutput(node, 0, context->sink, 0);
@@ -2107,11 +2126,9 @@ static HRESULT connect_to_converter(struct transform_output_type *output_type, s
if (SUCCEEDED(connect_to_sink(output_type, context)))
return S_OK;
- if (FAILED(hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node)))
+ if (FAILED(hr = topology_loader_create_transform(output_type, &node)))
return hr;
- IMFTopologyNode_SetObject(node, (IUnknown *)output_type->transform);
-
sink_ctx = *context;
sink_ctx.upstream_node = node;
--
2.29.2
Dec. 1, 2020
[PATCH 2/7] mfplat/mediatype: Do not add user data when converting from WAVE_FORMAT_EXTENSIBLE.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mfplat/mediatype.c | 2 +-
dlls/mfplat/tests/mfplat.c | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c
index 62d75e80146..2bf9b674ea7 100644
--- a/dlls/mfplat/mediatype.c
+++ b/dlls/mfplat/mediatype.c
@@ -3011,7 +3011,7 @@ HRESULT WINAPI MFInitMediaTypeFromWaveFormatEx(IMFMediaType *mediatype, const WA
mediatype_set_uint32(mediatype, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1, &hr);
}
- if (format->cbSize)
+ if (format->cbSize && format->wFormatTag != WAVE_FORMAT_EXTENSIBLE)
mediatype_set_blob(mediatype, &MF_MT_USER_DATA, (const UINT8 *)(format + 1), format->cbSize, &hr);
return hr;
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 38e8acb966e..b361d4da162 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -5625,9 +5625,13 @@ static void test_MFInitMediaTypeFromWaveFormatEx(void)
waveformatext.dwChannelMask = 0x8;
memcpy(&waveformatext.SubFormat, &MFAudioFormat_Base, sizeof(waveformatext.SubFormat));
waveformatext.SubFormat.Data1 = waveformatex_tests[i].wFormatTag;
+
hr = MFInitMediaTypeFromWaveFormatEx(mediatype, &waveformatext.Format, sizeof(waveformatext));
ok(hr == S_OK, "Failed to initialize media type, hr %#x.\n", hr);
+ hr = IMFMediaType_GetItem(mediatype, &MF_MT_USER_DATA, NULL);
+ ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
+
validate_media_type(mediatype, &waveformatext.Format);
}
--
2.29.2
Dec. 1, 2020
[PATCH 1/7] mfplat: Remove duplicated attribute from tracing.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mfplat/main.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 6394784593e..e4cd1c397ad 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -1579,7 +1579,6 @@ const char *debugstr_attr(const GUID *guid)
X(MF_SA_D3D_AWARE),
X(MF_MT_MAX_KEYFRAME_SPACING),
X(MFT_TRANSFORM_CLSID_Attribute),
- X(MFT_TRANSFORM_CLSID_Attribute),
X(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING),
X(MF_MT_AM_FORMAT_TYPE),
X(MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME),
--
2.29.2
Dec. 1, 2020
[PATCH 5/5] dwrite: Use font data access helpers when reading metrics tables.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/opentype.c | 200 ++++++++++++++++++++---------------------
1 file changed, 97 insertions(+), 103 deletions(-)
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index d7a0aaf8e51..68da6e4ecfb 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -126,7 +126,7 @@ enum opentype_cmap_table_encoding
/* PANOSE is 10 bytes in size, need to pack the structure properly */
#include "pshpack2.h"
-typedef struct
+struct tt_head
{
USHORT majorVersion;
USHORT minorVersion;
@@ -146,9 +146,9 @@ typedef struct
SHORT direction_hint;
SHORT index_format;
SHORT glyphdata_format;
-} TT_HEAD;
+};
-enum TT_HEAD_MACSTYLE
+enum tt_head_macstyle
{
TT_HEAD_MACSTYLE_BOLD = 1 << 0,
TT_HEAD_MACSTYLE_ITALIC = 1 << 1,
@@ -159,7 +159,7 @@ enum TT_HEAD_MACSTYLE
TT_HEAD_MACSTYLE_EXTENDED = 1 << 6,
};
-typedef struct
+struct tt_post
{
ULONG Version;
ULONG italicAngle;
@@ -170,9 +170,9 @@ typedef struct
ULONG maxmemType42;
ULONG minmemType1;
ULONG maxmemType1;
-} TT_POST;
+};
-typedef struct
+struct tt_os2
{
USHORT version;
SHORT xAvgCharWidth;
@@ -217,9 +217,10 @@ typedef struct
USHORT usDefaultChar;
USHORT usBreakChar;
USHORT usMaxContext;
-} TT_OS2_V2;
+};
-typedef struct {
+struct tt_hhea
+{
USHORT majorVersion;
USHORT minorVersion;
SHORT ascender;
@@ -235,7 +236,7 @@ typedef struct {
SHORT reserved[4];
SHORT metricDataFormat;
USHORT numberOfHMetrics;
-} TT_HHEA;
+};
struct sbix_header
{
@@ -1878,31 +1879,25 @@ HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_cmap *cmap, unsigne
void opentype_get_font_typo_metrics(struct file_stream_desc *stream_desc, unsigned int *ascent, unsigned int *descent)
{
struct dwrite_fonttable os2;
- const TT_OS2_V2 *data;
opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
- data = (const TT_OS2_V2 *)os2.data;
*ascent = *descent = 0;
- if (os2.size >= FIELD_OFFSET(TT_OS2_V2, sTypoLineGap))
+ if (os2.size >= FIELD_OFFSET(struct tt_os2, sTypoLineGap))
{
- SHORT value = GET_BE_WORD(data->sTypoDescender);
- *ascent = GET_BE_WORD(data->sTypoAscender);
+ SHORT value = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoDescender));
+ *ascent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoAscender));
*descent = value < 0 ? -value : 0;
}
- if (data)
+ if (os2.data)
IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, os2.context);
}
void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT_METRICS1 *metrics, DWRITE_CARET_METRICS *caret)
{
struct dwrite_fonttable os2, head, post, hhea;
- const TT_OS2_V2 *tt_os2;
- const TT_HEAD *tt_head;
- const TT_POST *tt_post;
- const TT_HHEA *tt_hhea;
memset(metrics, 0, sizeof(*metrics));
@@ -1911,88 +1906,89 @@ void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT
opentype_get_font_table(stream_desc, MS_POST_TAG, &post);
opentype_get_font_table(stream_desc, MS_HHEA_TAG, &hhea);
- tt_head = (const TT_HEAD *)head.data;
- tt_os2 = (const TT_OS2_V2 *)os2.data;
- tt_post = (const TT_POST *)post.data;
- tt_hhea = (const TT_HHEA *)hhea.data;
-
- if (tt_head) {
- metrics->designUnitsPerEm = GET_BE_WORD(tt_head->unitsPerEm);
- metrics->glyphBoxLeft = GET_BE_WORD(tt_head->xMin);
- metrics->glyphBoxTop = GET_BE_WORD(tt_head->yMax);
- metrics->glyphBoxRight = GET_BE_WORD(tt_head->xMax);
- metrics->glyphBoxBottom = GET_BE_WORD(tt_head->yMin);
+ if (head.data)
+ {
+ metrics->designUnitsPerEm = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, unitsPerEm));
+ metrics->glyphBoxLeft = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, xMin));
+ metrics->glyphBoxTop = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, yMax));
+ metrics->glyphBoxRight = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, xMax));
+ metrics->glyphBoxBottom = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, yMin));
}
if (caret)
{
- if (tt_hhea) {
- caret->slopeRise = GET_BE_WORD(tt_hhea->caretSlopeRise);
- caret->slopeRun = GET_BE_WORD(tt_hhea->caretSlopeRun);
- caret->offset = GET_BE_WORD(tt_hhea->caretOffset);
- }
- else {
- caret->slopeRise = 0;
- caret->slopeRun = 0;
- caret->offset = 0;
+ if (hhea.data)
+ {
+ caret->slopeRise = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, caretSlopeRise));
+ caret->slopeRun = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, caretSlopeRun));
+ caret->offset = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, caretOffset));
}
+ else
+ memset(caret, 0, sizeof(*caret));
}
- if (tt_os2) {
- USHORT version = GET_BE_WORD(tt_os2->version);
+ if (os2.data)
+ {
+ USHORT version = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, version));
- metrics->ascent = GET_BE_WORD(tt_os2->usWinAscent);
+ metrics->ascent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWinAscent));
/* Some fonts have usWinDescent value stored as signed short, which could be wrongly
interpreted as large unsigned value. */
- metrics->descent = abs((SHORT)GET_BE_WORD(tt_os2->usWinDescent));
+ metrics->descent = abs((SHORT)table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWinDescent)));
- /* line gap is estimated using two sets of ascender/descender values and 'hhea' line gap */
- if (tt_hhea) {
- SHORT descender = (SHORT)GET_BE_WORD(tt_hhea->descender);
+ /* Line gap is estimated using two sets of ascender/descender values and 'hhea' line gap. */
+ if (hhea.data)
+ {
+ SHORT descender = (SHORT)table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, descender));
INT32 linegap;
- linegap = GET_BE_WORD(tt_hhea->ascender) + abs(descender) + GET_BE_WORD(tt_hhea->linegap) -
- metrics->ascent - metrics->descent;
+ linegap = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, ascender)) + abs(descender) +
+ table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, linegap)) - metrics->ascent - metrics->descent;
metrics->lineGap = linegap > 0 ? linegap : 0;
}
- metrics->strikethroughPosition = GET_BE_WORD(tt_os2->yStrikeoutPosition);
- metrics->strikethroughThickness = GET_BE_WORD(tt_os2->yStrikeoutSize);
- metrics->subscriptPositionX = GET_BE_WORD(tt_os2->ySubscriptXOffset);
+ metrics->strikethroughPosition = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, yStrikeoutPosition));
+ metrics->strikethroughThickness = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, yStrikeoutSize));
+ metrics->subscriptPositionX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptXOffset));
/* Y offset is stored as positive offset below baseline */
- metrics->subscriptPositionY = -GET_BE_WORD(tt_os2->ySubscriptYOffset);
- metrics->subscriptSizeX = GET_BE_WORD(tt_os2->ySubscriptXSize);
- metrics->subscriptSizeY = GET_BE_WORD(tt_os2->ySubscriptYSize);
- metrics->superscriptPositionX = GET_BE_WORD(tt_os2->ySuperscriptXOffset);
- metrics->superscriptPositionY = GET_BE_WORD(tt_os2->ySuperscriptYOffset);
- metrics->superscriptSizeX = GET_BE_WORD(tt_os2->ySuperscriptXSize);
- metrics->superscriptSizeY = GET_BE_WORD(tt_os2->ySuperscriptYSize);
+ metrics->subscriptPositionY = -table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptYOffset));
+ metrics->subscriptSizeX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptXSize));
+ metrics->subscriptSizeY = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySubscriptYSize));
+ metrics->superscriptPositionX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptXOffset));
+ metrics->superscriptPositionY = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptYOffset));
+ metrics->superscriptSizeX = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptXSize));
+ metrics->superscriptSizeY = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, ySuperscriptYSize));
/* version 2 fields */
- if (version >= 2) {
- metrics->capHeight = GET_BE_WORD(tt_os2->sCapHeight);
- metrics->xHeight = GET_BE_WORD(tt_os2->sxHeight);
+ if (version >= 2)
+ {
+ metrics->capHeight = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sCapHeight));
+ metrics->xHeight = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sxHeight));
}
- if (GET_BE_WORD(tt_os2->fsSelection) & OS2_FSSELECTION_USE_TYPO_METRICS) {
- SHORT descent = GET_BE_WORD(tt_os2->sTypoDescender);
- metrics->ascent = GET_BE_WORD(tt_os2->sTypoAscender);
+ if (table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection)) & OS2_FSSELECTION_USE_TYPO_METRICS)
+ {
+ SHORT descent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoDescender));
+ metrics->ascent = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoAscender));
metrics->descent = descent < 0 ? -descent : 0;
- metrics->lineGap = GET_BE_WORD(tt_os2->sTypoLineGap);
+ metrics->lineGap = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, sTypoLineGap));
metrics->hasTypographicMetrics = TRUE;
}
}
- else {
+ else
+ {
metrics->strikethroughPosition = metrics->designUnitsPerEm / 3;
- if (tt_hhea) {
- metrics->ascent = GET_BE_WORD(tt_hhea->ascender);
- metrics->descent = abs((SHORT)GET_BE_WORD(tt_hhea->descender));
+ if (hhea.data)
+ {
+ metrics->ascent = table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, ascender));
+ metrics->descent = abs((SHORT)table_read_be_word(&hhea, FIELD_OFFSET(struct tt_hhea, descender)));
}
}
- if (tt_post) {
- metrics->underlinePosition = GET_BE_WORD(tt_post->underlinePosition);
- metrics->underlineThickness = GET_BE_WORD(tt_post->underlineThickness);
+ if (post.data)
+ {
+ metrics->underlinePosition = table_read_be_word(&post, FIELD_OFFSET(struct tt_post, underlinePosition));
+ metrics->underlineThickness = table_read_be_word(&post, FIELD_OFFSET(struct tt_post, underlineThickness));
}
if (metrics->underlineThickness == 0)
@@ -2006,13 +2002,13 @@ void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT
if (metrics->capHeight == 0)
metrics->capHeight = metrics->designUnitsPerEm * 7 / 10;
- if (tt_os2)
+ if (os2.data)
IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, os2.context);
- if (tt_head)
+ if (head.data)
IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, head.context);
- if (tt_post)
+ if (post.data)
IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, post.context);
- if (tt_hhea)
+ if (hhea.data)
IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, hhea.context);
}
@@ -2020,15 +2016,10 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
{
struct dwrite_fonttable os2, head, colr, cpal;
BOOL is_symbol, is_monospaced;
- const TT_OS2_V2 *tt_os2;
- const TT_HEAD *tt_head;
opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
opentype_get_font_table(stream_desc, MS_HEAD_TAG, &head);
- tt_os2 = (const TT_OS2_V2 *)os2.data;
- tt_head = (const TT_HEAD *)head.data;
-
/* default stretch, weight and style to normal */
props->stretch = DWRITE_FONT_STRETCH_NORMAL;
props->weight = DWRITE_FONT_WEIGHT_NORMAL;
@@ -2039,12 +2030,13 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
props->flags = 0;
/* DWRITE_FONT_STRETCH enumeration values directly match font data values */
- if (tt_os2)
+ if (os2.data)
{
- USHORT version = GET_BE_WORD(tt_os2->version);
- USHORT fsSelection = GET_BE_WORD(tt_os2->fsSelection);
- USHORT usWeightClass = GET_BE_WORD(tt_os2->usWeightClass);
- USHORT usWidthClass = GET_BE_WORD(tt_os2->usWidthClass);
+ USHORT version = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, version));
+ USHORT fsSelection = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection));
+ USHORT usWeightClass = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWeightClass));
+ USHORT usWidthClass = table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, usWidthClass));
+ const void *panose;
if (usWidthClass > DWRITE_FONT_STRETCH_UNDEFINED && usWidthClass <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED)
props->stretch = usWidthClass;
@@ -2063,22 +2055,24 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
props->style = DWRITE_FONT_STYLE_ITALIC;
props->lf.lfItalic = !!(fsSelection & OS2_FSSELECTION_ITALIC);
- memcpy(&props->panose, &tt_os2->panose, sizeof(props->panose));
+ if ((panose = table_read_ensure(&os2, FIELD_OFFSET(struct tt_os2, panose), sizeof(props->panose))))
+ memcpy(&props->panose, panose, sizeof(props->panose));
/* FONTSIGNATURE */
- props->fontsig.fsUsb[0] = GET_BE_DWORD(tt_os2->ulUnicodeRange1);
- props->fontsig.fsUsb[1] = GET_BE_DWORD(tt_os2->ulUnicodeRange2);
- props->fontsig.fsUsb[2] = GET_BE_DWORD(tt_os2->ulUnicodeRange3);
- props->fontsig.fsUsb[3] = GET_BE_DWORD(tt_os2->ulUnicodeRange4);
+ props->fontsig.fsUsb[0] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange1));
+ props->fontsig.fsUsb[1] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange2));
+ props->fontsig.fsUsb[2] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange3));
+ props->fontsig.fsUsb[3] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulUnicodeRange4));
if (version)
{
- props->fontsig.fsCsb[0] = GET_BE_DWORD(tt_os2->ulCodePageRange1);
- props->fontsig.fsCsb[1] = GET_BE_DWORD(tt_os2->ulCodePageRange2);
+ props->fontsig.fsCsb[0] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulCodePageRange1));
+ props->fontsig.fsCsb[1] = table_read_be_dword(&os2, FIELD_OFFSET(struct tt_os2, ulCodePageRange2));
}
}
- else if (tt_head) {
- USHORT macStyle = GET_BE_WORD(tt_head->macStyle);
+ else if (head.data)
+ {
+ USHORT macStyle = table_read_be_word(&head, FIELD_OFFSET(struct tt_head, macStyle));
if (macStyle & TT_HEAD_MACSTYLE_CONDENSED)
props->stretch = DWRITE_FONT_STRETCH_CONDENSED;
@@ -2137,7 +2131,7 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
if (post.data)
{
- is_monospaced = !!table_read_dword(&post, FIELD_OFFSET(TT_POST, fixed_pitch));
+ is_monospaced = !!table_read_dword(&post, FIELD_OFFSET(struct tt_post, fixed_pitch));
IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, post.context);
}
@@ -2544,20 +2538,20 @@ HRESULT opentype_get_font_info_strings(const struct file_stream_desc *stream_des
HRESULT opentype_get_font_familyname(struct file_stream_desc *stream_desc, IDWriteLocalizedStrings **names)
{
struct dwrite_fonttable os2, name;
- const TT_OS2_V2 *tt_os2;
const void *name_table;
+ UINT16 fsselection;
HRESULT hr;
opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
opentype_get_font_table(stream_desc, MS_NAME_TAG, &name);
- tt_os2 = (const TT_OS2_V2 *)os2.data;
name_table = (const void *)name.data;
*names = NULL;
- /* if Preferred Family doesn't conform to WWS model try WWS name */
- if (tt_os2 && !(GET_BE_WORD(tt_os2->fsSelection) & OS2_FSSELECTION_WWS))
+ /* If Preferred Family doesn't conform to WWS model try WWS name. */
+ fsselection = os2.data ? table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection)) : 0;
+ if (os2.data && !(fsselection & OS2_FSSELECTION_WWS))
hr = opentype_get_font_strings_from_id(name_table, OPENTYPE_STRING_WWS_FAMILY_NAME, names);
else
hr = E_FAIL;
@@ -2581,20 +2575,20 @@ HRESULT opentype_get_font_facename(struct file_stream_desc *stream_desc, WCHAR *
{
struct dwrite_fonttable os2, name;
IDWriteLocalizedStrings *lfnames;
- const TT_OS2_V2 *tt_os2;
const void *name_table;
+ UINT16 fsselection;
HRESULT hr;
opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
opentype_get_font_table(stream_desc, MS_NAME_TAG, &name);
- tt_os2 = (const TT_OS2_V2 *)os2.data;
name_table = name.data;
*names = NULL;
/* if Preferred Family doesn't conform to WWS model try WWS name */
- if (tt_os2 && !(GET_BE_WORD(tt_os2->fsSelection) & OS2_FSSELECTION_WWS))
+ fsselection = os2.data ? table_read_be_word(&os2, FIELD_OFFSET(struct tt_os2, fsSelection)) : 0;
+ if (os2.data && !(fsselection & OS2_FSSELECTION_WWS))
hr = opentype_get_font_strings_from_id(name_table, OPENTYPE_STRING_WWS_SUBFAMILY_NAME, names);
else
hr = E_FAIL;
--
2.29.2
Dec. 1, 2020
[PATCH 4/5] dwrite/font: Reimplement HasVerticalGlyphVariants() flag using general shaping logic.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/dwrite_private.h | 2 +-
dlls/dwrite/font.c | 2 +-
dlls/dwrite/opentype.c | 175 ++++++++++++++---------------------
dlls/dwrite/tests/font.c | 9 +-
4 files changed, 74 insertions(+), 114 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index be3f4b719e8..7c9fe8a6873 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -408,7 +408,6 @@ extern unsigned int opentype_get_cpal_palettecount(const struct dwrite_fonttable
extern unsigned int opentype_get_cpal_paletteentrycount(const struct dwrite_fonttable *table) DECLSPEC_HIDDEN;
extern HRESULT opentype_get_cpal_entries(const struct dwrite_fonttable *table, unsigned int palette,
unsigned int first_entry_index, unsigned int entry_count, DWRITE_COLOR_F *entries) DECLSPEC_HIDDEN;
-extern BOOL opentype_has_vertical_variants(IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
extern UINT32 opentype_get_glyph_image_formats(IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
extern DWRITE_CONTAINER_TYPE opentype_analyze_container_type(void const *, UINT32) DECLSPEC_HIDDEN;
@@ -650,6 +649,7 @@ extern void opentype_layout_apply_gpos_features(struct scriptshaping_context *co
extern BOOL opentype_layout_check_feature(struct scriptshaping_context *context, unsigned int script_index,
unsigned int language_index, struct shaping_feature *feature, unsigned int glyph_count,
const UINT16 *glyphs, UINT8 *feature_applies) DECLSPEC_HIDDEN;
+extern BOOL opentype_has_vertical_variants(struct dwrite_fontface *fontface) DECLSPEC_HIDDEN;
extern HRESULT opentype_get_vertical_glyph_variants(struct dwrite_fontface *fontface, unsigned int glyph_count,
const UINT16 *nominal_glyphs, UINT16 *glyphs) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 9889add8899..02ac75d2419 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -4970,7 +4970,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
if (freetype_has_kerning_pairs(&fontface->IDWriteFontFace5_iface))
fontface->flags |= FONTFACE_HAS_KERNING_PAIRS;
- if (opentype_has_vertical_variants(&fontface->IDWriteFontFace5_iface))
+ if (opentype_has_vertical_variants(fontface))
fontface->flags |= FONTFACE_HAS_VERTICAL_VARIANTS;
fontface->glyph_image_formats = opentype_get_glyph_image_formats(&fontface->IDWriteFontFace5_iface);
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 53925465a12..d7a0aaf8e51 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -2945,81 +2945,6 @@ void opentype_colr_next_glyph(const struct dwrite_fonttable *colr, struct dwrite
}
}
-BOOL opentype_has_vertical_variants(IDWriteFontFace5 *fontface)
-{
- const struct gpos_gsub_header *header;
- const struct ot_feature_list *featurelist;
- const struct ot_lookup_list *lookup_list;
- BOOL exists = FALSE, ret = FALSE;
- unsigned int i, j;
- const void *data;
- void *context;
- UINT32 size;
- HRESULT hr;
-
- hr = IDWriteFontFace5_TryGetFontTable(fontface, MS_GSUB_TAG, &data, &size, &context, &exists);
- if (FAILED(hr) || !exists)
- return FALSE;
-
- header = data;
- featurelist = (struct ot_feature_list *)((BYTE*)header + GET_BE_WORD(header->feature_list));
- lookup_list = (const struct ot_lookup_list *)((BYTE*)header + GET_BE_WORD(header->lookup_list));
-
- for (i = 0; i < GET_BE_WORD(featurelist->feature_count); i++) {
- if (featurelist->features[i].tag == DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING) {
- const struct ot_feature *feature = (const struct ot_feature*)((BYTE*)featurelist + GET_BE_WORD(featurelist->features[i].offset));
- UINT16 lookup_count = GET_BE_WORD(feature->lookup_count), index, count, type;
- const GSUB_SingleSubstFormat2 *subst2;
- const struct ot_lookup_table *lookup_table;
- UINT32 offset;
-
- if (lookup_count == 0)
- continue;
-
- for (j = 0; j < lookup_count; ++j) {
- /* check if lookup is empty */
- index = GET_BE_WORD(feature->lookuplist_index[j]);
- lookup_table = (const struct ot_lookup_table *)((BYTE*)lookup_list + GET_BE_WORD(lookup_list->lookup[index]));
-
- type = GET_BE_WORD(lookup_table->lookup_type);
- if (type != GSUB_LOOKUP_SINGLE_SUBST && type != GSUB_LOOKUP_EXTENSION_SUBST)
- continue;
-
- count = GET_BE_WORD(lookup_table->subtable_count);
- if (count == 0)
- continue;
-
- offset = GET_BE_WORD(lookup_table->subtable[0]);
- if (type == GSUB_LOOKUP_EXTENSION_SUBST) {
- const GSUB_ExtensionPosFormat1 *ext = (const GSUB_ExtensionPosFormat1 *)((const BYTE *)lookup_table + offset);
- if (GET_BE_WORD(ext->SubstFormat) == 1)
- offset += GET_BE_DWORD(ext->ExtensionOffset);
- else
- FIXME("Unhandled Extension Substitution Format %u\n", GET_BE_WORD(ext->SubstFormat));
- }
-
- subst2 = (const GSUB_SingleSubstFormat2*)((BYTE*)lookup_table + offset);
- index = GET_BE_WORD(subst2->SubstFormat);
- if (index == 1)
- FIXME("Validate Single Substitution Format 1\n");
- else if (index == 2) {
- /* SimSun-ExtB has 0 glyph count for this substitution */
- if (GET_BE_WORD(subst2->GlyphCount) > 0) {
- ret = TRUE;
- break;
- }
- }
- else
- WARN("Unknown Single Substitution Format, %u\n", index);
- }
- }
- }
-
- IDWriteFontFace5_ReleaseFontTable(fontface, context);
-
- return ret;
-}
-
static BOOL opentype_has_font_table(IDWriteFontFace5 *fontface, UINT32 tag)
{
BOOL exists = FALSE;
@@ -4329,10 +4254,16 @@ static BOOL opentype_layout_apply_gpos_mark_to_mark_attachment(struct scriptshap
}
static unsigned int opentype_layout_adjust_extension_subtable(struct scriptshaping_context *context,
- unsigned int *subtable_offset)
+ unsigned int *subtable_offset, const struct lookup *lookup)
{
const struct ot_gsubgpos_extension_format1 *format1;
+ if ((context->table == &context->cache->gsub && lookup->type != GSUB_LOOKUP_EXTENSION_SUBST) ||
+ (context->table == &context->cache->gpos && lookup->type != GPOS_LOOKUP_EXTENSION_POSITION))
+ {
+ return lookup->type;
+ }
+
if (!(format1 = table_read_ensure(&context->table->table, *subtable_offset, sizeof(*format1))))
return 0;
@@ -4361,14 +4292,7 @@ static BOOL opentype_layout_apply_gpos_lookup(struct scriptshaping_context *cont
{
unsigned int subtable_offset = opentype_layout_get_gsubgpos_subtable(context, lookup->offset, i);
- if (lookup->type == GPOS_LOOKUP_EXTENSION_POSITION)
- {
- lookup_type = opentype_layout_adjust_extension_subtable(context, &subtable_offset);
- if (!lookup_type)
- continue;
- }
- else
- lookup_type = lookup->type;
+ lookup_type = opentype_layout_adjust_extension_subtable(context, &subtable_offset, lookup);
switch (lookup_type)
{
@@ -5679,14 +5603,7 @@ static BOOL opentype_layout_apply_gsub_lookup(struct scriptshaping_context *cont
{
unsigned int subtable_offset = opentype_layout_get_gsubgpos_subtable(context, lookup->offset, i);
- if (lookup->type == GSUB_LOOKUP_EXTENSION_SUBST)
- {
- lookup_type = opentype_layout_adjust_extension_subtable(context, &subtable_offset);
- if (!lookup_type)
- continue;
- }
- else
- lookup_type = lookup->type;
+ lookup_type = opentype_layout_adjust_extension_subtable(context, &subtable_offset, lookup);
switch (lookup_type)
{
@@ -6005,14 +5922,7 @@ static BOOL opentype_layout_gsub_lookup_is_glyph_covered(struct scriptshaping_co
{
unsigned int subtable_offset = opentype_layout_get_gsubgpos_subtable(context, lookup->offset, i);
- if (lookup->type == GSUB_LOOKUP_EXTENSION_SUBST)
- {
- lookup_type = opentype_layout_adjust_extension_subtable(context, &subtable_offset);
- if (!lookup_type)
- continue;
- }
- else
- lookup_type = lookup->type;
+ lookup_type = opentype_layout_adjust_extension_subtable(context, &subtable_offset, lookup);
format = table_read_be_word(gsub, subtable_offset);
@@ -6079,14 +5989,7 @@ static BOOL opentype_layout_gpos_lookup_is_glyph_covered(struct scriptshaping_co
{
unsigned int subtable_offset = opentype_layout_get_gsubgpos_subtable(context, lookup->offset, i);
- if (lookup->type == GPOS_LOOKUP_EXTENSION_POSITION)
- {
- lookup_type = opentype_layout_adjust_extension_subtable(context, &subtable_offset);
- if (!lookup_type)
- continue;
- }
- else
- lookup_type = lookup->type;
+ lookup_type = opentype_layout_adjust_extension_subtable(context, &subtable_offset, lookup);
format = table_read_be_word(gpos, subtable_offset);
@@ -6178,6 +6081,61 @@ BOOL opentype_layout_check_feature(struct scriptshaping_context *context, unsign
return ret;
}
+BOOL opentype_has_vertical_variants(struct dwrite_fontface *fontface)
+{
+ unsigned int i, j, count = 0, lookup_type, subtable_offset;
+ struct shaping_features features = { 0 };
+ struct shaping_feature vert_feature = { 0 };
+ struct scriptshaping_context context = { 0 };
+ struct lookups lookups = { 0 };
+ UINT16 format;
+
+ context.cache = fontface_get_shaping_cache(fontface);
+ context.table = &context.cache->gsub;
+
+ vert_feature.tag = DWRITE_MAKE_OPENTYPE_TAG('v','e','r','t');
+ vert_feature.flags = FEATURE_GLOBAL | FEATURE_GLOBAL_SEARCH;
+ vert_feature.max_value = 1;
+ vert_feature.default_value = 1;
+
+ features.features = &vert_feature;
+ features.count = features.capacity = 1;
+
+ opentype_layout_collect_lookups(&context, ~0u, ~0u, &features, context.table, &lookups);
+
+ for (i = 0; i < lookups.count && !count; ++i)
+ {
+ const struct dwrite_fonttable *table = &context.table->table;
+ const struct lookup *lookup = &lookups.lookups[i];
+
+ for (j = 0; j < lookup->subtable_count && !count; ++j)
+ {
+ subtable_offset = opentype_layout_get_gsubgpos_subtable(&context, lookup->offset, j);
+ lookup_type = opentype_layout_adjust_extension_subtable(&context, &subtable_offset, lookup);
+
+ if (lookup_type != GSUB_LOOKUP_SINGLE_SUBST)
+ continue;
+
+ format = table_read_be_word(table, subtable_offset);
+
+ if (format == 1)
+ {
+ count = 1;
+ }
+ else if (format == 2)
+ {
+ count = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gsub_singlesubst_format2, count));
+ }
+ else
+ WARN("Unrecognized single substitution format %u.\n", format);
+ }
+ }
+
+ heap_free(lookups.lookups);
+
+ return !!count;
+}
+
HRESULT opentype_get_vertical_glyph_variants(struct dwrite_fontface *fontface, unsigned int glyph_count,
const UINT16 *nominal_glyphs, UINT16 *glyphs)
{
@@ -6215,6 +6173,7 @@ HRESULT opentype_get_vertical_glyph_variants(struct dwrite_fontface *fontface, u
{
const struct lookup *lookup = &lookups.lookups[i];
+ /* FIXME: should probably handle extension subtables. */
if (lookup->type != GSUB_LOOKUP_SINGLE_SUBST)
continue;
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index becb1a741f7..193f8ed9c48 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -8208,16 +8208,17 @@ static BOOL has_vertical_glyph_variants(IDWriteFontFace1 *fontface)
subst2 = (const GSUB_SingleSubstFormat2*)((BYTE*)lookup_table + offset);
index = GET_BE_WORD(subst2->SubstFormat);
if (index == 1)
- ok(0, "validate Single Substitution Format 1\n");
+ ret = TRUE;
else if (index == 2) {
/* SimSun-ExtB has 0 glyph count for this substitution */
- if (GET_BE_WORD(subst2->GlyphCount) > 0) {
+ if (GET_BE_WORD(subst2->GlyphCount) > 0)
ret = TRUE;
- break;
- }
}
else
ok(0, "unknown Single Substitution Format, %u\n", index);
+
+ if (ret)
+ break;
}
}
}
--
2.29.2
Dec. 1, 2020
[PATCH 3/5] dwrite/gdiinterop: Use consistent traces for the interop object.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/gdiinterop.c | 31 +++++++++++--------------------
1 file changed, 11 insertions(+), 20 deletions(-)
diff --git a/dlls/dwrite/gdiinterop.c b/dlls/dwrite/gdiinterop.c
index 47924011fd3..81cfc3a586b 100644
--- a/dlls/dwrite/gdiinterop.c
+++ b/dlls/dwrite/gdiinterop.c
@@ -637,9 +637,7 @@ static HRESULT create_rendertarget(IDWriteFactory7 *factory, HDC hdc, UINT32 wid
static HRESULT WINAPI gdiinterop_QueryInterface(IDWriteGdiInterop1 *iface, REFIID riid, void **obj)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
-
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IDWriteGdiInterop1) ||
IsEqualIID(riid, &IID_IDWriteGdiInterop) ||
@@ -686,9 +684,7 @@ static ULONG WINAPI gdiinterop_Release(IDWriteGdiInterop1 *iface)
static HRESULT WINAPI gdiinterop_CreateFontFromLOGFONT(IDWriteGdiInterop1 *iface,
LOGFONTW const *logfont, IDWriteFont **font)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
-
- TRACE("(%p)->(%p %p)\n", This, logfont, font);
+ TRACE("%p, %p, %p.\n", iface, logfont, font);
return IDWriteGdiInterop1_CreateFontFromLOGFONT(iface, logfont, NULL, font);
}
@@ -696,12 +692,11 @@ static HRESULT WINAPI gdiinterop_CreateFontFromLOGFONT(IDWriteGdiInterop1 *iface
static HRESULT WINAPI gdiinterop_ConvertFontToLOGFONT(IDWriteGdiInterop1 *iface,
IDWriteFont *font, LOGFONTW *logfont, BOOL *is_systemfont)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
IDWriteFontCollection *collection;
IDWriteFontFamily *family;
HRESULT hr;
- TRACE("(%p)->(%p %p %p)\n", This, font, logfont, is_systemfont);
+ TRACE("%p, %p, %p, %p.\n", iface, font, logfont, is_systemfont);
*is_systemfont = FALSE;
@@ -732,9 +727,7 @@ static HRESULT WINAPI gdiinterop_ConvertFontToLOGFONT(IDWriteGdiInterop1 *iface,
static HRESULT WINAPI gdiinterop_ConvertFontFaceToLOGFONT(IDWriteGdiInterop1 *iface,
IDWriteFontFace *fontface, LOGFONTW *logfont)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
-
- TRACE("(%p)->(%p %p)\n", This, fontface, logfont);
+ TRACE("%p, %p, %p.\n", iface, fontface, logfont);
memset(logfont, 0, sizeof(*logfont));
@@ -841,9 +834,11 @@ static HRESULT WINAPI gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop1 *iface
static HRESULT WINAPI gdiinterop_CreateBitmapRenderTarget(IDWriteGdiInterop1 *iface,
HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **target)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
- TRACE("(%p)->(%p %u %u %p)\n", This, hdc, width, height, target);
- return create_rendertarget(This->factory, hdc, width, height, target);
+ struct gdiinterop *interop = impl_from_IDWriteGdiInterop1(iface);
+
+ TRACE("%p, %p, %u, %u, %p.\n", iface, hdc, width, height, target);
+
+ return create_rendertarget(interop->factory, hdc, width, height, target);
}
static HRESULT WINAPI gdiinterop1_CreateFontFromLOGFONT(IDWriteGdiInterop1 *iface,
@@ -897,9 +892,7 @@ done:
static HRESULT WINAPI gdiinterop1_GetFontSignature_(IDWriteGdiInterop1 *iface, IDWriteFontFace *fontface,
FONTSIGNATURE *fontsig)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
-
- TRACE("(%p)->(%p %p)\n", This, fontface, fontsig);
+ TRACE("%p, %p, %p.\n", iface, fontface, fontsig);
return get_fontsig_from_fontface(fontface, fontsig);
}
@@ -919,9 +912,7 @@ static HRESULT WINAPI gdiinterop1_GetFontSignature(IDWriteGdiInterop1 *iface, ID
static HRESULT WINAPI gdiinterop1_GetMatchingFontsByLOGFONT(IDWriteGdiInterop1 *iface, LOGFONTW const *logfont,
IDWriteFontSet *fontset, IDWriteFontSet **subset)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
-
- FIXME("(%p)->(%p %p %p): stub\n", This, logfont, fontset, subset);
+ FIXME("%p, %p, %p, %p: stub.\n", iface, logfont, fontset, subset);
return E_NOTIMPL;
}
--
2.29.2
Dec. 1, 2020
[PATCH 2/5] dwrite/gdiinterop: Use consistent trace format for the bitmap render target.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/gdiinterop.c | 116 +++++++++++++++++++++------------------
1 file changed, 63 insertions(+), 53 deletions(-)
diff --git a/dlls/dwrite/gdiinterop.c b/dlls/dwrite/gdiinterop.c
index 7e88f7490ca..47924011fd3 100644
--- a/dlls/dwrite/gdiinterop.c
+++ b/dlls/dwrite/gdiinterop.c
@@ -46,7 +46,7 @@ struct rendertarget
IDWriteFactory7 *factory;
DWRITE_TEXT_ANTIALIAS_MODE antialiasmode;
- FLOAT ppdip;
+ float ppdip;
DWRITE_MATRIX m;
SIZE size;
HDC hdc;
@@ -149,20 +149,20 @@ static HRESULT WINAPI rendertarget_sink_QueryInterface(ID2D1SimplifiedGeometrySi
static ULONG WINAPI rendertarget_sink_AddRef(ID2D1SimplifiedGeometrySink *iface)
{
- struct rendertarget *This = impl_from_ID2D1SimplifiedGeometrySink(iface);
- return IDWriteBitmapRenderTarget1_AddRef(&This->IDWriteBitmapRenderTarget1_iface);
+ struct rendertarget *target = impl_from_ID2D1SimplifiedGeometrySink(iface);
+ return IDWriteBitmapRenderTarget1_AddRef(&target->IDWriteBitmapRenderTarget1_iface);
}
static ULONG WINAPI rendertarget_sink_Release(ID2D1SimplifiedGeometrySink *iface)
{
- struct rendertarget *This = impl_from_ID2D1SimplifiedGeometrySink(iface);
- return IDWriteBitmapRenderTarget1_Release(&This->IDWriteBitmapRenderTarget1_iface);
+ struct rendertarget *target = impl_from_ID2D1SimplifiedGeometrySink(iface);
+ return IDWriteBitmapRenderTarget1_Release(&target->IDWriteBitmapRenderTarget1_iface);
}
static void WINAPI rendertarget_sink_SetFillMode(ID2D1SimplifiedGeometrySink *iface, D2D1_FILL_MODE mode)
{
- struct rendertarget *This = impl_from_ID2D1SimplifiedGeometrySink(iface);
- SetPolyFillMode(This->hdc, mode == D2D1_FILL_MODE_ALTERNATE ? ALTERNATE : WINDING);
+ struct rendertarget *target = impl_from_ID2D1SimplifiedGeometrySink(iface);
+ SetPolyFillMode(target->hdc, mode == D2D1_FILL_MODE_ALTERNATE ? ALTERNATE : WINDING);
}
static void WINAPI rendertarget_sink_SetSegmentFlags(ID2D1SimplifiedGeometrySink *iface, D2D1_PATH_SEGMENT vertexFlags)
@@ -171,26 +171,28 @@ static void WINAPI rendertarget_sink_SetSegmentFlags(ID2D1SimplifiedGeometrySink
static void WINAPI rendertarget_sink_BeginFigure(ID2D1SimplifiedGeometrySink *iface, D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin)
{
- struct rendertarget *This = impl_from_ID2D1SimplifiedGeometrySink(iface);
- MoveToEx(This->hdc, startPoint.x, startPoint.y, NULL);
+ struct rendertarget *target = impl_from_ID2D1SimplifiedGeometrySink(iface);
+ MoveToEx(target->hdc, startPoint.x, startPoint.y, NULL);
}
static void WINAPI rendertarget_sink_AddLines(ID2D1SimplifiedGeometrySink *iface, const D2D1_POINT_2F *points, UINT32 count)
{
- struct rendertarget *This = impl_from_ID2D1SimplifiedGeometrySink(iface);
+ struct rendertarget *target = impl_from_ID2D1SimplifiedGeometrySink(iface);
- while (count--) {
- LineTo(This->hdc, points->x, points->y);
+ while (count--)
+ {
+ LineTo(target->hdc, points->x, points->y);
points++;
}
}
static void WINAPI rendertarget_sink_AddBeziers(ID2D1SimplifiedGeometrySink *iface, const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
{
- struct rendertarget *This = impl_from_ID2D1SimplifiedGeometrySink(iface);
+ struct rendertarget *target = impl_from_ID2D1SimplifiedGeometrySink(iface);
POINT points[3];
- while (count--) {
+ while (count--)
+ {
points[0].x = beziers->point1.x;
points[0].y = beziers->point1.y;
points[1].x = beziers->point2.x;
@@ -198,15 +200,15 @@ static void WINAPI rendertarget_sink_AddBeziers(ID2D1SimplifiedGeometrySink *ifa
points[2].x = beziers->point3.x;
points[2].y = beziers->point3.y;
- PolyBezierTo(This->hdc, points, 3);
+ PolyBezierTo(target->hdc, points, 3);
beziers++;
}
}
static void WINAPI rendertarget_sink_EndFigure(ID2D1SimplifiedGeometrySink *iface, D2D1_FIGURE_END figureEnd)
{
- struct rendertarget *This = impl_from_ID2D1SimplifiedGeometrySink(iface);
- CloseFigure(This->hdc);
+ struct rendertarget *target = impl_from_ID2D1SimplifiedGeometrySink(iface);
+ CloseFigure(target->hdc);
}
static HRESULT WINAPI rendertarget_sink_Close(ID2D1SimplifiedGeometrySink *iface)
@@ -214,7 +216,8 @@ static HRESULT WINAPI rendertarget_sink_Close(ID2D1SimplifiedGeometrySink *iface
return S_OK;
}
-static const ID2D1SimplifiedGeometrySinkVtbl rendertargetsinkvtbl = {
+static const ID2D1SimplifiedGeometrySinkVtbl rendertargetsinkvtbl =
+{
rendertarget_sink_QueryInterface,
rendertarget_sink_AddRef,
rendertarget_sink_Release,
@@ -229,9 +232,7 @@ static const ID2D1SimplifiedGeometrySinkVtbl rendertargetsinkvtbl = {
static HRESULT WINAPI rendertarget_QueryInterface(IDWriteBitmapRenderTarget1 *iface, REFIID riid, void **obj)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
-
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IDWriteBitmapRenderTarget1) ||
IsEqualIID(riid, &IID_IDWriteBitmapRenderTarget) ||
@@ -490,93 +491,101 @@ static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *ifac
static HDC WINAPI rendertarget_GetMemoryDC(IDWriteBitmapRenderTarget1 *iface)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
- TRACE("(%p)\n", This);
- return This->hdc;
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
+
+ TRACE("%p.\n", iface);
+
+ return target->hdc;
}
-static FLOAT WINAPI rendertarget_GetPixelsPerDip(IDWriteBitmapRenderTarget1 *iface)
+static float WINAPI rendertarget_GetPixelsPerDip(IDWriteBitmapRenderTarget1 *iface)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
- TRACE("(%p)\n", This);
- return This->ppdip;
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
+
+ TRACE("%p.\n", iface);
+
+ return target->ppdip;
}
-static HRESULT WINAPI rendertarget_SetPixelsPerDip(IDWriteBitmapRenderTarget1 *iface, FLOAT ppdip)
+static HRESULT WINAPI rendertarget_SetPixelsPerDip(IDWriteBitmapRenderTarget1 *iface, float ppdip)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
- TRACE("(%p)->(%.2f)\n", This, ppdip);
+ TRACE("%p, %.2f.\n", iface, ppdip);
if (ppdip <= 0.0f)
return E_INVALIDARG;
- This->ppdip = ppdip;
+ target->ppdip = ppdip;
return S_OK;
}
static HRESULT WINAPI rendertarget_GetCurrentTransform(IDWriteBitmapRenderTarget1 *iface, DWRITE_MATRIX *transform)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
- TRACE("(%p)->(%p)\n", This, transform);
+ TRACE("%p, %p.\n", iface, transform);
- *transform = This->m;
+ *transform = target->m;
return S_OK;
}
static HRESULT WINAPI rendertarget_SetCurrentTransform(IDWriteBitmapRenderTarget1 *iface, DWRITE_MATRIX const *transform)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
- TRACE("(%p)->(%p)\n", This, transform);
+ TRACE("%p, %p.\n", iface, transform);
- This->m = transform ? *transform : identity;
+ target->m = transform ? *transform : identity;
return S_OK;
}
static HRESULT WINAPI rendertarget_GetSize(IDWriteBitmapRenderTarget1 *iface, SIZE *size)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
- TRACE("(%p)->(%p)\n", This, size);
- *size = This->size;
+ TRACE("%p, %p.\n", iface, size);
+
+ *size = target->size;
return S_OK;
}
static HRESULT WINAPI rendertarget_Resize(IDWriteBitmapRenderTarget1 *iface, UINT32 width, UINT32 height)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
- TRACE("(%p)->(%u %u)\n", This, width, height);
+ TRACE("%p, %u, %u.\n", iface, width, height);
- if (This->size.cx == width && This->size.cy == height)
+ if (target->size.cx == width && target->size.cy == height)
return S_OK;
- return create_target_dibsection(This, width, height);
+ return create_target_dibsection(target, width, height);
}
static DWRITE_TEXT_ANTIALIAS_MODE WINAPI rendertarget_GetTextAntialiasMode(IDWriteBitmapRenderTarget1 *iface)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
- TRACE("(%p)\n", This);
- return This->antialiasmode;
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
+
+ TRACE("%p.\n", iface);
+
+ return target->antialiasmode;
}
static HRESULT WINAPI rendertarget_SetTextAntialiasMode(IDWriteBitmapRenderTarget1 *iface, DWRITE_TEXT_ANTIALIAS_MODE mode)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
- TRACE("(%p)->(%d)\n", This, mode);
+ TRACE("%p, %d.\n", iface, mode);
if ((DWORD)mode > DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
return E_INVALIDARG;
- This->antialiasmode = mode;
+ target->antialiasmode = mode;
return S_OK;
}
-static const IDWriteBitmapRenderTarget1Vtbl rendertargetvtbl = {
+static const IDWriteBitmapRenderTarget1Vtbl rendertargetvtbl =
+{
rendertarget_QueryInterface,
rendertarget_AddRef,
rendertarget_Release,
@@ -592,7 +601,8 @@ static const IDWriteBitmapRenderTarget1Vtbl rendertargetvtbl = {
rendertarget_SetTextAntialiasMode
};
-static HRESULT create_rendertarget(IDWriteFactory7 *factory, HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **ret)
+static HRESULT create_rendertarget(IDWriteFactory7 *factory, HDC hdc, UINT32 width, UINT32 height,
+ IDWriteBitmapRenderTarget **ret)
{
struct rendertarget *target;
HRESULT hr;
--
2.29.2
Dec. 1, 2020
[PATCH 1/5] dwrite/font: Use consistent traces for the font object.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/font.c | 121 +++++++++++++++++++++++++--------------------
1 file changed, 68 insertions(+), 53 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index aa51c744297..9889add8899 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -151,9 +151,10 @@ struct dwrite_fontlist
struct dwrite_fontfamily *family;
};
-struct dwrite_font {
+struct dwrite_font
+{
IDWriteFont3 IDWriteFont3_iface;
- LONG ref;
+ LONG refcount;
DWRITE_FONT_STYLE style;
struct dwrite_font_data *data;
@@ -1848,9 +1849,7 @@ static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace5
static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont3 *iface, REFIID riid, void **obj)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
-
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IDWriteFont3) ||
IsEqualIID(riid, &IID_IDWriteFont2) ||
@@ -1871,57 +1870,67 @@ static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont3 *iface, REFIID riid
static ULONG WINAPI dwritefont_AddRef(IDWriteFont3 *iface)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p)->(%d)\n", This, ref);
- return ref;
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
+ ULONG refcount = InterlockedIncrement(&font->refcount);
+
+ TRACE("%p, refcount %d.\n", iface, refcount);
+
+ return refcount;
}
static ULONG WINAPI dwritefont_Release(IDWriteFont3 *iface)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
+ ULONG refcount = InterlockedDecrement(&font->refcount);
- TRACE("(%p)->(%d)\n", This, ref);
+ TRACE("%p, refcount %d.\n", iface, refcount);
- if (!ref) {
- IDWriteFontFamily2_Release(&This->family->IDWriteFontFamily2_iface);
- release_font_data(This->data);
- heap_free(This);
+ if (!refcount)
+ {
+ IDWriteFontFamily2_Release(&font->family->IDWriteFontFamily2_iface);
+ release_font_data(font->data);
+ heap_free(font);
}
- return ref;
+ return refcount;
}
static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont3 *iface, IDWriteFontFamily **family)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
- TRACE("(%p)->(%p)\n", This, family);
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
+
+ TRACE("%p, %p.\n", iface, family);
- *family = (IDWriteFontFamily*)This->family;
+ *family = (IDWriteFontFamily *)font->family;
IDWriteFontFamily_AddRef(*family);
return S_OK;
}
static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont3 *iface)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
- TRACE("(%p)\n", This);
- return This->data->weight;
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
+
+ TRACE("%p.\n", iface);
+
+ return font->data->weight;
}
static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont3 *iface)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
- TRACE("(%p)\n", This);
- return This->data->stretch;
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
+
+ TRACE("%p.\n", iface);
+
+ return font->data->stretch;
}
static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont3 *iface)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
- TRACE("(%p)\n", This);
- return This->style;
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
+
+ TRACE("%p.\n", iface);
+
+ return font->style;
}
static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont3 *iface)
@@ -1960,17 +1969,20 @@ static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont3 *iface,
static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont3 *iface)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
- TRACE("(%p)\n", This);
- return This->data->simulations;
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
+
+ TRACE("%p.\n", iface);
+
+ return font->data->simulations;
}
static void WINAPI dwritefont_GetMetrics(IDWriteFont3 *iface, DWRITE_FONT_METRICS *metrics)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
- TRACE("(%p)->(%p)\n", This, metrics);
- memcpy(metrics, &This->data->metrics, sizeof(*metrics));
+ TRACE("%p, %p.\n", iface, metrics);
+
+ memcpy(metrics, &font->data->metrics, sizeof(*metrics));
}
static BOOL dwritefont_has_character(struct dwrite_font *font, UINT32 ch)
@@ -2003,16 +2015,20 @@ static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont3 *iface, IDWriteFont
static void WINAPI dwritefont1_GetMetrics(IDWriteFont3 *iface, DWRITE_FONT_METRICS1 *metrics)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
- TRACE("(%p)->(%p)\n", This, metrics);
- *metrics = This->data->metrics;
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
+
+ TRACE("%p, %p.\n", iface, metrics);
+
+ *metrics = font->data->metrics;
}
static void WINAPI dwritefont1_GetPanose(IDWriteFont3 *iface, DWRITE_PANOSE *panose)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
- TRACE("(%p)->(%p)\n", This, panose);
- *panose = This->data->panose;
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
+
+ TRACE("%p, %p.\n", iface, panose);
+
+ *panose = font->data->panose;
}
static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont3 *iface, UINT32 max_count, DWRITE_UNICODE_RANGE *ranges,
@@ -2093,8 +2109,8 @@ static BOOL WINAPI dwritefont3_HasCharacter(IDWriteFont3 *iface, UINT32 ch)
static DWRITE_LOCALITY WINAPI dwritefont3_GetLocality(IDWriteFont3 *iface)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
- FIXME("(%p): stub\n", This);
+ FIXME("%p: stub.\n", iface);
+
return DWRITE_LOCALITY_LOCAL;
}
@@ -2179,23 +2195,22 @@ HRESULT get_fontsig_from_fontface(IDWriteFontFace *iface, FONTSIGNATURE *fontsig
static HRESULT create_font(struct dwrite_fontfamily *family, UINT32 index, IDWriteFont3 **font)
{
- struct dwrite_font *This;
+ struct dwrite_font *object;
*font = NULL;
- This = heap_alloc(sizeof(*This));
- if (!This)
+ if (!(object = heap_alloc(sizeof(*object))))
return E_OUTOFMEMORY;
- This->IDWriteFont3_iface.lpVtbl = &dwritefontvtbl;
- This->ref = 1;
- This->family = family;
+ object->IDWriteFont3_iface.lpVtbl = &dwritefontvtbl;
+ object->refcount = 1;
+ object->family = family;
IDWriteFontFamily2_AddRef(&family->IDWriteFontFamily2_iface);
- This->data = family->data->fonts[index];
- This->style = This->data->style;
- addref_font_data(This->data);
+ object->data = family->data->fonts[index];
+ object->style = object->data->style;
+ addref_font_data(object->data);
- *font = &This->IDWriteFont3_iface;
+ *font = &object->IDWriteFont3_iface;
return S_OK;
}
--
2.29.2
Dec. 1, 2020
Re: [PATCH 2/2] plugplay: Send WM_DEVICECHANGE with DBT_DEVNODES_CHANGED with each event.
by Arkadiusz Hiler
On Wed, Nov 25, 2020 at 09:42:37AM -0600, Marvin wrote:
> Hi,
>
> While running your changed tests, I think I found new failures.
> Being a bot and all I'm not very good at pattern recognition, so I might be
> wrong, but could you please double-check?
>
> Full results can be found at:
> https://testbot.winehq.org/JobDetails.pl?Key=82429
>
> Your paranoid android.
>
>
> === debiant (32 bit report) ===
>
> user32:
> monitor: Timeout
> win.c:10147: Test failed: GetActiveWindow() = 00000000
> win.c:10147: Test failed: GetFocus() = 00000000
> win.c:10149: Test failed: Expected foreground window 001B0140, got 00E10102
> win.c:10152: Test failed: Received WM_ACTIVATEAPP(0), did not expect it.
> win.c:10159: Test failed: Expected foreground window 001B0140, got 00000000
> win.c:10161: Test failed: GetActiveWindow() = 00000000
> win.c:10161: Test failed: GetFocus() = 00000000
> win.c:10169: Test failed: Received WM_ACTIVATEAPP(1), did not expect it.
>
> === debiant (32 bit WoW report) ===
>
> user32:
> monitor: Timeout
>
> === debiant (64 bit WoW report) ===
>
> user32:
> clipboard.c:760: Test failed: 2: gle 5
> clipboard.c:765: Test failed: 2.0: got 0000 instead of 000d
> clipboard.c:805: Test failed: 2: gle 1418
> clipboard.c:815: Test failed: 2: count 4
> clipboard.c:818: Test failed: 2: gle 1418
> clipboard.c:853: Test failed: 2.0: formats 00000000 have been rendered
> clipboard.c:858: Test failed: 2.0: formats 00000000 have been rendered
> clipboard.c:853: Test failed: 2.2: formats 00000000 have been rendered
> clipboard.c:858: Test failed: 2.2: formats 00000000 have been rendered
> clipboard.c:853: Test failed: 2.3: formats 00000000 have been rendered
> clipboard.c:858: Test failed: 2.3: formats 00000000 have been rendered
> monitor: Timeout
Just in case someone wonders - both those and 1/2 results are false
negatives that are quite usual for user32 changes as far as I have
noticed.
--
Cheers,
Arek
Dec. 1, 2020
Re: [PATCH 5/5] gdi32: Only use the registry cache for application fonts.
by Huw Davies
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Dec. 1, 2020
Re: [PATCH 4/5] gdi32: Only request registry font path when necessary.
by Huw Davies
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Dec. 1, 2020
Re: [PATCH 3/5] gdi32: Update the external keys after all fonts are loaded.
by Huw Davies
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Dec. 1, 2020
Re: [PATCH 2/5] gdi32: Index scalable faces by full name in rbtree.
by Huw Davies
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Dec. 1, 2020
Re: [PATCH 1/5] gdi32: Load registry fonts after system fonts.
by Huw Davies
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Dec. 1, 2020
Re: [PATCH 4/5] gdi32: Only request registry font path when necessary.
by Rémi Bernon
On 12/1/20 10:33 AM, Huw Davies wrote:
> On Fri, Nov 27, 2020 at 03:38:04PM +0100, Rémi Bernon wrote:
>> Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
>> ---
>> dlls/gdi32/font.c | 9 ++++++++-
>> 1 file changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
>> index d3202d83a15..4cc072bd785 100644
>> --- a/dlls/gdi32/font.c
>> +++ b/dlls/gdi32/font.c
>> @@ -7910,7 +7910,7 @@ static void load_registry_fonts(void)
>>
>> vlen = ARRAY_SIZE(value);
>> dlen = sizeof(data);
>> - while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, (LPBYTE)data, &dlen ))
>> + while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, NULL, NULL ))
>> {
>> if (type != REG_SZ) goto next;
>> dlen /= sizeof(WCHAR);
>> @@ -7918,6 +7918,13 @@ static void load_registry_fonts(void)
>> if (find_face_from_full_name( value )) goto next;
>> if (tmp && !*tmp) *tmp = ' ';
>>
>> + if (RegQueryValueExW( hkey, value, NULL, NULL, (LPBYTE)data, &dlen ))
>> + {
>> + WARN( "Unable to get face path %s\n", debugstr_w(value) );
>> + goto next;
>> + }
>> +
>> + dlen /= sizeof(WCHAR);
>> if (data[0] && data[1] == ':')
>> add_font_resource( data, ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_TO_CACHE );
>> else if (dlen >= 6 && !wcsicmp( data + dlen - 5, L".fon" ))
>
> Just so I understand, this is essentially saving the memcpy() in
> RegEnumValueW() for the (many) external fonts at the expense of a
> second server round-trip for the (few) "internal" fonts?
>
> Huw.
>
The memcpy and the write/read from/to wineserver, yes.
--
Rémi Bernon <rbernon(a)codeweavers.com>
Dec. 1, 2020
Re: [PATCH 2/2] odbccp32: Implement SQLWriteDSNToIni/W
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=82841
Your paranoid android.
=== wvistau64 (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w2008s64 (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w864 (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w1064v1507 (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w1064v1809 (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w1064 (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w1064_2qxl (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w10pro64 (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w10pro64_ar (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w10pro64_he (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w10pro64_ja (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
=== w10pro64_zh_CN (64 bit report) ===
odbccp32:
misc.c:825: Test failed: Invalid value
Dec. 1, 2020
[PATCH 2/2] odbccp32: Implement SQLWriteDSNToIni/W
by Alistair Leslie-Hughes
Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=50150
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/odbccp32/odbccp32.c | 100 ++++++++++++++++++++++++++++++++--
dlls/odbccp32/tests/misc.c | 108 +++++++++++++++++++++++++++++++++++++
2 files changed, 203 insertions(+), 5 deletions(-)
diff --git a/dlls/odbccp32/odbccp32.c b/dlls/odbccp32/odbccp32.c
index 420f206b700..78fcc9de2c4 100644
--- a/dlls/odbccp32/odbccp32.c
+++ b/dlls/odbccp32/odbccp32.c
@@ -1691,16 +1691,106 @@ BOOL WINAPI SQLValidDSN(LPCSTR lpszDSN)
BOOL WINAPI SQLWriteDSNToIniW(LPCWSTR lpszDSN, LPCWSTR lpszDriver)
{
+ BOOL ret = FALSE;
+ HKEY hkey, hkeydriver;
+ WCHAR *filename = NULL;
+ DWORD size = 0, type;
+
+ TRACE("%s %s\n", debugstr_w(lpszDSN), debugstr_w(lpszDriver));
+
clear_errors();
- FIXME("%s %s\n", debugstr_w(lpszDSN), debugstr_w(lpszDriver));
- return TRUE;
+
+ if (!SQLValidDSNW(lpszDSN))
+ {
+ push_error(ODBC_ERROR_INVALID_DSN, odbc_error_invalid_dsn);
+ return FALSE;
+ }
+
+ /* It doesn't matter if we cannot find the driver, windows just writes a blank value. */
+ if ((ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, odbcini, &hkey)) == ERROR_SUCCESS)
+ {
+ HKEY hkeydriver;
+
+ if ((ret = RegOpenKeyW(hkey, lpszDriver, &hkeydriver)) == ERROR_SUCCESS)
+ {
+ ret = RegGetValueW(hkeydriver, NULL, L"driver", RRF_RT_REG_SZ, &type, NULL, &size);
+ if(ret != ERROR_SUCCESS || type != REG_SZ)
+ {
+ RegCloseKey(hkey);
+ }
+
+ if (size)
+ {
+ filename = HeapAlloc(GetProcessHeap(), 0, size);
+ if(!filename)
+ {
+ RegCloseKey(hkeydriver);
+ RegCloseKey(hkey);
+ push_error(ODBC_ERROR_OUT_OF_MEM, odbc_error_out_of_mem);
+
+ return FALSE;
+ }
+ ret = RegGetValueW(hkeydriver, NULL, L"driver", RRF_RT_REG_SZ, &type, filename, &size);
+ }
+
+ RegCloseKey(hkeydriver);
+ }
+
+ RegCloseKey(hkey);
+ }
+
+ if (RegCreateKeyW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\ODBC\\ODBC.INI", &hkey) == ERROR_SUCCESS)
+ {
+ HKEY sources;
+
+ if (RegCreateKeyW(hkey, L"ODBC Data Sources", &sources) == ERROR_SUCCESS)
+ {
+ RegSetValueExW(sources, lpszDSN, 0, REG_SZ, (BYTE*)lpszDriver, (lstrlenW(lpszDriver)+1)*sizeof(WCHAR));
+ RegCloseKey(sources);
+ }
+
+ RegDeleteTreeW(hkey, lpszDSN);
+
+ if (RegCreateKeyW(hkey, lpszDSN, &hkeydriver) == ERROR_SUCCESS)
+ {
+ if (filename)
+ RegSetValueExW(sources, L"driver", 0, REG_SZ, (BYTE*)filename, (lstrlenW(filename)+1)*sizeof(WCHAR));
+ else
+ RegSetValueExW(sources, L"driver", 0, REG_SZ, (BYTE*)L"", sizeof(L""));
+
+ RegCloseKey(hkeydriver);
+ ret = TRUE;
+ }
+
+ RegCloseKey(hkey);
+ }
+
+ if (!ret)
+ push_error(ODBC_ERROR_REQUEST_FAILED, odbc_error_request_failed);
+
+ heap_free(filename);
+
+ return ret;
}
BOOL WINAPI SQLWriteDSNToIni(LPCSTR lpszDSN, LPCSTR lpszDriver)
{
- clear_errors();
- FIXME("%s %s\n", debugstr_a(lpszDSN), debugstr_a(lpszDriver));
- return TRUE;
+ BOOL ret = FALSE;
+ WCHAR *dsn, *driver;
+
+ TRACE("%s %s\n", debugstr_a(lpszDSN), debugstr_a(lpszDriver));
+
+ dsn = SQLInstall_strdup(lpszDSN);
+ driver = SQLInstall_strdup(lpszDriver);
+ if (dsn && driver)
+ ret = SQLWriteDSNToIniW(dsn, driver);
+ else
+ push_error(ODBC_ERROR_OUT_OF_MEM, odbc_error_out_of_mem);
+
+ heap_free(dsn);
+ heap_free(driver);
+
+ return ret;
}
BOOL WINAPI SQLWriteFileDSNW(LPCWSTR lpszFileName, LPCWSTR lpszAppName,
diff --git a/dlls/odbccp32/tests/misc.c b/dlls/odbccp32/tests/misc.c
index 0120504227d..e89408fcaff 100644
--- a/dlls/odbccp32/tests/misc.c
+++ b/dlls/odbccp32/tests/misc.c
@@ -771,6 +771,113 @@ static void test_SQLConfigDataSource(void)
check_error(ODBC_ERROR_COMPONENT_NOT_FOUND);
}
+static void test_SQLWriteDSNToIni(void)
+{
+ BOOL ret;
+ char buffer[MAX_PATH];
+ char path[MAX_PATH];
+ DWORD type, size;
+
+ SQLSetConfigMode(ODBC_SYSTEM_DSN);
+
+ ret = SQLWriteDSNToIni("wine_dbs", "Microsoft Access Driver (*.mdb)");
+ if (!ret)
+ {
+ win_skip("Doesn't have permission to write a System DSN\n");
+ return;
+ }
+
+ if(ret)
+ {
+ HKEY hkey;
+ LONG res;
+
+ res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\ODBC\\ODBC.INI\\ODBC Data Sources", 0,
+ KEY_READ, &hkey);
+ ok(res == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
+ if (res == ERROR_SUCCESS)
+ {
+ type = 0xdeadbeef;
+ size = MAX_PATH;
+
+ memset(buffer, 0, sizeof(buffer));
+ res = RegQueryValueExA(hkey, "wine_dbs", NULL, &type, (BYTE *)buffer, &size);
+ ok(res == ERROR_SUCCESS, "RegGetValueA failed\n");
+ ok(type == REG_SZ, "got %u\n", type);
+ ok(!strcmp(buffer, "Microsoft Access Driver (*.mdb)"), "incorrect string '%s'\n", buffer);
+
+ RegCloseKey(hkey);
+ }
+
+ res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\ODBC\\ODBC.INI\\wine_dbs", 0,
+ KEY_READ, &hkey);
+ ok(res == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
+ if (res == ERROR_SUCCESS)
+ {
+ type = 0xdeadbeef;
+ size = MAX_PATH;
+
+ memset(path, 0, sizeof(path));
+ res = RegQueryValueExA(hkey, "driver", NULL, &type, (BYTE *)path, &size);
+ ok(res == ERROR_SUCCESS, "RegGetValueA failed\n");
+ ok(type == REG_SZ, "got %u\n", type);
+ /* WINE doesn't have a Microsoft Access Driver (*.mdb) driver aviable */
+ todo_wine ok(strlen(path) != 0, "Invalid value\n");
+
+ RegCloseKey(hkey);
+ }
+
+ ret = SQLRemoveDSNFromIni("wine_dbs");
+ ok(ret, "got %d\n", ret);
+ }
+
+ /* Show that values are writen, even though an invalid driver was specified. */
+ ret = SQLWriteDSNToIni("wine_mis", "Missing Access Driver (*.mis)");
+ ok(ret, "got %d\n", ret);
+ if(ret)
+ {
+ HKEY hkey;
+ LONG res;
+
+ res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\ODBC\\ODBC.INI\\ODBC Data Sources", 0,
+ KEY_READ, &hkey);
+ ok(res == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
+ if (res == ERROR_SUCCESS)
+ {
+ type = 0xdeadbeef;
+ size = MAX_PATH;
+
+ memset(buffer, 0, sizeof(buffer));
+ res = RegQueryValueExA(hkey, "wine_mis", NULL, &type, (BYTE *)buffer, &size);
+ ok(res == ERROR_SUCCESS, "RegGetValueA failed\n");
+ ok(type == REG_SZ, "got %u\n", type);
+ ok(!strcmp(buffer, "Missing Access Driver (*.mis)"), "incorrect string '%s'\n", buffer);
+
+ RegCloseKey(hkey);
+ }
+
+ res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\ODBC\\ODBC.INI\\wine_mis", 0,
+ KEY_READ, &hkey);
+ ok(res == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
+ if (res == ERROR_SUCCESS)
+ {
+ type = 0xdeadbeef;
+ size = MAX_PATH;
+
+ memset(path, 0, sizeof(path));
+ res = RegQueryValueExA(hkey, "driver", NULL, &type, (BYTE *)path, &size);
+ ok(res == ERROR_SUCCESS, "RegGetValueA failed\n");
+ ok(type == REG_SZ, "got %u\n", type);
+ ok(strlen(path) == 0, "Invalid value\n");
+
+ RegCloseKey(hkey);
+ }
+
+ ret = SQLRemoveDSNFromIni("wine_mis");
+ ok(ret, "got %d\n", ret);
+ }
+}
+
START_TEST(misc)
{
test_SQLConfigMode();
@@ -785,4 +892,5 @@ START_TEST(misc)
test_SQLValidDSN();
test_SQLValidDSNW();
test_SQLConfigDataSource();
+ test_SQLWriteDSNToIni();
}
--
2.29.2
Dec. 1, 2020
[PATCH 1/2] odbccp32: Implement SQLRemoveDSNFromIni/w
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/odbccp32/odbccp32.c | 39 +++++++++++++++++++++++++++++++++------
1 file changed, 33 insertions(+), 6 deletions(-)
diff --git a/dlls/odbccp32/odbccp32.c b/dlls/odbccp32/odbccp32.c
index 0e4a12534c8..420f206b700 100644
--- a/dlls/odbccp32/odbccp32.c
+++ b/dlls/odbccp32/odbccp32.c
@@ -1523,18 +1523,45 @@ BOOL WINAPI SQLRemoveDriverManager(LPDWORD pdwUsageCount)
BOOL WINAPI SQLRemoveDSNFromIniW(LPCWSTR lpszDSN)
{
+ HKEY hkey;
+
+ TRACE("%s\n", debugstr_w(lpszDSN));
+
clear_errors();
- FIXME("%s\n", debugstr_w(lpszDSN));
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+
+ if (RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\ODBC\\ODBC.INI\\ODBC Data Sources", &hkey) == ERROR_SUCCESS)
+ {
+ RegDeleteValueW(hkey, lpszDSN);
+ RegCloseKey(hkey);
+ }
+
+ if (RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\ODBC\\ODBC.INI", &hkey) == ERROR_SUCCESS)
+ {
+ RegDeleteTreeW(hkey, lpszDSN);
+ RegCloseKey(hkey);
+ }
+
+ return TRUE;
}
BOOL WINAPI SQLRemoveDSNFromIni(LPCSTR lpszDSN)
{
+ BOOL ret = FALSE;
+ WCHAR *dsn;
+
+ TRACE("%s\n", debugstr_a(lpszDSN));
+
clear_errors();
- FIXME("%s\n", debugstr_a(lpszDSN));
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+
+ dsn = SQLInstall_strdup(lpszDSN);
+ if (dsn)
+ ret = SQLRemoveDSNFromIniW(dsn);
+ else
+ push_error(ODBC_ERROR_OUT_OF_MEM, odbc_error_out_of_mem);
+
+ heap_free(dsn);
+
+ return ret;
}
BOOL WINAPI SQLRemoveTranslatorW(const WCHAR *translator, DWORD *usage_count)
--
2.29.2
Dec. 1, 2020
Re: [PATCH 4/5] gdi32: Only request registry font path when necessary.
by Huw Davies
On Fri, Nov 27, 2020 at 03:38:04PM +0100, Rémi Bernon wrote:
> Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
> ---
> dlls/gdi32/font.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
> index d3202d83a15..4cc072bd785 100644
> --- a/dlls/gdi32/font.c
> +++ b/dlls/gdi32/font.c
> @@ -7910,7 +7910,7 @@ static void load_registry_fonts(void)
>
> vlen = ARRAY_SIZE(value);
> dlen = sizeof(data);
> - while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, (LPBYTE)data, &dlen ))
> + while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, NULL, NULL ))
> {
> if (type != REG_SZ) goto next;
> dlen /= sizeof(WCHAR);
> @@ -7918,6 +7918,13 @@ static void load_registry_fonts(void)
> if (find_face_from_full_name( value )) goto next;
> if (tmp && !*tmp) *tmp = ' ';
>
> + if (RegQueryValueExW( hkey, value, NULL, NULL, (LPBYTE)data, &dlen ))
> + {
> + WARN( "Unable to get face path %s\n", debugstr_w(value) );
> + goto next;
> + }
> +
> + dlen /= sizeof(WCHAR);
> if (data[0] && data[1] == ':')
> add_font_resource( data, ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_TO_CACHE );
> else if (dlen >= 6 && !wcsicmp( data + dlen - 5, L".fon" ))
Just so I understand, this is essentially saving the memcpy() in
RegEnumValueW() for the (many) external fonts at the expense of a
second server round-trip for the (few) "internal" fonts?
Huw.
Dec. 1, 2020
[PATCH 5/5] qedit/nullrenderer: Don't drop csRenderLock in NullRenderer_DoRenderSample().
by Zebediah Figura
We don't grab stream_cs to change any variables checked here, except to reset
flush_event, and that cannot result in a deadlock.
The only possible deadlocks here are:
(1) between this function and EndOfStream(), which is correct, as the two
should presumably be serialized;
(2) between this function and EndFlush(); however, in that case we expect
BeginFlush() first, which will unblock the streaming thread.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/qedit/nullrenderer.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/dlls/qedit/nullrenderer.c b/dlls/qedit/nullrenderer.c
index a8594eade8b..97e3cdbb202 100644
--- a/dlls/qedit/nullrenderer.c
+++ b/dlls/qedit/nullrenderer.c
@@ -46,9 +46,7 @@ static HRESULT WINAPI NullRenderer_DoRenderSample(struct strmbase_renderer *ifac
const HANDLE events[2] = {filter->run_event, filter->renderer.flush_event};
SetEvent(filter->renderer.state_event);
- LeaveCriticalSection(&filter->renderer.csRenderLock);
WaitForMultipleObjects(2, events, FALSE, INFINITE);
- EnterCriticalSection(&filter->renderer.csRenderLock);
}
return S_OK;
--
2.29.2
Dec. 1, 2020
[PATCH 4/5] strmbase: Don't drop csRenderLock in BaseRenderer_Receive().
by Zebediah Figura
We don't grab stream_cs to change any variables checked here, except to reset
flush_event, and that cannot result in a deadlock.
The only possible deadlocks here are:
(1) between this function and EndOfStream(), which is correct, as the two
should presumably be serialized;
(2) between this function and EndFlush(); however, in that case we expect
BeginFlush() first, which will unblock the streaming thread.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/strmbase/renderer.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/dlls/strmbase/renderer.c b/dlls/strmbase/renderer.c
index dde56b7a346..24d209703ca 100644
--- a/dlls/strmbase/renderer.c
+++ b/dlls/strmbase/renderer.c
@@ -224,18 +224,15 @@ static HRESULT WINAPI BaseRenderer_Receive(struct strmbase_sink *pin, IMediaSamp
IReferenceClock_AdviseTime(filter->filter.clock, filter->stream_start,
start, (HEVENT)filter->advise_event, &cookie);
- LeaveCriticalSection(&filter->csRenderLock);
-
ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
IReferenceClock_Unadvise(filter->filter.clock, cookie);
if (ret == 1)
{
+ LeaveCriticalSection(&filter->csRenderLock);
TRACE("Flush signaled; discarding current sample.\n");
return S_OK;
}
-
- EnterCriticalSection(&filter->csRenderLock);
}
}
--
2.29.2
Dec. 1, 2020
[PATCH 3/5] quartz/dsoundrender: Don't drop stream_cs in DSoundRender_SendSampleData().
by Zebediah Figura
We don't grab stream_cs to change any variables checked here, except to reset
flush_event, and that cannot result in a deadlock.
The only possible deadlocks here are:
(1) between this function and EndOfStream(), which is correct, as the two
should presumably be serialized;
(2) between this function and EndFlush(); however, in that case we expect
BeginFlush() first, which will unblock the streaming thread.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/dsoundrender.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c
index d00c9e92570..fc64eae8f72 100644
--- a/dlls/quartz/dsoundrender.c
+++ b/dlls/quartz/dsoundrender.c
@@ -258,9 +258,7 @@ static HRESULT DSoundRender_SendSampleData(struct dsound_render *This,
hr = S_FALSE;
if (hr != S_OK) {
- LeaveCriticalSection(&This->stream_cs);
ret = WaitForSingleObject(This->flush_event, 10);
- EnterCriticalSection(&This->stream_cs);
if (This->sink.flushing || This->filter.state == State_Stopped)
return This->filter.state == State_Paused ? S_OK : VFW_E_WRONG_STATE;
if (ret != WAIT_TIMEOUT)
--
2.29.2
Dec. 1, 2020
[PATCH 2/5] quartz/dsoundrender: Don't drop stream_cs in DSoundRender_HandleEndOfStream().
by Zebediah Figura
We don't grab stream_cs to change any variables checked here, except to reset
flush_event, and that cannot result in a deadlock.
The only possible deadlocks here are:
(1) between this function and Receive(), which is correct, as the two
should presumably be serialized;
(2) between this function and EndFlush(); however, in that case we expect
BeginFlush() first, which will unblock the streaming thread.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/dsoundrender.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c
index c07dec56c09..d00c9e92570 100644
--- a/dlls/quartz/dsoundrender.c
+++ b/dlls/quartz/dsoundrender.c
@@ -237,9 +237,7 @@ static HRESULT DSoundRender_HandleEndOfStream(struct dsound_render *This)
if (pos1 == pos2)
break;
- LeaveCriticalSection(&This->stream_cs);
WaitForSingleObject(This->flush_event, 10);
- EnterCriticalSection(&This->stream_cs);
}
return S_OK;
--
2.29.2
Dec. 1, 2020