Wine-devel
Threads by month
- ----- 2026 -----
- 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
January 2020
- 75 participants
- 595 discussions
Signed-off-by: Sven Baars <sbaars(a)codeweavers.com>
---
dlls/d3dx9_36/tests/core.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/dlls/d3dx9_36/tests/core.c b/dlls/d3dx9_36/tests/core.c
index fa874a5ef5..75146575be 100644
--- a/dlls/d3dx9_36/tests/core.c
+++ b/dlls/d3dx9_36/tests/core.c
@@ -330,13 +330,13 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
/* D3DXCreateFont */
ref = get_ref((IUnknown*)device);
- hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font);
+ hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK);
check_ref((IUnknown*)device, ref + 1);
check_release((IUnknown*)font, 0);
check_ref((IUnknown*)device, ref);
- hr = D3DXCreateFontA(device, 0, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font);
+ hr = D3DXCreateFontA(device, 0, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK);
ID3DXFont_Release(font);
@@ -348,13 +348,13 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK);
ID3DXFont_Release(font);
- hr = D3DXCreateFontA(NULL, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font);
+ hr = D3DXCreateFontA(NULL, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
- hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", NULL);
+ hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", NULL);
ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
- hr = D3DXCreateFontA(NULL, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", NULL);
+ hr = D3DXCreateFontA(NULL, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", NULL);
ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
@@ -368,7 +368,7 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
desc.OutputPrecision = OUT_DEFAULT_PRECIS;
desc.Quality = DEFAULT_QUALITY;
desc.PitchAndFamily = DEFAULT_PITCH;
- strcpy(desc.FaceName, "Arial");
+ strcpy(desc.FaceName, "Tahoma");
hr = D3DXCreateFontIndirectA(device, &desc, &font);
ok(hr == D3D_OK, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3D_OK);
ID3DXFont_Release(font);
@@ -384,7 +384,7 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
/* ID3DXFont_GetDevice */
- hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font);
+ hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
if(SUCCEEDED(hr)) {
IDirect3DDevice9 *bufdev;
@@ -401,7 +401,7 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
/* ID3DXFont_GetDesc */
- hr = D3DXCreateFontA(device, 12, 8, FW_BOLD, 2, TRUE, ANSI_CHARSET, OUT_RASTER_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, "Arial", &font);
+ hr = D3DXCreateFontA(device, 12, 8, FW_BOLD, 2, TRUE, ANSI_CHARSET, OUT_RASTER_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, "Tahoma", &font);
if(SUCCEEDED(hr)) {
hr = ID3DXFont_GetDescA(font, NULL);
ok(hr == D3DERR_INVALIDCALL, "ID3DXFont_GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
@@ -418,14 +418,14 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
ok(desc.OutputPrecision == OUT_RASTER_PRECIS, "ID3DXFont_GetDesc returned an output precision of %d, expected %d\n", desc.OutputPrecision, OUT_RASTER_PRECIS);
ok(desc.Quality == ANTIALIASED_QUALITY, "ID3DXFont_GetDesc returned font quality %d, expected %d\n", desc.Quality, ANTIALIASED_QUALITY);
ok(desc.PitchAndFamily == VARIABLE_PITCH, "ID3DXFont_GetDesc returned pitch and family %d, expected %d\n", desc.PitchAndFamily, VARIABLE_PITCH);
- ok(strcmp(desc.FaceName, "Arial") == 0, "ID3DXFont_GetDesc returned facename \"%s\", expected \"%s\"\n", desc.FaceName, "Arial");
+ ok(strcmp(desc.FaceName, "Tahoma") == 0, "ID3DXFont_GetDesc returned facename \"%s\", expected \"%s\"\n", desc.FaceName, "Tahoma");
ID3DXFont_Release(font);
} else skip("Failed to create a ID3DXFont object\n");
/* ID3DXFont_GetDC + ID3DXFont_GetTextMetrics */
- hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font);
+ hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
if(SUCCEEDED(hr)) {
HDC hdc;
@@ -466,7 +466,7 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
/* ID3DXFont_PreloadText */
- hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font);
+ hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
if(SUCCEEDED(hr)) {
todo_wine {
hr = ID3DXFont_PreloadTextA(font, NULL, -1);
@@ -493,7 +493,7 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
/* ID3DXFont_GetGlyphData, ID3DXFont_PreloadGlyphs, ID3DXFont_PreloadCharacters */
- hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font);
+ hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
if(SUCCEEDED(hr)) {
char c;
HDC hdc;
@@ -565,7 +565,7 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
IDirect3DTexture9 *texture;
hr = D3DXCreateFontA(device, tests[i].font_height, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET,
- OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font);
+ OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
if(FAILED(hr)) {
skip("Failed to create a ID3DXFont object\n");
continue;
--
2.24.0
3
16
27 Jan '20
Currently rounded parts are approximated with quadratic Bézier curves.
Signed-off-by: Giovanni Mascellani <gio(a)debian.org>
---
dlls/d2d1/d2d1_private.h | 14 ++
dlls/d2d1/factory.c | 22 ++-
dlls/d2d1/geometry.c | 321 +++++++++++++++++++++++++++++++++++++++
dlls/d2d1/tests/d2d1.c | 1 -
4 files changed, 354 insertions(+), 4 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 2e42d6d550..d20fac9956 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -440,6 +440,7 @@ struct d2d_geometry
size_t face_count;
struct d2d_bezier_vertex *bezier_vertices;
+ size_t bezier_vertices_size;
size_t bezier_vertex_count;
} fill;
@@ -483,6 +484,10 @@ struct d2d_geometry
D2D1_RECT_F rect;
} rectangle;
struct
+ {
+ D2D1_ROUNDED_RECT rounded_rect;
+ } rounded_rectangle;
+ struct
{
ID2D1Geometry *src_geometry;
D2D_MATRIX_3X2_F transform;
@@ -499,6 +504,8 @@ struct d2d_geometry
void d2d_path_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory) DECLSPEC_HIDDEN;
HRESULT d2d_rectangle_geometry_init(struct d2d_geometry *geometry,
ID2D1Factory *factory, const D2D1_RECT_F *rect) DECLSPEC_HIDDEN;
+HRESULT d2d_rounded_rectangle_geometry_init(struct d2d_geometry *geometry,
+ ID2D1Factory *factory, const D2D1_ROUNDED_RECT *rounded_rect) DECLSPEC_HIDDEN;
void d2d_transformed_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory,
ID2D1Geometry *src_geometry, const D2D_MATRIX_3X2_F *transform) DECLSPEC_HIDDEN;
HRESULT d2d_geometry_group_init(struct d2d_geometry *geometry, ID2D1Factory *factory,
@@ -620,4 +627,11 @@ static inline const char *debug_d2d_rect_f(const D2D1_RECT_F *rect)
return wine_dbg_sprintf("(%.8e,%.8e)-(%.8e,%.8e)", rect->left, rect->top, rect->right, rect->bottom );
}
+static inline const char *debug_d2d_rounded_rect(const D2D1_ROUNDED_RECT *rounded_rect)
+{
+ if (!rounded_rect) return "(null)";
+ return wine_dbg_sprintf("(%.8e,%.8e)-(%.8e,%.8e)[%.8e,%.8e]", rounded_rect->rect.left, rounded_rect->rect.top,
+ rounded_rect->rect.right, rounded_rect->rect.bottom, rounded_rect->radiusX, rounded_rect->radiusY );
+}
+
#endif /* __WINE_D2D1_PRIVATE_H */
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 48a2efb96b..86284f4ae4 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -152,11 +152,27 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateRectangleGeometry(ID2D1Factor
}
static HRESULT STDMETHODCALLTYPE d2d_factory_CreateRoundedRectangleGeometry(ID2D1Factory2 *iface,
- const D2D1_ROUNDED_RECT *rect, ID2D1RoundedRectangleGeometry **geometry)
+ const D2D1_ROUNDED_RECT *rounded_rect, ID2D1RoundedRectangleGeometry **geometry)
{
- FIXME("iface %p, rect %p, geometry %p stub!\n", iface, rect, geometry);
+ struct d2d_geometry *object;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("iface %p, rounded_rect %s, geometry %p.\n", iface, debug_d2d_rounded_rect(rounded_rect), geometry);
+
+ if (!(object = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d2d_rounded_rectangle_geometry_init(object, (ID2D1Factory *)iface, rounded_rect)))
+ {
+ WARN("Failed to initialize rounded rectangle geometry, hr %#x.\n", hr);
+ heap_free(object);
+ return hr;
+ }
+
+ TRACE("Created rounded rectangle geometry %p.\n", object);
+ *geometry = (ID2D1RoundedRectangleGeometry *)&object->ID2D1Geometry_iface;
+
+ return S_OK;
}
static HRESULT STDMETHODCALLTYPE d2d_factory_CreateEllipseGeometry(ID2D1Factory2 *iface,
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index 6697eccee4..de7c808249 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -2257,6 +2257,14 @@ static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometr
return TRUE;
}
+static BOOL d2d_geometry_outline_add_arc_quadrant(struct d2d_geometry *geometry,
+ const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
+{
+ FIXME("Approximating arc quadrant with Bezier curve.\n");
+
+ return d2d_geometry_outline_add_bezier_segment(geometry, p0, p1, p2);
+}
+
static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry,
struct d2d_figure *figure, D2D1_FIGURE_END figure_end)
{
@@ -2329,6 +2337,26 @@ static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry,
return TRUE;
}
+static BOOL d2d_geometry_fill_add_arc_triangle(struct d2d_geometry *geometry,
+ const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
+{
+ struct d2d_bezier_vertex *bv;
+
+ FIXME("Approximating arc triangle with Bezier triangle.\n");
+
+ if (!d2d_array_reserve((void **)&geometry->fill.bezier_vertices, &geometry->fill.bezier_vertices_size,
+ geometry->fill.bezier_vertex_count + 3, sizeof(*geometry->fill.bezier_vertices)))
+ return FALSE;
+
+ bv = geometry->fill.bezier_vertices + geometry->fill.bezier_vertex_count;
+ d2d_bezier_vertex_set(&bv[0], p0, 0.0f, 0.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[1], p1, 0.5f, 0.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[2], p2, 1.0f, 1.0f, -1.0f);
+ geometry->fill.bezier_vertex_count += 3;
+
+ return TRUE;
+}
+
static void d2d_geometry_cleanup(struct d2d_geometry *geometry)
{
heap_free(geometry->outline.bezier_faces);
@@ -3840,6 +3868,298 @@ fail:
return E_OUTOFMEMORY;
}
+static inline struct d2d_geometry *impl_from_ID2D1RoundedRectangleGeometry(ID2D1RoundedRectangleGeometry *iface)
+{
+ return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_QueryInterface(ID2D1RoundedRectangleGeometry *iface,
+ REFIID iid, void **out)
+{
+ TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+ if (IsEqualGUID(iid, &IID_ID2D1RoundedRectangleGeometry)
+ || IsEqualGUID(iid, &IID_ID2D1Geometry)
+ || IsEqualGUID(iid, &IID_ID2D1Resource)
+ || IsEqualGUID(iid, &IID_IUnknown))
+ {
+ ID2D1RoundedRectangleGeometry_AddRef(iface);
+ *out = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_AddRef(ID2D1RoundedRectangleGeometry *iface)
+{
+ struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
+ ULONG refcount = InterlockedIncrement(&geometry->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Release(ID2D1RoundedRectangleGeometry *iface)
+{
+ struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
+ ULONG refcount = InterlockedDecrement(&geometry->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ d2d_geometry_cleanup(geometry);
+ heap_free(geometry);
+ }
+
+ return refcount;
+}
+
+static void STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetFactory(ID2D1RoundedRectangleGeometry *iface, ID2D1Factory **factory)
+{
+ struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
+
+ TRACE("iface %p, factory %p.\n", iface, factory);
+
+ ID2D1Factory_AddRef(*factory = geometry->factory);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetBounds(ID2D1RoundedRectangleGeometry *iface,
+ const D2D1_MATRIX_3X2_F *transform, D2D1_RECT_F *bounds)
+{
+ FIXME("iface %p, transform %p, bounds %p stub!\n", iface, transform, bounds);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetWidenedBounds(ID2D1RoundedRectangleGeometry *iface,
+ float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
+ float tolerance, D2D1_RECT_F *bounds)
+{
+ FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, bounds %p stub!\n",
+ iface, stroke_width, stroke_style, transform, tolerance, bounds);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_StrokeContainsPoint(ID2D1RoundedRectangleGeometry *iface,
+ D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
+ float tolerance, BOOL *contains)
+{
+ FIXME("iface %p, point %s, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, contains %p stub!\n",
+ iface, debug_d2d_point_2f(&point), stroke_width, stroke_style, transform, tolerance, contains);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_FillContainsPoint(ID2D1RoundedRectangleGeometry *iface,
+ D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
+{
+ FIXME("iface %p, point %s, transform %p, tolerance %.8e, contains %p stub!\n",
+ iface, debug_d2d_point_2f(&point), transform, tolerance, contains);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_CompareWithGeometry(ID2D1RoundedRectangleGeometry *iface,
+ ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
+{
+ FIXME("iface %p, geometry %p, transform %p, tolerance %.8e, relation %p stub!\n",
+ iface, geometry, transform, tolerance, relation);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Simplify(ID2D1RoundedRectangleGeometry *iface,
+ D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance,
+ ID2D1SimplifiedGeometrySink *sink)
+{
+ FIXME("iface %p, option %#x, transform %p, tolerance %.8e, sink %p stub!\n",
+ iface, option, transform, tolerance, sink);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Tessellate(ID2D1RoundedRectangleGeometry *iface,
+ const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
+{
+ FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_CombineWithGeometry(ID2D1RoundedRectangleGeometry *iface,
+ ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform,
+ float tolerance, ID2D1SimplifiedGeometrySink *sink)
+{
+ FIXME("iface %p, geometry %p, combine_mode %#x, transform %p, tolerance %.8e, sink %p stub!\n",
+ iface, geometry, combine_mode, transform, tolerance, sink);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Outline(ID2D1RoundedRectangleGeometry *iface,
+ const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
+{
+ FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_ComputeArea(ID2D1RoundedRectangleGeometry *iface,
+ const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
+{
+ FIXME("iface %p, transform %p, tolerance %.8e, area %p stub!\n", iface, transform, tolerance, area);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_ComputeLength(ID2D1RoundedRectangleGeometry *iface,
+ const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
+{
+ FIXME("iface %p, transform %p, tolerance %.8e, length %p stub!\n", iface, transform, tolerance, length);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_ComputePointAtLength(ID2D1RoundedRectangleGeometry *iface,
+ float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point,
+ D2D1_POINT_2F *tangent)
+{
+ FIXME("iface %p, length %.8e, transform %p, tolerance %.8e, point %p, tangent %p stub!\n",
+ iface, length, transform, tolerance, point, tangent);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Widen(ID2D1RoundedRectangleGeometry *iface, float stroke_width,
+ ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance,
+ ID2D1SimplifiedGeometrySink *sink)
+{
+ FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, sink %p stub!\n",
+ iface, stroke_width, stroke_style, transform, tolerance, sink);
+
+ return E_NOTIMPL;
+}
+
+static void STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetRoundedRect(ID2D1RoundedRectangleGeometry *iface, D2D1_ROUNDED_RECT *rounded_rect)
+{
+ struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
+
+ TRACE("iface %p, rounded_rect %p.\n", iface, rounded_rect);
+
+ *rounded_rect = geometry->u.rounded_rectangle.rounded_rect;
+}
+
+static const struct ID2D1RoundedRectangleGeometryVtbl d2d_rounded_rectangle_geometry_vtbl =
+{
+ d2d_rounded_rectangle_geometry_QueryInterface,
+ d2d_rounded_rectangle_geometry_AddRef,
+ d2d_rounded_rectangle_geometry_Release,
+ d2d_rounded_rectangle_geometry_GetFactory,
+ d2d_rounded_rectangle_geometry_GetBounds,
+ d2d_rounded_rectangle_geometry_GetWidenedBounds,
+ d2d_rounded_rectangle_geometry_StrokeContainsPoint,
+ d2d_rounded_rectangle_geometry_FillContainsPoint,
+ d2d_rounded_rectangle_geometry_CompareWithGeometry,
+ d2d_rounded_rectangle_geometry_Simplify,
+ d2d_rounded_rectangle_geometry_Tessellate,
+ d2d_rounded_rectangle_geometry_CombineWithGeometry,
+ d2d_rounded_rectangle_geometry_Outline,
+ d2d_rounded_rectangle_geometry_ComputeArea,
+ d2d_rounded_rectangle_geometry_ComputeLength,
+ d2d_rounded_rectangle_geometry_ComputePointAtLength,
+ d2d_rounded_rectangle_geometry_Widen,
+ d2d_rounded_rectangle_geometry_GetRoundedRect,
+};
+
+HRESULT d2d_rounded_rectangle_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory, const D2D1_ROUNDED_RECT *rounded_rect)
+{
+ struct d2d_face *f;
+ D2D1_POINT_2F *v, v1, v2, v3, v4;
+ float l, r, t, b;
+ float rX, rY;
+
+ d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_rounded_rectangle_geometry_vtbl);
+ geometry->u.rounded_rectangle.rounded_rect = *rounded_rect;
+
+ if (!(geometry->fill.vertices = heap_alloc(8 * sizeof(*geometry->fill.vertices))))
+ goto fail;
+ if (!d2d_array_reserve((void **)&geometry->fill.faces,
+ &geometry->fill.faces_size, 6, sizeof(*geometry->fill.faces)))
+ goto fail;
+
+ l = min(rounded_rect->rect.left, rounded_rect->rect.right);
+ r = max(rounded_rect->rect.left, rounded_rect->rect.right);
+ t = min(rounded_rect->rect.top, rounded_rect->rect.bottom);
+ b = max(rounded_rect->rect.top, rounded_rect->rect.bottom);
+
+ rX = min(rounded_rect->radiusX, 0.5f*(r-l));
+ rY = min(rounded_rect->radiusY, 0.5f*(b-t));
+
+ d2d_point_set(&v1, r, t);
+ d2d_point_set(&v2, r, b);
+ d2d_point_set(&v3, l, b);
+ d2d_point_set(&v4, l, t);
+
+ v = geometry->fill.vertices;
+ d2d_point_set(&v[0], l+rX, t);
+ d2d_point_set(&v[1], r-rX, t);
+ d2d_point_set(&v[2], r, t+rY);
+ d2d_point_set(&v[3], r, b-rY);
+ d2d_point_set(&v[4], r-rX, b);
+ d2d_point_set(&v[5], l+rX, b);
+ d2d_point_set(&v[6], l, b-rY);
+ d2d_point_set(&v[7], l, t+rY);
+ geometry->fill.vertex_count = 8;
+
+ f = geometry->fill.faces;
+ d2d_face_set(&f[0], 0, 7, 6);
+ d2d_face_set(&f[1], 0, 6, 5);
+ d2d_face_set(&f[2], 0, 5, 4);
+ d2d_face_set(&f[3], 0, 4, 1);
+ d2d_face_set(&f[4], 1, 4, 3);
+ d2d_face_set(&f[5], 1, 3, 2);
+ geometry->fill.face_count = 6;
+
+ if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[1], &v1, &v[2]))
+ goto fail;
+ if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[3], &v2, &v[4]))
+ goto fail;
+ if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[5], &v3, &v[6]))
+ goto fail;
+ if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[7], &v4, &v[0]))
+ goto fail;
+
+ if (!d2d_geometry_outline_add_line_segment(geometry, &v[0], &v[1]))
+ goto fail;
+ if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[1], &v1, &v[2]))
+ goto fail;
+ if (!d2d_geometry_outline_add_line_segment(geometry, &v[2], &v[3]))
+ goto fail;
+ if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[3], &v2, &v[4]))
+ goto fail;
+ if (!d2d_geometry_outline_add_line_segment(geometry, &v[4], &v[5]))
+ goto fail;
+ if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[5], &v3, &v[6]))
+ goto fail;
+ if (!d2d_geometry_outline_add_line_segment(geometry, &v[6], &v[7]))
+ goto fail;
+ if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[7], &v4, &v[0]))
+ goto fail;
+
+ return S_OK;
+
+fail:
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+}
+
static inline struct d2d_geometry *impl_from_ID2D1TransformedGeometry(ID2D1TransformedGeometry *iface)
{
return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
@@ -4385,6 +4705,7 @@ struct d2d_geometry *unsafe_impl_from_ID2D1Geometry(ID2D1Geometry *iface)
return NULL;
assert(iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_path_geometry_vtbl
|| iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_rectangle_geometry_vtbl
+ || iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_rounded_rectangle_geometry_vtbl
|| iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_transformed_geometry_vtbl
|| iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_geometry_group_vtbl);
return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 5377c4ea34..d2d59dbcba 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -3790,7 +3790,6 @@ static void test_rounded_rectangle_geometry(void)
set_rounded_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
-todo_wine
ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
if (FAILED(hr))
{
--
2.25.0
1
1
[PATCH 3/3] gdiplus/tests: Add more tests for GdipCreateBitmapFromHBITMAP and palette images.
by Dmitry Timoshkov 27 Jan '20
by Dmitry Timoshkov 27 Jan '20
27 Jan '20
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/gdiplus/tests/image.c | 88 ++++++++++++++++++++++++++++++++++----
1 file changed, 79 insertions(+), 9 deletions(-)
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c
index 62cd79fec6..eeeea8746a 100644
--- a/dlls/gdiplus/tests/image.c
+++ b/dlls/gdiplus/tests/image.c
@@ -866,7 +866,7 @@ static void test_LockBits_UserBuf(void)
struct BITMAPINFOWITHBITFIELDS
{
BITMAPINFOHEADER bmiHeader;
- DWORD masks[3];
+ DWORD masks[255];
};
union BITMAPINFOUNION
@@ -882,7 +882,10 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
HPALETTE hpal = NULL;
GpStatus stat;
BYTE buff[1000];
- LOGPALETTE* LogPal = NULL;
+ char logpalette_buf[sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 255];
+ LOGPALETTE *LogPal = (LOGPALETTE *)logpalette_buf;
+ char colorpalette_buf[sizeof(ColorPalette) + sizeof(ARGB) * 255];
+ ColorPalette *palette = (ColorPalette *)colorpalette_buf;
REAL width, height;
const REAL WIDTH1 = 5;
const REAL HEIGHT1 = 15;
@@ -892,6 +895,7 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
union BITMAPINFOUNION bmi;
BYTE *bits;
PixelFormat format;
+ int i;
stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
expect(InvalidParameter, stat);
@@ -905,6 +909,9 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
expectf(WIDTH1, width);
expectf(HEIGHT1, height);
+ stat = GdipGetImagePixelFormat((GpImage*)gpbm, &format);
+ expect(Ok, stat);
+ expect(PixelFormat1bppIndexed, format);
if (stat == Ok)
GdipDisposeImage((GpImage*)gpbm);
DeleteObject(hbm);
@@ -916,6 +923,10 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
/* raw format */
expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)gpbm, __LINE__, FALSE);
+ stat = GdipGetImagePixelFormat((GpImage*)gpbm, &format);
+ expect(Ok, stat);
+ expect(PixelFormat1bppIndexed, format);
+
expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
expectf(WIDTH2, width);
expectf(HEIGHT2, height);
@@ -943,6 +954,9 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
expectf(WIDTH1, width);
expectf(HEIGHT1, height);
+ stat = GdipGetImagePixelFormat((GpImage*)gpbm, &format);
+ expect(Ok, stat);
+ expect(PixelFormat24bppRGB, format);
if (stat == Ok)
{
/* test whether writing to the bitmap affects the original */
@@ -954,21 +968,77 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
GdipDisposeImage((GpImage*)gpbm);
}
- LogPal = GdipAlloc(sizeof(LOGPALETTE));
- ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
LogPal->palVersion = 0x300;
- LogPal->palNumEntries = 1;
+ LogPal->palNumEntries = 8;
+ for (i = 0; i < 8; i++)
+ {
+ LogPal->palPalEntry[i].peRed = i;
+ LogPal->palPalEntry[i].peGreen = i;
+ LogPal->palPalEntry[i].peBlue = i;
+ LogPal->palPalEntry[i].peFlags = 0;
+ }
+
hpal = CreatePalette(LogPal);
ok(hpal != NULL, "CreatePalette failed\n");
- GdipFree(LogPal);
stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
expect(Ok, stat);
+ stat = GdipGetImagePalette((GpImage *)gpbm, palette, sizeof(colorpalette_buf));
+ expect(Ok, stat);
+ expect(0, palette->Count);
+ GdipDisposeImage((GpImage*)gpbm);
+ DeleteObject(hbm);
- if (stat == Ok)
- GdipDisposeImage((GpImage*)gpbm);
+ for (i = 0; i < 16; i++)
+ {
+ RGBQUAD *colors = bmi.bi.bmiColors;
+ BYTE clr = 255 - i;
+ colors[i].rgbBlue = clr;
+ colors[i].rgbGreen = clr;
+ colors[i].rgbRed = clr;
+ colors[i].rgbReserved = 0;
+ }
+
+ bmi.bi.bmiHeader.biBitCount = 8;
+ bmi.bi.bmiHeader.biClrUsed = 16;
+ bmi.bi.bmiHeader.biClrImportant = 16;
+ hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
+ ok(hbm != NULL, "CreateDIBSection failed\n");
+
+ stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
+ expect(Ok, stat);
+ stat = GdipGetImagePixelFormat((GpImage*)gpbm, &format);
+ expect(Ok, stat);
+ expect(PixelFormat8bppIndexed, format);
+ stat = GdipGetImagePalette((GpImage *)gpbm, palette, sizeof(colorpalette_buf));
+ expect(Ok, stat);
+ expect(256, palette->Count);
+ for (i = 0; i < 16; i++)
+ {
+ BYTE clr = 255 - i;
+ ARGB argb = 0xff000000 | (clr << 16) | (clr << 8) | clr;
+ ok(palette->Entries[i] == argb, "got %08x, expected %08x\n", palette->Entries[i], argb);
+ }
+ GdipDisposeImage((GpImage*)gpbm);
DeleteObject(hpal);
+
+ stat = GdipCreateBitmapFromHBITMAP(hbm, 0, &gpbm);
+ expect(Ok, stat);
+ stat = GdipGetImagePixelFormat((GpImage*)gpbm, &format);
+ expect(Ok, stat);
+ expect(PixelFormat8bppIndexed, format);
+ stat = GdipGetImagePalette((GpImage *)gpbm, palette, sizeof(colorpalette_buf));
+ expect(Ok, stat);
+ expect(256, palette->Count);
+ for (i = 0; i < 16; i++)
+ {
+ BYTE clr = 255 - i;
+ ARGB argb = 0xff000000 | (clr << 16) | (clr << 8) | clr;
+ ok(palette->Entries[i] == argb, "got %08x, expected %08x\n", palette->Entries[i], argb);
+ }
+ GdipDisposeImage((GpImage*)gpbm);
+
DeleteObject(hbm);
/* 16-bit 555 dib, rgb */
@@ -999,7 +1069,7 @@ static void test_GdipCreateBitmapFromHBITMAP(void)
DeleteObject(hbm);
/* 16-bit 555 dib, with bitfields */
- bmi.bi.bmiHeader.biSize = sizeof(bmi);
+ bmi.bi.bmiHeader.biSize = sizeof(bmi.bi.bmiHeader);
bmi.bi.bmiHeader.biCompression = BI_BITFIELDS;
bmi.bf.masks[0] = 0x7c00;
bmi.bf.masks[1] = 0x3e0;
--
2.20.1
2
1
[PATCH 2/3] gdiplus: Reimplement GdipCreateBitmapFromGdiDib by using GdipCreateBitmapFromHBITMAP.
by Dmitry Timoshkov 27 Jan '20
by Dmitry Timoshkov 27 Jan '20
27 Jan '20
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/gdiplus/image.c | 47 ++++++++++++--------------------------------
1 file changed, 13 insertions(+), 34 deletions(-)
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index 218ca4cd9b..ddc0f38135 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -1381,50 +1381,29 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromGdiDib(GDIPCONST BITMAPINFO* info,
VOID *bits, GpBitmap **bitmap)
{
DWORD height, stride;
- PixelFormat format;
+ HBITMAP hbm;
+ void *bmbits;
+ GpStatus status;
- FIXME("(%p, %p, %p) - partially implemented\n", info, bits, bitmap);
+ TRACE("(%p, %p, %p)\n", info, bits, bitmap);
if (!info || !bits || !bitmap)
return InvalidParameter;
+ hbm = CreateDIBSection(0, info, DIB_RGB_COLORS, &bmbits, NULL, 0);
+ if (!hbm)
+ return InvalidParameter;
+
height = abs(info->bmiHeader.biHeight);
stride = ((info->bmiHeader.biWidth * info->bmiHeader.biBitCount + 31) >> 3) & ~3;
+ TRACE("height %u, stride %u, image size %u\n", height, stride, height * stride);
- if(info->bmiHeader.biHeight > 0) /* bottom-up */
- {
- bits = (BYTE*)bits + (height - 1) * stride;
- stride = -stride;
- }
+ memcpy(bmbits, bits, height * stride);
- switch(info->bmiHeader.biBitCount) {
- case 1:
- format = PixelFormat1bppIndexed;
- break;
- case 4:
- format = PixelFormat4bppIndexed;
- break;
- case 8:
- format = PixelFormat8bppIndexed;
- break;
- case 16:
- format = PixelFormat16bppRGB555;
- break;
- case 24:
- format = PixelFormat24bppRGB;
- break;
- case 32:
- format = PixelFormat32bppRGB;
- break;
- default:
- FIXME("don't know how to handle %d bpp\n", info->bmiHeader.biBitCount);
- *bitmap = NULL;
- return InvalidParameter;
- }
-
- return GdipCreateBitmapFromScan0(info->bmiHeader.biWidth, height, stride, format,
- bits, bitmap);
+ status = GdipCreateBitmapFromHBITMAP(hbm, NULL, bitmap);
+ DeleteObject(hbm);
+ return status;
}
/* FIXME: no icm */
--
2.20.1
2
1
[PATCH 1/3] gdiplus: GdipCreateBitmapFromHBITMAP should use palette from the GDI bitmap.
by Dmitry Timoshkov 27 Jan '20
by Dmitry Timoshkov 27 Jan '20
27 Jan '20
This patch fixes painting bitmaps with bpp <= 8.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/gdiplus/image.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index 1966401507..218ca4cd9b 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -5106,6 +5106,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
GpStatus retval;
PixelFormat format;
BitmapData lockeddata;
+ char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
+ BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
TRACE("%p %p %p\n", hbm, hpal, bitmap);
@@ -5155,8 +5157,6 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
if (retval == Ok)
{
HDC hdc;
- char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
- BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
INT src_height;
hdc = CreateCompatibleDC(NULL);
@@ -5176,29 +5176,28 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
GdipBitmapUnlockBits(*bitmap, &lockeddata);
}
- if (retval == Ok && hpal)
+ /* According to the tests hpal is ignored */
+ if (retval == Ok && pbmi->bmiHeader.biBitCount <= 8)
{
- PALETTEENTRY entry[256];
- ColorPalette *palette=NULL;
+ ColorPalette *palette;
int i, num_palette_entries;
- num_palette_entries = GetPaletteEntries(hpal, 0, 256, entry);
+ num_palette_entries = pbmi->bmiHeader.biClrUsed;
if (!num_palette_entries)
- retval = GenericError;
+ num_palette_entries = 1 << pbmi->bmiHeader.biBitCount;
palette = heap_alloc_zero(sizeof(ColorPalette) + sizeof(ARGB) * (num_palette_entries-1));
if (!palette)
retval = OutOfMemory;
-
- if (retval == Ok)
+ else
{
palette->Flags = 0;
palette->Count = num_palette_entries;
for (i=0; i<num_palette_entries; i++)
{
- palette->Entries[i] = 0xff000000 | entry[i].peRed << 16 |
- entry[i].peGreen << 8 | entry[i].peBlue;
+ palette->Entries[i] = 0xff000000 | pbmi->bmiColors[i].rgbRed << 16 |
+ pbmi->bmiColors[i].rgbGreen << 8 | pbmi->bmiColors[i].rgbBlue;
}
retval = GdipSetImagePalette(&(*bitmap)->image, palette);
--
2.20.1
2
1
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
This series cleans up failures seen on the XP test machine using the
"VMware SVGA II" driver, which seems to lack various features, such as
3D texture support.
dlls/ddraw/tests/ddraw1.c | 3 +++
dlls/ddraw/tests/ddraw2.c | 3 +++
dlls/ddraw/tests/ddraw4.c | 3 +++
dlls/ddraw/tests/ddraw7.c | 3 +++
4 files changed, 12 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index b513121fbb..b1045e2854 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -5488,6 +5488,9 @@ static void test_create_surface_pitch(void)
}
if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
continue;
+ if (((test_data[i].caps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE)) ==
+ (DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE)) && hr == DDERR_NOTEXTUREHW)
+ continue;
ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
if (FAILED(hr))
continue;
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index 541362c748..5a26d4eec4 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -6430,6 +6430,9 @@ static void test_create_surface_pitch(void)
}
if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
continue;
+ if (((test_data[i].caps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE)) ==
+ (DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE)) && hr == DDERR_NOTEXTUREHW)
+ continue;
ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
if (FAILED(hr))
continue;
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 8cadfae52a..33e3db259a 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -8266,6 +8266,9 @@ static void test_create_surface_pitch(void)
}
if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
continue;
+ if (((test_data[i].caps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE)) ==
+ (DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE)) && hr == DDERR_NOTEXTUREHW)
+ continue;
ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
if (FAILED(hr))
continue;
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index f4a709711b..8ad1e859fa 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -8110,6 +8110,9 @@ static void test_create_surface_pitch(void)
}
if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
continue;
+ if (((test_data[i].caps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE)) ==
+ (DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE)) && hr == DDERR_NOTEXTUREHW)
+ continue;
if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE) && SUCCEEDED(test_data[i].hr))
todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
else
--
2.23.0
4
13
27 Jan '20
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v4:
- Add support for older gcrypt versions (for Proton).
- Skip tests if BCryptSecretAgreement fails.
---
configure.ac | 14 ++
dlls/bcrypt/Makefile.in | 1 +
dlls/bcrypt/bcrypt_internal.h | 13 ++
dlls/bcrypt/bcrypt_main.c | 75 +++++++-
dlls/bcrypt/gcrypt.c | 337 ++++++++++++++++++++++++++++++++++
dlls/bcrypt/gnutls.c | 9 +
dlls/bcrypt/tests/bcrypt.c | 4 +-
7 files changed, 441 insertions(+), 12 deletions(-)
create mode 100644 dlls/bcrypt/gcrypt.c
diff --git a/configure.ac b/configure.ac
index 681d315eed..0fc02a533a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,6 +46,7 @@ AC_ARG_WITH(faudio, AS_HELP_STRING([--without-faudio],[do not use FAudio (XAu
AC_ARG_WITH(float-abi, AS_HELP_STRING([--with-float-abi=abi],[specify the ABI (soft|softfp|hard) for ARM platforms]))
AC_ARG_WITH(fontconfig,AS_HELP_STRING([--without-fontconfig],[do not use fontconfig]))
AC_ARG_WITH(freetype, AS_HELP_STRING([--without-freetype],[do not use the FreeType library]))
+AC_ARG_WITH(gcrypt, AS_HELP_STRING([--without-gcrypt],[do not use libgcrypt]))
AC_ARG_WITH(gettext, AS_HELP_STRING([--without-gettext],[do not use gettext]))
AC_ARG_WITH(gettextpo, AS_HELP_STRING([--with-gettextpo],[use the GetTextPO library to rebuild po files]),
[if test "x$withval" = "xno"; then ac_cv_header_gettext_po_h=no; fi])
@@ -1987,6 +1988,19 @@ WINE_NOTICE_WITH(vkd3d,[test "x$ac_cv_lib_soname_vkd3d" = "x"],
[vkd3d ${notice_platform}development files not found (or too old), Direct3D 12 won't be supported.])
test "x$ac_cv_lib_soname_vkd3d" != "x" || enable_d3d12=${enable_d3d12:-no}
+dnl **** Check for gcrypt ****
+if test "x$with_gcrypt" != "xno"
+then
+ WINE_PACKAGE_FLAGS(GCRYPT,[libgcrypt],,,,
+ [AC_CHECK_HEADERS([gcrypt.h])
+ if test "$ac_cv_header_gcrypt_h" = "yes"
+ then
+ WINE_CHECK_SONAME(gcrypt,gcry_sexp_build,,,[$GCRYPT_LIBS])
+ fi])
+fi
+WINE_NOTICE_WITH(gcrypt,[test "x$ac_cv_lib_soname_gcrypt" = "x"],
+ [libgcrypt ${notice_platform}development files not found, GCRYPT won't be supported.])
+
dnl **** Check for gcc specific options ****
AC_SUBST(EXTRACFLAGS,"")
diff --git a/dlls/bcrypt/Makefile.in b/dlls/bcrypt/Makefile.in
index dd6d4a7664..ea3486a400 100644
--- a/dlls/bcrypt/Makefile.in
+++ b/dlls/bcrypt/Makefile.in
@@ -5,6 +5,7 @@ EXTRAINCL = $(GNUTLS_CFLAGS)
C_SRCS = \
bcrypt_main.c \
+ gcrypt.c \
gnutls.c \
macos.c \
md2.c \
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index d026dab729..09e675a655 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -25,6 +25,9 @@
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#include <gnutls/abstract.h>
+#ifdef SONAME_LIBGCRYPT
+#include <gcrypt.h>
+#endif
#elif HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
#include <AvailabilityMacros.h>
#include <CommonCrypto/CommonCryptor.h>
@@ -157,6 +160,12 @@ struct algorithm
BOOL hmac;
};
+struct secret
+{
+ UCHAR *data;
+ ULONG len;
+};
+
#if defined(HAVE_GNUTLS_CIPHER_INIT)
struct key_symmetric
{
@@ -251,6 +260,7 @@ NTSTATUS key_destroy( struct key * ) DECLSPEC_HIDDEN;
BOOL key_is_symmetric( struct key * ) DECLSPEC_HIDDEN;
NTSTATUS key_export_ecc( struct key *, UCHAR *, ULONG, ULONG * ) DECLSPEC_HIDDEN;
NTSTATUS key_import_ecc( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
+NTSTATUS compute_secret_ecc (struct key *pubkey_in, struct key *privkey_in, struct secret *secret) DECLSPEC_HIDDEN;
BOOL is_zero_vector( const UCHAR *, ULONG ) DECLSPEC_HIDDEN;
BOOL is_equal_vector( const UCHAR *, ULONG, const UCHAR *, ULONG ) DECLSPEC_HIDDEN;
@@ -258,4 +268,7 @@ BOOL is_equal_vector( const UCHAR *, ULONG, const UCHAR *, ULONG ) DECLSPEC_HIDD
BOOL gnutls_initialize(void) DECLSPEC_HIDDEN;
void gnutls_uninitialize(void) DECLSPEC_HIDDEN;
+BOOL gcrypt_initialize(void) DECLSPEC_HIDDEN;
+void gcrypt_uninitialize(void) DECLSPEC_HIDDEN;
+
#endif /* __BCRYPT_INTERNAL_H */
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 2ac36d3db0..ed64cd1965 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -1331,6 +1331,12 @@ NTSTATUS key_import_ecc( struct key *key, UCHAR *input, ULONG len )
ERR( "support for keys not available at build time\n" );
return STATUS_NOT_IMPLEMENTED;
}
+
+NTSTATUS compute_secret_ecc (struct key *pubkey_in, struct key *privkey_in, struct secret *secret)
+{
+ ERR( "support for secrets not available at build time\n" );
+ return STATUS_NOT_IMPLEMENTED;
+}
#endif
NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle,
@@ -1696,27 +1702,70 @@ NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle, UCHAR *pwd, ULO
return STATUS_SUCCESS;
}
-NTSTATUS WINAPI BCryptSecretAgreement(BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE key, BCRYPT_SECRET_HANDLE *secret, ULONG flags)
+NTSTATUS WINAPI BCryptSecretAgreement(BCRYPT_KEY_HANDLE hPrivKey, BCRYPT_KEY_HANDLE hPubKey, BCRYPT_SECRET_HANDLE *secret_out, ULONG flags)
{
- FIXME( "%p, %p, %p, %08x\n", handle, key, secret, flags );
+ struct key *privkey = hPrivKey;
+ struct key *pubkey = hPubKey;
+ struct secret *secret;
+ NTSTATUS status;
- if(secret)
- *secret = (BCRYPT_SECRET_HANDLE *)0xDEADFEED;
+ TRACE( "%p, %p, %p, %08x\n", hPrivKey, hPubKey, secret_out, flags );
- return STATUS_SUCCESS;
+ secret = heap_alloc( sizeof(*secret) );
+
+ if ((status = compute_secret_ecc(privkey, pubkey, secret)))
+ {
+ heap_free(secret);
+ }
+ else
+ {
+ *secret_out = secret;
+ }
+
+ return status;
}
-NTSTATUS WINAPI BCryptDestroySecret(BCRYPT_SECRET_HANDLE secret)
+NTSTATUS WINAPI BCryptDestroySecret(BCRYPT_SECRET_HANDLE hSecret)
{
- FIXME( "%p\n", secret );
+ struct secret *secret = hSecret;
+
+ TRACE( "%p\n", hSecret );
+
+ heap_free(secret->data);
+ heap_free(secret);
+
return STATUS_SUCCESS;
}
-NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE secret, LPCWSTR kdf, BCryptBufferDesc *parameter,
+NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE hSecret, LPCWSTR deriv_func, BCryptBufferDesc *parameter,
PUCHAR derived, ULONG derived_size, ULONG *result, ULONG flags)
{
- FIXME( "%p, %s, %p, %p, %d, %p, %08x\n", secret, debugstr_w(kdf), parameter, derived, derived_size, result, flags );
- return STATUS_INTERNAL_ERROR;
+ struct secret *secret = hSecret;
+
+ TRACE( "%p, %s, %p, %p, %d, %p, %08x\n", secret, debugstr_w(deriv_func), parameter, derived, derived_size, result, flags );
+
+ if (!(strcmpW(deriv_func, BCRYPT_KDF_RAW_SECRET)))
+ {
+ ULONG n;
+ ULONG secret_length = secret->len;
+
+ if (!derived)
+ {
+ *result = secret_length;
+ return STATUS_SUCCESS;
+ }
+
+ /* outputs in little endian for some reason */
+ for (n = 0; n < secret_length && n < derived_size; n++)
+ {
+ derived[n] = secret->data[secret_length - n - 1];
+ }
+
+ *result = n;
+ return STATUS_SUCCESS;
+ }
+ FIXME( "Derivation function %s not supported.\n", debugstr_w(deriv_func) );
+ return STATUS_NOT_IMPLEMENTED;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
@@ -1728,6 +1777,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
DisableThreadLibraryCalls( hinst );
#ifdef HAVE_GNUTLS_CIPHER_INIT
gnutls_initialize();
+#ifdef SONAME_LIBGCRYPT
+ gcrypt_initialize();
+#endif
#endif
break;
@@ -1735,6 +1787,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
if (reserved) break;
#ifdef HAVE_GNUTLS_CIPHER_INIT
gnutls_uninitialize();
+#ifdef SONAME_LIBGCRYPT
+ gcrypt_uninitialize();
+#endif
#endif
break;
}
diff --git a/dlls/bcrypt/gcrypt.c b/dlls/bcrypt/gcrypt.c
new file mode 100644
index 0000000000..53c39e0b48
--- /dev/null
+++ b/dlls/bcrypt/gcrypt.c
@@ -0,0 +1,337 @@
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+#ifdef HAVE_GNUTLS_CIPHER_INIT
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#include <gnutls/abstract.h>
+#ifdef HAVE_LIBGCRYPT
+#include <libgcrypt/libgcrypt.h>
+#endif
+#endif
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "bcrypt.h"
+
+#include "bcrypt_internal.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+#include "wine/library.h"
+#include "wine/unicode.h"
+
+#if defined(HAVE_GNUTLS_CIPHER_INIT) && defined(SONAME_LIBGCRYPT)
+WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
+
+static void *libgcrypt_handle;
+#define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(gcry_sexp_build);
+MAKE_FUNCPTR(gcry_pk_encrypt);
+MAKE_FUNCPTR(gcry_mpi_new);
+MAKE_FUNCPTR(gcry_mpi_print);
+MAKE_FUNCPTR(gcry_sexp_release);
+MAKE_FUNCPTR(gcry_mpi_release);
+MAKE_FUNCPTR(gcry_strsource);
+MAKE_FUNCPTR(gcry_strerror);
+#if (GCRYPT_VERSION_NUMBER >= 0x010700)
+MAKE_FUNCPTR(gcry_sexp_extract_param);
+MAKE_FUNCPTR(gcry_mpi_point_new);
+MAKE_FUNCPTR(gcry_mpi_ec_decode_point);
+MAKE_FUNCPTR(gcry_mpi_point_snatch_get);
+#else
+MAKE_FUNCPTR(gcry_sexp_find_token);
+MAKE_FUNCPTR(gcry_sexp_nth_mpi);
+#endif
+#undef MAKE_FUNCPTR
+
+BOOL gcrypt_initialize(void)
+{
+ if (!(libgcrypt_handle = wine_dlopen( SONAME_LIBGCRYPT, RTLD_NOW, NULL, 0 )))
+ {
+ ERR_(winediag)( "failed to load libgcrypt, no support for diffie hellman key exchange\n" );
+ return FALSE;
+ }
+
+#define LOAD_FUNCPTR(f) \
+ if (!(p##f = wine_dlsym( libgcrypt_handle, #f, NULL, 0 ))) \
+ { \
+ ERR( "failed to load %s\n", #f ); \
+ goto fail; \
+ }
+
+ LOAD_FUNCPTR(gcry_sexp_build);
+ LOAD_FUNCPTR(gcry_pk_encrypt);
+ LOAD_FUNCPTR(gcry_mpi_new);
+ LOAD_FUNCPTR(gcry_mpi_print);
+ LOAD_FUNCPTR(gcry_sexp_release);
+ LOAD_FUNCPTR(gcry_mpi_release);
+ LOAD_FUNCPTR(gcry_strsource);
+ LOAD_FUNCPTR(gcry_strerror);
+#if (GCRYPT_VERSION_NUMBER >= 0x010700)
+ LOAD_FUNCPTR(gcry_sexp_extract_param);
+ LOAD_FUNCPTR(gcry_mpi_point_new);
+ LOAD_FUNCPTR(gcry_mpi_ec_decode_point);
+ LOAD_FUNCPTR(gcry_mpi_point_snatch_get);
+#else
+ LOAD_FUNCPTR(gcry_sexp_find_token);
+ LOAD_FUNCPTR(gcry_sexp_nth_mpi);
+#endif
+#undef LOAD_FUNCPTR
+
+ return TRUE;
+
+fail:
+ wine_dlclose( libgcrypt_handle, NULL, 0 );
+ libgcrypt_handle = NULL;
+ return FALSE;
+}
+
+
+void gcrypt_uninitialize(void)
+{
+ wine_dlclose( libgcrypt_handle, NULL, 0 );
+ libgcrypt_handle = NULL;
+}
+
+NTSTATUS extract_result_into_secret(gcry_sexp_t result, struct secret *secret)
+{
+ gcry_error_t err;
+ NTSTATUS status = STATUS_SUCCESS;
+#if (GCRYPT_VERSION_NUMBER >= 0x010700)
+ gcry_mpi_t result_mpi = NULL;
+ gcry_mpi_point_t result_point = NULL;
+ gcry_mpi_t secret_key = NULL;
+ UCHAR *tmp_buffer;
+ size_t size;
+
+ if ((err = pgcry_sexp_extract_param(result, "", "s", &result_mpi, NULL)))
+ {
+ ERR("Failed to extract result of key exchange\n");
+ goto done;
+ }
+
+ result_point = pgcry_mpi_point_new(0);
+
+ if ((err = pgcry_mpi_ec_decode_point(result_point, result_mpi, NULL)))
+ {
+ ERR("Failed decoding point from result\n");
+ goto done;
+ }
+
+ secret_key = pgcry_mpi_new(0);
+ if (!secret_key)
+ {
+ status = STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ /* releases result_point, (we don't need to free it later) */
+ pgcry_mpi_point_snatch_get(secret_key, NULL, NULL, result_point);
+
+ if ((err = pgcry_mpi_print(GCRYMPI_FMT_STD, NULL, 0, &size, secret_key)))
+ {
+ goto done;
+ }
+
+ tmp_buffer = heap_alloc(size);
+ if ((err = pgcry_mpi_print(GCRYMPI_FMT_STD, tmp_buffer, size, NULL, secret_key)))
+ {
+ heap_free(tmp_buffer);
+ goto done;
+ }
+
+ if (size % 2 == 0)
+ {
+ secret->data = tmp_buffer;
+ secret->len = size;
+ }
+ else
+ {
+ secret->data = heap_alloc(size - 1);
+ memcpy(secret->data, tmp_buffer + 1, size - 1);
+ secret->len = size - 1;
+ heap_free(tmp_buffer);
+ }
+
+ done:
+ pgcry_mpi_release(result_mpi);
+ pgcry_mpi_release(secret_key);
+#else
+ gcry_sexp_t fragment = NULL;
+ gcry_mpi_t fullcoords = NULL;
+ UCHAR *tmp_buffer, *pos;
+ size_t size;
+
+ fragment = pgcry_sexp_find_token(result, "s", 0);
+ if (!fragment)
+ {
+ status = STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ fullcoords = pgcry_sexp_nth_mpi(fragment, 1, GCRYMPI_FMT_USG);
+ if (!fullcoords)
+ {
+ status = STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ if ((err = pgcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &size, fullcoords)))
+ {
+ goto done;
+ }
+
+ tmp_buffer = heap_alloc(size);
+ if ((err = pgcry_mpi_print(GCRYMPI_FMT_STD, tmp_buffer, size, NULL, fullcoords)))
+ {
+ goto done;
+ }
+
+ secret->data = heap_alloc(size / 2);
+ memcpy(secret->data, tmp_buffer + size % 2, size / 2);
+ secret->len = size / 2;
+
+ done:
+ if (tmp_buffer)
+ {
+ heap_free(tmp_buffer);
+ }
+ pgcry_mpi_release(fullcoords);
+ pgcry_sexp_release(fragment);
+#endif
+ if (status)
+ {
+ return status;
+ }
+ if (err)
+ {
+ ERR("Error = %s/%s\n", pgcry_strsource (err), pgcry_strerror (err));
+ return STATUS_INTERNAL_ERROR;
+ }
+ return STATUS_SUCCESS;
+}
+
+/* this is necessary since GNUTLS doesn't support ECDH public key encryption, maybe we can replace this when it does:
+ https://github.com/gnutls/gnutls/blob/cdc4fc288d87f91f974aa23b6e8595a53970c… */
+NTSTATUS compute_secret_ecc (struct key *privkey_in, struct key *pubkey_in, struct secret *secret)
+{
+ const char *pubkey_format;
+ DWORD key_size;
+ gcry_sexp_t pubkey = NULL;
+ gcry_sexp_t privkey = NULL;
+ gcry_sexp_t xchg_result = NULL;
+ gcry_error_t err;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ switch (pubkey_in->alg_id)
+ {
+ case ALG_ID_ECDH_P256:
+ pubkey_format = "NIST P-256";
+ key_size = 32;
+ break;
+ default:
+ FIXME("Unsupported algorithm id: %u\n", pubkey_in->alg_id);
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ /* import public key -
+ copy public key into temporary buffer so we can prepend 0x04 (to indicate it is uncompressed) */
+ {
+ UCHAR *public_key_raw = heap_alloc((key_size * 2) + 1);
+ public_key_raw[0] = 0x04;
+ memcpy(public_key_raw + 1, pubkey_in->u.a.pubkey + sizeof(BCRYPT_ECCKEY_BLOB), key_size * 2);
+
+ err = pgcry_sexp_build(&pubkey, NULL,
+ "(key-data(public-key(ecdh(curve %s)(q %b))))",
+ pubkey_format,
+ (key_size * 2) + 1,
+ public_key_raw);
+
+ heap_free(public_key_raw);
+ }
+
+ if (err)
+ {
+ ERR("Failed to build gcrypt public key\n");
+ goto done;
+ }
+
+ /* import private key */
+ /* extract private key from blob structure */
+ {
+ UCHAR *private_key_raw = heap_alloc(key_size);
+ UCHAR *key_blob;
+ ULONG blob_size;
+
+ status = key_export_ecc( privkey_in, NULL, 0, &blob_size );
+ if (status)
+ goto done;
+
+ key_blob = heap_alloc(blob_size);
+ status = key_export_ecc( privkey_in, key_blob, blob_size, &blob_size);
+ if (status)
+ {
+ heap_free(private_key_raw);
+ heap_free(key_blob);
+ goto done;
+ }
+
+ memcpy(private_key_raw, key_blob + sizeof(BCRYPT_ECCKEY_BLOB) + key_size * 2, key_size);
+ heap_free(key_blob);
+
+ err = pgcry_sexp_build(&privkey, NULL,
+ "(data(flags raw)(value %b))",
+ key_size,
+ private_key_raw);
+
+ heap_free(private_key_raw);
+ }
+
+ if (err)
+ {
+ ERR("Failed to build gcrypt private key data\n");
+ goto done;
+ }
+
+ if ((err = pgcry_pk_encrypt(&xchg_result, privkey, pubkey)))
+ {
+ ERR("Failed to perform key exchange\n");
+ goto done;
+ }
+
+ status = extract_result_into_secret(xchg_result, secret);
+ if (status)
+ {
+ ERR("Failed to extract secret key\n");
+ goto done;
+ }
+
+ if (secret->len != key_size)
+ {
+ ERR("got secret size %u, expected %u\n", secret->len, key_size);
+ status = STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+
+ done:
+ pgcry_sexp_release(pubkey);
+ pgcry_sexp_release(privkey);
+ pgcry_sexp_release(xchg_result);
+
+ if (status)
+ {
+ return status;
+ }
+ if (err)
+ {
+ ERR("Error = %s/%s\n", pgcry_strsource (err), pgcry_strerror (err));
+ return STATUS_INTERNAL_ERROR;
+ }
+ return STATUS_SUCCESS;
+}
+#endif
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index 868f898bbb..d9680cb130 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -1297,4 +1297,13 @@ NTSTATUS key_destroy( struct key *key )
heap_free( key );
return STATUS_SUCCESS;
}
+
+#ifndef SONAME_LIBGCRYPT
+NTSTATUS compute_secret_ecc (struct key *pubkey_in, struct key *privkey_in, struct secret *secret)
+{
+ ERR("support for secrets not available without gcrypt\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+#endif
+
#endif
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index d26150f469..985a6f379b 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -2054,10 +2054,10 @@ static void test_ECDH(void)
ok(status == STATUS_SUCCESS, "got %08x\n", status);
status = pBCryptSecretAgreement(privkey, pubkey, &secret, 0);
- ok(status == STATUS_SUCCESS, "got %08x\n", status);
if (status != STATUS_SUCCESS)
{
+ skip("Secret key derivation not suppoted\n");
goto derive_end;
}
@@ -2070,7 +2070,7 @@ static void test_ECDH(void)
goto raw_secret_end;
}
- todo_wine ok(status == STATUS_SUCCESS, "got %08x\n", status);
+ ok(status == STATUS_SUCCESS, "got %08x\n", status);
if (status != STATUS_SUCCESS)
{
--
2.25.0
2
2
From: Puetz Kevin A <PuetzKevinA(a)JohnDeere.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/rpcrt4/ndr_typelib.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
1
0
27 Jan '20
Currently rounded parts are approximated with quadratic Bézier curves.
Signed-off-by: Giovanni Mascellani <gio(a)debian.org>
---
dlls/d2d1/d2d1_private.h | 13 ++
dlls/d2d1/factory.c | 22 ++-
dlls/d2d1/geometry.c | 310 +++++++++++++++++++++++++++++++++++++++
dlls/d2d1/tests/d2d1.c | 1 -
4 files changed, 342 insertions(+), 4 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 2e42d6d550..2c0a14a71f 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -483,6 +483,10 @@ struct d2d_geometry
D2D1_RECT_F rect;
} rectangle;
struct
+ {
+ D2D1_ROUNDED_RECT rounded_rect;
+ } rounded_rectangle;
+ struct
{
ID2D1Geometry *src_geometry;
D2D_MATRIX_3X2_F transform;
@@ -499,6 +503,8 @@ struct d2d_geometry
void d2d_path_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory) DECLSPEC_HIDDEN;
HRESULT d2d_rectangle_geometry_init(struct d2d_geometry *geometry,
ID2D1Factory *factory, const D2D1_RECT_F *rect) DECLSPEC_HIDDEN;
+HRESULT d2d_rounded_rectangle_geometry_init(struct d2d_geometry *geometry,
+ ID2D1Factory *factory, const D2D1_ROUNDED_RECT *rounded_rect) DECLSPEC_HIDDEN;
void d2d_transformed_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory,
ID2D1Geometry *src_geometry, const D2D_MATRIX_3X2_F *transform) DECLSPEC_HIDDEN;
HRESULT d2d_geometry_group_init(struct d2d_geometry *geometry, ID2D1Factory *factory,
@@ -620,4 +626,11 @@ static inline const char *debug_d2d_rect_f(const D2D1_RECT_F *rect)
return wine_dbg_sprintf("(%.8e,%.8e)-(%.8e,%.8e)", rect->left, rect->top, rect->right, rect->bottom );
}
+static inline const char *debug_d2d_rounded_rect(const D2D1_ROUNDED_RECT *rounded_rect)
+{
+ if (!rounded_rect) return "(null)";
+ return wine_dbg_sprintf("(%.8e,%.8e)-(%.8e,%.8e)[%.8e,%.8e]", rounded_rect->rect.left, rounded_rect->rect.top,
+ rounded_rect->rect.right, rounded_rect->rect.bottom, rounded_rect->radiusX, rounded_rect->radiusY );
+}
+
#endif /* __WINE_D2D1_PRIVATE_H */
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 48a2efb96b..86284f4ae4 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -152,11 +152,27 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateRectangleGeometry(ID2D1Factor
}
static HRESULT STDMETHODCALLTYPE d2d_factory_CreateRoundedRectangleGeometry(ID2D1Factory2 *iface,
- const D2D1_ROUNDED_RECT *rect, ID2D1RoundedRectangleGeometry **geometry)
+ const D2D1_ROUNDED_RECT *rounded_rect, ID2D1RoundedRectangleGeometry **geometry)
{
- FIXME("iface %p, rect %p, geometry %p stub!\n", iface, rect, geometry);
+ struct d2d_geometry *object;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("iface %p, rounded_rect %s, geometry %p.\n", iface, debug_d2d_rounded_rect(rounded_rect), geometry);
+
+ if (!(object = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d2d_rounded_rectangle_geometry_init(object, (ID2D1Factory *)iface, rounded_rect)))
+ {
+ WARN("Failed to initialize rounded rectangle geometry, hr %#x.\n", hr);
+ heap_free(object);
+ return hr;
+ }
+
+ TRACE("Created rounded rectangle geometry %p.\n", object);
+ *geometry = (ID2D1RoundedRectangleGeometry *)&object->ID2D1Geometry_iface;
+
+ return S_OK;
}
static HRESULT STDMETHODCALLTYPE d2d_factory_CreateEllipseGeometry(ID2D1Factory2 *iface,
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index 6697eccee4..072d360590 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -2257,6 +2257,14 @@ static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometr
return TRUE;
}
+static BOOL d2d_geometry_outline_add_arc_quadrant(struct d2d_geometry *geometry,
+ const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
+{
+ FIXME("Approximating arc quadrant with Bezier curve.\n");
+
+ return d2d_geometry_outline_add_bezier_segment(geometry, p0, p1, p2);
+}
+
static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry,
struct d2d_figure *figure, D2D1_FIGURE_END figure_end)
{
@@ -3840,6 +3848,307 @@ fail:
return E_OUTOFMEMORY;
}
+static inline struct d2d_geometry *impl_from_ID2D1RoundedRectangleGeometry(ID2D1RoundedRectangleGeometry *iface)
+{
+ return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_QueryInterface(ID2D1RoundedRectangleGeometry *iface,
+ REFIID iid, void **out)
+{
+ TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+ if (IsEqualGUID(iid, &IID_ID2D1RoundedRectangleGeometry)
+ || IsEqualGUID(iid, &IID_ID2D1Geometry)
+ || IsEqualGUID(iid, &IID_ID2D1Resource)
+ || IsEqualGUID(iid, &IID_IUnknown))
+ {
+ ID2D1RoundedRectangleGeometry_AddRef(iface);
+ *out = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_AddRef(ID2D1RoundedRectangleGeometry *iface)
+{
+ struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
+ ULONG refcount = InterlockedIncrement(&geometry->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Release(ID2D1RoundedRectangleGeometry *iface)
+{
+ struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
+ ULONG refcount = InterlockedDecrement(&geometry->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ d2d_geometry_cleanup(geometry);
+ heap_free(geometry);
+ }
+
+ return refcount;
+}
+
+static void STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetFactory(ID2D1RoundedRectangleGeometry *iface, ID2D1Factory **factory)
+{
+ struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
+
+ TRACE("iface %p, factory %p.\n", iface, factory);
+
+ ID2D1Factory_AddRef(*factory = geometry->factory);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetBounds(ID2D1RoundedRectangleGeometry *iface,
+ const D2D1_MATRIX_3X2_F *transform, D2D1_RECT_F *bounds)
+{
+ FIXME("iface %p, transform %p, bounds %p stub!\n", iface, transform, bounds);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetWidenedBounds(ID2D1RoundedRectangleGeometry *iface,
+ float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
+ float tolerance, D2D1_RECT_F *bounds)
+{
+ FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, bounds %p stub!\n",
+ iface, stroke_width, stroke_style, transform, tolerance, bounds);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_StrokeContainsPoint(ID2D1RoundedRectangleGeometry *iface,
+ D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
+ float tolerance, BOOL *contains)
+{
+ FIXME("iface %p, point %s, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, contains %p stub!\n",
+ iface, debug_d2d_point_2f(&point), stroke_width, stroke_style, transform, tolerance, contains);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_FillContainsPoint(ID2D1RoundedRectangleGeometry *iface,
+ D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
+{
+ FIXME("iface %p, point %s, transform %p, tolerance %.8e, contains %p stub!\n",
+ iface, debug_d2d_point_2f(&point), transform, tolerance, contains);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_CompareWithGeometry(ID2D1RoundedRectangleGeometry *iface,
+ ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
+{
+ FIXME("iface %p, geometry %p, transform %p, tolerance %.8e, relation %p stub!\n",
+ iface, geometry, transform, tolerance, relation);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Simplify(ID2D1RoundedRectangleGeometry *iface,
+ D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance,
+ ID2D1SimplifiedGeometrySink *sink)
+{
+ FIXME("iface %p, option %#x, transform %p, tolerance %.8e, sink %p stub!\n",
+ iface, option, transform, tolerance, sink);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Tessellate(ID2D1RoundedRectangleGeometry *iface,
+ const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
+{
+ FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_CombineWithGeometry(ID2D1RoundedRectangleGeometry *iface,
+ ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform,
+ float tolerance, ID2D1SimplifiedGeometrySink *sink)
+{
+ FIXME("iface %p, geometry %p, combine_mode %#x, transform %p, tolerance %.8e, sink %p stub!\n",
+ iface, geometry, combine_mode, transform, tolerance, sink);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Outline(ID2D1RoundedRectangleGeometry *iface,
+ const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
+{
+ FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_ComputeArea(ID2D1RoundedRectangleGeometry *iface,
+ const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
+{
+ FIXME("iface %p, transform %p, tolerance %.8e, area %p stub!\n", iface, transform, tolerance, area);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_ComputeLength(ID2D1RoundedRectangleGeometry *iface,
+ const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
+{
+ FIXME("iface %p, transform %p, tolerance %.8e, length %p stub!\n", iface, transform, tolerance, length);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_ComputePointAtLength(ID2D1RoundedRectangleGeometry *iface,
+ float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point,
+ D2D1_POINT_2F *tangent)
+{
+ FIXME("iface %p, length %.8e, transform %p, tolerance %.8e, point %p, tangent %p stub!\n",
+ iface, length, transform, tolerance, point, tangent);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Widen(ID2D1RoundedRectangleGeometry *iface, float stroke_width,
+ ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance,
+ ID2D1SimplifiedGeometrySink *sink)
+{
+ FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, sink %p stub!\n",
+ iface, stroke_width, stroke_style, transform, tolerance, sink);
+
+ return E_NOTIMPL;
+}
+
+static void STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetRoundedRect(ID2D1RoundedRectangleGeometry *iface, D2D1_ROUNDED_RECT *rounded_rect)
+{
+ struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
+
+ TRACE("iface %p, rounded_rect %p.\n", iface, rounded_rect);
+
+ *rounded_rect = geometry->u.rounded_rectangle.rounded_rect;
+}
+
+static const struct ID2D1RoundedRectangleGeometryVtbl d2d_rounded_rectangle_geometry_vtbl =
+{
+ d2d_rounded_rectangle_geometry_QueryInterface,
+ d2d_rounded_rectangle_geometry_AddRef,
+ d2d_rounded_rectangle_geometry_Release,
+ d2d_rounded_rectangle_geometry_GetFactory,
+ d2d_rounded_rectangle_geometry_GetBounds,
+ d2d_rounded_rectangle_geometry_GetWidenedBounds,
+ d2d_rounded_rectangle_geometry_StrokeContainsPoint,
+ d2d_rounded_rectangle_geometry_FillContainsPoint,
+ d2d_rounded_rectangle_geometry_CompareWithGeometry,
+ d2d_rounded_rectangle_geometry_Simplify,
+ d2d_rounded_rectangle_geometry_Tessellate,
+ d2d_rounded_rectangle_geometry_CombineWithGeometry,
+ d2d_rounded_rectangle_geometry_Outline,
+ d2d_rounded_rectangle_geometry_ComputeArea,
+ d2d_rounded_rectangle_geometry_ComputeLength,
+ d2d_rounded_rectangle_geometry_ComputePointAtLength,
+ d2d_rounded_rectangle_geometry_Widen,
+ d2d_rounded_rectangle_geometry_GetRoundedRect,
+};
+
+HRESULT d2d_rounded_rectangle_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory, const D2D1_ROUNDED_RECT *rounded_rect)
+{
+ struct d2d_face *f;
+ struct d2d_bezier_vertex *bv;
+ D2D1_POINT_2F *v, v1, v2, v3, v4;
+ float l, r, t, b;
+ float rX, rY;
+
+ d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_rounded_rectangle_geometry_vtbl);
+ geometry->u.rounded_rectangle.rounded_rect = *rounded_rect;
+
+ if (!(geometry->fill.vertices = heap_alloc(8 * sizeof(*geometry->fill.vertices))))
+ goto fail;
+ if (!d2d_array_reserve((void **)&geometry->fill.faces,
+ &geometry->fill.faces_size, 6, sizeof(*geometry->fill.faces)))
+ goto fail;
+ if (!(geometry->fill.bezier_vertices = heap_alloc(12 * sizeof(*geometry->fill.bezier_vertices))))
+ goto fail;
+
+ l = min(rounded_rect->rect.left, rounded_rect->rect.right);
+ r = max(rounded_rect->rect.left, rounded_rect->rect.right);
+ t = min(rounded_rect->rect.top, rounded_rect->rect.bottom);
+ b = max(rounded_rect->rect.top, rounded_rect->rect.bottom);
+
+ rX = min(rounded_rect->radiusX, 0.5f*(r-l));
+ rY = min(rounded_rect->radiusY, 0.5f*(b-t));
+
+ d2d_point_set(&v1, r, t);
+ d2d_point_set(&v2, r, b);
+ d2d_point_set(&v3, l, b);
+ d2d_point_set(&v4, l, t);
+
+ v = geometry->fill.vertices;
+ d2d_point_set(&v[0], l+rX, t);
+ d2d_point_set(&v[1], r-rX, t);
+ d2d_point_set(&v[2], r, t+rY);
+ d2d_point_set(&v[3], r, b-rY);
+ d2d_point_set(&v[4], r-rX, b);
+ d2d_point_set(&v[5], l+rX, b);
+ d2d_point_set(&v[6], l, b-rY);
+ d2d_point_set(&v[7], l, t+rY);
+ geometry->fill.vertex_count = 8;
+
+ f = geometry->fill.faces;
+ d2d_face_set(&f[0], 0, 7, 6);
+ d2d_face_set(&f[1], 0, 6, 5);
+ d2d_face_set(&f[2], 0, 5, 4);
+ d2d_face_set(&f[3], 0, 4, 1);
+ d2d_face_set(&f[4], 1, 4, 3);
+ d2d_face_set(&f[5], 1, 3, 2);
+ geometry->fill.face_count = 6;
+
+ bv = geometry->fill.bezier_vertices;
+ d2d_bezier_vertex_set(&bv[0], &v[1], 0.0f, 0.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[1], &v1, 0.5f, 0.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[2], &v[2], 1.0f, 1.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[3], &v[3], 0.0f, 0.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[4], &v2, 0.5f, 0.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[5], &v[4], 1.0f, 1.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[6], &v[5], 0.0f, 0.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[7], &v3, 0.5f, 0.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[8], &v[6], 1.0f, 1.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[9], &v[7], 0.0f, 0.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[10], &v4, 0.5f, 0.0f, -1.0f);
+ d2d_bezier_vertex_set(&bv[11], &v[0], 1.0f, 1.0f, -1.0f);
+ geometry->fill.bezier_vertex_count = 12;
+
+ if (!d2d_geometry_outline_add_line_segment(geometry, &v[0], &v[1]))
+ goto fail;
+ if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[1], &v1, &v[2]))
+ goto fail;
+ if (!d2d_geometry_outline_add_line_segment(geometry, &v[2], &v[3]))
+ goto fail;
+ if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[3], &v2, &v[4]))
+ goto fail;
+ if (!d2d_geometry_outline_add_line_segment(geometry, &v[4], &v[5]))
+ goto fail;
+ if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[5], &v3, &v[6]))
+ goto fail;
+ if (!d2d_geometry_outline_add_line_segment(geometry, &v[6], &v[7]))
+ goto fail;
+ if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[7], &v4, &v[0]))
+ goto fail;
+
+ return S_OK;
+
+fail:
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+}
+
static inline struct d2d_geometry *impl_from_ID2D1TransformedGeometry(ID2D1TransformedGeometry *iface)
{
return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
@@ -4385,6 +4694,7 @@ struct d2d_geometry *unsafe_impl_from_ID2D1Geometry(ID2D1Geometry *iface)
return NULL;
assert(iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_path_geometry_vtbl
|| iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_rectangle_geometry_vtbl
+ || iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_rounded_rectangle_geometry_vtbl
|| iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_transformed_geometry_vtbl
|| iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_geometry_group_vtbl);
return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 5377c4ea34..d2d59dbcba 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -3790,7 +3790,6 @@ static void test_rounded_rectangle_geometry(void)
set_rounded_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
-todo_wine
ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
if (FAILED(hr))
{
--
2.25.0
2
3
[PATCH 2/3] d2d1: Pass previous and next vectors to d2d_geometry_outline_add_join().
by Henri Verbeet 27 Jan '20
by Henri Verbeet 27 Jan '20
27 Jan '20
Instead of the points.
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/d2d1/geometry.c | 90 +++++++++++++++++++++++++++++-----------------------
1 file changed, 50 insertions(+), 40 deletions(-)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index 6697eccee46..6adf50e7c4d 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -2090,7 +2090,7 @@ static BOOL d2d_path_geometry_add_figure(struct d2d_geometry *geometry)
static BOOL d2d_geometry_outline_add_join(struct d2d_geometry *geometry,
const D2D1_POINT_2F *prev, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *next)
{
- D2D1_POINT_2F q_prev, q_next;
+ static const D2D1_POINT_2F origin = {0.0f, 0.0f};
struct d2d_outline_vertex *v;
struct d2d_face *f;
size_t base_idx;
@@ -2113,35 +2113,29 @@ static BOOL d2d_geometry_outline_add_join(struct d2d_geometry *geometry,
}
f = &geometry->outline.faces[geometry->outline.face_count];
- d2d_point_subtract(&q_prev, p0, prev);
- d2d_point_subtract(&q_next, next, p0);
-
- d2d_point_normalise(&q_prev);
- d2d_point_normalise(&q_next);
-
- ccw = d2d_point_ccw(p0, prev, next);
+ ccw = d2d_point_ccw(&origin, prev, next);
if (ccw == 0.0f)
{
- d2d_outline_vertex_set(&v[0], p0->x, p0->y, q_prev.x, q_prev.y, q_prev.x, q_prev.y);
- d2d_outline_vertex_set(&v[1], p0->x, p0->y, -q_prev.x, -q_prev.y, -q_prev.x, -q_prev.y);
- d2d_outline_vertex_set(&v[2], p0->x + 25.0f * q_prev.x, p0->y + 25.0f * q_prev.y,
- -q_prev.x, -q_prev.y, -q_prev.x, -q_prev.y);
- d2d_outline_vertex_set(&v[3], p0->x + 25.0f * q_prev.x, p0->y + 25.0f * q_prev.y,
- q_prev.x, q_prev.y, q_prev.x, q_prev.y);
+ d2d_outline_vertex_set(&v[0], p0->x, p0->y, -prev->x, -prev->y, -prev->x, -prev->y);
+ d2d_outline_vertex_set(&v[1], p0->x, p0->y, prev->x, prev->y, prev->x, prev->y);
+ d2d_outline_vertex_set(&v[2], p0->x + 25.0f * -prev->x, p0->y + 25.0f * -prev->y,
+ prev->x, prev->y, prev->x, prev->y);
+ d2d_outline_vertex_set(&v[3], p0->x + 25.0f * -prev->x, p0->y + 25.0f * -prev->y,
+ -prev->x, -prev->y, -prev->x, -prev->y);
}
else if (ccw < 0.0f)
{
- d2d_outline_vertex_set(&v[0], p0->x, p0->y, q_next.x, q_next.y, q_prev.x, q_prev.y);
- d2d_outline_vertex_set(&v[1], p0->x, p0->y, -q_next.x, -q_next.y, -q_next.x, -q_next.y);
- d2d_outline_vertex_set(&v[2], p0->x, p0->y, -q_next.x, -q_next.y, -q_prev.x, -q_prev.y);
- d2d_outline_vertex_set(&v[3], p0->x, p0->y, -q_prev.x, -q_prev.y, -q_prev.x, -q_prev.y);
+ d2d_outline_vertex_set(&v[0], p0->x, p0->y, next->x, next->y, -prev->x, -prev->y);
+ d2d_outline_vertex_set(&v[1], p0->x, p0->y, -next->x, -next->y, -next->x, -next->y);
+ d2d_outline_vertex_set(&v[2], p0->x, p0->y, -next->x, -next->y, prev->x, prev->y);
+ d2d_outline_vertex_set(&v[3], p0->x, p0->y, prev->x, prev->y, prev->x, prev->y);
}
else
{
- d2d_outline_vertex_set(&v[0], p0->x, p0->y, -q_prev.x, -q_prev.y, -q_next.x, -q_next.y);
- d2d_outline_vertex_set(&v[1], p0->x, p0->y, q_prev.x, q_prev.y, q_prev.x, q_prev.y);
- d2d_outline_vertex_set(&v[2], p0->x, p0->y, q_prev.x, q_prev.y, q_next.x, q_next.y);
- d2d_outline_vertex_set(&v[3], p0->x, p0->y, q_next.x, q_next.y, q_next.x, q_next.y);
+ d2d_outline_vertex_set(&v[0], p0->x, p0->y, prev->x, prev->y, -next->x, -next->y);
+ d2d_outline_vertex_set(&v[1], p0->x, p0->y, -prev->x, -prev->y, -prev->x, -prev->y);
+ d2d_outline_vertex_set(&v[2], p0->x, p0->y, -prev->x, -prev->y, next->x, next->y);
+ d2d_outline_vertex_set(&v[3], p0->x, p0->y, next->x, next->y, next->x, next->y);
}
geometry->outline.vertex_count += 4;
@@ -2296,11 +2290,21 @@ static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry,
else
next = &figure->vertices[i + 1];
- if ((figure_end == D2D1_FIGURE_END_CLOSED || (i && i < figure->vertex_count - 1))
- && !d2d_geometry_outline_add_join(geometry, prev, p0, next))
+ if (figure_end == D2D1_FIGURE_END_CLOSED || (i && i < figure->vertex_count - 1))
{
- ERR("Failed to add join.\n");
- return FALSE;
+ D2D1_POINT_2F q_next, q_prev;
+
+ d2d_point_subtract(&q_prev, prev, p0);
+ d2d_point_subtract(&q_next, next, p0);
+
+ d2d_point_normalise(&q_prev);
+ d2d_point_normalise(&q_next);
+
+ if (!d2d_geometry_outline_add_join(geometry, &q_prev, p0, &q_next))
+ {
+ ERR("Failed to add join.\n");
+ return FALSE;
+ }
}
if (type == D2D_VERTEX_TYPE_LINE && (figure_end == D2D1_FIGURE_END_CLOSED || i < figure->vertex_count - 1)
@@ -3777,9 +3781,24 @@ static const struct ID2D1RectangleGeometryVtbl d2d_rectangle_geometry_vtbl =
HRESULT d2d_rectangle_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory, const D2D1_RECT_F *rect)
{
struct d2d_face *f;
- D2D1_POINT_2F *v, v0p, v0n, v1p, v1n, v2p, v2n, v3p, v3n;
+ D2D1_POINT_2F *v;
float l, r, t, b;
+ static const D2D1_POINT_2F prev[] =
+ {
+ { 1.0f, 0.0f},
+ { 0.0f, -1.0f},
+ {-1.0f, 0.0f},
+ { 0.0f, 1.0f},
+ };
+ static const D2D1_POINT_2F next[] =
+ {
+ { 0.0f, 1.0f},
+ { 1.0f, 0.0f},
+ { 0.0f, -1.0f},
+ {-1.0f, 0.0f},
+ };
+
d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_rectangle_geometry_vtbl);
geometry->u.rectangle.rect = *rect;
@@ -3806,15 +3825,6 @@ HRESULT d2d_rectangle_geometry_init(struct d2d_geometry *geometry, ID2D1Factory
d2d_face_set(&f[1], 0, 2, 3);
geometry->fill.face_count = 2;
- d2d_point_set(&v0p, l+1.0f, t);
- d2d_point_set(&v0n, l, t+1.0f);
- d2d_point_set(&v1p, l, b-1.0f);
- d2d_point_set(&v1n, l+1.0f, b);
- d2d_point_set(&v2p, r-1.0f, b);
- d2d_point_set(&v2n, r, b-1.0f);
- d2d_point_set(&v3p, r, t+1.0f);
- d2d_point_set(&v3n, r-1.0f, t);
-
if (!d2d_geometry_outline_add_line_segment(geometry, &v[0], &v[1]))
goto fail;
if (!d2d_geometry_outline_add_line_segment(geometry, &v[1], &v[2]))
@@ -3824,13 +3834,13 @@ HRESULT d2d_rectangle_geometry_init(struct d2d_geometry *geometry, ID2D1Factory
if (!d2d_geometry_outline_add_line_segment(geometry, &v[3], &v[0]))
goto fail;
- if (!d2d_geometry_outline_add_join(geometry, &v0p, &v[0], &v0n))
+ if (!d2d_geometry_outline_add_join(geometry, &prev[0], &v[0], &next[0]))
goto fail;
- if (!d2d_geometry_outline_add_join(geometry, &v1p, &v[1], &v1n))
+ if (!d2d_geometry_outline_add_join(geometry, &prev[1], &v[1], &next[1]))
goto fail;
- if (!d2d_geometry_outline_add_join(geometry, &v2p, &v[2], &v2n))
+ if (!d2d_geometry_outline_add_join(geometry, &prev[2], &v[2], &next[2]))
goto fail;
- if (!d2d_geometry_outline_add_join(geometry, &v3p, &v[3], &v3n))
+ if (!d2d_geometry_outline_add_join(geometry, &prev[3], &v[3], &next[3]))
goto fail;
return S_OK;
--
2.11.0
3
2