d2d1/tests: Add some tests for ID2D1DeviceContext::CreateImageBrush().
[wine.git] / dlls / d2d1 / tests / d2d1.c
blob035915491fdea0557f80bb03b738b328735d911f
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
20 #include <limits.h>
21 #include <math.h>
22 #include <float.h>
23 #include "d2d1_3.h"
24 #include "d3d11.h"
25 #include "wincrypt.h"
26 #include "wine/test.h"
27 #include "initguid.h"
28 #include "dwrite.h"
29 #include "wincodec.h"
30 #include "wine/heap.h"
32 static HRESULT (WINAPI *pD2D1CreateDevice)(IDXGIDevice *dxgi_device,
33 const D2D1_CREATION_PROPERTIES *properties, ID2D1Device **device);
34 static void (WINAPI *pD2D1SinCos)(float angle, float *s, float *c);
35 static float (WINAPI *pD2D1Tan)(float angle);
36 static float (WINAPI *pD2D1Vec3Length)(float x, float y, float z);
37 static D2D1_COLOR_F (WINAPI *pD2D1ConvertColorSpace)(D2D1_COLOR_SPACE src_colour_space,
38 D2D1_COLOR_SPACE dst_colour_space, const D2D1_COLOR_F *colour);
40 static BOOL use_mt = TRUE;
42 static struct test_entry
44 void (*test)(BOOL d3d11);
45 BOOL d3d11;
46 } *mt_tests;
47 size_t mt_tests_size, mt_test_count;
49 struct d2d1_test_context
51 BOOL d3d11;
52 IDXGIDevice *device;
53 HWND window;
54 IDXGISwapChain *swapchain;
55 IDXGISurface *surface;
56 ID2D1RenderTarget *rt;
59 struct resource_readback
61 BOOL d3d11;
62 union
64 ID3D10Resource *d3d10_resource;
65 ID3D11Resource *d3d11_resource;
66 } u;
67 unsigned int pitch, width, height;
68 void *data;
71 struct figure
73 unsigned int *spans;
74 unsigned int spans_size;
75 unsigned int span_count;
78 struct geometry_sink
80 ID2D1SimplifiedGeometrySink ID2D1SimplifiedGeometrySink_iface;
82 struct geometry_figure
84 D2D1_FIGURE_BEGIN begin;
85 D2D1_FIGURE_END end;
86 D2D1_POINT_2F start_point;
87 struct geometry_segment
89 enum
91 SEGMENT_BEZIER,
92 SEGMENT_LINE,
93 } type;
94 union
96 D2D1_BEZIER_SEGMENT bezier;
97 D2D1_POINT_2F line;
98 } u;
99 DWORD flags;
100 } *segments;
101 unsigned int segments_size;
102 unsigned int segment_count;
103 } *figures;
104 unsigned int figures_size;
105 unsigned int figure_count;
107 D2D1_FILL_MODE fill_mode;
108 DWORD segment_flags;
109 BOOL closed;
112 struct expected_geometry_figure
114 D2D1_FIGURE_BEGIN begin;
115 D2D1_FIGURE_END end;
116 D2D1_POINT_2F start_point;
117 unsigned int segment_count;
118 const struct geometry_segment *segments;
121 static void queue_d3d1x_test(void (*test)(BOOL d3d11), BOOL d3d11)
123 if (mt_test_count >= mt_tests_size)
125 mt_tests_size = max(16, mt_tests_size * 2);
126 mt_tests = heap_realloc(mt_tests, mt_tests_size * sizeof(*mt_tests));
128 mt_tests[mt_test_count].test = test;
129 mt_tests[mt_test_count++].d3d11 = d3d11;
132 static void queue_d3d10_test(void (*test)(BOOL d3d11))
134 queue_d3d1x_test(test, FALSE);
137 static void queue_test(void (*test)(BOOL d3d11))
139 queue_d3d1x_test(test, FALSE);
140 queue_d3d1x_test(test, TRUE);
143 static DWORD WINAPI thread_func(void *ctx)
145 LONG *i = ctx, j;
147 while (*i < mt_test_count)
149 j = *i;
150 if (InterlockedCompareExchange(i, j + 1, j) == j)
151 mt_tests[j].test(mt_tests[j].d3d11);
154 return 0;
157 static void run_queued_tests(void)
159 unsigned int thread_count, i;
160 HANDLE *threads;
161 SYSTEM_INFO si;
162 LONG test_idx;
164 if (!use_mt)
166 for (i = 0; i < mt_test_count; ++i)
168 mt_tests[i].test(mt_tests[i].d3d11);
171 return;
174 GetSystemInfo(&si);
175 thread_count = si.dwNumberOfProcessors;
176 threads = heap_calloc(thread_count, sizeof(*threads));
177 for (i = 0, test_idx = 0; i < thread_count; ++i)
179 threads[i] = CreateThread(NULL, 0, thread_func, &test_idx, 0, NULL);
180 ok(!!threads[i], "Failed to create thread %u.\n", i);
182 WaitForMultipleObjects(thread_count, threads, TRUE, INFINITE);
183 for (i = 0; i < thread_count; ++i)
185 CloseHandle(threads[i]);
187 heap_free(threads);
190 static void set_point(D2D1_POINT_2F *point, float x, float y)
192 point->x = x;
193 point->y = y;
196 static void set_quadratic(D2D1_QUADRATIC_BEZIER_SEGMENT *quadratic, float x1, float y1, float x2, float y2)
198 quadratic->point1.x = x1;
199 quadratic->point1.y = y1;
200 quadratic->point2.x = x2;
201 quadratic->point2.y = y2;
204 static void set_rect(D2D1_RECT_F *rect, float left, float top, float right, float bottom)
206 rect->left = left;
207 rect->top = top;
208 rect->right = right;
209 rect->bottom = bottom;
212 static void set_rounded_rect(D2D1_ROUNDED_RECT *rect, float left, float top, float right, float bottom,
213 float radius_x, float radius_y)
215 set_rect(&rect->rect, left, top, right, bottom);
216 rect->radiusX = radius_x;
217 rect->radiusY = radius_y;
220 static void set_rect_u(D2D1_RECT_U *rect, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
222 rect->left = left;
223 rect->top = top;
224 rect->right = right;
225 rect->bottom = bottom;
228 static void set_ellipse(D2D1_ELLIPSE *ellipse, float x, float y, float rx, float ry)
230 set_point(&ellipse->point, x, y);
231 ellipse->radiusX = rx;
232 ellipse->radiusY = ry;
235 static void set_color(D2D1_COLOR_F *color, float r, float g, float b, float a)
237 color->r = r;
238 color->g = g;
239 color->b = b;
240 color->a = a;
243 static void set_size_u(D2D1_SIZE_U *size, unsigned int w, unsigned int h)
245 size->width = w;
246 size->height = h;
249 static void set_size_f(D2D1_SIZE_F *size, float w, float h)
251 size->width = w;
252 size->height = h;
255 static void set_matrix_identity(D2D1_MATRIX_3X2_F *matrix)
257 matrix->_11 = 1.0f;
258 matrix->_12 = 0.0f;
259 matrix->_21 = 0.0f;
260 matrix->_22 = 1.0f;
261 matrix->_31 = 0.0f;
262 matrix->_32 = 0.0f;
265 static void rotate_matrix(D2D1_MATRIX_3X2_F *matrix, float theta)
267 float sin_theta, cos_theta, tmp_11, tmp_12;
269 sin_theta = sinf(theta);
270 cos_theta = cosf(theta);
271 tmp_11 = matrix->_11;
272 tmp_12 = matrix->_12;
274 matrix->_11 = cos_theta * tmp_11 + sin_theta * matrix->_21;
275 matrix->_12 = cos_theta * tmp_12 + sin_theta * matrix->_22;
276 matrix->_21 = -sin_theta * tmp_11 + cos_theta * matrix->_21;
277 matrix->_22 = -sin_theta * tmp_12 + cos_theta * matrix->_22;
280 static void skew_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
282 float tmp_11, tmp_12;
284 tmp_11 = matrix->_11;
285 tmp_12 = matrix->_12;
287 matrix->_11 += y * matrix->_21;
288 matrix->_12 += y * matrix->_22;
289 matrix->_21 += x * tmp_11;
290 matrix->_22 += x * tmp_12;
293 static void scale_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
295 matrix->_11 *= x;
296 matrix->_12 *= x;
297 matrix->_21 *= y;
298 matrix->_22 *= y;
301 static void translate_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
303 matrix->_31 += x * matrix->_11 + y * matrix->_21;
304 matrix->_32 += x * matrix->_12 + y * matrix->_22;
307 static void line_to(ID2D1GeometrySink *sink, float x, float y)
309 D2D1_POINT_2F point;
311 set_point(&point, x, y);
312 ID2D1GeometrySink_AddLine(sink, point);
315 static void quadratic_to(ID2D1GeometrySink *sink, float x1, float y1, float x2, float y2)
317 D2D1_QUADRATIC_BEZIER_SEGMENT quadratic;
319 set_quadratic(&quadratic, x1, y1, x2, y2);
320 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
323 static void cubic_to(ID2D1GeometrySink *sink, float x1, float y1, float x2, float y2, float x3, float y3)
325 D2D1_BEZIER_SEGMENT b;
327 b.point1.x = x1;
328 b.point1.y = y1;
329 b.point2.x = x2;
330 b.point2.y = y2;
331 b.point3.x = x3;
332 b.point3.y = y3;
333 ID2D1GeometrySink_AddBezier(sink, &b);
336 static void get_d3d10_surface_readback(IDXGISurface *surface, struct resource_readback *rb)
338 D3D10_TEXTURE2D_DESC texture_desc;
339 D3D10_MAPPED_TEXTURE2D map_desc;
340 DXGI_SURFACE_DESC surface_desc;
341 ID3D10Resource *src_resource;
342 ID3D10Device *device;
343 HRESULT hr;
345 hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
346 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
347 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
348 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
350 hr = IDXGISurface_GetDesc(surface, &surface_desc);
351 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
352 texture_desc.Width = surface_desc.Width;
353 texture_desc.Height = surface_desc.Height;
354 texture_desc.MipLevels = 1;
355 texture_desc.ArraySize = 1;
356 texture_desc.Format = surface_desc.Format;
357 texture_desc.SampleDesc = surface_desc.SampleDesc;
358 texture_desc.Usage = D3D10_USAGE_STAGING;
359 texture_desc.BindFlags = 0;
360 texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
361 texture_desc.MiscFlags = 0;
362 hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D10Texture2D **)&rb->u.d3d10_resource);
363 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
365 rb->width = texture_desc.Width;
366 rb->height = texture_desc.Height;
368 ID3D10Device_CopyResource(device, rb->u.d3d10_resource, src_resource);
369 ID3D10Resource_Release(src_resource);
370 ID3D10Device_Release(device);
372 hr = ID3D10Texture2D_Map((ID3D10Texture2D *)rb->u.d3d10_resource, 0, D3D10_MAP_READ, 0, &map_desc);
373 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
375 rb->pitch = map_desc.RowPitch;
376 rb->data = map_desc.pData;
379 static void get_d3d11_surface_readback(IDXGISurface *surface, struct resource_readback *rb)
381 D3D11_TEXTURE2D_DESC texture_desc;
382 D3D11_MAPPED_SUBRESOURCE map_desc;
383 DXGI_SURFACE_DESC surface_desc;
384 ID3D11Resource *src_resource;
385 ID3D11DeviceContext *context;
386 ID3D11Device *device;
387 HRESULT hr;
389 hr = IDXGISurface_GetDevice(surface, &IID_ID3D11Device, (void **)&device);
390 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
391 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D11Resource, (void **)&src_resource);
392 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
394 hr = IDXGISurface_GetDesc(surface, &surface_desc);
395 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
396 texture_desc.Width = surface_desc.Width;
397 texture_desc.Height = surface_desc.Height;
398 texture_desc.MipLevels = 1;
399 texture_desc.ArraySize = 1;
400 texture_desc.Format = surface_desc.Format;
401 texture_desc.SampleDesc = surface_desc.SampleDesc;
402 texture_desc.Usage = D3D11_USAGE_STAGING;
403 texture_desc.BindFlags = 0;
404 texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
405 texture_desc.MiscFlags = 0;
406 hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D11Texture2D **)&rb->u.d3d11_resource);
407 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
409 rb->width = texture_desc.Width;
410 rb->height = texture_desc.Height;
412 ID3D11Device_GetImmediateContext(device, &context);
413 ID3D11DeviceContext_CopyResource(context, rb->u.d3d11_resource, src_resource);
414 ID3D11Resource_Release(src_resource);
415 ID3D11Device_Release(device);
417 hr = ID3D11DeviceContext_Map(context, rb->u.d3d11_resource, 0, D3D11_MAP_READ, 0, &map_desc);
418 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
419 ID3D11DeviceContext_Release(context);
421 rb->pitch = map_desc.RowPitch;
422 rb->data = map_desc.pData;
425 static void get_surface_readback(struct d2d1_test_context *ctx, struct resource_readback *rb)
427 if ((rb->d3d11 = ctx->d3d11))
428 get_d3d11_surface_readback(ctx->surface, rb);
429 else
430 get_d3d10_surface_readback(ctx->surface, rb);
433 static void release_d3d10_resource_readback(struct resource_readback *rb)
435 ID3D10Texture2D_Unmap((ID3D10Texture2D *)rb->u.d3d10_resource, 0);
436 ID3D10Resource_Release(rb->u.d3d10_resource);
439 static void release_d3d11_resource_readback(struct resource_readback *rb)
441 ID3D11DeviceContext *context;
442 ID3D11Device *device;
444 ID3D11Resource_GetDevice(rb->u.d3d11_resource, &device);
445 ID3D11Device_GetImmediateContext(device, &context);
446 ID3D11Device_Release(device);
448 ID3D11DeviceContext_Unmap(context, rb->u.d3d11_resource, 0);
449 ID3D11Resource_Release(rb->u.d3d11_resource);
450 ID3D11DeviceContext_Release(context);
453 static void release_resource_readback(struct resource_readback *rb)
455 if (rb->d3d11)
456 release_d3d11_resource_readback(rb);
457 else
458 release_d3d10_resource_readback(rb);
461 static DWORD get_readback_colour(struct resource_readback *rb, unsigned int x, unsigned int y)
463 return ((DWORD *)((BYTE *)rb->data + y * rb->pitch))[x];
466 static float clamp_float(float f, float lower, float upper)
468 return f < lower ? lower : f > upper ? upper : f;
471 static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
473 unsigned int diff = x > y ? x - y : y - x;
475 return diff <= max_diff;
478 static BOOL compare_colour(DWORD c1, DWORD c2, BYTE max_diff)
480 return compare_uint(c1 & 0xff, c2 & 0xff, max_diff)
481 && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff)
482 && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff)
483 && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
486 static BOOL compare_float(float f, float g, unsigned int ulps)
488 int x = *(int *)&f;
489 int y = *(int *)&g;
491 if (x < 0)
492 x = INT_MIN - x;
493 if (y < 0)
494 y = INT_MIN - y;
496 if (abs(x - y) > ulps)
497 return FALSE;
499 return TRUE;
502 static BOOL compare_colour_f(const D2D1_COLOR_F *colour, float r, float g, float b, float a, unsigned int ulps)
504 return compare_float(colour->r, r, ulps)
505 && compare_float(colour->g, g, ulps)
506 && compare_float(colour->b, b, ulps)
507 && compare_float(colour->a, a, ulps);
510 static BOOL compare_point(const D2D1_POINT_2F *point, float x, float y, unsigned int ulps)
512 return compare_float(point->x, x, ulps)
513 && compare_float(point->y, y, ulps);
516 static BOOL compare_rect(const D2D1_RECT_F *rect, float left, float top, float right, float bottom, unsigned int ulps)
518 return compare_float(rect->left, left, ulps)
519 && compare_float(rect->top, top, ulps)
520 && compare_float(rect->right, right, ulps)
521 && compare_float(rect->bottom, bottom, ulps);
524 static BOOL compare_bezier_segment(const D2D1_BEZIER_SEGMENT *b, float x1, float y1,
525 float x2, float y2, float x3, float y3, unsigned int ulps)
527 return compare_point(&b->point1, x1, y1, ulps)
528 && compare_point(&b->point2, x2, y2, ulps)
529 && compare_point(&b->point3, x3, y3, ulps);
532 static BOOL compare_sha1(void *data, unsigned int pitch, unsigned int bpp,
533 unsigned int w, unsigned int h, const char *ref_sha1)
535 static const char hex_chars[] = "0123456789abcdef";
536 HCRYPTPROV provider;
537 BYTE hash_data[20];
538 HCRYPTHASH hash;
539 DWORD hash_size;
540 unsigned int i;
541 char sha1[41];
542 BOOL ret;
544 ret = CryptAcquireContextW(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
545 ok(ret, "Failed to acquire crypt context.\n");
546 ret = CryptCreateHash(provider, CALG_SHA1, 0, 0, &hash);
547 ok(ret, "Failed to create hash.\n");
549 for (i = 0; i < h; ++i)
551 if (!(ret = CryptHashData(hash, (BYTE *)data + pitch * i, w * bpp, 0)))
552 break;
554 ok(ret, "Failed to hash data.\n");
556 hash_size = sizeof(hash_data);
557 ret = CryptGetHashParam(hash, HP_HASHVAL, hash_data, &hash_size, 0);
558 ok(ret, "Failed to get hash value.\n");
559 ok(hash_size == sizeof(hash_data), "Got unexpected hash size %lu.\n", hash_size);
561 ret = CryptDestroyHash(hash);
562 ok(ret, "Failed to destroy hash.\n");
563 ret = CryptReleaseContext(provider, 0);
564 ok(ret, "Failed to release crypt context.\n");
566 for (i = 0; i < 20; ++i)
568 sha1[i * 2] = hex_chars[hash_data[i] >> 4];
569 sha1[i * 2 + 1] = hex_chars[hash_data[i] & 0xf];
571 sha1[40] = 0;
573 return !strcmp(ref_sha1, (char *)sha1);
576 static BOOL compare_surface(struct d2d1_test_context *ctx, const char *ref_sha1)
578 struct resource_readback rb;
579 BOOL ret;
581 get_surface_readback(ctx, &rb);
582 ret = compare_sha1(rb.data, rb.pitch, 4, rb.width, rb.height, ref_sha1);
583 release_resource_readback(&rb);
585 return ret;
588 static BOOL compare_wic_bitmap(IWICBitmap *bitmap, const char *ref_sha1)
590 UINT stride, width, height, buffer_size;
591 IWICBitmapLock *lock;
592 BYTE *data;
593 HRESULT hr;
594 BOOL ret;
596 hr = IWICBitmap_Lock(bitmap, NULL, WICBitmapLockRead, &lock);
597 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
599 hr = IWICBitmapLock_GetDataPointer(lock, &buffer_size, &data);
600 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
602 hr = IWICBitmapLock_GetStride(lock, &stride);
603 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
605 hr = IWICBitmapLock_GetSize(lock, &width, &height);
606 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
608 ret = compare_sha1(data, stride, 4, width, height, ref_sha1);
610 IWICBitmapLock_Release(lock);
612 return ret;
615 static void serialize_figure(struct figure *figure)
617 static const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
618 unsigned int i, j, k, span;
619 char output[76];
620 char t[3];
621 char *p;
623 for (i = 0, j = 0, k = 0, p = output; i < figure->span_count; ++i)
625 span = figure->spans[i];
626 while (span)
628 t[j] = span & 0x7f;
629 if (span > 0x7f)
630 t[j] |= 0x80;
631 span >>= 7;
632 if (++j == 3)
634 p[0] = lookup[(t[0] & 0xfc) >> 2];
635 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
636 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
637 p[3] = lookup[t[2] & 0x3f];
638 p += 4;
639 if (++k == 19)
641 trace("%.76s\n", output);
642 p = output;
643 k = 0;
645 j = 0;
649 if (j)
651 for (i = j; i < 3; ++i)
652 t[i] = 0;
653 p[0] = lookup[(t[0] & 0xfc) >> 2];
654 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
655 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
656 p[3] = lookup[t[2] & 0x3f];
657 ++k;
659 if (k)
660 trace("%.*s\n", k * 4, output);
663 static void figure_add_span(struct figure *figure, unsigned int span)
665 if (figure->span_count == figure->spans_size)
667 figure->spans_size *= 2;
668 figure->spans = HeapReAlloc(GetProcessHeap(), 0, figure->spans,
669 figure->spans_size * sizeof(*figure->spans));
672 figure->spans[figure->span_count++] = span;
675 static void deserialize_span(struct figure *figure, unsigned int *current, unsigned int *shift, unsigned int c)
677 *current |= (c & 0x7f) << *shift;
678 if (c & 0x80)
680 *shift += 7;
681 return;
684 if (*current)
685 figure_add_span(figure, *current);
686 *current = 0;
687 *shift = 0;
690 static void deserialize_figure(struct figure *figure, const BYTE *s)
692 static const BYTE lookup[] =
694 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
695 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
696 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
697 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
698 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
699 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
700 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
701 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
703 unsigned int current = 0, shift = 0;
704 const BYTE *ptr;
705 BYTE x, y;
707 figure->span_count = 0;
708 figure->spans_size = 64;
709 figure->spans = HeapAlloc(GetProcessHeap(), 0, figure->spans_size * sizeof(*figure->spans));
711 for (ptr = s; *ptr; ptr += 4)
713 x = lookup[ptr[0]];
714 y = lookup[ptr[1]];
715 deserialize_span(figure, &current, &shift, ((x & 0x3f) << 2) | ((y & 0x3f) >> 4));
716 x = lookup[ptr[2]];
717 deserialize_span(figure, &current, &shift, ((y & 0x0f) << 4) | ((x & 0x3f) >> 2));
718 y = lookup[ptr[3]];
719 deserialize_span(figure, &current, &shift, ((x & 0x03) << 6) | (y & 0x3f));
723 static void read_figure(struct figure *figure, BYTE *data, unsigned int pitch,
724 unsigned int x, unsigned int y, unsigned int w, unsigned int h, DWORD prev)
726 unsigned int i, j, span;
728 figure->span_count = 0;
729 for (i = 0, span = 0; i < h; ++i)
731 const DWORD *row = (DWORD *)&data[(y + i) * pitch + x * 4];
732 for (j = 0; j < w; ++j, ++span)
734 if ((i || j) && prev != row[j])
736 figure_add_span(figure, span);
737 prev = row[j];
738 span = 0;
742 if (span)
743 figure_add_span(figure, span);
746 static BOOL compare_figure(struct d2d1_test_context *ctx, unsigned int x, unsigned int y,
747 unsigned int w, unsigned int h, DWORD prev, unsigned int max_diff, const char *ref)
749 struct figure ref_figure, figure;
750 unsigned int i, j, span, diff;
751 struct resource_readback rb;
753 get_surface_readback(ctx, &rb);
755 figure.span_count = 0;
756 figure.spans_size = 64;
757 figure.spans = HeapAlloc(GetProcessHeap(), 0, figure.spans_size * sizeof(*figure.spans));
759 read_figure(&figure, rb.data, rb.pitch, x, y, w, h, prev);
761 deserialize_figure(&ref_figure, (BYTE *)ref);
762 span = w * h;
763 for (i = 0; i < ref_figure.span_count; ++i)
765 span -= ref_figure.spans[i];
767 if (span)
768 figure_add_span(&ref_figure, span);
770 for (i = 0, j = 0, diff = 0; i < figure.span_count && j < ref_figure.span_count;)
772 if (figure.spans[i] == ref_figure.spans[j])
774 if ((i ^ j) & 1)
775 diff += ref_figure.spans[j];
776 ++i;
777 ++j;
779 else if (figure.spans[i] > ref_figure.spans[j])
781 if ((i ^ j) & 1)
782 diff += ref_figure.spans[j];
783 figure.spans[i] -= ref_figure.spans[j];
784 ++j;
786 else
788 if ((i ^ j) & 1)
789 diff += figure.spans[i];
790 ref_figure.spans[j] -= figure.spans[i];
791 ++i;
794 if (diff > max_diff)
796 trace("diff %u > max_diff %u.\n", diff, max_diff);
797 read_figure(&figure, rb.data, rb.pitch, x, y, w, h, prev);
798 serialize_figure(&figure);
801 HeapFree(GetProcessHeap(), 0, ref_figure.spans);
802 HeapFree(GetProcessHeap(), 0, figure.spans);
803 release_resource_readback(&rb);
805 return diff <= max_diff;
808 static ID3D10Device1 *create_d3d10_device(void)
810 ID3D10Device1 *device;
812 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL,
813 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
814 return device;
815 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_WARP, NULL,
816 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
817 return device;
818 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL,
819 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
820 return device;
822 return NULL;
825 static ID3D11Device *create_d3d11_device(void)
827 D3D_FEATURE_LEVEL level = D3D_FEATURE_LEVEL_11_0;
828 ID3D11Device *device;
830 if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL,
831 D3D10_CREATE_DEVICE_BGRA_SUPPORT, &level, 1, D3D11_SDK_VERSION, &device, NULL, NULL)))
832 return device;
833 if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL,
834 D3D10_CREATE_DEVICE_BGRA_SUPPORT, &level, 1, D3D11_SDK_VERSION, &device, NULL, NULL)))
835 return device;
836 if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL,
837 D3D10_CREATE_DEVICE_BGRA_SUPPORT, &level, 1, D3D11_SDK_VERSION, &device, NULL, NULL)))
838 return device;
840 return NULL;
843 static IDXGIDevice *create_device(BOOL d3d11)
845 ID3D10Device1 *d3d10_device;
846 ID3D11Device *d3d11_device;
847 IDXGIDevice *device;
848 HRESULT hr;
850 if (d3d11)
852 if (!(d3d11_device = create_d3d11_device()))
853 return NULL;
854 hr = ID3D11Device_QueryInterface(d3d11_device, &IID_IDXGIDevice, (void **)&device);
855 ID3D11Device_Release(d3d11_device);
857 else
859 if (!(d3d10_device = create_d3d10_device()))
860 return NULL;
861 hr = ID3D10Device1_QueryInterface(d3d10_device, &IID_IDXGIDevice, (void **)&device);
862 ID3D10Device1_Release(d3d10_device);
865 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
867 return device;
870 static HWND create_window(void)
872 RECT r = {0, 0, 640, 480};
874 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
876 return CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
877 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
880 static IDXGISwapChain *create_swapchain(IDXGIDevice *device, HWND window, BOOL windowed)
882 IDXGISwapChain *swapchain;
883 DXGI_SWAP_CHAIN_DESC desc;
884 IDXGIAdapter *adapter;
885 IDXGIFactory *factory;
886 HRESULT hr;
888 hr = IDXGIDevice_GetAdapter(device, &adapter);
889 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
890 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
891 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
892 IDXGIAdapter_Release(adapter);
894 desc.BufferDesc.Width = 640;
895 desc.BufferDesc.Height = 480;
896 desc.BufferDesc.RefreshRate.Numerator = 60;
897 desc.BufferDesc.RefreshRate.Denominator = 1;
898 desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
899 desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
900 desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
901 desc.SampleDesc.Count = 1;
902 desc.SampleDesc.Quality = 0;
903 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
904 desc.BufferCount = 1;
905 desc.OutputWindow = window;
906 desc.Windowed = windowed;
907 desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
908 desc.Flags = 0;
910 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &desc, &swapchain);
911 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
912 IDXGIFactory_Release(factory);
914 return swapchain;
917 static IDXGISwapChain *create_d3d10_swapchain(ID3D10Device1 *device, HWND window, BOOL windowed)
919 IDXGISwapChain *swapchain;
920 IDXGIDevice *dxgi_device;
921 HRESULT hr;
923 hr = ID3D10Device1_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
924 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
925 swapchain = create_swapchain(dxgi_device, window, windowed);
926 IDXGIDevice_Release(dxgi_device);
927 return swapchain;
930 static ID2D1RenderTarget *create_render_target_desc(IDXGISurface *surface,
931 const D2D1_RENDER_TARGET_PROPERTIES *desc, BOOL d3d11)
933 ID2D1RenderTarget *render_target;
934 ID2D1Factory *factory;
935 HRESULT hr;
937 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
938 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
939 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, desc, &render_target);
940 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
941 ID2D1Factory_Release(factory);
943 return render_target;
946 static ID2D1RenderTarget *create_render_target(IDXGISurface *surface, BOOL d3d11)
948 D2D1_RENDER_TARGET_PROPERTIES desc;
950 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
951 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
952 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
953 desc.dpiX = 0.0f;
954 desc.dpiY = 0.0f;
955 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
956 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
958 return create_render_target_desc(surface, &desc, d3d11);
961 #define release_test_context(ctx) release_test_context_(__LINE__, ctx)
962 static void release_test_context_(unsigned int line, struct d2d1_test_context *ctx)
964 ID2D1Factory *factory;
965 ULONG ref;
967 ID2D1RenderTarget_GetFactory(ctx->rt, &factory);
968 ID2D1RenderTarget_Release(ctx->rt);
969 ref = ID2D1Factory_Release(factory);
970 ok_(__FILE__, line)(!ref, "Factory has %lu references left.\n", ref);
972 IDXGISurface_Release(ctx->surface);
973 IDXGISwapChain_Release(ctx->swapchain);
974 DestroyWindow(ctx->window);
975 IDXGIDevice_Release(ctx->device);
978 #define init_test_context(ctx, d3d11) init_test_context_(__LINE__, ctx, d3d11)
979 static BOOL init_test_context_(unsigned int line, struct d2d1_test_context *ctx, BOOL d3d11)
981 HRESULT hr;
983 memset(ctx, 0, sizeof(*ctx));
985 ctx->d3d11 = d3d11;
986 if (!(ctx->device = create_device(d3d11)))
988 skip_(__FILE__, line)("Failed to create device, skipping tests.\n");
989 return FALSE;
992 ctx->window = create_window();
993 ok_(__FILE__, line)(!!ctx->window, "Failed to create test window.\n");
994 ctx->swapchain = create_swapchain(ctx->device, ctx->window, TRUE);
995 ok_(__FILE__, line)(!!ctx->swapchain, "Failed to create swapchain.\n");
996 hr = IDXGISwapChain_GetBuffer(ctx->swapchain, 0, &IID_IDXGISurface, (void **)&ctx->surface);
997 ok_(__FILE__, line)(hr == S_OK, "Failed to get buffer, hr %#lx.\n", hr);
999 ctx->rt = create_render_target(ctx->surface, d3d11);
1000 if (!ctx->rt && d3d11)
1002 todo_wine win_skip_(__FILE__, line)("Skipping d3d11 tests.\n");
1004 IDXGISurface_Release(ctx->surface);
1005 IDXGISwapChain_Release(ctx->swapchain);
1006 DestroyWindow(ctx->window);
1007 IDXGIDevice_Release(ctx->device);
1009 return FALSE;
1011 ok_(__FILE__, line)(!!ctx->rt, "Failed to create render target.\n");
1013 return TRUE;
1016 #define check_bitmap_surface(b, s, o) check_bitmap_surface_(__LINE__, b, s, o)
1017 static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL has_surface, DWORD expected_options)
1019 D2D1_BITMAP_OPTIONS options;
1020 IDXGISurface *surface;
1021 ID2D1Bitmap1 *bitmap1;
1022 HRESULT hr;
1024 hr = ID2D1Bitmap_QueryInterface(bitmap, &IID_ID2D1Bitmap1, (void **)&bitmap1);
1025 if (FAILED(hr))
1026 return;
1028 options = ID2D1Bitmap1_GetOptions(bitmap1);
1029 ok_(__FILE__, line)(options == expected_options, "Got unexpected bitmap options %#x, expected %#lx.\n",
1030 options, expected_options);
1032 surface = (void *)0xdeadbeef;
1033 hr = ID2D1Bitmap1_GetSurface(bitmap1, &surface);
1034 if (has_surface)
1036 D3D10_TEXTURE2D_DESC desc;
1037 ID3D10Texture2D *texture;
1038 D2D1_SIZE_U pixel_size;
1039 DWORD bind_flags = 0;
1041 ok_(__FILE__, line)(hr == S_OK, "Failed to get bitmap surface, hr %#lx.\n", hr);
1042 ok_(__FILE__, line)(!!surface, "Expected surface instance.\n");
1044 /* Correlate with resource configuration. */
1045 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Texture2D, (void **)&texture);
1046 ok_(__FILE__, line)(hr == S_OK, "Failed to get texture pointer, hr %#lx.\n", hr);
1048 ID3D10Texture2D_GetDesc(texture, &desc);
1049 ok_(__FILE__, line)(desc.Usage == 0, "Unexpected usage %#x.\n", desc.Usage);
1051 if (options & D2D1_BITMAP_OPTIONS_TARGET)
1052 bind_flags |= D3D10_BIND_RENDER_TARGET;
1053 if (!(options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW))
1054 bind_flags |= D3D10_BIND_SHADER_RESOURCE;
1056 ok_(__FILE__, line)(desc.BindFlags == bind_flags, "Unexpected bind flags %#x for bitmap options %#x.\n",
1057 desc.BindFlags, options);
1058 ok_(__FILE__, line)(!desc.CPUAccessFlags, "Unexpected cpu access flags %#x.\n", desc.CPUAccessFlags);
1059 ok_(__FILE__, line)(!desc.MiscFlags, "Unexpected misc flags %#x.\n", desc.MiscFlags);
1061 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
1062 if (!pixel_size.width || !pixel_size.height)
1063 pixel_size.width = pixel_size.height = 1;
1064 ok_(__FILE__, line)(desc.Width == pixel_size.width, "Got width %u, expected %u.\n",
1065 desc.Width, pixel_size.width);
1066 ok_(__FILE__, line)(desc.Height == pixel_size.height, "Got height %u, expected %u.\n",
1067 desc.Height, pixel_size.height);
1069 ID3D10Texture2D_Release(texture);
1071 IDXGISurface_Release(surface);
1073 else
1075 ok_(__FILE__, line)(hr == D2DERR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr);
1076 ok_(__FILE__, line)(!surface, "Unexpected surface instance.\n");
1079 ID2D1Bitmap1_Release(bitmap1);
1082 static inline struct geometry_sink *impl_from_ID2D1SimplifiedGeometrySink(ID2D1SimplifiedGeometrySink *iface)
1084 return CONTAINING_RECORD(iface, struct geometry_sink, ID2D1SimplifiedGeometrySink_iface);
1087 static HRESULT STDMETHODCALLTYPE geometry_sink_QueryInterface(ID2D1SimplifiedGeometrySink *iface,
1088 REFIID iid, void **out)
1090 if (IsEqualGUID(iid, &IID_ID2D1SimplifiedGeometrySink)
1091 || IsEqualGUID(iid, &IID_IUnknown))
1093 *out = iface;
1094 return S_OK;
1097 *out = NULL;
1098 return E_NOINTERFACE;
1101 static ULONG STDMETHODCALLTYPE geometry_sink_AddRef(ID2D1SimplifiedGeometrySink *iface)
1103 return 0;
1106 static ULONG STDMETHODCALLTYPE geometry_sink_Release(ID2D1SimplifiedGeometrySink *iface)
1108 return 0;
1111 static void STDMETHODCALLTYPE geometry_sink_SetFillMode(ID2D1SimplifiedGeometrySink *iface, D2D1_FILL_MODE mode)
1113 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
1115 sink->fill_mode = mode;
1118 static void STDMETHODCALLTYPE geometry_sink_SetSegmentFlags(ID2D1SimplifiedGeometrySink *iface,
1119 D2D1_PATH_SEGMENT flags)
1121 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
1123 sink->segment_flags = flags;
1126 static void STDMETHODCALLTYPE geometry_sink_BeginFigure(ID2D1SimplifiedGeometrySink *iface,
1127 D2D1_POINT_2F start_point, D2D1_FIGURE_BEGIN figure_begin)
1129 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
1130 struct geometry_figure *figure;
1132 if (sink->figure_count == sink->figures_size)
1134 sink->figures_size *= 2;
1135 sink->figures = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sink->figures,
1136 sink->figures_size * sizeof(*sink->figures));
1138 figure = &sink->figures[sink->figure_count++];
1140 figure->begin = figure_begin;
1141 figure->start_point = start_point;
1142 figure->segments_size = 4;
1143 figure->segments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1144 figure->segments_size * sizeof(*figure->segments));
1147 static struct geometry_segment *geometry_figure_add_segment(struct geometry_figure *figure)
1149 if (figure->segment_count == figure->segments_size)
1151 figure->segments_size *= 2;
1152 figure->segments = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, figure->segments,
1153 figure->segments_size * sizeof(*figure->segments));
1155 return &figure->segments[figure->segment_count++];
1158 static void STDMETHODCALLTYPE geometry_sink_AddLines(ID2D1SimplifiedGeometrySink *iface,
1159 const D2D1_POINT_2F *points, UINT32 count)
1161 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
1162 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
1163 struct geometry_segment *segment;
1164 unsigned int i;
1166 for (i = 0; i < count; ++i)
1168 segment = geometry_figure_add_segment(figure);
1169 segment->type = SEGMENT_LINE;
1170 segment->u.line = points[i];
1171 segment->flags = sink->segment_flags;
1175 static void STDMETHODCALLTYPE geometry_sink_AddBeziers(ID2D1SimplifiedGeometrySink *iface,
1176 const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
1178 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
1179 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
1180 struct geometry_segment *segment;
1181 unsigned int i;
1183 for (i = 0; i < count; ++i)
1185 segment = geometry_figure_add_segment(figure);
1186 segment->type = SEGMENT_BEZIER;
1187 segment->u.bezier = beziers[i];
1188 segment->flags = sink->segment_flags;
1192 static void STDMETHODCALLTYPE geometry_sink_EndFigure(ID2D1SimplifiedGeometrySink *iface,
1193 D2D1_FIGURE_END figure_end)
1195 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
1196 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
1198 figure->end = figure_end;
1201 static HRESULT STDMETHODCALLTYPE geometry_sink_Close(ID2D1SimplifiedGeometrySink *iface)
1203 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
1205 sink->closed = TRUE;
1207 return S_OK;
1210 static const struct ID2D1SimplifiedGeometrySinkVtbl geometry_sink_vtbl =
1212 geometry_sink_QueryInterface,
1213 geometry_sink_AddRef,
1214 geometry_sink_Release,
1215 geometry_sink_SetFillMode,
1216 geometry_sink_SetSegmentFlags,
1217 geometry_sink_BeginFigure,
1218 geometry_sink_AddLines,
1219 geometry_sink_AddBeziers,
1220 geometry_sink_EndFigure,
1221 geometry_sink_Close,
1224 static void geometry_sink_init(struct geometry_sink *sink)
1226 memset(sink, 0, sizeof(*sink));
1227 sink->ID2D1SimplifiedGeometrySink_iface.lpVtbl = &geometry_sink_vtbl;
1228 sink->figures_size = 4;
1229 sink->figures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1230 sink->figures_size * sizeof(*sink->figures));
1233 static void geometry_sink_cleanup(struct geometry_sink *sink)
1235 unsigned int i;
1237 for (i = 0; i < sink->figure_count; ++i)
1239 HeapFree(GetProcessHeap(), 0, sink->figures[i].segments);
1241 HeapFree(GetProcessHeap(), 0, sink->figures);
1244 #define geometry_sink_check(a, b, c, d, e) geometry_sink_check_(__LINE__, a, b, c, d, e)
1245 static void geometry_sink_check_(unsigned int line, const struct geometry_sink *sink, D2D1_FILL_MODE fill_mode,
1246 unsigned int figure_count, const struct expected_geometry_figure *expected_figures, unsigned int ulps)
1248 const struct geometry_segment *segment, *expected_segment;
1249 const struct expected_geometry_figure *expected_figure;
1250 const struct geometry_figure *figure;
1251 unsigned int i, j;
1252 unsigned int segment_count;
1253 BOOL match;
1255 ok_(__FILE__, line)(sink->fill_mode == fill_mode,
1256 "Got unexpected fill mode %#x.\n", sink->fill_mode);
1257 ok_(__FILE__, line)(sink->figure_count == figure_count,
1258 "Got unexpected figure count %u, expected %u.\n", sink->figure_count, figure_count);
1259 ok_(__FILE__, line)(!sink->closed, "Sink is closed.\n");
1261 for (i = 0; i < figure_count; ++i)
1263 expected_figure = &expected_figures[i];
1264 figure = &sink->figures[i];
1266 ok_(__FILE__, line)(figure->begin == expected_figure->begin,
1267 "Got unexpected figure %u begin %#x, expected %#x.\n",
1268 i, figure->begin, expected_figure->begin);
1269 ok_(__FILE__, line)(figure->end == expected_figure->end,
1270 "Got unexpected figure %u end %#x, expected %#x.\n",
1271 i, figure->end, expected_figure->end);
1272 match = compare_point(&figure->start_point,
1273 expected_figure->start_point.x, expected_figure->start_point.y, ulps);
1274 ok_(__FILE__, line)(match, "Got unexpected figure %u start point {%.8e, %.8e}, expected {%.8e, %.8e}.\n",
1275 i, figure->start_point.x, figure->start_point.y,
1276 expected_figure->start_point.x, expected_figure->start_point.y);
1277 ok_(__FILE__, line)(figure->segment_count == expected_figure->segment_count,
1278 "Got unexpected figure %u segment count %u, expected %u.\n",
1279 i, figure->segment_count, expected_figure->segment_count);
1281 segment_count = expected_figure->segment_count < figure->segment_count ?
1282 expected_figure->segment_count : figure->segment_count;
1284 for (j = 0; j < segment_count; ++j)
1286 expected_segment = &expected_figure->segments[j];
1287 segment = &figure->segments[j];
1288 ok_(__FILE__, line)(segment->type == expected_segment->type,
1289 "Got unexpected figure %u, segment %u type %#x, expected %#x.\n",
1290 i, j, segment->type, expected_segment->type);
1291 ok_(__FILE__, line)(segment->flags == expected_segment->flags,
1292 "Got unexpected figure %u, segment %u flags %#lx, expected %#lx.\n",
1293 i, j, segment->flags, expected_segment->flags);
1294 switch (segment->type)
1296 case SEGMENT_LINE:
1297 match = compare_point(&segment->u.line,
1298 expected_segment->u.line.x, expected_segment->u.line.y, ulps);
1299 ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u {%.8e, %.8e}, "
1300 "expected {%.8e, %.8e}.\n",
1301 i, j, segment->u.line.x, segment->u.line.y,
1302 expected_segment->u.line.x, expected_segment->u.line.y);
1303 break;
1305 case SEGMENT_BEZIER:
1306 match = compare_bezier_segment(&segment->u.bezier,
1307 expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
1308 expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
1309 expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y,
1310 ulps);
1311 ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u "
1312 "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}, "
1313 "expected {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1314 i, j, segment->u.bezier.point1.x, segment->u.bezier.point1.y,
1315 segment->u.bezier.point2.x, segment->u.bezier.point2.y,
1316 segment->u.bezier.point3.x, segment->u.bezier.point3.y,
1317 expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
1318 expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
1319 expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y);
1320 break;
1324 for (j = segment_count; j < expected_figure->segment_count; ++j)
1326 segment = &expected_figure->segments[j];
1327 switch (segment->type)
1329 case SEGMENT_LINE:
1330 ok_(__FILE__, line)(FALSE, "Missing figure %u segment %u {%.8e, %.8e}.\n",
1331 i, j, segment->u.line.x, segment->u.line.y);
1332 break;
1333 case SEGMENT_BEZIER:
1334 ok_(__FILE__, line)(FALSE, "Missing figure %u segment %u "
1335 "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}\n",
1336 i, j, segment->u.bezier.point1.x, segment->u.bezier.point1.y,
1337 segment->u.bezier.point2.x, segment->u.bezier.point2.y,
1338 segment->u.bezier.point3.x, segment->u.bezier.point3.y);
1339 break;
1343 for (j = segment_count; j < figure->segment_count; ++j)
1345 segment = &figure->segments[j];
1346 switch (segment->type)
1348 case SEGMENT_LINE:
1349 ok_(__FILE__, line)(FALSE, "Got unexpected figure %u segment %u {%.8e, %.8e}.\n",
1350 i, j, segment->u.line.x, segment->u.line.y);
1351 break;
1352 case SEGMENT_BEZIER:
1353 ok_(__FILE__, line)(FALSE, "Got unexpected figure %u segment %u "
1354 "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}\n",
1355 i, j, segment->u.bezier.point1.x, segment->u.bezier.point1.y,
1356 segment->u.bezier.point2.x, segment->u.bezier.point2.y,
1357 segment->u.bezier.point3.x, segment->u.bezier.point3.y);
1358 break;
1364 static void test_clip(BOOL d3d11)
1366 struct d2d1_test_context ctx;
1367 D2D1_MATRIX_3X2_F matrix;
1368 D2D1_SIZE_U pixel_size;
1369 ID2D1RenderTarget *rt;
1370 D2D1_POINT_2F point;
1371 D2D1_COLOR_F color;
1372 float dpi_x, dpi_y;
1373 D2D1_RECT_F rect;
1374 D2D1_SIZE_F size;
1375 HRESULT hr;
1376 BOOL match;
1377 static const D2D1_MATRIX_3X2_F identity =
1379 1.0f, 0.0f,
1380 0.0f, 1.0f,
1381 0.0f, 0.0f,
1382 }}};
1384 if (!init_test_context(&ctx, d3d11))
1385 return;
1387 rt = ctx.rt;
1388 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1389 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1390 ok(dpi_y == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
1391 size = ID2D1RenderTarget_GetSize(rt);
1392 ok(size.width == 640.0f, "Got unexpected width %.8e.\n", size.width);
1393 ok(size.height == 480.0f, "Got unexpected height %.8e.\n", size.height);
1394 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
1395 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
1396 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
1398 ID2D1RenderTarget_GetTransform(rt, &matrix);
1399 ok(!memcmp(&matrix, &identity, sizeof(matrix)),
1400 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1401 matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32);
1403 ID2D1RenderTarget_BeginDraw(rt);
1405 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
1406 ID2D1RenderTarget_Clear(rt, &color);
1408 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
1409 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1410 ok(dpi_x == 48.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1411 ok(dpi_y == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
1412 size = ID2D1RenderTarget_GetSize(rt);
1413 ok(size.width == 1280.0f, "Got unexpected width %.8e.\n", size.width);
1414 ok(size.height == 240.0f, "Got unexpected height %.8e.\n", size.height);
1415 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
1416 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
1417 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
1419 /* The effective clip rect is the intersection of all currently pushed
1420 * clip rects. Clip rects are in DIPs. */
1421 set_rect(&rect, 0.0f, 0.0f, 1280.0f, 80.0f);
1422 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1423 set_rect(&rect, 0.0f, 0.0f, 426.0f, 240.0f);
1424 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1426 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
1427 ID2D1RenderTarget_Clear(rt, &color);
1428 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1429 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1431 ID2D1RenderTarget_SetDpi(rt, 0.0f, 0.0f);
1432 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1433 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1434 ok(dpi_y == 96.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1436 ID2D1RenderTarget_SetDpi(rt, 192.0f, 192.0f);
1437 ID2D1RenderTarget_SetDpi(rt, 0.0f, 96.0f);
1438 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1439 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1440 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1442 ID2D1RenderTarget_SetDpi(rt, -10.0f, 96.0f);
1443 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1444 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1445 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1447 ID2D1RenderTarget_SetDpi(rt, 96.0f, -10.0f);
1448 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1449 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1450 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1452 ID2D1RenderTarget_SetDpi(rt, 96.0f, 0.0f);
1453 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1454 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1455 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1457 ID2D1RenderTarget_SetDpi(rt, 96.0f, 96.0f);
1459 /* Transformations apply to clip rects, the effective clip rect is the
1460 * (axis-aligned) bounding box of the transformed clip rect. */
1461 set_point(&point, 320.0f, 240.0f);
1462 D2D1MakeRotateMatrix(30.0f, point, &matrix);
1463 ID2D1RenderTarget_SetTransform(rt, &matrix);
1464 set_rect(&rect, 215.0f, 208.0f, 425.0f, 272.0f);
1465 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1466 set_color(&color, 1.0f, 1.0f, 1.0f, 1.0f);
1467 ID2D1RenderTarget_Clear(rt, &color);
1468 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1470 /* Transformations are applied when pushing the clip rect, transformations
1471 * set afterwards have no effect on the current clip rect. This includes
1472 * SetDpi(). */
1473 ID2D1RenderTarget_SetTransform(rt, &identity);
1474 set_rect(&rect, 427.0f, 320.0f, 640.0f, 480.0f);
1475 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1476 ID2D1RenderTarget_SetTransform(rt, &matrix);
1477 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
1478 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
1479 ID2D1RenderTarget_Clear(rt, &color);
1480 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1482 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1483 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1484 match = compare_surface(&ctx, "035a44d4198d6e422e9de6185b5b2c2bac5e33c9");
1485 ok(match, "Surface does not match.\n");
1487 /* Fractional clip rectangle coordinates, aliased mode. */
1488 set_matrix_identity(&matrix);
1489 ID2D1RenderTarget_SetTransform(rt, &matrix);
1490 ID2D1RenderTarget_SetDpi(rt, 96.0f, 96.0f);
1492 ID2D1RenderTarget_BeginDraw(rt);
1494 set_color(&color, 0.0f, 0.0f, 0.0f, 1.0f);
1495 ID2D1RenderTarget_Clear(rt, &color);
1497 scale_matrix(&matrix, 2.0f, 2.0f);
1498 ID2D1RenderTarget_SetTransform(rt, &matrix);
1499 set_rect(&rect, 0.0f, 0.5f, 200.0f, 100.5f);
1500 set_color(&color, 1.0f, 0.0f, 1.0f, 1.0f);
1501 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1502 ID2D1RenderTarget_Clear(rt, &color);
1503 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1505 set_matrix_identity(&matrix);
1506 ID2D1RenderTarget_SetTransform(rt, &matrix);
1507 set_rect(&rect, 0.0f, 0.5f, 100.0f, 200.5f);
1508 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
1509 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1510 ID2D1RenderTarget_Clear(rt, &color);
1511 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1513 ID2D1RenderTarget_SetTransform(rt, &matrix);
1514 set_rect(&rect, 0.5f, 250.0f, 100.5f, 300.0f);
1515 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
1516 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1517 ID2D1RenderTarget_Clear(rt, &color);
1518 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1520 translate_matrix(&matrix, 0.1f, 0.0f);
1521 ID2D1RenderTarget_SetTransform(rt, &matrix);
1522 set_rect(&rect, 110.0f, 250.25f, 150.0f, 300.25f);
1523 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
1524 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1525 ID2D1RenderTarget_Clear(rt, &color);
1526 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1528 set_rect(&rect, 160.0f, 250.75f, 200.0f, 300.75f);
1529 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1530 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1531 ID2D1RenderTarget_Clear(rt, &color);
1532 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1534 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
1535 set_rect(&rect, 160.25f, 0.0f, 200.25f, 100.0f);
1536 set_color(&color, 1.0f, 0.0f, 1.0f, 1.0f);
1537 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1538 ID2D1RenderTarget_Clear(rt, &color);
1539 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1541 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1542 set_rect(&rect, 160.75f, 100.0f, 200.75f, 120.0f);
1543 set_color(&color, 0.0f, 1.0f, 1.0f, 1.0f);
1544 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1545 ID2D1RenderTarget_Clear(rt, &color);
1546 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1548 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1549 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1550 match = compare_surface(&ctx, "cb418ec4a7c8407b5e36db06fc6292a06bb8476c");
1551 ok(match, "Surface does not match.\n");
1553 release_test_context(&ctx);
1556 static void test_state_block(BOOL d3d11)
1558 IDWriteRenderingParams *text_rendering_params1, *text_rendering_params2;
1559 D2D1_DRAWING_STATE_DESCRIPTION drawing_state;
1560 ID2D1DrawingStateBlock *state_block;
1561 IDWriteFactory *dwrite_factory;
1562 struct d2d1_test_context ctx;
1563 ID2D1Factory1 *factory1;
1564 ID2D1RenderTarget *rt;
1565 ID2D1Factory *factory;
1566 ULONG refcount;
1567 HRESULT hr;
1568 static const D2D1_MATRIX_3X2_F identity =
1570 1.0f, 0.0f,
1571 0.0f, 1.0f,
1572 0.0f, 0.0f,
1573 }}};
1574 static const D2D1_MATRIX_3X2_F transform1 =
1576 1.0f, 2.0f,
1577 3.0f, 4.0f,
1578 5.0f, 6.0f,
1579 }}};
1580 static const D2D1_MATRIX_3X2_F transform2 =
1582 7.0f, 8.0f,
1583 9.0f, 10.0f,
1584 11.0f, 12.0f,
1585 }}};
1587 if (!init_test_context(&ctx, d3d11))
1588 return;
1590 rt = ctx.rt;
1591 ID2D1RenderTarget_GetFactory(rt, &factory);
1592 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
1593 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1594 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &text_rendering_params1);
1595 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1596 IDWriteFactory_Release(dwrite_factory);
1598 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1599 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1600 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1601 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1602 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
1603 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1604 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1605 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %s:%s.\n",
1606 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1607 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1608 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
1609 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1610 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1611 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1612 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1613 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1615 hr = ID2D1Factory_CreateDrawingStateBlock(factory, NULL, NULL, &state_block);
1616 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1617 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1618 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1619 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1620 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
1621 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1622 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %s:%s.\n",
1623 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1624 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
1625 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1626 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1627 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1628 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1629 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1630 ID2D1DrawingStateBlock_Release(state_block);
1632 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
1633 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
1634 drawing_state.tag1 = 0xdead;
1635 drawing_state.tag2 = 0xbeef;
1636 drawing_state.transform = transform1;
1637 hr = ID2D1Factory_CreateDrawingStateBlock(factory, &drawing_state, text_rendering_params1, &state_block);
1638 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1640 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1641 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1642 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1643 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
1644 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1645 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %s:%s.\n",
1646 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1647 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1648 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1649 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1650 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1651 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1652 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1653 text_rendering_params2, text_rendering_params1);
1654 IDWriteRenderingParams_Release(text_rendering_params2);
1656 ID2D1RenderTarget_RestoreDrawingState(rt, state_block);
1658 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1659 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1660 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1661 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1662 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
1663 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1664 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1665 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %s:%s.\n",
1666 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1667 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1668 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1669 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1670 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1671 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1672 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1673 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1674 text_rendering_params2, text_rendering_params1);
1675 IDWriteRenderingParams_Release(text_rendering_params2);
1677 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
1678 ID2D1RenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
1679 ID2D1RenderTarget_SetTags(rt, 1, 2);
1680 ID2D1RenderTarget_SetTransform(rt, &transform2);
1681 ID2D1RenderTarget_SetTextRenderingParams(rt, NULL);
1683 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1684 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1685 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1686 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1687 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
1688 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1689 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1690 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %s:%s.\n",
1691 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1692 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1693 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
1694 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1695 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1696 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1697 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1698 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1700 ID2D1RenderTarget_SaveDrawingState(rt, state_block);
1702 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1703 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1704 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1705 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
1706 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1707 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %s:%s.\n",
1708 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1709 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
1710 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1711 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1712 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1713 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1714 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1716 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
1717 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1718 drawing_state.tag1 = 3;
1719 drawing_state.tag2 = 4;
1720 drawing_state.transform = transform1;
1721 ID2D1DrawingStateBlock_SetDescription(state_block, &drawing_state);
1722 ID2D1DrawingStateBlock_SetTextRenderingParams(state_block, text_rendering_params1);
1724 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1725 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1726 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1727 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE,
1728 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1729 ok(drawing_state.tag1 == 3 && drawing_state.tag2 == 4, "Got unexpected tags %s:%s.\n",
1730 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1731 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1732 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1733 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1734 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1735 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1736 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1737 text_rendering_params2, text_rendering_params1);
1738 IDWriteRenderingParams_Release(text_rendering_params2);
1740 if (SUCCEEDED(ID2D1Factory_QueryInterface(factory, &IID_ID2D1Factory1, (void **)&factory1)))
1742 D2D1_DRAWING_STATE_DESCRIPTION1 drawing_state1;
1743 ID2D1DrawingStateBlock1 *state_block1;
1745 hr = ID2D1DrawingStateBlock_QueryInterface(state_block, &IID_ID2D1DrawingStateBlock1, (void **)&state_block1);
1746 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1748 ID2D1DrawingStateBlock1_GetDescription(state_block1, &drawing_state1);
1749 ok(drawing_state1.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1750 "Got unexpected antialias mode %#x.\n", drawing_state1.antialiasMode);
1751 ok(drawing_state1.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE,
1752 "Got unexpected text antialias mode %#x.\n", drawing_state1.textAntialiasMode);
1753 ok(drawing_state1.tag1 == 3 && drawing_state1.tag2 == 4, "Got unexpected tags %s:%s.\n",
1754 wine_dbgstr_longlong(drawing_state1.tag1), wine_dbgstr_longlong(drawing_state1.tag2));
1755 ok(!memcmp(&drawing_state1.transform, &transform1, sizeof(drawing_state1.transform)),
1756 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1757 drawing_state1.transform._11, drawing_state1.transform._12, drawing_state1.transform._21,
1758 drawing_state1.transform._22, drawing_state1.transform._31, drawing_state1.transform._32);
1759 ok(drawing_state1.primitiveBlend == D2D1_PRIMITIVE_BLEND_SOURCE_OVER,
1760 "Got unexpected primitive blend mode %#x.\n", drawing_state1.primitiveBlend);
1761 ok(drawing_state1.unitMode == D2D1_UNIT_MODE_DIPS, "Got unexpected unit mode %#x.\n", drawing_state1.unitMode);
1762 ID2D1DrawingStateBlock1_GetTextRenderingParams(state_block1, &text_rendering_params2);
1763 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1764 text_rendering_params2, text_rendering_params1);
1765 IDWriteRenderingParams_Release(text_rendering_params2);
1767 drawing_state1.primitiveBlend = D2D1_PRIMITIVE_BLEND_COPY;
1768 drawing_state1.unitMode = D2D1_UNIT_MODE_PIXELS;
1769 ID2D1DrawingStateBlock1_SetDescription(state_block1, &drawing_state1);
1770 ID2D1DrawingStateBlock1_GetDescription(state_block1, &drawing_state1);
1771 ok(drawing_state1.primitiveBlend == D2D1_PRIMITIVE_BLEND_COPY,
1772 "Got unexpected primitive blend mode %#x.\n", drawing_state1.primitiveBlend);
1773 ok(drawing_state1.unitMode == D2D1_UNIT_MODE_PIXELS,
1774 "Got unexpected unit mode %#x.\n", drawing_state1.unitMode);
1776 ID2D1DrawingStateBlock_SetDescription(state_block, &drawing_state);
1777 ID2D1DrawingStateBlock1_GetDescription(state_block1, &drawing_state1);
1778 ok(drawing_state1.primitiveBlend == D2D1_PRIMITIVE_BLEND_COPY,
1779 "Got unexpected primitive blend mode %#x.\n", drawing_state1.primitiveBlend);
1780 ok(drawing_state1.unitMode == D2D1_UNIT_MODE_PIXELS,
1781 "Got unexpected unit mode %#x.\n", drawing_state1.unitMode);
1783 ID2D1DrawingStateBlock1_Release(state_block1);
1785 hr = ID2D1Factory1_CreateDrawingStateBlock(factory1, NULL, NULL, &state_block1);
1786 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1787 ID2D1DrawingStateBlock1_GetDescription(state_block1, &drawing_state1);
1788 ok(drawing_state1.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1789 "Got unexpected antialias mode %#x.\n", drawing_state1.antialiasMode);
1790 ok(drawing_state1.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
1791 "Got unexpected text antialias mode %#x.\n", drawing_state1.textAntialiasMode);
1792 ok(drawing_state1.tag1 == 0 && drawing_state1.tag2 == 0, "Got unexpected tags %s:%s.\n",
1793 wine_dbgstr_longlong(drawing_state1.tag1), wine_dbgstr_longlong(drawing_state1.tag2));
1794 ok(!memcmp(&drawing_state1.transform, &identity, sizeof(drawing_state1.transform)),
1795 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1796 drawing_state1.transform._11, drawing_state1.transform._12, drawing_state1.transform._21,
1797 drawing_state1.transform._22, drawing_state1.transform._31, drawing_state1.transform._32);
1798 ok(drawing_state1.primitiveBlend == D2D1_PRIMITIVE_BLEND_SOURCE_OVER,
1799 "Got unexpected primitive blend mode %#x.\n", drawing_state1.primitiveBlend);
1800 ok(drawing_state1.unitMode == D2D1_UNIT_MODE_DIPS, "Got unexpected unit mode %#x.\n", drawing_state1.unitMode);
1801 ID2D1DrawingStateBlock1_GetTextRenderingParams(state_block1, &text_rendering_params2);
1802 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1803 ID2D1DrawingStateBlock1_Release(state_block1);
1805 ID2D1Factory1_Release(factory1);
1808 ID2D1DrawingStateBlock_Release(state_block);
1810 refcount = IDWriteRenderingParams_Release(text_rendering_params1);
1811 ok(!refcount, "Rendering params %lu references left.\n", refcount);
1812 ID2D1Factory_Release(factory);
1813 release_test_context(&ctx);
1816 static void test_color_brush(BOOL d3d11)
1818 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1819 D2D1_BRUSH_PROPERTIES brush_desc;
1820 D2D1_COLOR_F color, tmp_color;
1821 struct d2d1_test_context ctx;
1822 ID2D1SolidColorBrush *brush;
1823 ID2D1RenderTarget *rt;
1824 D2D1_RECT_F rect;
1825 float opacity;
1826 HRESULT hr;
1827 BOOL match;
1829 if (!init_test_context(&ctx, d3d11))
1830 return;
1832 rt = ctx.rt;
1833 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1834 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1836 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
1837 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
1838 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1839 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
1840 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
1841 set_matrix_identity(&matrix);
1842 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
1843 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1844 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1845 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1846 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1847 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
1848 ok(!memcmp(&tmp_color, &color, sizeof(color)),
1849 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
1850 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
1851 ID2D1SolidColorBrush_Release(brush);
1853 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
1854 brush_desc.opacity = 0.3f;
1855 set_matrix_identity(&matrix);
1856 scale_matrix(&matrix, 2.0f, 2.0f);
1857 brush_desc.transform = matrix;
1858 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, &brush_desc, &brush);
1859 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1860 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
1861 ok(opacity == 0.3f, "Got unexpected opacity %.8e.\n", opacity);
1862 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
1863 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1864 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1865 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1866 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1867 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
1868 ok(!memcmp(&tmp_color, &color, sizeof(color)),
1869 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
1870 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
1872 ID2D1RenderTarget_BeginDraw(rt);
1874 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1875 ID2D1RenderTarget_Clear(rt, &color);
1877 ID2D1SolidColorBrush_SetOpacity(brush, 1.0f);
1878 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
1879 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
1881 set_matrix_identity(&matrix);
1882 scale_matrix(&matrix, 0.5f, 2.0f);
1883 translate_matrix(&matrix, 320.0f, 240.0f);
1884 rotate_matrix(&matrix, M_PI / 4.0f);
1885 ID2D1RenderTarget_SetTransform(rt, &matrix);
1886 set_color(&color, 1.0f, 0.0f, 0.0f, 0.625f);
1887 ID2D1SolidColorBrush_SetColor(brush, &color);
1888 ID2D1SolidColorBrush_SetOpacity(brush, 0.75f);
1889 set_rect(&rect, -80.0f, -60.0f, 80.0f, 60.0f);
1890 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
1892 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1893 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1894 match = compare_surface(&ctx, "6d1218fca5e21fb7e287b3a439d60dbc251f5ceb");
1895 ok(match, "Surface does not match.\n");
1897 ID2D1SolidColorBrush_Release(brush);
1898 release_test_context(&ctx);
1901 static void test_bitmap_brush(BOOL d3d11)
1903 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode;
1904 ID2D1TransformedGeometry *transformed_geometry;
1905 ID2D1RectangleGeometry *rectangle_geometry;
1906 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1907 D2D1_BITMAP_PROPERTIES bitmap_desc;
1908 ID2D1Bitmap *bitmap, *tmp_bitmap;
1909 D2D1_RECT_F src_rect, dst_rect;
1910 struct d2d1_test_context ctx;
1911 D2D1_EXTEND_MODE extend_mode;
1912 ID2D1BitmapBrush1 *brush1;
1913 ID2D1BitmapBrush *brush;
1914 D2D1_SIZE_F image_size;
1915 ID2D1RenderTarget *rt;
1916 ID2D1Factory *factory;
1917 D2D1_COLOR_F color;
1918 ID2D1Image *image;
1919 D2D1_SIZE_U size;
1920 unsigned int i;
1921 ULONG refcount;
1922 float opacity;
1923 HRESULT hr;
1924 BOOL match;
1926 static const struct
1928 D2D1_EXTEND_MODE extend_mode_x;
1929 D2D1_EXTEND_MODE extend_mode_y;
1930 float translate_x;
1931 float translate_y;
1932 D2D1_RECT_F rect;
1934 extend_mode_tests[] =
1936 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_MIRROR, -7.0f, 1.0f, {-4.0f, 0.0f, -8.0f, 4.0f}},
1937 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_MIRROR, -3.0f, 1.0f, {-4.0f, 4.0f, 0.0f, 0.0f}},
1938 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_MIRROR, 1.0f, 1.0f, { 4.0f, 0.0f, 0.0f, 4.0f}},
1939 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_WRAP, -7.0f, 5.0f, {-8.0f, 8.0f, -4.0f, 4.0f}},
1940 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP, -3.0f, 5.0f, { 0.0f, 4.0f, -4.0f, 8.0f}},
1941 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_WRAP, 1.0f, 5.0f, { 0.0f, 8.0f, 4.0f, 4.0f}},
1942 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_CLAMP, -7.0f, 9.0f, {-4.0f, 8.0f, -8.0f, 12.0f}},
1943 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, -3.0f, 9.0f, {-4.0f, 12.0f, 0.0f, 8.0f}},
1944 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_CLAMP, 1.0f, 9.0f, { 4.0f, 8.0f, 0.0f, 12.0f}},
1946 static const DWORD bitmap_data[] =
1948 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
1949 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
1950 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
1951 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
1954 if (!init_test_context(&ctx, d3d11))
1955 return;
1957 rt = ctx.rt;
1958 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1959 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1961 set_size_u(&size, 4, 4);
1962 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1963 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1964 bitmap_desc.dpiX = 96.0f;
1965 bitmap_desc.dpiY = 96.0f;
1966 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1967 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1968 image_size = ID2D1Bitmap_GetSize(bitmap);
1970 hr = ID2D1Bitmap_QueryInterface(bitmap, &IID_ID2D1Image, (void **)&image);
1971 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Vista */, "Got unexpected hr %#lx.\n", hr);
1972 if (hr == S_OK)
1974 ID2D1DeviceContext *context;
1975 D2D1_POINT_2F offset;
1976 D2D1_RECT_F src_rect;
1978 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&context);
1979 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
1981 ID2D1RenderTarget_BeginDraw(rt);
1982 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1983 ID2D1RenderTarget_Clear(rt, &color);
1985 ID2D1RenderTarget_GetTransform(rt, &tmp_matrix);
1986 set_matrix_identity(&matrix);
1987 translate_matrix(&matrix, 20.0f, 12.0f);
1988 scale_matrix(&matrix, 2.0f, 6.0f);
1989 ID2D1RenderTarget_SetTransform(rt, &matrix);
1991 /* Crash on Windows 7+ */
1992 if (0)
1994 ID2D1DeviceContext_DrawImage(context, NULL, NULL, NULL, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
1995 D2D1_COMPOSITE_MODE_SOURCE_OVER);
1998 ID2D1DeviceContext_DrawImage(context, image, NULL, NULL, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
1999 D2D1_COMPOSITE_MODE_SOURCE_OVER);
2001 set_rect(&src_rect, 0.0f, 0.0f, image_size.width, image_size.height);
2003 ID2D1DeviceContext_DrawImage(context, image, NULL, &src_rect, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2004 D2D1_COMPOSITE_MODE_SOURCE_OVER);
2006 offset.x = -1;
2007 offset.y = -1;
2008 ID2D1DeviceContext_DrawImage(context, image, &offset, NULL, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2009 D2D1_COMPOSITE_MODE_SOURCE_OVER);
2011 offset.x = image_size.width * 2;
2012 offset.y = image_size.height;
2013 ID2D1DeviceContext_DrawImage(context, image, &offset, NULL, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2014 D2D1_COMPOSITE_MODE_SOURCE_OVER);
2016 offset.x = image_size.width * 3;
2017 set_rect(&src_rect, image_size.width / 2, image_size.height / 2, image_size.width, image_size.height);
2018 ID2D1DeviceContext_DrawImage(context, image, &offset, &src_rect, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2019 D2D1_COMPOSITE_MODE_SOURCE_OVER);
2021 offset.x = image_size.width * 4;
2022 set_rect(&src_rect, 0.0f, 0.0f, image_size.width * 2, image_size.height * 2);
2023 ID2D1DeviceContext_DrawImage(context, image, &offset, &src_rect, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2024 D2D1_COMPOSITE_MODE_SOURCE_OVER);
2026 offset.x = image_size.width * 5;
2027 set_rect(&src_rect, image_size.width, image_size.height, 0.0f, 0.0f);
2028 ID2D1DeviceContext_DrawImage(context, image, &offset, &src_rect, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2029 D2D1_COMPOSITE_MODE_SOURCE_OVER);
2031 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2032 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2033 match = compare_surface(&ctx, "95675fbc4a16404c9568d41b14e8f6be64240998");
2034 ok(match, "Surface does not match.\n");
2036 ID2D1RenderTarget_BeginDraw(rt);
2038 offset.x = image_size.width * 6;
2039 set_rect(&src_rect, 1.0f, 0.0f, 1.0f, image_size.height);
2040 ID2D1DeviceContext_DrawImage(context, image, &offset, &src_rect, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2041 D2D1_COMPOSITE_MODE_SOURCE_OVER);
2043 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2044 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2045 match = compare_surface(&ctx, "95675fbc4a16404c9568d41b14e8f6be64240998");
2046 ok(match, "Surface does not match.\n");
2048 ID2D1RenderTarget_SetTransform(rt, &tmp_matrix);
2049 ID2D1DeviceContext_Release(context);
2050 ID2D1Image_Release(image);
2053 /* Creating a brush with a NULL bitmap crashes on Vista, but works fine on
2054 * Windows 7+. */
2055 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
2056 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2057 ID2D1BitmapBrush_GetBitmap(brush, &tmp_bitmap);
2058 ok(tmp_bitmap == bitmap, "Got unexpected bitmap %p, expected %p.\n", tmp_bitmap, bitmap);
2059 ID2D1Bitmap_Release(tmp_bitmap);
2060 opacity = ID2D1BitmapBrush_GetOpacity(brush);
2061 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
2062 set_matrix_identity(&matrix);
2063 ID2D1BitmapBrush_GetTransform(brush, &tmp_matrix);
2064 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
2065 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2066 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
2067 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
2068 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
2069 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
2070 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
2071 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
2072 interpolation_mode = ID2D1BitmapBrush_GetInterpolationMode(brush);
2073 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
2074 "Got unexpected interpolation mode %#x.\n", interpolation_mode);
2075 ID2D1BitmapBrush_Release(brush);
2077 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
2078 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2079 set_matrix_identity(&matrix);
2080 translate_matrix(&matrix, 40.0f, 120.0f);
2081 scale_matrix(&matrix, 20.0f, 60.0f);
2082 ID2D1BitmapBrush_SetTransform(brush, &matrix);
2083 ID2D1BitmapBrush_SetInterpolationMode(brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
2085 ID2D1RenderTarget_BeginDraw(rt);
2087 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
2088 ID2D1RenderTarget_Clear(rt, &color);
2090 set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
2091 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
2093 set_matrix_identity(&matrix);
2094 scale_matrix(&matrix, 0.5f, 2.0f);
2095 translate_matrix(&matrix, 320.0f, 240.0f);
2096 rotate_matrix(&matrix, M_PI / 4.0f);
2097 ID2D1RenderTarget_SetTransform(rt, &matrix);
2098 set_matrix_identity(&matrix);
2099 translate_matrix(&matrix, -80.0f, -60.0f);
2100 scale_matrix(&matrix, 64.0f, 32.0f);
2101 ID2D1BitmapBrush_SetTransform(brush, &matrix);
2102 ID2D1BitmapBrush_SetOpacity(brush, 0.75f);
2103 set_rect(&dst_rect, -80.0f, -60.0f, 80.0f, 60.0f);
2104 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
2106 set_matrix_identity(&matrix);
2107 translate_matrix(&matrix, 200.0f, 120.0f);
2108 scale_matrix(&matrix, 20.0f, 60.0f);
2109 ID2D1RenderTarget_SetTransform(rt, &matrix);
2110 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f,
2111 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2112 set_rect(&dst_rect, -4.0f, 12.0f, -8.0f, 8.0f);
2113 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 0.75f,
2114 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2115 set_rect(&dst_rect, 0.0f, 8.0f, 4.0f, 12.0f);
2116 set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
2117 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
2118 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
2119 set_rect(&dst_rect, 4.0f, 12.0f, 12.0f, 20.0f);
2120 set_rect(&src_rect, 0.0f, 0.0f, image_size.width * 2, image_size.height * 2);
2121 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
2122 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
2123 set_rect(&dst_rect, 4.0f, 8.0f, 12.0f, 12.0f);
2124 set_rect(&src_rect, image_size.width / 2, image_size.height / 2, image_size.width, image_size.height);
2125 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
2126 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
2127 set_rect(&dst_rect, 0.0f, 4.0f, 4.0f, 8.0f);
2128 set_rect(&src_rect, image_size.width, 0.0f, 0.0f, image_size.height);
2129 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
2130 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
2132 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2133 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2134 match = compare_surface(&ctx, "f5d039c280fa33ba05496c9883192a34108efbbe");
2135 ok(match, "Surface does not match.\n");
2137 /* Invalid interpolation mode. */
2138 ID2D1RenderTarget_BeginDraw(rt);
2140 set_rect(&dst_rect, 4.0f, 8.0f, 8.0f, 12.0f);
2141 set_rect(&src_rect, 0.0f, 1.0f, image_size.width, 1.0f);
2142 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
2143 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
2145 set_rect(&dst_rect, 1.0f, 8.0f, 4.0f, 12.0f);
2146 set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
2147 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
2148 D2D1_BITMAP_INTERPOLATION_MODE_LINEAR + 1, &src_rect);
2150 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2151 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2152 match = compare_surface(&ctx, "f5d039c280fa33ba05496c9883192a34108efbbe");
2153 ok(match, "Surface does not match.\n");
2155 ID2D1RenderTarget_BeginDraw(rt);
2156 ID2D1RenderTarget_Clear(rt, &color);
2158 set_rect(&src_rect, image_size.width, 0.0f, 0.0f, image_size.height);
2159 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 1.0f,
2160 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
2162 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2163 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2164 match = compare_surface(&ctx, "59043096393570ad800dbcbfdd644394b79493bd");
2165 ok(match, "Surface does not match.\n");
2167 ID2D1RenderTarget_BeginDraw(rt);
2169 ID2D1RenderTarget_Clear(rt, &color);
2171 ID2D1BitmapBrush_SetOpacity(brush, 1.0f);
2172 for (i = 0; i < ARRAY_SIZE(extend_mode_tests); ++i)
2174 ID2D1BitmapBrush_SetExtendModeX(brush, extend_mode_tests[i].extend_mode_x);
2175 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
2176 ok(extend_mode == extend_mode_tests[i].extend_mode_x,
2177 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
2178 i, extend_mode, extend_mode_tests[i].extend_mode_x);
2179 ID2D1BitmapBrush_SetExtendModeY(brush, extend_mode_tests[i].extend_mode_y);
2180 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
2181 ok(extend_mode == extend_mode_tests[i].extend_mode_y,
2182 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
2183 i, extend_mode, extend_mode_tests[i].extend_mode_y);
2184 set_matrix_identity(&matrix);
2185 translate_matrix(&matrix, extend_mode_tests[i].translate_x, extend_mode_tests[i].translate_y);
2186 scale_matrix(&matrix, 0.5f, 0.5f);
2187 ID2D1BitmapBrush_SetTransform(brush, &matrix);
2188 ID2D1RenderTarget_FillRectangle(rt, &extend_mode_tests[i].rect, (ID2D1Brush *)brush);
2191 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2192 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2193 match = compare_surface(&ctx, "b4b775afecdae2d26642001f4faff73663bb8b31");
2194 ok(match, "Surface does not match.\n");
2196 ID2D1Bitmap_Release(bitmap);
2197 bitmap_desc.dpiX = 96.0f / 20.0f;
2198 bitmap_desc.dpiY = 96.0f / 60.0f;
2199 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2200 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2201 ID2D1BitmapBrush_SetBitmap(brush, bitmap);
2203 ID2D1RenderTarget_BeginDraw(rt);
2205 ID2D1RenderTarget_Clear(rt, &color);
2207 set_matrix_identity(&matrix);
2208 translate_matrix(&matrix, 40.0f, 120.0f);
2209 skew_matrix(&matrix, 0.125f, 2.0f);
2210 ID2D1RenderTarget_SetTransform(rt, &matrix);
2211 set_matrix_identity(&matrix);
2212 ID2D1BitmapBrush_SetTransform(brush, &matrix);
2213 set_rect(&dst_rect, 0.0f, 0.0f, 80.0f, 240.0f);
2214 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
2216 ID2D1RenderTarget_GetFactory(rt, &factory);
2218 set_rect(&dst_rect, -1.0f, -1.0f, 1.0f, 1.0f);
2219 hr = ID2D1Factory_CreateRectangleGeometry(factory, &dst_rect, &rectangle_geometry);
2220 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2222 set_matrix_identity(&matrix);
2223 translate_matrix(&matrix, 240.0f, 720.0f);
2224 scale_matrix(&matrix, 40.0f, 120.0f);
2225 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)rectangle_geometry,
2226 &matrix, &transformed_geometry);
2227 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2228 ID2D1RectangleGeometry_Release(rectangle_geometry);
2230 set_matrix_identity(&matrix);
2231 ID2D1RenderTarget_SetTransform(rt, &matrix);
2232 set_matrix_identity(&matrix);
2233 translate_matrix(&matrix, 200.0f, 600.0f);
2234 ID2D1BitmapBrush_SetTransform(brush, &matrix);
2235 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2236 ID2D1TransformedGeometry_Release(transformed_geometry);
2238 ID2D1Factory_Release(factory);
2240 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2241 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2242 match = compare_surface(&ctx, "cf7b90ba7b139fdfbe9347e1907d635cfb4ed197");
2243 ok(match, "Surface does not match.\n");
2245 if (SUCCEEDED(ID2D1BitmapBrush_QueryInterface(brush, &IID_ID2D1BitmapBrush1, (void **)&brush1)))
2247 D2D1_INTERPOLATION_MODE interpolation_mode1;
2249 interpolation_mode = ID2D1BitmapBrush1_GetInterpolationMode(brush1);
2250 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2251 "Unexpected interpolation mode %#x.\n", interpolation_mode);
2253 interpolation_mode1 = ID2D1BitmapBrush1_GetInterpolationMode1(brush1);
2254 ok(interpolation_mode1 == D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2255 "Unexpected interpolation mode %#x.\n", interpolation_mode1);
2257 ID2D1BitmapBrush1_SetInterpolationMode1(brush1, D2D1_INTERPOLATION_MODE_CUBIC);
2258 interpolation_mode = ID2D1BitmapBrush1_GetInterpolationMode(brush1);
2259 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
2260 "Unexpected interpolation mode %#x.\n", interpolation_mode);
2262 interpolation_mode1 = ID2D1BitmapBrush1_GetInterpolationMode1(brush1);
2263 ok(interpolation_mode1 == D2D1_INTERPOLATION_MODE_CUBIC,
2264 "Unexpected interpolation mode %#x.\n", interpolation_mode1);
2266 ID2D1BitmapBrush1_SetInterpolationMode1(brush1, 100);
2267 interpolation_mode1 = ID2D1BitmapBrush1_GetInterpolationMode1(brush1);
2268 ok(interpolation_mode1 == D2D1_INTERPOLATION_MODE_CUBIC,
2269 "Unexpected interpolation mode %#x.\n", interpolation_mode1);
2271 ID2D1BitmapBrush1_SetInterpolationMode(brush1, 100);
2272 interpolation_mode1 = ID2D1BitmapBrush1_GetInterpolationMode1(brush1);
2273 ok(interpolation_mode1 == D2D1_INTERPOLATION_MODE_CUBIC,
2274 "Unexpected interpolation mode %#x.\n", interpolation_mode1);
2276 ID2D1BitmapBrush1_SetInterpolationMode(brush1, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
2277 interpolation_mode = ID2D1BitmapBrush1_GetInterpolationMode(brush1);
2278 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2279 "Unexpected interpolation mode %#x.\n", interpolation_mode);
2281 interpolation_mode1 = ID2D1BitmapBrush1_GetInterpolationMode1(brush1);
2282 ok(interpolation_mode1 == D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
2283 "Unexpected interpolation mode %#x.\n", interpolation_mode1);
2285 ID2D1BitmapBrush1_Release(brush1);
2288 ID2D1BitmapBrush_Release(brush);
2289 refcount = ID2D1Bitmap_Release(bitmap);
2290 ok(!refcount, "Bitmap has %lu references left.\n", refcount);
2291 release_test_context(&ctx);
2294 static void test_image_brush(BOOL d3d11)
2296 D2D1_IMAGE_BRUSH_PROPERTIES image_brush_desc;
2297 D2D1_INTERPOLATION_MODE interp_mode;
2298 ID2D1DeviceContext *device_context;
2299 D2D1_BITMAP_PROPERTIES bitmap_desc;
2300 D2D1_BRUSH_PROPERTIES brush_desc;
2301 ID2D1Image *image, *tmp_image;
2302 struct d2d1_test_context ctx;
2303 D2D1_EXTEND_MODE extend_mode;
2304 D2D1_MATRIX_3X2_F matrix;
2305 ID2D1ImageBrush *brush;
2306 ID2D1Bitmap *bitmap;
2307 D2D1_SIZE_U size;
2308 D2D1_RECT_F rect;
2309 ULONG refcount;
2310 float opacity;
2311 HRESULT hr;
2312 BOOL match;
2314 static const DWORD bitmap_data[] =
2316 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
2317 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
2318 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
2319 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
2321 static const D2D1_MATRIX_3X2_F identity =
2323 1.0f, 0.0f,
2324 0.0f, 1.0f,
2325 0.0f, 0.0f,
2326 }}};
2328 if (!init_test_context(&ctx, d3d11))
2329 return;
2331 hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&device_context);
2332 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2334 set_size_u(&size, 4, 4);
2335 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2336 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2337 bitmap_desc.dpiX = 96.0f;
2338 bitmap_desc.dpiY = 96.0f;
2339 hr = ID2D1RenderTarget_CreateBitmap(ctx.rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2340 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2342 hr = ID2D1Bitmap_QueryInterface(bitmap, &IID_ID2D1Image, (void **)&image);
2343 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2345 /* Only image brush description is required. */
2346 set_rect(&image_brush_desc.sourceRectangle, 1.0f, 2.0f, 3.0f, 4.0f);
2347 image_brush_desc.extendModeX = D2D1_EXTEND_MODE_WRAP;
2348 image_brush_desc.extendModeY = D2D1_EXTEND_MODE_MIRROR;
2349 image_brush_desc.interpolationMode = D2D1_INTERPOLATION_MODE_LINEAR;
2351 hr = ID2D1DeviceContext_CreateImageBrush(device_context, NULL, &image_brush_desc, NULL, &brush);
2352 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2354 tmp_image = (void *)0xdeadbeef;
2355 ID2D1ImageBrush_GetImage(brush, &tmp_image);
2356 ok(!tmp_image, "Unexpected image %p.\n", image);
2358 opacity = ID2D1ImageBrush_GetOpacity(brush);
2359 ok(opacity == 1.0f, "Unexpected opacity %.8e.\n", opacity);
2360 ID2D1ImageBrush_GetTransform(brush, &matrix);
2361 ok(!memcmp(&matrix, &identity, sizeof(matrix)),
2362 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2363 matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32);
2365 ID2D1ImageBrush_GetSourceRectangle(brush, &rect);
2366 match = compare_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0);
2367 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2368 rect.left, rect.top, rect.right, rect.bottom);
2370 extend_mode = ID2D1ImageBrush_GetExtendModeX(brush);
2371 ok(extend_mode == D2D1_EXTEND_MODE_WRAP, "Unexpected extend mode %u.\n", extend_mode);
2372 extend_mode = ID2D1ImageBrush_GetExtendModeY(brush);
2373 ok(extend_mode == D2D1_EXTEND_MODE_MIRROR, "Unexpected extend mode %u.\n", extend_mode);
2374 interp_mode = ID2D1ImageBrush_GetInterpolationMode(brush);
2375 ok(interp_mode == D2D1_INTERPOLATION_MODE_LINEAR, "Unexpected interpolation mode %u.\n", interp_mode);
2377 ID2D1ImageBrush_Release(brush);
2379 /* Custom brush description and image pointer. */
2380 brush_desc.opacity = 2.0f;
2381 set_matrix_identity(&brush_desc.transform);
2382 scale_matrix(&brush_desc.transform, 2.0f, 3.0f);
2384 hr = ID2D1DeviceContext_CreateImageBrush(device_context, image, &image_brush_desc, &brush_desc, &brush);
2385 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2387 ID2D1ImageBrush_GetImage(brush, &tmp_image);
2388 ok(tmp_image == image, "Got unexpected image %p, expected %p.\n", tmp_image, image);
2389 ID2D1Image_Release(tmp_image);
2391 opacity = ID2D1ImageBrush_GetOpacity(brush);
2392 ok(opacity == 2.0f, "Unexpected opacity %.8e.\n", opacity);
2393 ID2D1ImageBrush_GetTransform(brush, &matrix);
2394 ok(!memcmp(&matrix, &brush_desc.transform, sizeof(matrix)),
2395 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2396 matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32);
2398 ID2D1ImageBrush_Release(brush);
2400 ID2D1Image_Release(image);
2401 refcount = ID2D1Bitmap_Release(bitmap);
2402 ok(!refcount, "Bitmap has %lu references left.\n", refcount);
2404 ID2D1DeviceContext_Release(device_context);
2405 release_test_context(&ctx);
2408 static void test_linear_brush(BOOL d3d11)
2410 D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES gradient_properties;
2411 ID2D1GradientStopCollection *gradient, *tmp_gradient;
2412 ID2D1TransformedGeometry *transformed_geometry;
2413 ID2D1RectangleGeometry *rectangle_geometry;
2414 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
2415 ID2D1LinearGradientBrush *brush;
2416 struct d2d1_test_context ctx;
2417 struct resource_readback rb;
2418 ID2D1RenderTarget *rt;
2419 ID2D1Factory *factory;
2420 D2D1_COLOR_F colour;
2421 D2D1_POINT_2F p;
2422 unsigned int i;
2423 ULONG refcount;
2424 D2D1_RECT_F r;
2425 float opacity;
2426 HRESULT hr;
2428 static const D2D1_GRADIENT_STOP stops[] =
2430 {0.0f, {1.0f, 0.0f, 0.0f, 1.0f}},
2431 {0.5f, {0.0f, 1.0f, 0.0f, 1.0f}},
2432 {1.0f, {0.0f, 0.0f, 1.0f, 1.0f}},
2434 static const struct
2436 unsigned int x, y;
2437 DWORD colour;
2439 test1[] =
2441 {80, 80, 0xff857a00}, {240, 80, 0xff926d00}, {400, 80, 0xff9f6000}, {560, 80, 0xffac5300},
2442 {80, 240, 0xff00eb14}, {240, 240, 0xff00f807}, {400, 240, 0xff06f900}, {560, 240, 0xff13ec00},
2443 {80, 400, 0xff0053ac}, {240, 400, 0xff005fa0}, {400, 400, 0xff006c93}, {560, 400, 0xff007986},
2445 test2[] =
2447 { 40, 30, 0xff005ba4}, {120, 30, 0xffffffff}, { 40, 60, 0xffffffff}, { 80, 60, 0xff00b44b},
2448 {120, 60, 0xff006c93}, {200, 60, 0xffffffff}, { 40, 90, 0xffffffff}, {120, 90, 0xff0ef100},
2449 {160, 90, 0xff00c53a}, {200, 90, 0xffffffff}, { 80, 120, 0xffffffff}, {120, 120, 0xffaf5000},
2450 {160, 120, 0xff679800}, {200, 120, 0xff1fe000}, {240, 120, 0xffffffff}, {160, 150, 0xffffffff},
2451 {200, 150, 0xffc03e00}, {240, 150, 0xffffffff}, {280, 150, 0xffffffff}, {320, 150, 0xffffffff},
2452 {240, 180, 0xffffffff}, {280, 180, 0xffff4040}, {320, 180, 0xffff4040}, {380, 180, 0xffffffff},
2453 {200, 210, 0xffffffff}, {240, 210, 0xffa99640}, {280, 210, 0xffb28d40}, {320, 210, 0xffbb8440},
2454 {360, 210, 0xffc47b40}, {400, 210, 0xffffffff}, {200, 240, 0xffffffff}, {280, 240, 0xff41fe40},
2455 {320, 240, 0xff49f540}, {360, 240, 0xff52ec40}, {440, 240, 0xffffffff}, {240, 270, 0xffffffff},
2456 {280, 270, 0xff408eb0}, {320, 270, 0xff4097a7}, {360, 270, 0xff40a19e}, {440, 270, 0xffffffff},
2457 {280, 300, 0xffffffff}, {320, 300, 0xff4040ff}, {360, 300, 0xff4040ff}, {400, 300, 0xff406ad4},
2458 {440, 300, 0xff4061de}, {480, 300, 0xff4057e7}, {520, 300, 0xff404ef1}, {280, 330, 0xffffffff},
2459 {360, 330, 0xffffffff}, {400, 330, 0xff40c17e}, {440, 330, 0xff40b788}, {480, 330, 0xff40ae91},
2460 {520, 330, 0xff40a49b}, {400, 360, 0xff57e740}, {440, 360, 0xff4ef140}, {480, 360, 0xff44fb40},
2461 {520, 360, 0xff40fa45}, {400, 390, 0xffae9140}, {440, 390, 0xffa49b40}, {480, 390, 0xff9aa540},
2462 {520, 390, 0xff90ae40},
2465 if (!init_test_context(&ctx, d3d11))
2466 return;
2468 rt = ctx.rt;
2469 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
2470 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2472 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops, ARRAY_SIZE(stops),
2473 D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &gradient);
2474 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2476 set_point(&gradient_properties.startPoint, 320.0f, 0.0f);
2477 set_point(&gradient_properties.endPoint, 0.0f, 960.0f);
2478 hr = ID2D1RenderTarget_CreateLinearGradientBrush(rt, &gradient_properties, NULL, gradient, &brush);
2479 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2481 opacity = ID2D1LinearGradientBrush_GetOpacity(brush);
2482 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
2483 set_matrix_identity(&matrix);
2484 ID2D1LinearGradientBrush_GetTransform(brush, &tmp_matrix);
2485 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
2486 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2487 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
2488 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
2489 p = ID2D1LinearGradientBrush_GetStartPoint(brush);
2490 ok(compare_point(&p, 320.0f, 0.0f, 0), "Got unexpected start point {%.8e, %.8e}.\n", p.x, p.y);
2491 p = ID2D1LinearGradientBrush_GetEndPoint(brush);
2492 ok(compare_point(&p, 0.0f, 960.0f, 0), "Got unexpected end point {%.8e, %.8e}.\n", p.x, p.y);
2493 ID2D1LinearGradientBrush_GetGradientStopCollection(brush, &tmp_gradient);
2494 ok(tmp_gradient == gradient, "Got unexpected gradient %p, expected %p.\n", tmp_gradient, gradient);
2495 ID2D1GradientStopCollection_Release(tmp_gradient);
2497 ID2D1RenderTarget_BeginDraw(rt);
2499 set_color(&colour, 1.0f, 1.0f, 1.0f, 1.0f);
2500 ID2D1RenderTarget_Clear(rt, &colour);
2502 set_rect(&r, 0.0f, 0.0f, 320.0f, 960.0f);
2503 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2505 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2506 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2508 get_surface_readback(&ctx, &rb);
2509 for (i = 0; i < ARRAY_SIZE(test1); ++i)
2511 DWORD colour;
2513 colour = get_readback_colour(&rb, test1[i].x, test1[i].y);
2514 ok(compare_colour(colour, test1[i].colour, 1),
2515 "Got unexpected colour 0x%08lx at position {%u, %u}.\n",
2516 colour, test1[i].x, test1[i].y);
2518 release_resource_readback(&rb);
2520 ID2D1RenderTarget_BeginDraw(rt);
2522 ID2D1RenderTarget_Clear(rt, &colour);
2524 set_matrix_identity(&matrix);
2525 skew_matrix(&matrix, 0.2146f, 1.575f);
2526 ID2D1RenderTarget_SetTransform(rt, &matrix);
2528 set_matrix_identity(&matrix);
2529 translate_matrix(&matrix, 0.0f, 240.0f);
2530 scale_matrix(&matrix, 0.25f, -0.25f);
2531 ID2D1LinearGradientBrush_SetTransform(brush, &matrix);
2533 set_rect(&r, 0.0f, 0.0f, 80.0f, 240.0f);
2534 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2536 set_matrix_identity(&matrix);
2537 scale_matrix(&matrix, 0.5f, 2.0f);
2538 translate_matrix(&matrix, 320.0f, 240.0f);
2539 rotate_matrix(&matrix, M_PI / 4.0f);
2540 ID2D1RenderTarget_SetTransform(rt, &matrix);
2542 set_matrix_identity(&matrix);
2543 translate_matrix(&matrix, 0.0f, -50.0f);
2544 scale_matrix(&matrix, 0.1f, 0.1f);
2545 rotate_matrix(&matrix, -M_PI / 3.0f);
2546 ID2D1LinearGradientBrush_SetTransform(brush, &matrix);
2548 ID2D1LinearGradientBrush_SetOpacity(brush, 0.75f);
2549 set_rect(&r, -80.0f, -60.0f, 80.0f, 60.0f);
2550 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2552 ID2D1RenderTarget_GetFactory(rt, &factory);
2554 set_rect(&r, -1.0f, -1.0f, 1.0f, 1.0f);
2555 hr = ID2D1Factory_CreateRectangleGeometry(factory, &r, &rectangle_geometry);
2556 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2558 set_matrix_identity(&matrix);
2559 translate_matrix(&matrix, 228.5f, 714.0f);
2560 scale_matrix(&matrix, 40.0f, 120.0f);
2561 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)rectangle_geometry,
2562 &matrix, &transformed_geometry);
2563 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2564 ID2D1RectangleGeometry_Release(rectangle_geometry);
2566 set_matrix_identity(&matrix);
2567 ID2D1RenderTarget_SetTransform(rt, &matrix);
2568 ID2D1LinearGradientBrush_SetTransform(brush, &matrix);
2569 set_point(&p, 188.5f, 834.0f);
2570 ID2D1LinearGradientBrush_SetStartPoint(brush, p);
2571 set_point(&p, 268.5f, 594.0f);
2572 ID2D1LinearGradientBrush_SetEndPoint(brush, p);
2573 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2574 ID2D1TransformedGeometry_Release(transformed_geometry);
2576 ID2D1Factory_Release(factory);
2578 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2579 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2581 get_surface_readback(&ctx, &rb);
2582 for (i = 0; i < ARRAY_SIZE(test2); ++i)
2584 DWORD colour;
2586 colour = get_readback_colour(&rb, test2[i].x, test2[i].y);
2587 ok(compare_colour(colour, test2[i].colour, 1),
2588 "Got unexpected colour 0x%08lx at position {%u, %u}.\n",
2589 colour, test2[i].x, test2[i].y);
2591 release_resource_readback(&rb);
2593 ID2D1LinearGradientBrush_Release(brush);
2594 refcount = ID2D1GradientStopCollection_Release(gradient);
2595 ok(!refcount, "Gradient has %lu references left.\n", refcount);
2596 release_test_context(&ctx);
2599 static void test_radial_brush(BOOL d3d11)
2601 D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES gradient_properties;
2602 ID2D1GradientStopCollection *gradient, *tmp_gradient;
2603 ID2D1TransformedGeometry *transformed_geometry;
2604 ID2D1RectangleGeometry *rectangle_geometry;
2605 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
2606 ID2D1RadialGradientBrush *brush;
2607 struct d2d1_test_context ctx;
2608 struct resource_readback rb;
2609 ID2D1RenderTarget *rt;
2610 ID2D1Factory *factory;
2611 D2D1_COLOR_F colour;
2612 D2D1_POINT_2F p;
2613 unsigned int i;
2614 ULONG refcount;
2615 D2D1_RECT_F r;
2616 HRESULT hr;
2617 float f;
2619 static const D2D1_GRADIENT_STOP stops[] =
2621 {0.0f, {1.0f, 0.0f, 0.0f, 1.0f}},
2622 {0.5f, {0.0f, 1.0f, 0.0f, 1.0f}},
2623 {1.0f, {0.0f, 0.0f, 1.0f, 1.0f}},
2625 static const struct
2627 unsigned int x, y;
2628 DWORD colour;
2630 test1[] =
2632 {80, 80, 0xff0000ff}, {240, 80, 0xff00a857}, {400, 80, 0xff00d728}, {560, 80, 0xff0000ff},
2633 {80, 240, 0xff006699}, {240, 240, 0xff29d600}, {400, 240, 0xff966900}, {560, 240, 0xff00a55a},
2634 {80, 400, 0xff0000ff}, {240, 400, 0xff006e91}, {400, 400, 0xff007d82}, {560, 400, 0xff0000ff},
2636 test2[] =
2638 { 40, 30, 0xff000df2}, {120, 30, 0xffffffff}, { 40, 60, 0xffffffff}, { 80, 60, 0xff00b04f},
2639 {120, 60, 0xff007689}, {200, 60, 0xffffffff}, { 40, 90, 0xffffffff}, {120, 90, 0xff47b800},
2640 {160, 90, 0xff00c13e}, {200, 90, 0xffffffff}, { 80, 120, 0xffffffff}, {120, 120, 0xff0000ff},
2641 {160, 120, 0xff6f9000}, {200, 120, 0xff00718e}, {240, 120, 0xffffffff}, {160, 150, 0xffffffff},
2642 {200, 150, 0xff00609f}, {240, 150, 0xffffffff}, {280, 150, 0xffffffff}, {320, 150, 0xffffffff},
2643 {240, 180, 0xffffffff}, {280, 180, 0xff4040ff}, {320, 180, 0xff40b788}, {380, 180, 0xffffffff},
2644 {200, 210, 0xffffffff}, {240, 210, 0xff4040ff}, {280, 210, 0xff4040ff}, {320, 210, 0xff76c940},
2645 {360, 210, 0xff40cc73}, {400, 210, 0xffffffff}, {200, 240, 0xffffffff}, {280, 240, 0xff4061de},
2646 {320, 240, 0xff9fa040}, {360, 240, 0xff404af5}, {440, 240, 0xffffffff}, {240, 270, 0xffffffff},
2647 {280, 270, 0xff40aa95}, {320, 270, 0xff4ef140}, {360, 270, 0xff4040ff}, {440, 270, 0xffffffff},
2648 {280, 300, 0xffffffff}, {320, 300, 0xff4093ac}, {360, 300, 0xff4040ff}, {400, 300, 0xff4040ff},
2649 {440, 300, 0xff404af5}, {480, 300, 0xff4045fa}, {520, 300, 0xff4040ff}, {280, 330, 0xffffffff},
2650 {360, 330, 0xffffffff}, {400, 330, 0xff4069d6}, {440, 330, 0xff40c579}, {480, 330, 0xff40e956},
2651 {520, 330, 0xff4072cd}, {400, 360, 0xff408ab4}, {440, 360, 0xff49f540}, {480, 360, 0xffb98640},
2652 {520, 360, 0xff40dc62}, {400, 390, 0xff405ee1}, {440, 390, 0xff40d56a}, {480, 390, 0xff62dd40},
2653 {520, 390, 0xff4059e6},
2656 if (!init_test_context(&ctx, d3d11))
2657 return;
2659 rt = ctx.rt;
2660 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
2661 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2663 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops, ARRAY_SIZE(stops),
2664 D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &gradient);
2665 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2667 set_point(&gradient_properties.center, 160.0f, 480.0f);
2668 set_point(&gradient_properties.gradientOriginOffset, 40.0f, -120.0f);
2669 gradient_properties.radiusX = 160.0f;
2670 gradient_properties.radiusY = 480.0f;
2671 hr = ID2D1RenderTarget_CreateRadialGradientBrush(rt, &gradient_properties, NULL, gradient, &brush);
2672 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2674 f = ID2D1RadialGradientBrush_GetOpacity(brush);
2675 ok(f == 1.0f, "Got unexpected opacity %.8e.\n", f);
2676 set_matrix_identity(&matrix);
2677 ID2D1RadialGradientBrush_GetTransform(brush, &tmp_matrix);
2678 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
2679 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2680 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
2681 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
2682 p = ID2D1RadialGradientBrush_GetCenter(brush);
2683 ok(compare_point(&p, 160.0f, 480.0f, 0), "Got unexpected center {%.8e, %.8e}.\n", p.x, p.y);
2684 p = ID2D1RadialGradientBrush_GetGradientOriginOffset(brush);
2685 ok(compare_point(&p, 40.0f, -120.0f, 0), "Got unexpected origin offset {%.8e, %.8e}.\n", p.x, p.y);
2686 f = ID2D1RadialGradientBrush_GetRadiusX(brush);
2687 ok(compare_float(f, 160.0f, 0), "Got unexpected x-radius %.8e.\n", f);
2688 f = ID2D1RadialGradientBrush_GetRadiusY(brush);
2689 ok(compare_float(f, 480.0f, 0), "Got unexpected y-radius %.8e.\n", f);
2690 ID2D1RadialGradientBrush_GetGradientStopCollection(brush, &tmp_gradient);
2691 ok(tmp_gradient == gradient, "Got unexpected gradient %p, expected %p.\n", tmp_gradient, gradient);
2692 ID2D1GradientStopCollection_Release(tmp_gradient);
2694 ID2D1RenderTarget_BeginDraw(rt);
2696 set_color(&colour, 1.0f, 1.0f, 1.0f, 1.0f);
2697 ID2D1RenderTarget_Clear(rt, &colour);
2699 set_rect(&r, 0.0f, 0.0f, 320.0f, 960.0f);
2700 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2702 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2703 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2705 get_surface_readback(&ctx, &rb);
2706 for (i = 0; i < ARRAY_SIZE(test1); ++i)
2708 DWORD colour;
2710 colour = get_readback_colour(&rb, test1[i].x, test1[i].y);
2711 ok(compare_colour(colour, test1[i].colour, 1),
2712 "Got unexpected colour 0x%08lx at position {%u, %u}.\n",
2713 colour, test1[i].x, test1[i].y);
2715 release_resource_readback(&rb);
2717 ID2D1RenderTarget_BeginDraw(rt);
2719 ID2D1RenderTarget_Clear(rt, &colour);
2721 set_matrix_identity(&matrix);
2722 skew_matrix(&matrix, 0.2146f, 1.575f);
2723 ID2D1RenderTarget_SetTransform(rt, &matrix);
2725 set_matrix_identity(&matrix);
2726 translate_matrix(&matrix, 0.0f, 240.0f);
2727 scale_matrix(&matrix, 0.25f, -0.25f);
2728 ID2D1RadialGradientBrush_SetTransform(brush, &matrix);
2730 set_rect(&r, 0.0f, 0.0f, 80.0f, 240.0f);
2731 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2733 set_matrix_identity(&matrix);
2734 scale_matrix(&matrix, 0.5f, 2.0f);
2735 translate_matrix(&matrix, 320.0f, 240.0f);
2736 rotate_matrix(&matrix, M_PI / 4.0f);
2737 ID2D1RenderTarget_SetTransform(rt, &matrix);
2739 set_matrix_identity(&matrix);
2740 translate_matrix(&matrix, -75.0f, -50.0f);
2741 scale_matrix(&matrix, 0.15f, 0.5f);
2742 rotate_matrix(&matrix, -M_PI / 3.0f);
2743 ID2D1RadialGradientBrush_SetTransform(brush, &matrix);
2745 ID2D1RadialGradientBrush_SetOpacity(brush, 0.75f);
2746 set_rect(&r, -80.0f, -60.0f, 80.0f, 60.0f);
2747 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2749 ID2D1RenderTarget_GetFactory(rt, &factory);
2751 set_rect(&r, -1.0f, -1.0f, 1.0f, 1.0f);
2752 hr = ID2D1Factory_CreateRectangleGeometry(factory, &r, &rectangle_geometry);
2753 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2755 set_matrix_identity(&matrix);
2756 translate_matrix(&matrix, 228.5f, 714.0f);
2757 scale_matrix(&matrix, 40.0f, 120.0f);
2758 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)rectangle_geometry,
2759 &matrix, &transformed_geometry);
2760 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2761 ID2D1RectangleGeometry_Release(rectangle_geometry);
2763 set_matrix_identity(&matrix);
2764 ID2D1RenderTarget_SetTransform(rt, &matrix);
2765 ID2D1RadialGradientBrush_SetTransform(brush, &matrix);
2766 set_point(&p, 228.5f, 714.0f);
2767 ID2D1RadialGradientBrush_SetCenter(brush, p);
2768 ID2D1RadialGradientBrush_SetRadiusX(brush, -40.0f);
2769 ID2D1RadialGradientBrush_SetRadiusY(brush, 120.0f);
2770 set_point(&p, 20.0f, 30.0f);
2771 ID2D1RadialGradientBrush_SetGradientOriginOffset(brush, p);
2772 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2773 ID2D1TransformedGeometry_Release(transformed_geometry);
2775 ID2D1Factory_Release(factory);
2777 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2778 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2780 get_surface_readback(&ctx, &rb);
2781 for (i = 0; i < ARRAY_SIZE(test2); ++i)
2783 DWORD colour;
2785 colour = get_readback_colour(&rb, test2[i].x, test2[i].y);
2786 ok(compare_colour(colour, test2[i].colour, 1),
2787 "Got unexpected colour 0x%08lx at position {%u, %u}.\n",
2788 colour, test2[i].x, test2[i].y);
2790 release_resource_readback(&rb);
2792 ID2D1RadialGradientBrush_Release(brush);
2793 refcount = ID2D1GradientStopCollection_Release(gradient);
2794 ok(!refcount, "Gradient has %lu references left.\n", refcount);
2795 release_test_context(&ctx);
2798 static void fill_geometry_sink(ID2D1GeometrySink *sink, unsigned int hollow_count)
2800 D2D1_FIGURE_BEGIN begin;
2801 unsigned int idx = 0;
2802 D2D1_POINT_2F point;
2804 set_point(&point, 15.0f, 20.0f);
2805 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2806 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2807 line_to(sink, 55.0f, 20.0f);
2808 line_to(sink, 55.0f, 220.0f);
2809 line_to(sink, 25.0f, 220.0f);
2810 line_to(sink, 25.0f, 100.0f);
2811 line_to(sink, 75.0f, 100.0f);
2812 line_to(sink, 75.0f, 300.0f);
2813 line_to(sink, 5.0f, 300.0f);
2814 line_to(sink, 5.0f, 60.0f);
2815 line_to(sink, 45.0f, 60.0f);
2816 line_to(sink, 45.0f, 180.0f);
2817 line_to(sink, 35.0f, 180.0f);
2818 line_to(sink, 35.0f, 140.0f);
2819 line_to(sink, 65.0f, 140.0f);
2820 line_to(sink, 65.0f, 260.0f);
2821 line_to(sink, 15.0f, 260.0f);
2822 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2824 set_point(&point, 155.0f, 300.0f);
2825 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2826 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2827 line_to(sink, 155.0f, 160.0f);
2828 line_to(sink, 85.0f, 160.0f);
2829 line_to(sink, 85.0f, 300.0f);
2830 line_to(sink, 120.0f, 300.0f);
2831 line_to(sink, 120.0f, 20.0f);
2832 line_to(sink, 155.0f, 20.0f);
2833 line_to(sink, 155.0f, 160.0f);
2834 line_to(sink, 85.0f, 160.0f);
2835 line_to(sink, 85.0f, 20.0f);
2836 line_to(sink, 120.0f, 20.0f);
2837 line_to(sink, 120.0f, 300.0f);
2838 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2840 set_point(&point, 165.0f, 20.0f);
2841 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2842 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2843 line_to(sink, 165.0f, 300.0f);
2844 line_to(sink, 235.0f, 300.0f);
2845 line_to(sink, 235.0f, 20.0f);
2846 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2847 set_point(&point, 225.0f, 60.0f);
2848 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2849 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2850 line_to(sink, 225.0f, 260.0f);
2851 line_to(sink, 175.0f, 260.0f);
2852 line_to(sink, 175.0f, 60.0f);
2853 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2854 set_point(&point, 215.0f, 220.0f);
2855 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2856 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2857 line_to(sink, 185.0f, 220.0f);
2858 line_to(sink, 185.0f, 100.0f);
2859 line_to(sink, 215.0f, 100.0f);
2860 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2861 set_point(&point, 195.0f, 180.0f);
2862 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2863 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2864 line_to(sink, 205.0f, 180.0f);
2865 line_to(sink, 205.0f, 140.0f);
2866 line_to(sink, 195.0f, 140.0f);
2867 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2870 static void fill_geometry_sink_bezier(ID2D1GeometrySink *sink, unsigned int hollow_count)
2872 D2D1_FIGURE_BEGIN begin;
2873 unsigned int idx = 0;
2874 D2D1_POINT_2F point;
2876 set_point(&point, 5.0f, 160.0f);
2877 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2878 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2879 quadratic_to(sink, 40.0f, 160.0f, 40.0f, 20.0f);
2880 quadratic_to(sink, 40.0f, 160.0f, 75.0f, 160.0f);
2881 quadratic_to(sink, 40.0f, 160.0f, 40.0f, 300.0f);
2882 quadratic_to(sink, 40.0f, 160.0f, 5.0f, 160.0f);
2883 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2885 set_point(&point, 20.0f, 160.0f);
2886 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2887 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2888 quadratic_to(sink, 20.0f, 80.0f, 40.0f, 80.0f);
2889 quadratic_to(sink, 60.0f, 80.0f, 60.0f, 160.0f);
2890 quadratic_to(sink, 60.0f, 240.0f, 40.0f, 240.0f);
2891 quadratic_to(sink, 20.0f, 240.0f, 20.0f, 160.0f);
2892 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2894 set_point(&point, 5.0f, 612.0f);
2895 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2896 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2897 quadratic_to(sink, 40.0f, 612.0f, 40.0f, 752.0f);
2898 quadratic_to(sink, 40.0f, 612.0f, 75.0f, 612.0f);
2899 quadratic_to(sink, 40.0f, 612.0f, 40.0f, 472.0f);
2900 quadratic_to(sink, 40.0f, 612.0f, 5.0f, 612.0f);
2901 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2903 set_point(&point, 20.0f, 612.0f);
2904 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2905 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2906 quadratic_to(sink, 20.0f, 692.0f, 40.0f, 692.0f);
2907 quadratic_to(sink, 60.0f, 692.0f, 60.0f, 612.0f);
2908 quadratic_to(sink, 60.0f, 532.0f, 40.0f, 532.0f);
2909 quadratic_to(sink, 20.0f, 532.0f, 20.0f, 612.0f);
2910 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2913 static void test_path_geometry(BOOL d3d11)
2915 ID2D1TransformedGeometry *transformed_geometry;
2916 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
2917 ID2D1GeometrySink *sink, *tmp_sink;
2918 struct geometry_sink simplify_sink;
2919 D2D1_POINT_2F point = {0.0f, 0.0f};
2920 struct d2d1_test_context ctx;
2921 ID2D1SolidColorBrush *brush;
2922 ID2D1PathGeometry *geometry;
2923 ID2D1Geometry *tmp_geometry;
2924 ID2D1RenderTarget *rt;
2925 ID2D1Factory *factory;
2926 BOOL match, contains;
2927 D2D1_COLOR_F color;
2928 D2D1_RECT_F rect;
2929 UINT32 count;
2930 HRESULT hr;
2932 static const struct geometry_segment expected_segments[] =
2934 /* Figure 0. */
2935 {SEGMENT_LINE, {{{ 55.0f, 20.0f}}}},
2936 {SEGMENT_LINE, {{{ 55.0f, 220.0f}}}},
2937 {SEGMENT_LINE, {{{ 25.0f, 220.0f}}}},
2938 {SEGMENT_LINE, {{{ 25.0f, 100.0f}}}},
2939 {SEGMENT_LINE, {{{ 75.0f, 100.0f}}}},
2940 {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}},
2941 {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}},
2942 {SEGMENT_LINE, {{{ 5.0f, 60.0f}}}},
2943 {SEGMENT_LINE, {{{ 45.0f, 60.0f}}}},
2944 {SEGMENT_LINE, {{{ 45.0f, 180.0f}}}},
2945 {SEGMENT_LINE, {{{ 35.0f, 180.0f}}}},
2946 {SEGMENT_LINE, {{{ 35.0f, 140.0f}}}},
2947 {SEGMENT_LINE, {{{ 65.0f, 140.0f}}}},
2948 {SEGMENT_LINE, {{{ 65.0f, 260.0f}}}},
2949 {SEGMENT_LINE, {{{ 15.0f, 260.0f}}}},
2950 /* Figure 1. */
2951 {SEGMENT_LINE, {{{155.0f, 160.0f}}}},
2952 {SEGMENT_LINE, {{{ 85.0f, 160.0f}}}},
2953 {SEGMENT_LINE, {{{ 85.0f, 300.0f}}}},
2954 {SEGMENT_LINE, {{{120.0f, 300.0f}}}},
2955 {SEGMENT_LINE, {{{120.0f, 20.0f}}}},
2956 {SEGMENT_LINE, {{{155.0f, 20.0f}}}},
2957 {SEGMENT_LINE, {{{155.0f, 160.0f}}}},
2958 {SEGMENT_LINE, {{{ 85.0f, 160.0f}}}},
2959 {SEGMENT_LINE, {{{ 85.0f, 20.0f}}}},
2960 {SEGMENT_LINE, {{{120.0f, 20.0f}}}},
2961 {SEGMENT_LINE, {{{120.0f, 300.0f}}}},
2962 /* Figure 2. */
2963 {SEGMENT_LINE, {{{165.0f, 300.0f}}}},
2964 {SEGMENT_LINE, {{{235.0f, 300.0f}}}},
2965 {SEGMENT_LINE, {{{235.0f, 20.0f}}}},
2966 /* Figure 3. */
2967 {SEGMENT_LINE, {{{225.0f, 260.0f}}}},
2968 {SEGMENT_LINE, {{{175.0f, 260.0f}}}},
2969 {SEGMENT_LINE, {{{175.0f, 60.0f}}}},
2970 /* Figure 4. */
2971 {SEGMENT_LINE, {{{185.0f, 220.0f}}}},
2972 {SEGMENT_LINE, {{{185.0f, 100.0f}}}},
2973 {SEGMENT_LINE, {{{215.0f, 100.0f}}}},
2974 /* Figure 5. */
2975 {SEGMENT_LINE, {{{205.0f, 180.0f}}}},
2976 {SEGMENT_LINE, {{{205.0f, 140.0f}}}},
2977 {SEGMENT_LINE, {{{195.0f, 140.0f}}}},
2978 /* Figure 6. */
2979 {SEGMENT_LINE, {{{135.0f, 620.0f}}}},
2980 {SEGMENT_LINE, {{{135.0f, 420.0f}}}},
2981 {SEGMENT_LINE, {{{105.0f, 420.0f}}}},
2982 {SEGMENT_LINE, {{{105.0f, 540.0f}}}},
2983 {SEGMENT_LINE, {{{155.0f, 540.0f}}}},
2984 {SEGMENT_LINE, {{{155.0f, 340.0f}}}},
2985 {SEGMENT_LINE, {{{ 85.0f, 340.0f}}}},
2986 {SEGMENT_LINE, {{{ 85.0f, 580.0f}}}},
2987 {SEGMENT_LINE, {{{125.0f, 580.0f}}}},
2988 {SEGMENT_LINE, {{{125.0f, 460.0f}}}},
2989 {SEGMENT_LINE, {{{115.0f, 460.0f}}}},
2990 {SEGMENT_LINE, {{{115.0f, 500.0f}}}},
2991 {SEGMENT_LINE, {{{145.0f, 500.0f}}}},
2992 {SEGMENT_LINE, {{{145.0f, 380.0f}}}},
2993 {SEGMENT_LINE, {{{ 95.0f, 380.0f}}}},
2994 /* Figure 7. */
2995 {SEGMENT_LINE, {{{235.0f, 480.0f}}}},
2996 {SEGMENT_LINE, {{{165.0f, 480.0f}}}},
2997 {SEGMENT_LINE, {{{165.0f, 340.0f}}}},
2998 {SEGMENT_LINE, {{{200.0f, 340.0f}}}},
2999 {SEGMENT_LINE, {{{200.0f, 620.0f}}}},
3000 {SEGMENT_LINE, {{{235.0f, 620.0f}}}},
3001 {SEGMENT_LINE, {{{235.0f, 480.0f}}}},
3002 {SEGMENT_LINE, {{{165.0f, 480.0f}}}},
3003 {SEGMENT_LINE, {{{165.0f, 620.0f}}}},
3004 {SEGMENT_LINE, {{{200.0f, 620.0f}}}},
3005 {SEGMENT_LINE, {{{200.0f, 340.0f}}}},
3006 /* Figure 8. */
3007 {SEGMENT_LINE, {{{245.0f, 340.0f}}}},
3008 {SEGMENT_LINE, {{{315.0f, 340.0f}}}},
3009 {SEGMENT_LINE, {{{315.0f, 620.0f}}}},
3010 /* Figure 9. */
3011 {SEGMENT_LINE, {{{305.0f, 380.0f}}}},
3012 {SEGMENT_LINE, {{{255.0f, 380.0f}}}},
3013 {SEGMENT_LINE, {{{255.0f, 580.0f}}}},
3014 /* Figure 10. */
3015 {SEGMENT_LINE, {{{265.0f, 420.0f}}}},
3016 {SEGMENT_LINE, {{{265.0f, 540.0f}}}},
3017 {SEGMENT_LINE, {{{295.0f, 540.0f}}}},
3018 /* Figure 11. */
3019 {SEGMENT_LINE, {{{285.0f, 460.0f}}}},
3020 {SEGMENT_LINE, {{{285.0f, 500.0f}}}},
3021 {SEGMENT_LINE, {{{275.0f, 500.0f}}}},
3022 /* Figure 12. */
3023 {SEGMENT_BEZIER, {{{2.83333340e+01f, 1.60000000e+02f},
3024 {4.00000000e+01f, 1.13333336e+02f},
3025 {4.00000000e+01f, 2.00000000e+01f}}}},
3026 {SEGMENT_BEZIER, {{{4.00000000e+01f, 1.13333336e+02f},
3027 {5.16666641e+01f, 1.60000000e+02f},
3028 {7.50000000e+01f, 1.60000000e+02f}}}},
3029 {SEGMENT_BEZIER, {{{5.16666641e+01f, 1.60000000e+02f},
3030 {4.00000000e+01f, 2.06666656e+02f},
3031 {4.00000000e+01f, 3.00000000e+02f}}}},
3032 {SEGMENT_BEZIER, {{{4.00000000e+01f, 2.06666656e+02f},
3033 {2.83333340e+01f, 1.60000000e+02f},
3034 {5.00000000e+00f, 1.60000000e+02f}}}},
3035 /* Figure 13. */
3036 {SEGMENT_BEZIER, {{{2.00000000e+01f, 1.06666664e+02f},
3037 {2.66666660e+01f, 8.00000000e+01f},
3038 {4.00000000e+01f, 8.00000000e+01f}}}},
3039 {SEGMENT_BEZIER, {{{5.33333321e+01f, 8.00000000e+01f},
3040 {6.00000000e+01f, 1.06666664e+02f},
3041 {6.00000000e+01f, 1.60000000e+02f}}}},
3042 {SEGMENT_BEZIER, {{{6.00000000e+01f, 2.13333328e+02f},
3043 {5.33333321e+01f, 2.40000000e+02f},
3044 {4.00000000e+01f, 2.40000000e+02f}}}},
3045 {SEGMENT_BEZIER, {{{2.66666660e+01f, 2.40000000e+02f},
3046 {2.00000000e+01f, 2.13333328e+02f},
3047 {2.00000000e+01f, 1.60000000e+02f}}}},
3048 /* Figure 14. */
3049 {SEGMENT_BEZIER, {{{2.83333340e+01f, 6.12000000e+02f},
3050 {4.00000000e+01f, 6.58666687e+02f},
3051 {4.00000000e+01f, 7.52000000e+02f}}}},
3052 {SEGMENT_BEZIER, {{{4.00000000e+01f, 6.58666687e+02f},
3053 {5.16666641e+01f, 6.12000000e+02f},
3054 {7.50000000e+01f, 6.12000000e+02f}}}},
3055 {SEGMENT_BEZIER, {{{5.16666641e+01f, 6.12000000e+02f},
3056 {4.00000000e+01f, 5.65333313e+02f},
3057 {4.00000000e+01f, 4.72000000e+02f}}}},
3058 {SEGMENT_BEZIER, {{{4.00000000e+01f, 5.65333313e+02f},
3059 {2.83333340e+01f, 6.12000000e+02f},
3060 {5.00000000e+00f, 6.12000000e+02f}}}},
3061 /* Figure 15. */
3062 {SEGMENT_BEZIER, {{{2.00000000e+01f, 6.65333313e+02f},
3063 {2.66666660e+01f, 6.92000000e+02f},
3064 {4.00000000e+01f, 6.92000000e+02f}}}},
3065 {SEGMENT_BEZIER, {{{5.33333321e+01f, 6.92000000e+02f},
3066 {6.00000000e+01f, 6.65333313e+02f},
3067 {6.00000000e+01f, 6.12000000e+02f}}}},
3068 {SEGMENT_BEZIER, {{{6.00000000e+01f, 5.58666687e+02f},
3069 {5.33333321e+01f, 5.32000000e+02f},
3070 {4.00000000e+01f, 5.32000000e+02f}}}},
3071 {SEGMENT_BEZIER, {{{2.66666660e+01f, 5.32000000e+02f},
3072 {2.00000000e+01f, 5.58666687e+02f},
3073 {2.00000000e+01f, 6.12000000e+02f}}}},
3074 /* Figure 16. */
3075 {SEGMENT_BEZIER, {{{1.91750427e+02f, 1.27275856e+02f},
3076 {2.08249573e+02f, 1.27275856e+02f},
3077 {2.24748734e+02f, 6.12792168e+01f}}}},
3078 {SEGMENT_BEZIER, {{{2.08249573e+02f, 1.27275856e+02f},
3079 {2.08249573e+02f, 1.93272476e+02f},
3080 {2.24748734e+02f, 2.59269104e+02f}}}},
3081 {SEGMENT_BEZIER, {{{2.08249573e+02f, 1.93272476e+02f},
3082 {1.91750427e+02f, 1.93272476e+02f},
3083 {1.75251266e+02f, 2.59269104e+02f}}}},
3084 {SEGMENT_BEZIER, {{{1.91750427e+02f, 1.93272476e+02f},
3085 {1.91750427e+02f, 1.27275856e+02f},
3086 {1.75251266e+02f, 6.12792168e+01f}}}},
3087 /* Figure 17. */
3088 {SEGMENT_BEZIER, {{{1.95285950e+02f, 6.59932632e+01f},
3089 {2.04714050e+02f, 6.59932632e+01f},
3090 {2.14142136e+02f, 1.03705627e+02f}}}},
3091 {SEGMENT_BEZIER, {{{2.23570221e+02f, 1.41417984e+02f},
3092 {2.23570221e+02f, 1.79130356e+02f},
3093 {2.14142136e+02f, 2.16842712e+02f}}}},
3094 {SEGMENT_BEZIER, {{{2.04714050e+02f, 2.54555069e+02f},
3095 {1.95285950e+02f, 2.54555069e+02f},
3096 {1.85857864e+02f, 2.16842712e+02f}}}},
3097 {SEGMENT_BEZIER, {{{1.76429779e+02f, 1.79130356e+02f},
3098 {1.76429779e+02f, 1.41417984e+02f},
3099 {1.85857864e+02f, 1.03705627e+02f}}}},
3100 /* Figure 18. */
3101 {SEGMENT_BEZIER, {{{1.11847351e+02f, 4.46888092e+02f},
3102 {1.11847351e+02f, 5.12884705e+02f},
3103 {9.53481979e+01f, 5.78881348e+02f}}}},
3104 {SEGMENT_BEZIER, {{{1.11847351e+02f, 5.12884705e+02f},
3105 {1.28346512e+02f, 5.12884705e+02f},
3106 {1.44845673e+02f, 5.78881348e+02f}}}},
3107 {SEGMENT_BEZIER, {{{1.28346512e+02f, 5.12884705e+02f},
3108 {1.28346512e+02f, 4.46888092e+02f},
3109 {1.44845673e+02f, 3.80891479e+02f}}}},
3110 {SEGMENT_BEZIER, {{{1.28346512e+02f, 4.46888092e+02f},
3111 {1.11847351e+02f, 4.46888092e+02f},
3112 {9.53481979e+01f, 3.80891479e+02f}}}},
3113 /* Figure 19. */
3114 {SEGMENT_BEZIER, {{{9.65267105e+01f, 4.61030243e+02f},
3115 {9.65267105e+01f, 4.98742584e+02f},
3116 {1.05954803e+02f, 5.36454956e+02f}}}},
3117 {SEGMENT_BEZIER, {{{1.15382889e+02f, 5.74167297e+02f},
3118 {1.24810982e+02f, 5.74167297e+02f},
3119 {1.34239075e+02f, 5.36454956e+02f}}}},
3120 {SEGMENT_BEZIER, {{{1.43667160e+02f, 4.98742584e+02f},
3121 {1.43667160e+02f, 4.61030243e+02f},
3122 {1.34239075e+02f, 4.23317871e+02f}}}},
3123 {SEGMENT_BEZIER, {{{1.24810982e+02f, 3.85605499e+02f},
3124 {1.15382889e+02f, 3.85605499e+02f},
3125 {1.05954803e+02f, 4.23317871e+02f}}}},
3126 /* Figure 20. */
3127 {SEGMENT_LINE, {{{ 40.0f, 20.0f}}}},
3128 {SEGMENT_LINE, {{{ 75.0f, 160.0f}}}},
3129 {SEGMENT_LINE, {{{ 40.0f, 300.0f}}}},
3130 {SEGMENT_LINE, {{{ 5.0f, 160.0f}}}},
3131 /* Figure 21. */
3132 {SEGMENT_LINE, {{{ 40.0f, 80.0f}}}},
3133 {SEGMENT_LINE, {{{ 60.0f, 160.0f}}}},
3134 {SEGMENT_LINE, {{{ 40.0f, 240.0f}}}},
3135 {SEGMENT_LINE, {{{ 20.0f, 160.0f}}}},
3136 /* Figure 22. */
3137 {SEGMENT_LINE, {{{ 40.0f, 752.0f}}}},
3138 {SEGMENT_LINE, {{{ 75.0f, 612.0f}}}},
3139 {SEGMENT_LINE, {{{ 40.0f, 472.0f}}}},
3140 {SEGMENT_LINE, {{{ 5.0f, 612.0f}}}},
3141 /* Figure 23. */
3142 {SEGMENT_LINE, {{{ 40.0f, 692.0f}}}},
3143 {SEGMENT_LINE, {{{ 60.0f, 612.0f}}}},
3144 {SEGMENT_LINE, {{{ 40.0f, 532.0f}}}},
3145 {SEGMENT_LINE, {{{ 20.0f, 612.0f}}}},
3146 /* Figure 24. */
3147 {SEGMENT_LINE, {{{2.03125019e+01f, 1.51250000e+02f}}}},
3148 {SEGMENT_LINE, {{{3.12500019e+01f, 1.25000008e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3149 {SEGMENT_LINE, {{{3.78125000e+01f, 8.12500076e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3150 {SEGMENT_LINE, {{{4.00000000e+01f, 2.00000000e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3151 {SEGMENT_LINE, {{{4.21875000e+01f, 8.12500076e+01f}}}},
3152 {SEGMENT_LINE, {{{4.87500000e+01f, 1.25000008e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3153 {SEGMENT_LINE, {{{5.96875000e+01f, 1.51250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3154 {SEGMENT_LINE, {{{7.50000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3155 {SEGMENT_LINE, {{{5.96875000e+01f, 1.68750000e+02f}}}},
3156 {SEGMENT_LINE, {{{4.87500000e+01f, 1.95000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3157 {SEGMENT_LINE, {{{4.21875000e+01f, 2.38750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3158 {SEGMENT_LINE, {{{4.00000000e+01f, 3.00000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3159 {SEGMENT_LINE, {{{3.78125000e+01f, 2.38750000e+02f}}}},
3160 {SEGMENT_LINE, {{{3.12500019e+01f, 1.95000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3161 {SEGMENT_LINE, {{{2.03125019e+01f, 1.68750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3162 {SEGMENT_LINE, {{{5.00000000e+00f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3163 /* Figure 25. */
3164 {SEGMENT_LINE, {{{2.50000000e+01f, 1.00000000e+02f}}}},
3165 {SEGMENT_LINE, {{{4.00000000e+01f, 8.00000000e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3166 {SEGMENT_LINE, {{{5.50000000e+01f, 1.00000000e+02f}}}},
3167 {SEGMENT_LINE, {{{6.00000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3168 {SEGMENT_LINE, {{{5.50000000e+01f, 2.20000000e+02f}}}},
3169 {SEGMENT_LINE, {{{4.00000000e+01f, 2.40000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3170 {SEGMENT_LINE, {{{2.50000000e+01f, 2.20000000e+02f}}}},
3171 {SEGMENT_LINE, {{{2.00000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3172 /* Figure 26. */
3173 {SEGMENT_LINE, {{{2.03125019e+01f, 6.20750000e+02f}}}},
3174 {SEGMENT_LINE, {{{3.12500019e+01f, 6.47000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3175 {SEGMENT_LINE, {{{3.78125000e+01f, 6.90750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3176 {SEGMENT_LINE, {{{4.00000000e+01f, 7.52000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3177 {SEGMENT_LINE, {{{4.21875000e+01f, 6.90750000e+02f}}}},
3178 {SEGMENT_LINE, {{{4.87500000e+01f, 6.47000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3179 {SEGMENT_LINE, {{{5.96875000e+01f, 6.20750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3180 {SEGMENT_LINE, {{{7.50000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3181 {SEGMENT_LINE, {{{5.96875000e+01f, 6.03250000e+02f}}}},
3182 {SEGMENT_LINE, {{{4.87500000e+01f, 5.77000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3183 {SEGMENT_LINE, {{{4.21875000e+01f, 5.33250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3184 {SEGMENT_LINE, {{{4.00000000e+01f, 4.72000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3185 {SEGMENT_LINE, {{{3.78125000e+01f, 5.33250000e+02f}}}},
3186 {SEGMENT_LINE, {{{3.12500019e+01f, 5.77000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3187 {SEGMENT_LINE, {{{2.03125019e+01f, 6.03250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3188 {SEGMENT_LINE, {{{5.00000000e+00f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3189 /* Figure 27. */
3190 {SEGMENT_LINE, {{{2.50000000e+01f, 6.72000000e+02f}}}},
3191 {SEGMENT_LINE, {{{4.00000000e+01f, 6.92000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3192 {SEGMENT_LINE, {{{5.50000000e+01f, 6.72000000e+02f}}}},
3193 {SEGMENT_LINE, {{{6.00000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3194 {SEGMENT_LINE, {{{5.50000000e+01f, 5.52000000e+02f}}}},
3195 {SEGMENT_LINE, {{{4.00000000e+01f, 5.32000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3196 {SEGMENT_LINE, {{{2.50000000e+01f, 5.52000000e+02f}}}},
3197 {SEGMENT_LINE, {{{2.00000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
3198 /* Figure 28. */
3199 {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}},
3200 {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}},
3201 /* Figure 29. */
3202 {SEGMENT_LINE, {{{ 40.0f, 100.0f}}}},
3203 {SEGMENT_BEZIER, {{{4.00000000e+01f, 7.66666666e+01f},
3204 {3.33333333e+01f, 7.00000000e+01f},
3205 {2.00000000e+01f, 8.00000000e+01f}}}},
3206 {SEGMENT_LINE, {{{ 60.0f, 40.0f}}}},
3207 {SEGMENT_BEZIER, {{{8.33333333e+01f, 4.00000000e+01f},
3208 {9.00000000e+01f, 3.33333333e+01f},
3209 {8.00000000e+01f, 2.00000000e+01f}}}},
3210 {SEGMENT_LINE, {{{140.0f, 160.0f}}}},
3211 {SEGMENT_BEZIER, {{{1.16666666e+02f, 1.60000000e+02f},
3212 {1.10000000e+02f, 1.66666666e+02f},
3213 {1.20000000e+02f, 1.80000000e+02f}}}},
3214 {SEGMENT_LINE, {{{170.0f, 110.0f}}}},
3215 {SEGMENT_BEZIER, {{{1.70000000e+02f, 1.26666666e+02f},
3216 {1.73333333e+02f, 1.30000000e+02f},
3217 {1.80000000e+02f, 1.20000000e+02f}}}},
3219 static const struct expected_geometry_figure expected_figures[] =
3221 /* 0 */
3222 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 15.0f, 20.0f}, 15, &expected_segments[0]},
3223 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {155.0f, 300.0f}, 11, &expected_segments[15]},
3224 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {165.0f, 20.0f}, 3, &expected_segments[26]},
3225 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {225.0f, 60.0f}, 3, &expected_segments[29]},
3226 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {215.0f, 220.0f}, 3, &expected_segments[32]},
3227 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {195.0f, 180.0f}, 3, &expected_segments[35]},
3228 /* 6 */
3229 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 95.0f, 620.0f}, 15, &expected_segments[38]},
3230 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {235.0f, 340.0f}, 11, &expected_segments[53]},
3231 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {245.0f, 620.0f}, 3, &expected_segments[64]},
3232 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {305.0f, 580.0f}, 3, &expected_segments[67]},
3233 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {295.0f, 420.0f}, 3, &expected_segments[70]},
3234 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {275.0f, 460.0f}, 3, &expected_segments[73]},
3235 /* 12 */
3236 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 4, &expected_segments[76]},
3237 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 4, &expected_segments[80]},
3238 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 4, &expected_segments[84]},
3239 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 4, &expected_segments[88]},
3240 /* 16 */
3241 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
3242 {1.75251266e+02f, 6.12792168e+01f}, 4, &expected_segments[92]},
3243 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
3244 {1.85857864e+02f, 1.03705627e+02f}, 4, &expected_segments[96]},
3245 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
3246 {9.53481979e+01f, 3.80891479e+02f}, 4, &expected_segments[100]},
3247 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
3248 {1.05954803e+02f, 4.23317871e+02f}, 4, &expected_segments[104]},
3249 /* 20 */
3250 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 4, &expected_segments[108]},
3251 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 4, &expected_segments[112]},
3252 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 4, &expected_segments[116]},
3253 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 4, &expected_segments[120]},
3254 /* 24 */
3255 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 16, &expected_segments[124]},
3256 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 8, &expected_segments[140]},
3257 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 16, &expected_segments[148]},
3258 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 8, &expected_segments[164]},
3259 /* 28 */
3260 {D2D1_FIGURE_BEGIN_HOLLOW, D2D1_FIGURE_END_OPEN, { 40.0f, 20.0f}, 2, &expected_segments[172]},
3261 /* 29 */
3262 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_OPEN, { 20.0f, 80.0f}, 2, &expected_segments[174]},
3263 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_OPEN, { 80.0f, 20.0f}, 2, &expected_segments[176]},
3264 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 120.0f, 180.0f}, 2, &expected_segments[178]},
3265 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 180.0f, 120.0f}, 2, &expected_segments[180]},
3268 if (!init_test_context(&ctx, d3d11))
3269 return;
3271 rt = ctx.rt;
3272 ID2D1RenderTarget_GetFactory(rt, &factory);
3274 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
3275 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
3276 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
3277 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
3278 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3280 /* Close() when closed. */
3281 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3282 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3283 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3284 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3285 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3286 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3287 hr = ID2D1PathGeometry_Open(geometry, &sink);
3288 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3289 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3290 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3291 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3292 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3293 hr = ID2D1GeometrySink_Close(sink);
3294 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3295 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3296 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3297 ok(!count, "Got unexpected figure count %u.\n", count);
3298 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3299 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3300 ok(!count, "Got unexpected segment count %u.\n", count);
3301 hr = ID2D1GeometrySink_Close(sink);
3302 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3303 ID2D1GeometrySink_Release(sink);
3304 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3305 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3306 ok(!count, "Got unexpected figure count %u.\n", count);
3307 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3308 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3309 ok(!count, "Got unexpected segment count %u.\n", count);
3310 ID2D1PathGeometry_Release(geometry);
3312 /* Open() when closed. */
3313 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3314 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3315 hr = ID2D1PathGeometry_Open(geometry, &sink);
3316 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3317 hr = ID2D1GeometrySink_Close(sink);
3318 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3319 ID2D1GeometrySink_Release(sink);
3320 hr = ID2D1PathGeometry_Open(geometry, &sink);
3321 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3322 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3323 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3324 ok(!count, "Got unexpected figure count %u.\n", count);
3325 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3326 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3327 ok(!count, "Got unexpected segment count %u.\n", count);
3328 ID2D1PathGeometry_Release(geometry);
3330 /* Open() when open. */
3331 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3332 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3333 hr = ID2D1PathGeometry_Open(geometry, &sink);
3334 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3335 hr = ID2D1PathGeometry_Open(geometry, &tmp_sink);
3336 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3337 hr = ID2D1GeometrySink_Close(sink);
3338 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3339 ID2D1GeometrySink_Release(sink);
3340 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3341 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3342 ok(!count, "Got unexpected figure count %u.\n", count);
3343 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3344 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3345 ok(!count, "Got unexpected segment count %u.\n", count);
3346 ID2D1PathGeometry_Release(geometry);
3348 /* BeginFigure() without EndFigure(). */
3349 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3350 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3351 hr = ID2D1PathGeometry_Open(geometry, &sink);
3352 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3353 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
3354 hr = ID2D1GeometrySink_Close(sink);
3355 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3356 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3357 hr = ID2D1GeometrySink_Close(sink);
3358 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3359 ID2D1GeometrySink_Release(sink);
3360 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3361 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3362 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3363 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3364 ID2D1PathGeometry_Release(geometry);
3366 /* EndFigure() without BeginFigure(). */
3367 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3368 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3369 hr = ID2D1PathGeometry_Open(geometry, &sink);
3370 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3371 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3372 hr = ID2D1GeometrySink_Close(sink);
3373 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3374 ID2D1GeometrySink_Release(sink);
3375 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3376 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3377 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3378 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3379 ID2D1PathGeometry_Release(geometry);
3381 /* BeginFigure()/EndFigure() mismatch. */
3382 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3383 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3384 hr = ID2D1PathGeometry_Open(geometry, &sink);
3385 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3386 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
3387 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
3388 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3389 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3390 hr = ID2D1GeometrySink_Close(sink);
3391 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3392 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3393 hr = ID2D1GeometrySink_Close(sink);
3394 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3395 ID2D1GeometrySink_Release(sink);
3396 ID2D1PathGeometry_Release(geometry);
3398 /* AddLine() outside BeginFigure()/EndFigure(). */
3399 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3400 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3401 hr = ID2D1PathGeometry_Open(geometry, &sink);
3402 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3403 ID2D1GeometrySink_AddLine(sink, point);
3404 hr = ID2D1GeometrySink_Close(sink);
3405 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3406 ID2D1GeometrySink_AddLine(sink, point);
3407 ID2D1GeometrySink_Release(sink);
3408 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3409 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3410 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3411 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3412 ID2D1PathGeometry_Release(geometry);
3414 /* Empty figure. */
3415 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3416 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3417 hr = ID2D1PathGeometry_Open(geometry, &sink);
3418 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3419 set_point(&point, 123.0f, 456.0f);
3420 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
3421 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3422 hr = ID2D1GeometrySink_Close(sink);
3423 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3424 ID2D1GeometrySink_Release(sink);
3425 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3426 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3427 ok(count == 1, "Got unexpected figure count %u.\n", count);
3428 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3429 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3430 ok(count == 1, "Got unexpected segment count %u.\n", count);
3432 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3433 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3434 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3435 match = compare_rect(&rect, 123.0f, 456.0f, 123.0f, 456.0f, 0);
3436 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3437 rect.left, rect.top, rect.right, rect.bottom);
3439 set_matrix_identity(&matrix);
3440 translate_matrix(&matrix, 80.0f, 640.0f);
3441 scale_matrix(&matrix, 2.0f, 0.5f);
3442 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3443 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3444 match = compare_rect(&rect, 326.0f, 868.0f, 326.0f, 868.0f, 0);
3445 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3446 rect.left, rect.top, rect.right, rect.bottom);
3448 ID2D1PathGeometry_Release(geometry);
3450 /* Degenerate figure. */
3451 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3452 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3453 hr = ID2D1PathGeometry_Open(geometry, &sink);
3454 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3455 set_point(&point, 123.0f, 456.0f);
3456 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
3457 quadratic_to(sink, 123.0f, 456.0f, 123.0f, 456.0f);
3458 quadratic_to(sink, 123.0f, 456.0f, 123.0f, 456.0f);
3459 quadratic_to(sink, 123.0f, 456.0f, 123.0f, 456.0f);
3460 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3461 hr = ID2D1GeometrySink_Close(sink);
3462 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3463 ID2D1GeometrySink_Release(sink);
3464 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3465 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3466 ok(count == 1, "Got unexpected figure count %u.\n", count);
3467 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3468 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3469 ok(count == 4, "Got unexpected segment count %u.\n", count);
3470 ID2D1PathGeometry_Release(geometry);
3472 /* Close right after Open(). */
3473 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3474 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3476 /* Not open yet. */
3477 set_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f);
3478 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3479 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3480 match = compare_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0);
3481 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3482 rect.left, rect.top, rect.right, rect.bottom);
3484 hr = ID2D1PathGeometry_Open(geometry, &sink);
3485 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3487 /* Open, not closed. */
3488 set_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f);
3489 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3490 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
3491 match = compare_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0);
3492 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3493 rect.left, rect.top, rect.right, rect.bottom);
3495 hr = ID2D1GeometrySink_Close(sink);
3496 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3497 ID2D1GeometrySink_Release(sink);
3498 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3499 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3500 ok(count == 0, "Got unexpected figure count %u.\n", count);
3501 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3502 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3503 ok(count == 0, "Got unexpected segment count %u.\n", count);
3505 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3506 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3507 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3508 ok(rect.left > rect.right && rect.top > rect.bottom,
3509 "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom);
3511 set_matrix_identity(&matrix);
3512 translate_matrix(&matrix, 10.0f, 20.0f);
3513 scale_matrix(&matrix, 10.0f, 20.0f);
3514 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3515 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3516 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3517 ok(rect.left > rect.right && rect.top > rect.bottom,
3518 "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom);
3520 ID2D1PathGeometry_Release(geometry);
3522 /* GetBounds() with bezier segments. */
3523 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3524 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3525 hr = ID2D1PathGeometry_Open(geometry, &sink);
3526 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3527 fill_geometry_sink_bezier(sink, 0);
3528 hr = ID2D1GeometrySink_Close(sink);
3529 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3530 ID2D1GeometrySink_Release(sink);
3532 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3533 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3534 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3535 match = compare_rect(&rect, 5.0f, 20.0f, 75.0f, 752.0f, 0);
3536 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3537 rect.left, rect.top, rect.right, rect.bottom);
3539 set_matrix_identity(&matrix);
3540 translate_matrix(&matrix, 80.0f, 640.0f);
3541 scale_matrix(&matrix, 2.0f, 0.5f);
3542 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3543 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3544 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3545 match = compare_rect(&rect, 90.0f, 650.0f, 230.0f, 1016.0f, 0);
3546 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3547 rect.left, rect.top, rect.right, rect.bottom);
3549 ID2D1PathGeometry_Release(geometry);
3551 /* GetBounds() with bezier segments and some hollow components. */
3552 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3553 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3554 hr = ID2D1PathGeometry_Open(geometry, &sink);
3555 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3556 fill_geometry_sink_bezier(sink, 2);
3557 hr = ID2D1GeometrySink_Close(sink);
3558 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3559 ID2D1GeometrySink_Release(sink);
3561 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3562 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3563 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3564 match = compare_rect(&rect, 5.0f, 472.0f, 75.0f, 752.0f, 0);
3565 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3566 rect.left, rect.top, rect.right, rect.bottom);
3568 set_matrix_identity(&matrix);
3569 translate_matrix(&matrix, 80.0f, 640.0f);
3570 scale_matrix(&matrix, 2.0f, 0.5f);
3571 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3572 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3573 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3574 match = compare_rect(&rect, 90.0f, 876.0f, 230.0f, 1016.0f, 0);
3575 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3576 rect.left, rect.top, rect.right, rect.bottom);
3578 ID2D1PathGeometry_Release(geometry);
3580 /* GetBounds() with bezier segments and all hollow components. */
3581 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3582 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3583 hr = ID2D1PathGeometry_Open(geometry, &sink);
3584 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3585 fill_geometry_sink_bezier(sink, 4);
3586 hr = ID2D1GeometrySink_Close(sink);
3587 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3588 ID2D1GeometrySink_Release(sink);
3590 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3591 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3592 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3593 match = compare_rect(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0);
3594 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3595 rect.left, rect.top, rect.right, rect.bottom);
3597 set_matrix_identity(&matrix);
3598 translate_matrix(&matrix, 80.0f, 640.0f);
3599 scale_matrix(&matrix, 2.0f, 0.5f);
3600 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3601 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3602 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3603 match = compare_rect(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0);
3604 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3605 rect.left, rect.top, rect.right, rect.bottom);
3607 ID2D1PathGeometry_Release(geometry);
3609 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3610 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3611 hr = ID2D1PathGeometry_Open(geometry, &sink);
3612 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3613 /* The fillmode that's used is the last one set before the sink is closed. */
3614 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
3615 fill_geometry_sink(sink, 0);
3616 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
3617 hr = ID2D1GeometrySink_Close(sink);
3618 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3619 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3620 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3621 ok(count == 6, "Got unexpected figure count %u.\n", count);
3622 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3623 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3624 /* Intersections don't create extra segments. */
3625 ok(count == 44, "Got unexpected segment count %u.\n", count);
3626 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
3627 ID2D1GeometrySink_Release(sink);
3629 geometry_sink_init(&simplify_sink);
3630 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3631 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3632 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3633 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[0], 0);
3634 geometry_sink_cleanup(&simplify_sink);
3635 geometry_sink_init(&simplify_sink);
3636 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3637 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3638 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3639 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[0], 0);
3640 geometry_sink_cleanup(&simplify_sink);
3642 set_matrix_identity(&matrix);
3643 translate_matrix(&matrix, 80.0f, 640.0f);
3644 scale_matrix(&matrix, 1.0f, -1.0f);
3645 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
3646 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3648 geometry_sink_init(&simplify_sink);
3649 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3650 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3651 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3652 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[6], 0);
3653 geometry_sink_cleanup(&simplify_sink);
3655 ID2D1TransformedGeometry_GetSourceGeometry(transformed_geometry, &tmp_geometry);
3656 ok(tmp_geometry == (ID2D1Geometry *)geometry,
3657 "Got unexpected source geometry %p, expected %p.\n", tmp_geometry, geometry);
3658 ID2D1TransformedGeometry_GetTransform(transformed_geometry, &tmp_matrix);
3659 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
3660 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
3661 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
3662 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
3663 geometry_sink_init(&simplify_sink);
3664 hr = ID2D1Geometry_Simplify(tmp_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3665 &tmp_matrix, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3666 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3667 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[6], 0);
3668 geometry_sink_cleanup(&simplify_sink);
3669 ID2D1Geometry_Release(tmp_geometry);
3671 ID2D1RenderTarget_BeginDraw(rt);
3672 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
3673 ID2D1RenderTarget_Clear(rt, &color);
3674 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
3675 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
3676 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3677 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3678 match = compare_surface(&ctx, "3aace1b22aae111cb577614fed16e4eb1650dba5");
3679 ok(match, "Surface does not match.\n");
3681 /* Edge test. */
3682 set_point(&point, 94.0f, 620.0f);
3683 contains = TRUE;
3684 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, NULL, 0.0f, &contains);
3685 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3686 ok(!contains, "Got unexpected contains %#x.\n", contains);
3688 set_point(&point, 95.0f, 620.0f);
3689 contains = FALSE;
3690 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, NULL, 0.0f, &contains);
3691 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3692 ok(contains == TRUE, "Got unexpected contains %#x.\n", contains);
3694 /* With transformation matrix. */
3695 set_matrix_identity(&matrix);
3696 translate_matrix(&matrix, -10.0f, 0.0f);
3697 set_point(&point, 85.0f, 620.0f);
3698 contains = FALSE;
3699 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, &matrix, 0.0f, &contains);
3700 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3701 ok(contains == TRUE, "Got unexpected contains %#x.\n", contains);
3703 ID2D1TransformedGeometry_Release(transformed_geometry);
3704 ID2D1PathGeometry_Release(geometry);
3706 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3707 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3708 hr = ID2D1PathGeometry_Open(geometry, &sink);
3709 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3710 fill_geometry_sink(sink, 0);
3711 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
3712 hr = ID2D1GeometrySink_Close(sink);
3713 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3714 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3715 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3716 ok(count == 6, "Got unexpected figure count %u.\n", count);
3717 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3718 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3719 ok(count == 44, "Got unexpected segment count %u.\n", count);
3720 ID2D1GeometrySink_Release(sink);
3722 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3723 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3724 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3725 match = compare_rect(&rect, 5.0f, 20.0f, 235.0f, 300.0f, 0);
3726 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3727 rect.left, rect.top, rect.right, rect.bottom);
3729 set_matrix_identity(&matrix);
3730 translate_matrix(&matrix, 100.0f, 50.0f);
3731 scale_matrix(&matrix, 2.0f, 1.5f);
3732 rotate_matrix(&matrix, M_PI / 4.0f);
3733 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3734 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3735 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3736 match = compare_rect(&rect, -3.17192993e+02f, 8.71231079e+01f, 4.04055908e+02f, 6.17453125e+02f, 1);
3737 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3738 rect.left, rect.top, rect.right, rect.bottom);
3740 geometry_sink_init(&simplify_sink);
3741 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3742 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3743 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3744 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 6, &expected_figures[0], 0);
3745 geometry_sink_cleanup(&simplify_sink);
3747 set_matrix_identity(&matrix);
3748 translate_matrix(&matrix, 320.0f, 320.0f);
3749 scale_matrix(&matrix, -1.0f, 1.0f);
3750 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
3751 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3753 ID2D1RenderTarget_BeginDraw(rt);
3754 ID2D1RenderTarget_Clear(rt, &color);
3755 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
3756 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
3757 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3758 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3759 match = compare_surface(&ctx, "bfb40a1f007694fa07dbd3b854f3f5d9c3e1d76b");
3760 ok(match, "Surface does not match.\n");
3761 ID2D1TransformedGeometry_Release(transformed_geometry);
3762 ID2D1PathGeometry_Release(geometry);
3764 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3765 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3766 hr = ID2D1PathGeometry_Open(geometry, &sink);
3767 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3768 fill_geometry_sink_bezier(sink, 0);
3769 hr = ID2D1GeometrySink_Close(sink);
3770 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3771 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3772 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3773 ok(count == 4, "Got unexpected figure count %u.\n", count);
3774 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3775 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3776 ok(count == 20, "Got unexpected segment count %u.\n", count);
3777 ID2D1GeometrySink_Release(sink);
3779 geometry_sink_init(&simplify_sink);
3780 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3781 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3782 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3783 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[12], 1);
3784 geometry_sink_cleanup(&simplify_sink);
3785 geometry_sink_init(&simplify_sink);
3786 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3787 NULL, 100.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3788 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3789 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[20], 1);
3790 geometry_sink_cleanup(&simplify_sink);
3791 geometry_sink_init(&simplify_sink);
3792 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3793 NULL, 10.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3794 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3795 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[24], 1);
3796 geometry_sink_cleanup(&simplify_sink);
3798 set_matrix_identity(&matrix);
3799 scale_matrix(&matrix, 0.5f, 2.0f);
3800 translate_matrix(&matrix, 400.0f, -33.0f);
3801 rotate_matrix(&matrix, M_PI / 4.0f);
3802 scale_matrix(&matrix, 2.0f, 0.5f);
3803 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
3804 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3806 geometry_sink_init(&simplify_sink);
3807 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3808 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3809 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3810 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[16], 4);
3811 geometry_sink_cleanup(&simplify_sink);
3813 ID2D1RenderTarget_BeginDraw(rt);
3814 ID2D1RenderTarget_Clear(rt, &color);
3815 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
3816 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
3817 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3818 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3819 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 64,
3820 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
3821 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
3822 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
3823 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
3824 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
3825 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
3826 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
3827 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
3828 ok(match, "Figure does not match.\n");
3829 match = compare_figure(&ctx, 0, 226, 160, 160, 0xff652e89, 64,
3830 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
3831 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
3832 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
3833 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
3834 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
3835 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
3836 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
3837 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
3838 ok(match, "Figure does not match.\n");
3839 match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 64,
3840 "gVQBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQEjDCMB7AECHhQeAu0BAxoYGgPvAQMWHhYD8QEDFCAU"
3841 "A/MBBBAkEAT0AQUOJw0F9QEGCioKBvcBBggsCAb4AQgFLgUI+QEJATIBCfsBCAIwAgj8AQcFLAUH"
3842 "/QEFCCgIBf4BBAwiDAT/AQIQHBAClwISlwIBPgGAAgI8Av8BAzwD/QEEPAT7AQY6BvkBBzoH+AEI"
3843 "OAj3AQk4CfYBCTgK9AELNgvzAQw2DPIBDDYM8QEONA7wAQ40DvABDjQO7wEPNA/uAQ80D+4BEDIQ"
3844 "7QERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewB"
3845 "ETIR7AERMhHsAREyEe0BEDIQ7gEQMw/uAQ80D+4BDzQP7wEONA7wAQ40DvEBDDYM8gEMNgzzAQs2"
3846 "C/QBCzcK9QEJOAn3AQg4CfcBBzoH+QEGOgb7AQU6BfwBBDwE/QEDPAP/AQE+AZkCDpkCAhIYEgKA"
3847 "AgMNIA0D/wEFCSYJBf4BBgYqBgf8AQgDLgMI+wFG+gEIAzADCPkBBwYuBgf3AQYKKgoG9gEFDCgM"
3848 "BfUBBBAlDwTzAQQSIhIE8QEDFh4WA/ABAhkaGQLvAQIcFhwC7QECIBAgAusBASgEKAHpAQFWAecB"
3849 "AVgB5QEBWgHAAgHhUgAA");
3850 ok(match, "Figure does not match.\n");
3851 match = compare_figure(&ctx, 160, 160, 320, 160, 0xff652e89, 64,
3852 "/VUB5QEBWAHnAQFWAekBAVQB6wECIQ8hAe0BAh0VHQLuAQIZGhkD7wEDFh4WA/EBBBMhEwPzAQQQ"
3853 "JQ8F9AEFDCgNBfUBBgoqCgb3AQcHLQcG+QEIBC8ECPkBPAEJ+wEIAy8CCP0BBgYrBQf9AQUJJgkF"
3854 "/wEDDSANBP8BAhEaEQKYAhAXAYACAT4BgAICPQL+AQM8BPwBBTsE+wEGOgb6AQc5B/gBCDgJ9gEJ"
3855 "OAn2AQo3CvQBCzcK8wEMNgzyAQ01DPIBDTUN8AEONA7wAQ40D+4BDzQP7gEQMw/uARAzEO0BEDIR"
3856 "7AERMhHsAREyEewBETIR7AERMhLrAREyEusBETIS6wERMhLrAREyEusBETIS6wERMhHsAREyEewB"
3857 "ETIR7QEQMhHtARAzEO0BEDMP7gEPNA/vAQ40D+8BDjQO8QENNQ3xAQ01DPMBCzYM8wELNwr1AQo3"
3858 "CvUBCTgJ9wEIOAn4AQc5B/kBBjoG+wEFOwT9AQM8BP4BAj0C/wEBPgGYAhAXAYACAhEaEQKAAgMN"
3859 "IA0E/gEFCSYJBf4BBgYrBQf8AQgDLwII+wE8AQn6AQgELwQI+AEHBy0HBvcBBgoqCgb2AQUNJw0F"
3860 "9AEEECQQBfIBBBMhEwPxAQMWHhYD8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB"
3861 "wAIBwlYA");
3862 ok(match, "Figure does not match.\n");
3863 ID2D1TransformedGeometry_Release(transformed_geometry);
3864 ID2D1PathGeometry_Release(geometry);
3866 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3867 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3868 hr = ID2D1PathGeometry_Open(geometry, &sink);
3869 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3870 fill_geometry_sink_bezier(sink, 0);
3871 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
3872 hr = ID2D1GeometrySink_Close(sink);
3873 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3874 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3875 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3876 ok(count == 4, "Got unexpected figure count %u.\n", count);
3877 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3878 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3879 ok(count == 20, "Got unexpected segment count %u.\n", count);
3880 ID2D1GeometrySink_Release(sink);
3882 geometry_sink_init(&simplify_sink);
3883 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3884 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3885 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3886 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[12], 1);
3887 geometry_sink_cleanup(&simplify_sink);
3888 geometry_sink_init(&simplify_sink);
3889 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3890 NULL, 100.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3891 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3892 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[20], 1);
3893 geometry_sink_cleanup(&simplify_sink);
3894 geometry_sink_init(&simplify_sink);
3895 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3896 NULL, 10.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3897 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3898 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[24], 1);
3899 geometry_sink_cleanup(&simplify_sink);
3901 set_matrix_identity(&matrix);
3902 scale_matrix(&matrix, 0.5f, 2.0f);
3903 translate_matrix(&matrix, 127.0f, 80.0f);
3904 rotate_matrix(&matrix, M_PI / -4.0f);
3905 scale_matrix(&matrix, 2.0f, 0.5f);
3906 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
3907 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3909 ID2D1RenderTarget_BeginDraw(rt);
3910 ID2D1RenderTarget_Clear(rt, &color);
3911 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
3912 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
3913 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3914 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3915 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 64,
3916 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
3917 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
3918 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
3919 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
3920 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
3921 ok(match, "Figure does not match.\n");
3922 match = compare_figure(&ctx, 0, 226, 160, 160, 0xff652e89, 64,
3923 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
3924 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
3925 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
3926 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
3927 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
3928 ok(match, "Figure does not match.\n");
3929 match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 64,
3930 "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQIhDiIB7QECHRUdAu4BAhkaGQPvAQMWHhYD8QEEEyET"
3931 "A/MBBBAkEAT1AQUMKA0F9QEGCioKBvcBBwctBwb5AQgELwQI+QEJATIBCfsBRP0BQ/0BQv8BQf8B"
3932 "QIECP4ACQIACQf4BQ/wBRPsBRvoBR/gBSPcBSvYBS/QBTPMBTvIBTvIBT/ABUPABUe4BUu4BUu4B"
3933 "U+0BU+wBVOwBVOwBVOwBVOwBVesBVesBVesBVesBVOwBVOwBVOwBVO0BU+0BU+0BUu4BUu8BUe8B"
3934 "UPEBT/EBTvIBTvMBTPUBS/UBSvcBSfcBSPkBRvsBRP0BQ/4BQf8BQIECP4ACQIACQf4BQv4BQ/wB"
3935 "RPsBCQEyAQn6AQgELwQI+AEHBy0GB/cBBgoqCgb2AQUMKA0F9AEEECUPBPMBBBIiEwPxAQMWHhYD"
3936 "8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB5QEBWgHAAgEA");
3937 ok(match, "Figure does not match.\n");
3938 match = compare_figure(&ctx, 160, 160, 320, 160, 0xff652e89, 64,
3939 "gVQBXAHjAQFaAeUBAVgB5wEBVgHpAQEpAikB6wECIBAgAu0BAhwWHALvAQIZGhkC8AEDFh4WA/EB"
3940 "BBIiEgTzAQQPJRAE9QEFDCgMBfYBBgoqCgb3AQcGLgYH+QEIAzADCPoBRvsBRPwBRP0BQv8BQIAC"
3941 "QIECPoECQP8BQv0BRPwBRPsBRvkBSPgBSPcBSvUBTPQBTPMBTvIBTvEBUPABUO8BUu4BUu4BUu4B"
3942 "Uu0BVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVO0BUu4BUu4BUu8BUPAB"
3943 "UPABUPEBTvIBTvMBTPQBS/YBSvcBSPgBSPkBRvsBRP0BQv8BQIACQIECPoECQP8BQv4BQv0BRPwB"
3944 "RPsBCQEyAQn5AQgFLgUI+AEGCCwIBvcBBgoqCgb1AQUNJw4F9AEEECQQBPMBAxQgFAPxAQMWHhYD"
3945 "7wEDGhgaA+0BAh4UHgLsAQEjDCMB6wEBVAHpAQFWAecBAVgB5QEBWgGiVQAA");
3946 ok(match, "Figure does not match.\n");
3947 ID2D1TransformedGeometry_Release(transformed_geometry);
3948 ID2D1PathGeometry_Release(geometry);
3950 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3951 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3952 hr = ID2D1PathGeometry_Open(geometry, &sink);
3953 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3955 set_point(&point, 40.0f, 20.0f);
3956 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
3957 line_to(sink, 75.0f, 300.0f);
3958 line_to(sink, 5.0f, 300.0f);
3959 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3961 set_point(&point, 40.0f, 290.0f);
3962 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
3963 line_to(sink, 55.0f, 160.0f);
3964 line_to(sink, 25.0f, 160.0f);
3965 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3967 hr = ID2D1GeometrySink_Close(sink);
3968 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3969 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3970 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3971 ok(count == 2, "Got unexpected figure count %u.\n", count);
3972 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3973 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3974 ok(count == 6, "Got unexpected segment count %u.\n", count);
3975 ID2D1GeometrySink_Release(sink);
3977 ID2D1RenderTarget_BeginDraw(rt);
3978 ID2D1RenderTarget_Clear(rt, &color);
3979 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
3980 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3981 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3982 match = compare_surface(&ctx, "a875e68e0cb9c055927b1b50b879f90b24e38470");
3983 ok(match, "Surface does not match.\n");
3984 ID2D1PathGeometry_Release(geometry);
3986 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3987 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3988 hr = ID2D1PathGeometry_Open(geometry, &sink);
3989 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3990 set_point(&point, 40.0f, 20.0f);
3991 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
3992 line_to(sink, 75.0f, 300.0f);
3993 line_to(sink, 5.0f, 300.0f);
3994 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
3995 hr = ID2D1GeometrySink_Close(sink);
3996 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
3997 ID2D1GeometrySink_Release(sink);
3998 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3999 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4000 ok(count == 2, "Got unexpected segment count %u.\n", count);
4002 geometry_sink_init(&simplify_sink);
4003 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
4004 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
4005 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4006 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[28], 1);
4007 geometry_sink_cleanup(&simplify_sink);
4009 ID2D1PathGeometry_Release(geometry);
4011 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
4012 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4013 hr = ID2D1PathGeometry_Open(geometry, &sink);
4014 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4016 set_point(&point, 20.0f, 80.0f);
4017 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4018 line_to(sink, 40.0f, 100.0f);
4019 quadratic_to(sink, 40.0f, 65.0f, 20.0f, 80.0f);
4020 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
4022 set_point(&point, 80.0f, 20.0f);
4023 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4024 line_to(sink, 60.0f, 40.0f);
4025 quadratic_to(sink, 95.0f, 40.0f, 80.0f, 20.0f);
4026 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
4028 set_point(&point, 120.0f, 180.0f);
4029 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4030 line_to(sink, 140.0f, 160.0f);
4031 quadratic_to(sink, 105.0f, 160.0f, 120.0f, 180.0f);
4032 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
4034 set_point(&point, 180.0f, 120.0f);
4035 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4036 line_to(sink, 170.0f, 110.0f);
4037 quadratic_to(sink, 170.0f, 135.0f, 180.0f, 120.0f);
4038 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
4040 hr = ID2D1GeometrySink_Close(sink);
4041 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4042 ID2D1GeometrySink_Release(sink);
4044 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
4045 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
4046 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4047 match = compare_rect(&rect, 20.0f, 20.0f, 180.0f, 180.0f, 0);
4048 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
4049 rect.left, rect.top, rect.right, rect.bottom);
4051 geometry_sink_init(&simplify_sink);
4052 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
4053 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
4054 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4055 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[29], 1);
4056 geometry_sink_cleanup(&simplify_sink);
4058 ID2D1PathGeometry_Release(geometry);
4060 ID2D1SolidColorBrush_Release(brush);
4061 ID2D1Factory_Release(factory);
4062 release_test_context(&ctx);
4065 static void test_rectangle_geometry(BOOL d3d11)
4067 ID2D1TransformedGeometry *transformed_geometry;
4068 ID2D1RectangleGeometry *geometry;
4069 struct geometry_sink sink;
4070 D2D1_MATRIX_3X2_F matrix;
4071 D2D1_RECT_F rect, rect2;
4072 ID2D1Factory *factory;
4073 D2D1_POINT_2F point;
4074 BOOL contains;
4075 HRESULT hr;
4076 BOOL match;
4078 static const struct geometry_segment expected_segments[] =
4080 /* Figure 0. */
4081 {SEGMENT_LINE, {{{10.0f, 0.0f}}}},
4082 {SEGMENT_LINE, {{{10.0f, 20.0f}}}},
4083 {SEGMENT_LINE, {{{ 0.0f, 20.0f}}}},
4084 /* Figure 1. */
4085 {SEGMENT_LINE, {{{4.42705116e+01f, 1.82442951e+01f}}}},
4086 {SEGMENT_LINE, {{{7.95376282e+01f, 5.06049728e+01f}}}},
4087 {SEGMENT_LINE, {{{5.52671127e+01f, 6.23606796e+01f}}}},
4088 /* Figure 2. */
4089 {SEGMENT_LINE, {{{25.0f, 15.0f}}}},
4090 {SEGMENT_LINE, {{{25.0f, 55.0f}}}},
4091 {SEGMENT_LINE, {{{25.0f, 55.0f}}}},
4092 /* Figure 3. */
4093 {SEGMENT_LINE, {{{35.0f, 45.0f}}}},
4094 {SEGMENT_LINE, {{{35.0f, 45.0f}}}},
4095 {SEGMENT_LINE, {{{30.0f, 45.0f}}}},
4096 /* Figure 4. */
4097 {SEGMENT_LINE, {{{ 1.07179585e+01f, 2.23205078e+02f}}}},
4098 {SEGMENT_LINE, {{{-5.85640755e+01f, 2.73205078e+02f}}}},
4099 {SEGMENT_LINE, {{{-7.85640717e+01f, 2.29903809e+02f}}}},
4100 /* Figure 5. */
4101 {SEGMENT_LINE, {{{40.0f, 20.0f}}}},
4102 {SEGMENT_LINE, {{{40.0f, 40.0f}}}},
4103 {SEGMENT_LINE, {{{30.0f, 40.0f}}}},
4104 /* Figure 6. */
4105 {SEGMENT_LINE, {{{ 2.14359169e+01f, 0.0f}}}},
4106 {SEGMENT_LINE, {{{-1.17128151e+02f, 0.0f}}}},
4107 {SEGMENT_LINE, {{{-1.57128143e+02f, 0.0f}}}},
4108 /* Figure 7. */
4109 {SEGMENT_LINE, {{{0.0f, 1.11602539e+02f}}}},
4110 {SEGMENT_LINE, {{{0.0f, 1.36602539e+02f}}}},
4111 {SEGMENT_LINE, {{{0.0f, 1.14951904e+02f}}}},
4113 static const struct expected_geometry_figure expected_figures[] =
4115 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 0.0f, 0.0f}, 3, &expected_segments[0]},
4116 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {20.0f, 30.0f}, 3, &expected_segments[3]},
4117 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {25.0f, 15.0f}, 3, &expected_segments[6]},
4118 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {30.0f, 45.0f}, 3, &expected_segments[9]},
4119 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {-9.28203964e+00f, 1.79903809e+02f},
4120 3, &expected_segments[12]},
4121 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {30.0f, 20.0f}, 3, &expected_segments[15]},
4122 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {-1.85640793e+01f, 0.0f}, 3, &expected_segments[18]},
4123 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {0.0f, 8.99519043e+01f}, 3, &expected_segments[21]},
4126 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4127 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4129 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
4130 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4131 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4132 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
4133 match = compare_rect(&rect2, 0.0f, 0.0f, 0.0f, 0.0f, 0);
4134 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
4135 rect2.left, rect2.top, rect2.right, rect2.bottom);
4136 ID2D1RectangleGeometry_Release(geometry);
4138 set_rect(&rect, 50.0f, 0.0f, 40.0f, 100.0f);
4139 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4140 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4141 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
4142 match = compare_rect(&rect2, 50.0f, 0.0f, 40.0f, 100.0f, 0);
4143 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
4144 rect2.left, rect2.top, rect2.right, rect2.bottom);
4145 ID2D1RectangleGeometry_Release(geometry);
4147 set_rect(&rect, 0.0f, 100.0f, 40.0f, 50.0f);
4148 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4149 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4150 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
4151 match = compare_rect(&rect2, 0.0f, 100.0f, 40.0f, 50.0f, 0);
4152 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
4153 rect2.left, rect2.top, rect2.right, rect2.bottom);
4154 ID2D1RectangleGeometry_Release(geometry);
4156 set_rect(&rect, 50.0f, 100.0f, 40.0f, 50.0f);
4157 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4158 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4159 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
4160 match = compare_rect(&rect2, 50.0f, 100.0f, 40.0f, 50.0f, 0);
4161 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
4162 rect2.left, rect2.top, rect2.right, rect2.bottom);
4163 ID2D1RectangleGeometry_Release(geometry);
4165 set_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f);
4166 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4167 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4169 /* Edge. */
4170 contains = FALSE;
4171 set_point(&point, 0.0f, 0.0f);
4172 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
4173 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4174 ok(!!contains, "Got wrong hit test result %d.\n", contains);
4176 /* Within tolerance limit around corner. */
4177 contains = TRUE;
4178 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE, 0.0f);
4179 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
4180 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4181 ok(!contains, "Got wrong hit test result %d.\n", contains);
4183 contains = FALSE;
4184 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE + 0.01f, 0.0f);
4185 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
4186 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4187 ok(!!contains, "Got wrong hit test result %d.\n", contains);
4189 contains = TRUE;
4190 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE - 0.01f, 0.0f);
4191 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
4192 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4193 ok(!contains, "Got wrong hit test result %d.\n", contains);
4195 contains = TRUE;
4196 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE, -D2D1_DEFAULT_FLATTENING_TOLERANCE);
4197 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
4198 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4199 ok(!contains, "Got wrong hit test result %d.\n", contains);
4201 /* Inside. */
4202 contains = FALSE;
4203 set_point(&point, 5.0f, 5.0f);
4204 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
4205 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4206 ok(!!contains, "Got wrong hit test result %d.\n", contains);
4208 /* Test GetBounds() and Simplify(). */
4209 hr = ID2D1RectangleGeometry_GetBounds(geometry, NULL, &rect);
4210 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4211 match = compare_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f, 0);
4212 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
4213 rect.left, rect.top, rect.right, rect.bottom);
4214 geometry_sink_init(&sink);
4215 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
4216 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
4217 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4218 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[0], 0);
4219 geometry_sink_cleanup(&sink);
4220 geometry_sink_init(&sink);
4221 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
4222 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
4223 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4224 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[0], 0);
4225 geometry_sink_cleanup(&sink);
4227 set_matrix_identity(&matrix);
4228 translate_matrix(&matrix, 20.0f, 30.0f);
4229 scale_matrix(&matrix, 3.0f, 2.0f);
4230 rotate_matrix(&matrix, M_PI / -5.0f);
4231 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
4232 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4233 match = compare_rect(&rect, 2.00000000e+01f, 1.82442951e+01f, 7.95376282e+01f, 6.23606796e+01f, 0);
4234 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
4235 rect.left, rect.top, rect.right, rect.bottom);
4236 geometry_sink_init(&sink);
4237 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
4238 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
4239 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4240 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[1], 1);
4241 geometry_sink_cleanup(&sink);
4243 set_matrix_identity(&matrix);
4244 translate_matrix(&matrix, 25.0f, 15.0f);
4245 scale_matrix(&matrix, 0.0f, 2.0f);
4246 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
4247 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4248 match = compare_rect(&rect, 25.0f, 15.0f, 25.0f, 55.0f, 0);
4249 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
4250 rect.left, rect.top, rect.right, rect.bottom);
4251 geometry_sink_init(&sink);
4252 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
4253 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
4254 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4255 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[2], 0);
4256 geometry_sink_cleanup(&sink);
4258 set_matrix_identity(&matrix);
4259 translate_matrix(&matrix, 30.0f, 45.0f);
4260 scale_matrix(&matrix, 0.5f, 0.0f);
4261 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
4262 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4263 match = compare_rect(&rect, 30.0f, 45.0f, 35.0f, 45.0f, 0);
4264 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
4265 rect.left, rect.top, rect.right, rect.bottom);
4266 geometry_sink_init(&sink);
4267 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
4268 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
4269 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4270 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[3], 0);
4271 geometry_sink_cleanup(&sink);
4273 set_matrix_identity(&matrix);
4274 scale_matrix(&matrix, 4.0f, 5.0f);
4275 rotate_matrix(&matrix, M_PI / 3.0f);
4276 translate_matrix(&matrix, 30.0f, 20.0f);
4277 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
4278 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4280 hr = ID2D1TransformedGeometry_GetBounds(transformed_geometry, NULL, &rect);
4281 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4282 match = compare_rect(&rect, -7.85640717e+01f, 1.79903809e+02f, 1.07179594e+01f, 2.73205078e+02f, 1);
4283 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
4284 rect.left, rect.top, rect.right, rect.bottom);
4285 geometry_sink_init(&sink);
4286 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
4287 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
4288 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4289 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[4], 1);
4290 geometry_sink_cleanup(&sink);
4291 geometry_sink_init(&sink);
4292 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
4293 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
4294 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4295 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[4], 1);
4296 geometry_sink_cleanup(&sink);
4298 set_matrix_identity(&matrix);
4299 rotate_matrix(&matrix, M_PI / -3.0f);
4300 scale_matrix(&matrix, 0.25f, 0.2f);
4301 hr = ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
4302 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4303 match = compare_rect(&rect, 30.0f, 20.0f, 40.0f, 40.0f, 2);
4304 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
4305 rect.left, rect.top, rect.right, rect.bottom);
4306 geometry_sink_init(&sink);
4307 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
4308 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
4309 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4310 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[5], 4);
4311 geometry_sink_cleanup(&sink);
4313 set_matrix_identity(&matrix);
4314 scale_matrix(&matrix, 2.0f, 0.0f);
4315 hr = ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
4316 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4317 match = compare_rect(&rect, -1.57128143e+02f, 0.00000000e+00f, 2.14359188e+01f, 0.00000000e+00f, 1);
4318 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
4319 rect.left, rect.top, rect.right, rect.bottom);
4320 geometry_sink_init(&sink);
4321 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
4322 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
4323 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4324 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[6], 1);
4325 geometry_sink_cleanup(&sink);
4327 set_matrix_identity(&matrix);
4328 scale_matrix(&matrix, 0.0f, 0.5f);
4329 hr = ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
4330 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4331 match = compare_rect(&rect, 0.00000000e+00f, 8.99519043e+01f, 0.00000000e+00, 1.36602539e+02f, 1);
4332 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
4333 rect.left, rect.top, rect.right, rect.bottom);
4334 geometry_sink_init(&sink);
4335 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
4336 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
4337 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4338 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[7], 1);
4339 geometry_sink_cleanup(&sink);
4341 ID2D1TransformedGeometry_Release(transformed_geometry);
4342 ID2D1RectangleGeometry_Release(geometry);
4343 ID2D1Factory_Release(factory);
4346 static void test_rounded_rectangle_geometry(BOOL d3d11)
4348 ID2D1RoundedRectangleGeometry *geometry;
4349 D2D1_ROUNDED_RECT rect, rect2;
4350 ID2D1Factory *factory;
4351 HRESULT hr;
4353 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4354 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4356 set_rounded_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
4357 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
4358 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4360 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
4361 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
4362 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
4363 ID2D1RoundedRectangleGeometry_Release(geometry);
4365 /* X radius larger than half width. */
4366 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 30.0f, 5.0f);
4367 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
4368 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
4369 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
4370 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
4371 ID2D1RoundedRectangleGeometry_Release(geometry);
4373 /* Y radius larger than half height. */
4374 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 5.0f, 30.0f);
4375 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
4376 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
4377 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
4378 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
4379 ID2D1RoundedRectangleGeometry_Release(geometry);
4381 /* Both exceed rectangle size. */
4382 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 30.0f, 25.0f);
4383 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
4384 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
4385 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
4386 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
4387 ID2D1RoundedRectangleGeometry_Release(geometry);
4389 ID2D1Factory_Release(factory);
4392 static void test_bitmap_formats(BOOL d3d11)
4394 D2D1_BITMAP_PROPERTIES bitmap_desc;
4395 struct d2d1_test_context ctx;
4396 D2D1_SIZE_U size = {4, 4};
4397 ID2D1RenderTarget *rt;
4398 ID2D1Bitmap *bitmap;
4399 unsigned int i, j;
4400 HRESULT hr;
4402 static const struct
4404 DXGI_FORMAT format;
4405 DWORD mask;
4407 bitmap_formats[] =
4409 {DXGI_FORMAT_R32G32B32A32_FLOAT, 0x8a},
4410 {DXGI_FORMAT_R16G16B16A16_FLOAT, 0x8a},
4411 {DXGI_FORMAT_R16G16B16A16_UNORM, 0x8a},
4412 {DXGI_FORMAT_R8G8B8A8_TYPELESS, 0x00},
4413 {DXGI_FORMAT_R8G8B8A8_UNORM, 0x0a},
4414 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0x8a},
4415 {DXGI_FORMAT_R8G8B8A8_UINT, 0x00},
4416 {DXGI_FORMAT_R8G8B8A8_SNORM, 0x00},
4417 {DXGI_FORMAT_R8G8B8A8_SINT, 0x00},
4418 {DXGI_FORMAT_A8_UNORM, 0x06},
4419 {DXGI_FORMAT_B8G8R8A8_UNORM, 0x0a},
4420 {DXGI_FORMAT_B8G8R8X8_UNORM, 0x88},
4421 {DXGI_FORMAT_B8G8R8A8_TYPELESS, 0x00},
4422 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 0x8a},
4425 if (!init_test_context(&ctx, d3d11))
4426 return;
4428 rt = ctx.rt;
4429 bitmap_desc.dpiX = 96.0f;
4430 bitmap_desc.dpiY = 96.0f;
4431 for (i = 0; i < ARRAY_SIZE(bitmap_formats); ++i)
4433 for (j = 0; j < 4; ++j)
4435 if ((bitmap_formats[i].mask & (0x80 | (1u << j))) == (0x80 | (1u << j)))
4436 continue;
4438 bitmap_desc.pixelFormat.format = bitmap_formats[i].format;
4439 bitmap_desc.pixelFormat.alphaMode = j;
4440 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
4441 if (bitmap_formats[i].mask & (1u << j))
4442 ok(hr == S_OK, "Got unexpected hr %#lx, for format %#x/%#x.\n",
4443 hr, bitmap_formats[i].format, j);
4444 else
4445 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#lx, for format %#x/%#x.\n",
4446 hr, bitmap_formats[i].format, j);
4447 if (SUCCEEDED(hr))
4448 ID2D1Bitmap_Release(bitmap);
4452 release_test_context(&ctx);
4455 static void test_alpha_mode(BOOL d3d11)
4457 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
4458 D2D1_BITMAP_PROPERTIES1 bitmap_desc1;
4459 D2D1_BITMAP_PROPERTIES bitmap_desc;
4460 ID2D1SolidColorBrush *color_brush;
4461 ID2D1BitmapBrush *bitmap_brush;
4462 struct d2d1_test_context ctx;
4463 ID2D1DeviceContext *context;
4464 ID2D1Bitmap1 *bitmap1;
4465 ID2D1RenderTarget *rt;
4466 IDXGISurface *surface;
4467 ID2D1Bitmap *bitmap;
4468 D2D1_COLOR_F color;
4469 BOOL match, match2;
4470 D2D1_RECT_F rect;
4471 D2D1_SIZE_U size;
4472 ULONG refcount;
4473 HRESULT hr;
4475 static const DWORD bitmap_data[] =
4477 0x7f7f0000, 0x7f7f7f00, 0x7f007f00, 0x7f007f7f,
4478 0x7f00007f, 0x7f7f007f, 0x7f000000, 0x7f404040,
4479 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f000000,
4480 0x7f7f7f7f, 0x7f000000, 0x7f000000, 0x7f000000,
4483 if (!init_test_context(&ctx, d3d11))
4484 return;
4486 rt = ctx.rt;
4487 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4489 set_size_u(&size, 4, 4);
4490 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4491 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
4492 bitmap_desc.dpiX = 96.0f / 40.0f;
4493 bitmap_desc.dpiY = 96.0f / 30.0f;
4494 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
4495 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4497 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
4498 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4499 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
4500 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
4501 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
4503 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
4504 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
4505 ok(SUCCEEDED(hr), "Failed to create brush, hr %#lx.\n", hr);
4507 ID2D1RenderTarget_BeginDraw(rt);
4508 ID2D1RenderTarget_Clear(rt, NULL);
4509 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4510 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4511 match = compare_surface(&ctx, "48c41aff3a130a17ee210866b2ab7d36763934d5");
4512 ok(match, "Surface does not match.\n");
4514 ID2D1RenderTarget_BeginDraw(rt);
4515 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
4516 ID2D1RenderTarget_Clear(rt, &color);
4517 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4518 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4519 match = compare_surface(&ctx, "6487e683730fb5a77c1911388d00b04664c5c4e4");
4520 ok(match, "Surface does not match.\n");
4522 ID2D1RenderTarget_BeginDraw(rt);
4523 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
4524 ID2D1RenderTarget_Clear(rt, &color);
4525 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4526 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4527 match = compare_surface(&ctx, "7a35ba09e43cbaf591388ff1ef8de56157630c98");
4528 ok(match, "Surface does not match.\n");
4530 ID2D1RenderTarget_BeginDraw(rt);
4532 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
4533 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4534 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
4535 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
4536 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4537 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
4538 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
4539 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4541 ID2D1Bitmap_Release(bitmap);
4542 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4543 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
4544 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4545 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
4547 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
4548 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
4549 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4550 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
4551 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
4552 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4553 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
4554 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
4555 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4557 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
4558 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4559 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
4560 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
4561 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4562 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
4563 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
4564 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4566 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4567 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4568 match = compare_surface(&ctx, "14f8ac64b70966c7c3c6281c59aaecdb17c3b16a");
4569 ok(match, "Surface does not match.\n");
4571 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4572 rt_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
4573 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
4574 rt_desc.dpiX = 0.0f;
4575 rt_desc.dpiY = 0.0f;
4576 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4577 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4578 rt = create_render_target_desc(ctx.surface, &rt_desc, d3d11);
4579 ok(!!rt, "Failed to create render target.\n");
4581 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4583 ID2D1Bitmap_Release(bitmap);
4584 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
4585 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
4586 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4587 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
4589 ID2D1BitmapBrush_Release(bitmap_brush);
4590 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
4591 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4592 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
4593 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
4594 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
4596 ID2D1SolidColorBrush_Release(color_brush);
4597 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
4598 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
4599 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4601 ID2D1RenderTarget_BeginDraw(rt);
4602 ID2D1RenderTarget_Clear(rt, NULL);
4603 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4604 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4605 match = compare_surface(&ctx, "b44510bf2d2e61a8d7c0ad862de49a471f1fd13f");
4606 ok(match, "Surface does not match.\n");
4608 ID2D1RenderTarget_BeginDraw(rt);
4609 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
4610 ID2D1RenderTarget_Clear(rt, &color);
4611 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4612 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4613 match = compare_surface(&ctx, "2184f4a9198fc1de09ac85301b7a03eebadd9b81");
4614 ok(match, "Surface does not match.\n");
4616 ID2D1RenderTarget_BeginDraw(rt);
4617 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
4618 ID2D1RenderTarget_Clear(rt, &color);
4619 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4620 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4621 match = compare_surface(&ctx, "6527ec83b4039c895b50f9b3e144fe0cf90d1889");
4622 ok(match, "Surface does not match.\n");
4624 ID2D1RenderTarget_BeginDraw(rt);
4626 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
4627 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4628 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
4629 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
4630 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4631 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
4632 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
4633 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4635 ID2D1Bitmap_Release(bitmap);
4636 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4637 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
4638 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4639 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
4641 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
4642 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
4643 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4644 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
4645 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
4646 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4647 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
4648 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
4649 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4651 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
4652 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4653 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
4654 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
4655 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4656 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
4657 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
4658 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4660 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4661 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4662 match = compare_surface(&ctx, "465f5a3190d7bde408b3206b4be939fb22f8a3d6");
4663 ok(match, "Surface does not match.\n");
4665 refcount = ID2D1Bitmap_Release(bitmap);
4666 ok(refcount == 1, "Bitmap has %lu references left.\n", refcount);
4667 ID2D1BitmapBrush_Release(bitmap_brush);
4669 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&context);
4670 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4672 set_size_u(&size, 4, 4);
4673 memset(&bitmap_desc1, 0, sizeof(bitmap_desc1));
4674 bitmap_desc1.dpiX = 96.0f;
4675 bitmap_desc1.dpiY = 96.0f;
4676 bitmap_desc1.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4677 bitmap_desc1.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
4678 bitmap_desc1.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
4679 hr = ID2D1DeviceContext_CreateBitmap(context, size, bitmap_data, 4 * sizeof(*bitmap_data),
4680 &bitmap_desc1, &bitmap1);
4681 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4683 ID2D1DeviceContext_BeginDraw(context);
4684 ID2D1DeviceContext_SetTarget(context, (ID2D1Image *)bitmap1);
4685 set_rect(&rect, 0.0f, 2.0f, 1.0f, 2.0f);
4686 ID2D1SolidColorBrush_SetOpacity(color_brush, 1.0f);
4687 ID2D1DeviceContext_FillRectangle(context, &rect, (ID2D1Brush *)color_brush);
4688 set_rect(&rect, 1.0f, 2.0f, 3.0f, 3.0f);
4689 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
4690 ID2D1DeviceContext_FillRectangle(context, &rect, (ID2D1Brush *)color_brush);
4691 set_rect(&rect, 3.0f, 2.0f, 3.0f, 3.0f);
4692 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
4693 ID2D1DeviceContext_FillRectangle(context, &rect, (ID2D1Brush *)color_brush);
4694 hr = ID2D1DeviceContext_EndDraw(context, NULL, NULL);
4695 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4697 surface = ctx.surface;
4698 hr = ID2D1Bitmap1_GetSurface(bitmap1, &ctx.surface);
4699 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4700 match = compare_surface(&ctx, "e7ee77e89745fa5d195fd78bd398738330cfcde8");
4701 match2 = compare_surface(&ctx, "4855c7c082c8ede364cf6e2dcde83f95b88aecbe");
4702 ok(match || broken(match2) /* Win7 TestBots */, "Surface does not match.\n");
4703 IDXGISurface_Release(ctx.surface);
4704 ctx.surface = surface;
4705 ID2D1DeviceContext_SetTarget(context, NULL);
4707 ID2D1Bitmap1_Release(bitmap1);
4708 ID2D1DeviceContext_Release(context);
4709 ID2D1SolidColorBrush_Release(color_brush);
4710 ID2D1RenderTarget_Release(rt);
4711 release_test_context(&ctx);
4714 static void test_shared_bitmap(BOOL d3d11)
4716 IWICBitmap *wic_bitmap1, *wic_bitmap2;
4717 ID2D1GdiInteropRenderTarget *interop;
4718 D2D1_RENDER_TARGET_PROPERTIES desc;
4719 D2D1_BITMAP_PROPERTIES bitmap_desc;
4720 ID2D1RenderTarget *rt1, *rt2, *rt3;
4721 IDXGISurface *surface2;
4722 ID2D1Factory *factory1, *factory2;
4723 IWICImagingFactory *wic_factory;
4724 ID2D1Bitmap *bitmap1, *bitmap2;
4725 DXGI_SURFACE_DESC surface_desc;
4726 D2D1_PIXEL_FORMAT pixel_format;
4727 struct d2d1_test_context ctx;
4728 IDXGISwapChain *swapchain2;
4729 D2D1_SIZE_U size = {4, 4};
4730 IDXGISurface1 *surface3;
4731 IDXGIDevice *device2;
4732 HWND window2;
4733 HRESULT hr;
4735 if (!init_test_context(&ctx, d3d11))
4736 return;
4738 window2 = create_window();
4739 swapchain2 = create_swapchain(ctx.device, window2, TRUE);
4740 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
4741 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4743 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
4744 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
4745 &IID_IWICImagingFactory, (void **)&wic_factory);
4746 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4747 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
4748 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap1);
4749 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4750 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
4751 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap2);
4752 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4753 IWICImagingFactory_Release(wic_factory);
4755 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4756 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
4757 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4758 desc.dpiX = 0.0f;
4759 desc.dpiY = 0.0f;
4760 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4761 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4763 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4764 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4765 bitmap_desc.dpiX = 96.0f;
4766 bitmap_desc.dpiY = 96.0f;
4768 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory1);
4769 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4770 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
4771 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4773 /* DXGI surface render targets with the same device and factory. */
4774 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, ctx.surface, &desc, &rt1);
4775 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4776 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
4777 check_bitmap_surface(bitmap1, TRUE, 0);
4778 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4780 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
4781 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4782 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4783 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4784 check_bitmap_surface(bitmap2, TRUE, 0);
4785 ID2D1Bitmap_Release(bitmap2);
4786 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IUnknown, bitmap1, NULL, &bitmap2);
4787 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
4788 ID2D1RenderTarget_Release(rt2);
4790 /* DXGI surface render targets with the same device but different factories. */
4791 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
4792 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4793 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4794 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#lx.\n", hr);
4795 ID2D1RenderTarget_Release(rt2);
4797 /* DXGI surface render targets with different devices but the same factory. */
4798 IDXGISurface_Release(surface2);
4799 IDXGISwapChain_Release(swapchain2);
4800 device2 = create_device(d3d11);
4801 ok(!!device2, "Failed to create device.\n");
4802 swapchain2 = create_swapchain(device2, window2, TRUE);
4803 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
4804 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4806 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
4807 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4808 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4809 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#lx.\n", hr);
4810 ID2D1RenderTarget_Release(rt2);
4812 /* DXGI surface render targets with different devices and different factories. */
4813 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
4814 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4815 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4816 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#lx.\n", hr);
4817 ID2D1RenderTarget_Release(rt2);
4819 /* DXGI surface render target and WIC bitmap render target, same factory. */
4820 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
4821 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4822 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4823 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#lx.\n", hr);
4824 ID2D1RenderTarget_Release(rt2);
4826 /* WIC bitmap render targets on different D2D factories. */
4827 ID2D1Bitmap_Release(bitmap1);
4828 ID2D1RenderTarget_Release(rt1);
4829 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap1, &desc, &rt1);
4830 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4831 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
4832 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4834 hr = ID2D1RenderTarget_QueryInterface(rt1, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
4835 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4836 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
4837 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4838 ok(rt3 == rt1, "Unexpected render target\n");
4839 ID2D1RenderTarget_Release(rt3);
4840 ID2D1GdiInteropRenderTarget_Release(interop);
4842 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory2, wic_bitmap2, &desc, &rt2);
4843 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4844 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4845 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#lx.\n", hr);
4846 ID2D1RenderTarget_Release(rt2);
4848 /* WIC bitmap render targets on the same D2D factory. */
4849 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
4850 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4851 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4852 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4853 check_bitmap_surface(bitmap2, FALSE, 0);
4854 ID2D1Bitmap_Release(bitmap2);
4855 ID2D1RenderTarget_Release(rt2);
4857 /* Shared DXGI surface. */
4858 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4859 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4860 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4861 desc.dpiX = 0.0f;
4862 desc.dpiY = 0.0f;
4863 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4864 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4866 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
4867 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4869 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4870 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4871 bitmap_desc.dpiX = 0.0f;
4872 bitmap_desc.dpiY = 0.0f;
4874 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface, surface2, &bitmap_desc, &bitmap2);
4875 ok(hr == S_OK || broken(hr == E_INVALIDARG) /* vista */, "Got unexpected hr %#lx.\n", hr);
4877 if (SUCCEEDED(hr))
4879 static const struct bitmap_format_test
4881 D2D1_PIXEL_FORMAT original;
4882 D2D1_PIXEL_FORMAT result;
4883 HRESULT hr;
4885 bitmap_format_tests[] =
4887 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
4888 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED } },
4890 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE },
4891 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
4893 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
4895 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
4897 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE },
4898 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
4900 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
4901 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
4903 unsigned int i;
4905 size = ID2D1Bitmap_GetPixelSize(bitmap2);
4906 hr = IDXGISurface_GetDesc(surface2, &surface_desc);
4907 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4908 ok(size.width == surface_desc.Width && size.height == surface_desc.Height, "Got wrong bitmap size.\n");
4910 check_bitmap_surface(bitmap2, TRUE, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW);
4912 ID2D1Bitmap_Release(bitmap2);
4914 /* IDXGISurface1 is supported too. */
4915 if (IDXGISurface_QueryInterface(surface2, &IID_IDXGISurface1, (void **)&surface3) == S_OK)
4917 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface1, surface3, &bitmap_desc, &bitmap2);
4918 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
4920 ID2D1Bitmap_Release(bitmap2);
4921 IDXGISurface1_Release(surface3);
4924 for (i = 0; i < ARRAY_SIZE(bitmap_format_tests); ++i)
4926 bitmap_desc.pixelFormat = bitmap_format_tests[i].original;
4928 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface, surface2, &bitmap_desc, &bitmap2);
4929 todo_wine_if(i == 2 || i == 3 || i == 5 || i == 6)
4930 ok(hr == bitmap_format_tests[i].hr, "%u: Got unexpected hr %#lx.\n", i, hr);
4932 if (SUCCEEDED(bitmap_format_tests[i].hr))
4934 pixel_format = ID2D1Bitmap_GetPixelFormat(bitmap2);
4935 ok(pixel_format.format == bitmap_format_tests[i].result.format, "%u: unexpected pixel format %#x.\n",
4936 i, pixel_format.format);
4937 ok(pixel_format.alphaMode == bitmap_format_tests[i].result.alphaMode, "%u: unexpected alpha mode %d.\n",
4938 i, pixel_format.alphaMode);
4940 ID2D1Bitmap_Release(bitmap2);
4945 ID2D1RenderTarget_Release(rt2);
4947 ID2D1Bitmap_Release(bitmap1);
4948 ID2D1RenderTarget_Release(rt1);
4949 ID2D1Factory_Release(factory2);
4950 ID2D1Factory_Release(factory1);
4951 IWICBitmap_Release(wic_bitmap2);
4952 IWICBitmap_Release(wic_bitmap1);
4953 IDXGISurface_Release(surface2);
4954 IDXGISwapChain_Release(swapchain2);
4955 IDXGIDevice_Release(device2);
4956 release_test_context(&ctx);
4957 DestroyWindow(window2);
4958 CoUninitialize();
4961 static void test_bitmap_updates(BOOL d3d11)
4963 D2D1_BITMAP_PROPERTIES bitmap_desc;
4964 ID2D1Bitmap *bitmap, *dst_bitmap;
4965 D2D1_RECT_U dst_rect, src_rect;
4966 struct d2d1_test_context ctx;
4967 D2D1_POINT_2U dst_point;
4968 ID2D1RenderTarget *rt;
4969 D2D1_COLOR_F color;
4970 D2D1_RECT_F rect;
4971 D2D1_SIZE_U size;
4972 HRESULT hr;
4973 BOOL match;
4975 static const DWORD bitmap_data[] =
4977 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
4978 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
4979 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
4980 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
4983 if (!init_test_context(&ctx, d3d11))
4984 return;
4986 rt = ctx.rt;
4987 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4989 ID2D1RenderTarget_BeginDraw(rt);
4990 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
4991 ID2D1RenderTarget_Clear(rt, &color);
4993 set_size_u(&size, 4, 4);
4994 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4995 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4996 bitmap_desc.dpiX = 96.0f;
4997 bitmap_desc.dpiY = 96.0f;
4998 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
4999 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5001 set_rect(&rect, 0.0f, 0.0f, 320.0f, 240.0f);
5002 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
5003 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
5005 ID2D1Bitmap_Release(bitmap);
5007 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
5008 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
5009 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5011 set_rect(&rect, 0.0f, 240.0f, 320.0f, 480.0f);
5012 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
5013 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
5015 set_rect_u(&dst_rect, 1, 1, 3, 3);
5016 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, 4 * sizeof(*bitmap_data));
5017 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5018 set_rect_u(&dst_rect, 0, 3, 3, 4);
5019 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[6], 4 * sizeof(*bitmap_data));
5020 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5021 set_rect_u(&dst_rect, 0, 0, 4, 1);
5022 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[10], 4 * sizeof(*bitmap_data));
5023 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5024 set_rect_u(&dst_rect, 0, 1, 1, 3);
5025 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[2], sizeof(*bitmap_data));
5026 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5027 set_rect_u(&dst_rect, 4, 4, 3, 1);
5028 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, sizeof(*bitmap_data));
5029 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5030 set_rect(&rect, 320.0f, 240.0f, 640.0f, 480.0f);
5031 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
5032 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
5034 hr = ID2D1Bitmap_CopyFromMemory(bitmap, NULL, bitmap_data, 4 * sizeof(*bitmap_data));
5035 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5036 set_rect(&rect, 320.0f, 0.0f, 640.0f, 240.0f);
5037 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
5038 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
5040 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5041 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5043 match = compare_surface(&ctx, "cb8136c91fbbdc76bb83b8c09edc1907b0a5d0a6");
5044 ok(match, "Surface does not match.\n");
5046 ID2D1RenderTarget_BeginDraw(rt);
5047 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
5048 ID2D1RenderTarget_Clear(rt, &color);
5049 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
5050 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &dst_bitmap);
5051 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5053 hr = ID2D1Bitmap_CopyFromBitmap(dst_bitmap, NULL, bitmap, NULL);
5054 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5055 dst_point.x = 1; dst_point.y = 1;
5056 hr = ID2D1Bitmap_CopyFromBitmap(dst_bitmap, &dst_point, bitmap, NULL);
5057 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5058 dst_point.x = 0; dst_point.y = 1;
5059 set_rect_u(&src_rect, 1, 1, 3, 3);
5060 hr = ID2D1Bitmap_CopyFromBitmap(dst_bitmap, &dst_point, bitmap, &src_rect);
5061 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5062 dst_point.x = 1; dst_point.y = 0;
5063 set_rect_u(&src_rect, 2, 2, 1, 1);
5064 hr = ID2D1Bitmap_CopyFromBitmap(dst_bitmap, &dst_point, bitmap, &src_rect);
5065 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5066 set_rect_u(&src_rect, 1, 1, 2, 2);
5067 hr = ID2D1Bitmap_CopyFromBitmap(dst_bitmap, NULL, bitmap, &src_rect);
5068 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5070 set_rect(&rect, 320.0f, 0.0f, 640.0f, 240.0f);
5071 ID2D1RenderTarget_DrawBitmap(rt, dst_bitmap, &rect, 1.0f,
5072 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
5074 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5075 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5076 match = compare_surface(&ctx, "a1758bd644d897f75d43769ba26456af70cd9056");
5077 ok(match, "Surface does not match.\n");
5078 ID2D1Bitmap_Release(dst_bitmap);
5080 ID2D1Bitmap_Release(bitmap);
5081 release_test_context(&ctx);
5084 static void test_opacity_brush(BOOL d3d11)
5086 ID2D1BitmapBrush *bitmap_brush, *opacity_brush;
5087 D2D1_BITMAP_PROPERTIES bitmap_desc;
5088 ID2D1RectangleGeometry *geometry;
5089 ID2D1SolidColorBrush *color_brush;
5090 struct d2d1_test_context ctx;
5091 D2D1_MATRIX_3X2_F matrix;
5092 ID2D1RenderTarget *rt;
5093 ID2D1Factory *factory;
5094 ID2D1Bitmap *bitmap;
5095 D2D1_COLOR_F color;
5096 D2D1_RECT_F rect;
5097 D2D1_SIZE_U size;
5098 ULONG refcount;
5099 HRESULT hr;
5100 BOOL match;
5102 static const DWORD bitmap_data[] =
5104 0xffff0000, 0x40ffff00, 0x4000ff00, 0xff00ffff,
5105 0x7f0000ff, 0x00ff00ff, 0x00000000, 0x7f7f7f7f,
5106 0x7fffffff, 0x00ffffff, 0x00ffffff, 0x7f000000,
5107 0xffffffff, 0x40000000, 0x40000000, 0xff000000,
5110 if (!init_test_context(&ctx, d3d11))
5111 return;
5113 rt = ctx.rt;
5114 ID2D1RenderTarget_GetFactory(rt, &factory);
5116 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
5117 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
5119 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
5120 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
5121 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5123 set_size_u(&size, 4, 4);
5124 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
5125 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5126 bitmap_desc.dpiX = 96.0f;
5127 bitmap_desc.dpiY = 96.0f;
5128 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
5129 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5130 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &opacity_brush);
5131 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5132 ID2D1BitmapBrush_SetInterpolationMode(opacity_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
5133 refcount = ID2D1Bitmap_Release(bitmap);
5134 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
5136 set_size_u(&size, 1, 1);
5137 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
5138 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
5139 bitmap_desc.dpiX = 96.0f;
5140 bitmap_desc.dpiY = 96.0f;
5141 hr = ID2D1RenderTarget_CreateBitmap(rt, size, &bitmap_data[2], sizeof(*bitmap_data), &bitmap_desc, &bitmap);
5142 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5143 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
5144 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5145 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
5146 refcount = ID2D1Bitmap_Release(bitmap);
5147 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
5149 ID2D1RenderTarget_BeginDraw(rt);
5151 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
5152 ID2D1RenderTarget_Clear(rt, &color);
5154 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
5155 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
5157 set_matrix_identity(&matrix);
5158 translate_matrix(&matrix, 120.0f, 120.0f);
5159 scale_matrix(&matrix, 20.0f, 60.0f);
5160 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
5161 set_rect(&rect, 120.0f, 120.0f, 200.0f, 360.0f);
5162 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)opacity_brush);
5164 set_rect(&rect, 200.0f, 120.0f, 280.0f, 360.0f);
5165 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
5167 set_matrix_identity(&matrix);
5168 translate_matrix(&matrix, 40.0f, 360.0f);
5169 scale_matrix(&matrix, 20.0f, 60.0f);
5170 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
5171 set_rect(&rect, 40.0f, 360.0f, 120.0f, 600.0f);
5172 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
5173 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
5174 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
5175 ID2D1RectangleGeometry_Release(geometry);
5177 set_matrix_identity(&matrix);
5178 translate_matrix(&matrix, 120.0f, 360.0f);
5179 scale_matrix(&matrix, 20.0f, 60.0f);
5180 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
5181 set_rect(&rect, 120.0f, 360.0f, 200.0f, 600.0f);
5182 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
5183 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
5184 (ID2D1Brush *)color_brush, (ID2D1Brush *)opacity_brush);
5185 ID2D1RectangleGeometry_Release(geometry);
5187 set_matrix_identity(&matrix);
5188 translate_matrix(&matrix, 200.0f, 360.0f);
5189 scale_matrix(&matrix, 20.0f, 60.0f);
5190 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
5191 set_rect(&rect, 200.0f, 360.0f, 280.0f, 600.0f);
5192 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
5193 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
5194 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
5196 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5197 ok(hr == D2DERR_INCOMPATIBLE_BRUSH_TYPES, "Got unexpected hr %#lx.\n", hr);
5198 match = compare_surface(&ctx, "7141c6c7b3decb91196428efb1856bcbf9872935");
5199 ok(match, "Surface does not match.\n");
5200 ID2D1RenderTarget_BeginDraw(rt);
5202 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
5203 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
5204 ID2D1RectangleGeometry_Release(geometry);
5206 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.5f);
5207 set_matrix_identity(&matrix);
5208 translate_matrix(&matrix, 40.0f, 600.0f);
5209 scale_matrix(&matrix, 20.0f, 60.0f);
5210 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
5211 set_rect(&rect, 40.0f, 600.0f, 120.0f, 840.0f);
5212 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
5213 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
5214 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
5215 ID2D1RectangleGeometry_Release(geometry);
5217 ID2D1BitmapBrush_SetOpacity(opacity_brush, 0.8f);
5218 set_matrix_identity(&matrix);
5219 translate_matrix(&matrix, 120.0f, 600.0f);
5220 scale_matrix(&matrix, 20.0f, 60.0f);
5221 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
5222 set_rect(&rect, 120.0f, 600.0f, 200.0f, 840.0f);
5223 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
5224 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
5225 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)bitmap_brush);
5226 ID2D1RectangleGeometry_Release(geometry);
5228 set_matrix_identity(&matrix);
5229 translate_matrix(&matrix, 200.0f, 600.0f);
5230 scale_matrix(&matrix, 20.0f, 60.0f);
5231 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
5232 set_rect(&rect, 200.0f, 600.0f, 280.0f, 840.0f);
5233 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
5234 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
5235 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
5236 ID2D1RectangleGeometry_Release(geometry);
5238 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5239 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5240 match = compare_surface(&ctx, "c3a5802d1750efa3e9122c1a92f6064df3872732");
5241 ok(match, "Surface does not match.\n");
5243 ID2D1BitmapBrush_Release(bitmap_brush);
5244 ID2D1BitmapBrush_Release(opacity_brush);
5245 ID2D1SolidColorBrush_Release(color_brush);
5246 ID2D1Factory_Release(factory);
5247 release_test_context(&ctx);
5250 static void test_create_target(BOOL d3d11)
5252 struct d2d1_test_context ctx;
5253 ID2D1Factory *factory;
5254 ID2D1RenderTarget *rt;
5255 HRESULT hr;
5256 static const struct
5258 float dpi_x, dpi_y;
5259 float rt_dpi_x, rt_dpi_y;
5260 HRESULT hr;
5262 create_dpi_tests[] =
5264 { 0.0f, 0.0f, 96.0f, 96.0f, S_OK },
5265 { 192.0f, 0.0f, 96.0f, 96.0f, E_INVALIDARG },
5266 { 0.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
5267 { 192.0f, -10.0f, 96.0f, 96.0f, E_INVALIDARG },
5268 { -10.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
5269 { 48.0f, 96.0f, 48.0f, 96.0f, S_OK },
5271 unsigned int i;
5273 if (!init_test_context(&ctx, d3d11))
5274 return;
5276 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5277 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5279 for (i = 0; i < ARRAY_SIZE(create_dpi_tests); ++i)
5281 ID2D1GdiInteropRenderTarget *interop;
5282 D2D1_RENDER_TARGET_PROPERTIES desc;
5283 ID2D1RenderTarget *rt2;
5284 float dpi_x, dpi_y;
5285 IUnknown *unk;
5287 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5288 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
5289 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5290 desc.dpiX = create_dpi_tests[i].dpi_x;
5291 desc.dpiY = create_dpi_tests[i].dpi_y;
5292 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5293 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5295 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, ctx.surface, &desc, &rt);
5296 ok(hr == create_dpi_tests[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n",
5297 i, hr, create_dpi_tests[i].hr);
5299 if (FAILED(hr))
5300 continue;
5302 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_IUnknown, (void **)&unk);
5303 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
5304 ok(unk == (IUnknown *)rt, "Expected same interface pointer.\n");
5305 IUnknown_Release(unk);
5307 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5308 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
5309 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt2);
5310 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
5311 ok(rt2 == rt, "Unexpected render target\n");
5312 ID2D1RenderTarget_Release(rt2);
5313 ID2D1GdiInteropRenderTarget_Release(interop);
5315 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
5316 ok(dpi_x == create_dpi_tests[i].rt_dpi_x, "Wrong dpi_x %.8e, expected %.8e, test %u\n",
5317 dpi_x, create_dpi_tests[i].rt_dpi_x, i);
5318 ok(dpi_y == create_dpi_tests[i].rt_dpi_y, "Wrong dpi_y %.8e, expected %.8e, test %u\n",
5319 dpi_y, create_dpi_tests[i].rt_dpi_y, i);
5321 ID2D1RenderTarget_Release(rt);
5324 ID2D1Factory_Release(factory);
5325 release_test_context(&ctx);
5328 static void test_draw_text_layout(BOOL d3d11)
5330 static const struct
5332 D2D1_TEXT_ANTIALIAS_MODE aa_mode;
5333 DWRITE_RENDERING_MODE rendering_mode;
5334 HRESULT hr;
5336 antialias_mode_tests[] =
5338 { D2D1_TEXT_ANTIALIAS_MODE_DEFAULT, DWRITE_RENDERING_MODE_ALIASED },
5339 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_ALIASED },
5340 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_DEFAULT },
5341 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_OUTLINE },
5342 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_DEFAULT },
5343 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_OUTLINE },
5344 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL },
5345 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC },
5346 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL },
5347 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC },
5348 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_DEFAULT },
5349 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL },
5350 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC },
5351 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL },
5352 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC },
5353 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_OUTLINE, E_INVALIDARG },
5354 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_ALIASED, E_INVALIDARG },
5355 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_ALIASED, E_INVALIDARG },
5356 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL, E_INVALIDARG },
5357 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, E_INVALIDARG },
5358 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL, E_INVALIDARG },
5359 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC, E_INVALIDARG },
5361 D2D1_RENDER_TARGET_PROPERTIES desc;
5362 ID2D1Factory *factory, *factory2;
5363 ID2D1RenderTarget *rt, *rt2;
5364 HRESULT hr;
5365 IDWriteFactory *dwrite_factory;
5366 IDWriteTextFormat *text_format;
5367 IDWriteTextLayout *text_layout;
5368 struct d2d1_test_context ctx;
5369 D2D1_POINT_2F origin;
5370 DWRITE_TEXT_RANGE range;
5371 D2D1_COLOR_F color;
5372 ID2D1SolidColorBrush *brush, *brush2;
5373 ID2D1RectangleGeometry *geometry;
5374 D2D1_RECT_F rect;
5375 unsigned int i;
5377 if (!init_test_context(&ctx, d3d11))
5378 return;
5381 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5382 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5384 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
5385 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5386 ok(factory != factory2, "got same factory\n");
5388 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5389 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
5390 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5391 desc.dpiX = 0.0f;
5392 desc.dpiY = 0.0f;
5393 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5394 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5396 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, ctx.surface, &desc, &rt);
5397 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5399 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, ctx.surface, &desc, &rt2);
5400 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5402 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
5403 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5405 hr = IDWriteFactory_CreateTextFormat(dwrite_factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL,
5406 DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"", &text_format);
5407 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5409 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, L"text", 4, text_format, 100.0f, 100.0f, &text_layout);
5410 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5412 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
5413 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
5414 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5416 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt2, &color, NULL, &brush2);
5417 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5419 /* effect brush is created from different factory */
5420 range.startPosition = 0;
5421 range.length = 4;
5422 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)brush2, range);
5423 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5425 ID2D1RenderTarget_BeginDraw(rt);
5427 origin.x = origin.y = 0.0f;
5428 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
5430 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5431 todo_wine ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#lx.\n", hr);
5433 /* Effect is d2d resource, but not a brush. */
5434 set_rect(&rect, 0.0f, 0.0f, 10.0f, 10.0f);
5435 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
5436 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5438 range.startPosition = 0;
5439 range.length = 4;
5440 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)geometry, range);
5441 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5442 ID2D1RectangleGeometry_Release(geometry);
5444 ID2D1RenderTarget_BeginDraw(rt);
5446 origin.x = origin.y = 0.0f;
5447 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
5449 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5450 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5452 for (i = 0; i < ARRAY_SIZE(antialias_mode_tests); ++i)
5454 IDWriteRenderingParams *rendering_params;
5456 ID2D1RenderTarget_SetTextAntialiasMode(rt, antialias_mode_tests[i].aa_mode);
5458 hr = IDWriteFactory_CreateCustomRenderingParams(dwrite_factory, 2.0f, 1.0f, 0.0f, DWRITE_PIXEL_GEOMETRY_FLAT,
5459 antialias_mode_tests[i].rendering_mode, &rendering_params);
5460 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
5462 ID2D1RenderTarget_SetTextRenderingParams(rt, rendering_params);
5464 ID2D1RenderTarget_BeginDraw(rt);
5466 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush *)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
5468 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5469 ok(hr == antialias_mode_tests[i].hr, "Test %u: Got unexpected hr %#lx.\n", i, hr);
5471 IDWriteRenderingParams_Release(rendering_params);
5474 IDWriteTextFormat_Release(text_format);
5475 IDWriteTextLayout_Release(text_layout);
5476 IDWriteFactory_Release(dwrite_factory);
5477 ID2D1RenderTarget_Release(rt);
5478 ID2D1RenderTarget_Release(rt2);
5480 ID2D1Factory_Release(factory);
5481 ID2D1Factory_Release(factory2);
5482 release_test_context(&ctx);
5485 static void create_target_dibsection(HDC hdc, UINT32 width, UINT32 height)
5487 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
5488 BITMAPINFO *bmi = (BITMAPINFO*)bmibuf;
5489 HBITMAP hbm;
5491 memset(bmi, 0, sizeof(bmibuf));
5492 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
5493 bmi->bmiHeader.biHeight = -height;
5494 bmi->bmiHeader.biWidth = width;
5495 bmi->bmiHeader.biBitCount = 32;
5496 bmi->bmiHeader.biPlanes = 1;
5497 bmi->bmiHeader.biCompression = BI_RGB;
5499 hbm = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
5500 ok(hbm != NULL, "Failed to create a dib section.\n");
5502 DeleteObject(SelectObject(hdc, hbm));
5505 static void test_dc_target(BOOL d3d11)
5507 static const D2D1_PIXEL_FORMAT invalid_formats[] =
5509 { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
5510 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN },
5511 { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
5513 D2D1_TEXT_ANTIALIAS_MODE text_aa_mode;
5514 ID2D1GdiInteropRenderTarget *interop;
5515 D2D1_RENDER_TARGET_PROPERTIES desc;
5516 D2D1_MATRIX_3X2_F matrix, matrix2;
5517 ID2D1DCRenderTarget *rt, *rt2;
5518 struct d2d1_test_context ctx;
5519 D2D1_ANTIALIAS_MODE aa_mode;
5520 ID2D1SolidColorBrush *brush;
5521 ID2D1RenderTarget *rt3;
5522 ID2D1Factory *factory;
5523 FLOAT dpi_x, dpi_y;
5524 D2D1_COLOR_F color;
5525 D2D1_SIZE_U sizeu;
5526 D2D1_SIZE_F size;
5527 D2D1_TAG t1, t2;
5528 unsigned int i;
5529 HDC hdc, hdc2;
5530 D2D_RECT_F r;
5531 COLORREF clr;
5532 HRESULT hr;
5533 RECT rect;
5535 if (!init_test_context(&ctx, d3d11))
5536 return;
5537 release_test_context(&ctx);
5539 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5540 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5542 for (i = 0; i < ARRAY_SIZE(invalid_formats); ++i)
5544 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5545 desc.pixelFormat = invalid_formats[i];
5546 desc.dpiX = 96.0f;
5547 desc.dpiY = 96.0f;
5548 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5549 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5551 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
5552 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#lx.\n", hr);
5555 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5556 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
5557 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5558 desc.dpiX = 96.0f;
5559 desc.dpiY = 96.0f;
5560 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5561 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5562 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
5563 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5565 hr = ID2D1DCRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5566 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5567 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
5568 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5569 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
5570 ID2D1RenderTarget_Release(rt3);
5571 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1DCRenderTarget, (void **)&rt2);
5572 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5573 ok(rt2 == rt, "Unexpected render target\n");
5574 ID2D1DCRenderTarget_Release(rt2);
5575 ID2D1GdiInteropRenderTarget_Release(interop);
5577 size = ID2D1DCRenderTarget_GetSize(rt);
5578 ok(size.width == 0.0f, "got width %.08e.\n", size.width);
5579 ok(size.height == 0.0f, "got height %.08e.\n", size.height);
5581 sizeu = ID2D1DCRenderTarget_GetPixelSize(rt);
5582 ok(sizeu.width == 0, "got width %u.\n", sizeu.width);
5583 ok(sizeu.height == 0, "got height %u.\n", sizeu.height);
5585 /* object creation methods work without BindDC() */
5586 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
5587 hr = ID2D1DCRenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
5588 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5589 ID2D1SolidColorBrush_Release(brush);
5591 ID2D1DCRenderTarget_BeginDraw(rt);
5592 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
5593 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
5595 ID2D1DCRenderTarget_Release(rt);
5597 /* BindDC() */
5598 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
5599 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5601 aa_mode = ID2D1DCRenderTarget_GetAntialiasMode(rt);
5602 ok(aa_mode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, "Got wrong default aa mode %d.\n", aa_mode);
5603 text_aa_mode = ID2D1DCRenderTarget_GetTextAntialiasMode(rt);
5604 ok(text_aa_mode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT, "Got wrong default text aa mode %d.\n", text_aa_mode);
5606 ID2D1DCRenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
5607 ok(dpi_x == 96.0f && dpi_y == 96.0f, "Got dpi_x %f, dpi_y %f.\n", dpi_x, dpi_y);
5609 hdc = CreateCompatibleDC(NULL);
5610 ok(hdc != NULL, "Failed to create an HDC.\n");
5612 create_target_dibsection(hdc, 16, 16);
5614 SetRect(&rect, 0, 0, 32, 32);
5615 hr = ID2D1DCRenderTarget_BindDC(rt, NULL, &rect);
5616 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
5618 /* Target properties are retained during BindDC() */
5619 ID2D1DCRenderTarget_SetTags(rt, 1, 2);
5620 ID2D1DCRenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
5621 ID2D1DCRenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
5623 set_matrix_identity(&matrix);
5624 translate_matrix(&matrix, 200.0f, 600.0f);
5625 ID2D1DCRenderTarget_SetTransform(rt, &matrix);
5627 hr = ID2D1DCRenderTarget_BindDC(rt, hdc, &rect);
5628 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5630 ID2D1DCRenderTarget_GetTags(rt, &t1, &t2);
5631 ok(t1 == 1 && t2 == 2, "Got wrong tags.\n");
5633 aa_mode = ID2D1DCRenderTarget_GetAntialiasMode(rt);
5634 ok(aa_mode == D2D1_ANTIALIAS_MODE_ALIASED, "Got wrong aa mode %d.\n", aa_mode);
5636 text_aa_mode = ID2D1DCRenderTarget_GetTextAntialiasMode(rt);
5637 ok(text_aa_mode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, "Got wrong text aa mode %d.\n", text_aa_mode);
5639 ID2D1DCRenderTarget_GetTransform(rt, &matrix2);
5640 ok(!memcmp(&matrix, &matrix2, sizeof(matrix)), "Got wrong target transform.\n");
5642 set_matrix_identity(&matrix);
5643 ID2D1DCRenderTarget_SetTransform(rt, &matrix);
5645 /* target size comes from specified dimensions, not from selected bitmap size */
5646 size = ID2D1DCRenderTarget_GetSize(rt);
5647 ok(size.width == 32.0f, "got width %.08e.\n", size.width);
5648 ok(size.height == 32.0f, "got height %.08e.\n", size.height);
5650 /* clear one HDC to red, switch to another one, partially fill it and test contents */
5651 ID2D1DCRenderTarget_BeginDraw(rt);
5653 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
5654 ID2D1DCRenderTarget_Clear(rt, &color);
5656 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
5657 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5659 clr = GetPixel(hdc, 0, 0);
5660 ok(clr == RGB(255, 0, 0), "Got unexpected colour 0x%08lx.\n", clr);
5662 hdc2 = CreateCompatibleDC(NULL);
5663 ok(hdc2 != NULL, "Failed to create an HDC.\n");
5665 create_target_dibsection(hdc2, 16, 16);
5667 hr = ID2D1DCRenderTarget_BindDC(rt, hdc2, &rect);
5668 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5670 clr = GetPixel(hdc2, 0, 0);
5671 ok(clr == 0, "Got unexpected colour 0x%08lx.\n", clr);
5673 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
5674 hr = ID2D1DCRenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
5675 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5677 ID2D1DCRenderTarget_BeginDraw(rt);
5679 r.left = r.top = 0.0f;
5680 r.bottom = 16.0f;
5681 r.right = 8.0f;
5682 ID2D1DCRenderTarget_FillRectangle(rt, &r, (ID2D1Brush*)brush);
5684 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
5685 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5687 ID2D1SolidColorBrush_Release(brush);
5689 clr = GetPixel(hdc2, 0, 0);
5690 ok(clr == RGB(0, 255, 0), "Got unexpected colour 0x%08lx.\n", clr);
5692 clr = GetPixel(hdc2, 10, 0);
5693 ok(clr == 0, "Got unexpected colour 0x%08lx.\n", clr);
5695 /* Invalid DC. */
5696 hr = ID2D1DCRenderTarget_BindDC(rt, (HDC)0xdeadbeef, &rect);
5697 todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
5699 ID2D1DCRenderTarget_BeginDraw(rt);
5701 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
5702 ID2D1DCRenderTarget_Clear(rt, &color);
5704 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
5705 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5707 clr = GetPixel(hdc2, 0, 0);
5708 todo_wine ok(clr == RGB(255, 0, 0), "Got unexpected colour 0x%08lx.\n", clr);
5710 hr = ID2D1DCRenderTarget_BindDC(rt, NULL, &rect);
5711 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
5713 ID2D1DCRenderTarget_BeginDraw(rt);
5715 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
5716 ID2D1DCRenderTarget_Clear(rt, &color);
5718 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
5719 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5721 clr = GetPixel(hdc2, 0, 0);
5722 todo_wine ok(clr == RGB(0, 0, 255), "Got unexpected colour 0x%08lx.\n", clr);
5724 DeleteDC(hdc);
5725 DeleteDC(hdc2);
5726 ID2D1DCRenderTarget_Release(rt);
5727 ID2D1Factory_Release(factory);
5730 static void test_hwnd_target(BOOL d3d11)
5732 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
5733 ID2D1GdiInteropRenderTarget *interop;
5734 D2D1_RENDER_TARGET_PROPERTIES desc;
5735 ID2D1HwndRenderTarget *rt, *rt2;
5736 struct d2d1_test_context ctx;
5737 ID2D1RenderTarget *rt3;
5738 ID2D1Factory *factory;
5739 D2D1_SIZE_U size;
5740 HRESULT hr;
5742 if (!init_test_context(&ctx, d3d11))
5743 return;
5744 release_test_context(&ctx);
5746 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5747 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5749 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5750 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
5751 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5752 desc.dpiX = 0.0f;
5753 desc.dpiY = 0.0f;
5754 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5755 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5757 hwnd_rt_desc.hwnd = NULL;
5758 hwnd_rt_desc.pixelSize.width = 64;
5759 hwnd_rt_desc.pixelSize.height = 64;
5760 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
5762 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
5763 ok(hr != S_OK, "Got unexpected hr %#lx.\n", hr);
5765 hwnd_rt_desc.hwnd = (HWND)0xdeadbeef;
5766 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
5767 ok(hr != S_OK, "Got unexpected hr %#lx.\n", hr);
5769 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
5770 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
5771 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
5772 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5774 hr = ID2D1HwndRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5775 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5776 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
5777 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5778 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
5779 ID2D1RenderTarget_Release(rt3);
5780 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1HwndRenderTarget, (void **)&rt2);
5781 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5782 ok(rt2 == rt, "Unexpected render target\n");
5783 ID2D1HwndRenderTarget_Release(rt2);
5784 ID2D1GdiInteropRenderTarget_Release(interop);
5786 size.width = 128;
5787 size.height = 64;
5788 hr = ID2D1HwndRenderTarget_Resize(rt, &size);
5789 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5791 ID2D1HwndRenderTarget_Release(rt);
5793 DestroyWindow(hwnd_rt_desc.hwnd);
5794 ID2D1Factory_Release(factory);
5797 #define test_compatible_target_size(r) test_compatible_target_size_(__LINE__, r)
5798 static void test_compatible_target_size_(unsigned int line, ID2D1RenderTarget *rt)
5800 static const D2D1_SIZE_F size_1_0 = { 1.0f, 0.0f };
5801 static const D2D1_SIZE_F size_1_1 = { 1.0f, 1.0f };
5802 static const D2D1_SIZE_U px_size_1_1 = { 1, 1 };
5803 static const D2D1_SIZE_U zero_px_size;
5804 static const D2D1_SIZE_F zero_size;
5805 static const struct size_test
5807 const D2D1_SIZE_U *pixel_size;
5808 const D2D1_SIZE_F *size;
5810 size_tests[] =
5812 { &zero_px_size, NULL },
5813 { &zero_px_size, &zero_size },
5814 { NULL, &zero_size },
5815 { NULL, &size_1_0 },
5816 { &px_size_1_1, &size_1_1 },
5818 float dpi_x, dpi_y, rt_dpi_x, rt_dpi_y;
5819 D2D1_SIZE_U pixel_size, expected_size;
5820 ID2D1BitmapRenderTarget *bitmap_rt;
5821 ID2D1DeviceContext *context;
5822 unsigned int i;
5823 HRESULT hr;
5825 ID2D1RenderTarget_GetDpi(rt, &rt_dpi_x, &rt_dpi_y);
5827 for (i = 0; i < ARRAY_SIZE(size_tests); ++i)
5829 hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, size_tests[i].size, size_tests[i].pixel_size,
5830 NULL, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &bitmap_rt);
5831 ok_(__FILE__, line)(SUCCEEDED(hr), "%u: Failed to create render target, hr %#lx.\n", i, hr);
5833 if (size_tests[i].pixel_size)
5835 expected_size = *size_tests[i].pixel_size;
5837 else if (size_tests[i].size)
5839 expected_size.width = ceilf((size_tests[i].size->width * rt_dpi_x) / 96.0f);
5840 expected_size.height = ceilf((size_tests[i].size->height * rt_dpi_y) / 96.0f);
5842 else
5844 expected_size = ID2D1RenderTarget_GetPixelSize(rt);
5847 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(bitmap_rt);
5848 ok_(__FILE__, line)(!memcmp(&pixel_size, &expected_size, sizeof(pixel_size)),
5849 "%u: unexpected target size %ux%u.\n", i, pixel_size.width, pixel_size.height);
5851 ID2D1BitmapRenderTarget_GetDpi(bitmap_rt, &dpi_x, &dpi_y);
5852 if (size_tests[i].pixel_size && size_tests[i].size && size_tests[i].size->width != 0.0f
5853 && size_tests[i].size->height != 0.0f)
5855 ok_(__FILE__, line)(dpi_x == pixel_size.width * 96.0f / size_tests[i].size->width
5856 && dpi_y == pixel_size.height * 96.0f / size_tests[i].size->height,
5857 "%u: unexpected target dpi %.8ex%.8e.\n", i, dpi_x, dpi_y);
5859 else
5860 ok_(__FILE__, line)(dpi_x == rt_dpi_x && dpi_y == rt_dpi_y,
5861 "%u: unexpected target dpi %.8ex%.8e.\n", i, dpi_x, dpi_y);
5862 ID2D1BitmapRenderTarget_Release(bitmap_rt);
5865 pixel_size.height = pixel_size.width = 0;
5866 hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, NULL, &pixel_size, NULL,
5867 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &bitmap_rt);
5868 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create render target, hr %#lx.\n", hr);
5870 if (SUCCEEDED(ID2D1BitmapRenderTarget_QueryInterface(bitmap_rt, &IID_ID2D1DeviceContext, (void **)&context)))
5872 ID2D1Bitmap *bitmap;
5874 pixel_size = ID2D1DeviceContext_GetPixelSize(context);
5875 ok_(__FILE__, line)(!pixel_size.width && !pixel_size.height, "Unexpected target size %ux%u.\n",
5876 pixel_size.width, pixel_size.height);
5878 ID2D1DeviceContext_GetTarget(context, (ID2D1Image **)&bitmap);
5879 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
5880 ok_(__FILE__, line)(!pixel_size.width && !pixel_size.height, "Unexpected target size %ux%u.\n",
5881 pixel_size.width, pixel_size.height);
5882 ID2D1Bitmap_Release(bitmap);
5884 ID2D1DeviceContext_Release(context);
5887 ID2D1BitmapRenderTarget_Release(bitmap_rt);
5890 static void test_bitmap_target(BOOL d3d11)
5892 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
5893 ID2D1GdiInteropRenderTarget *interop;
5894 D2D1_SIZE_U pixel_size, pixel_size2;
5895 D2D1_RENDER_TARGET_PROPERTIES desc;
5896 ID2D1BitmapRenderTarget *rt, *rt2;
5897 ID2D1HwndRenderTarget *hwnd_rt;
5898 ID2D1Bitmap *bitmap, *bitmap2;
5899 struct d2d1_test_context ctx;
5900 ID2D1DCRenderTarget *dc_rt;
5901 D2D1_SIZE_F size, size2;
5902 ID2D1RenderTarget *rt3;
5903 ID2D1Factory *factory;
5904 float dpi[2], dpi2[2];
5905 D2D1_COLOR_F color;
5906 ULONG refcount;
5907 HRESULT hr;
5909 if (!init_test_context(&ctx, d3d11))
5910 return;
5911 release_test_context(&ctx);
5913 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5914 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5916 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5917 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
5918 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5919 desc.dpiX = 96.0f;
5920 desc.dpiY = 192.0f;
5921 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5922 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5924 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
5925 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
5926 hwnd_rt_desc.pixelSize.width = 64;
5927 hwnd_rt_desc.pixelSize.height = 64;
5928 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
5930 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &hwnd_rt);
5931 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5933 test_compatible_target_size((ID2D1RenderTarget *)hwnd_rt);
5935 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, NULL, NULL,
5936 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
5937 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5939 hr = ID2D1BitmapRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5940 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5941 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
5942 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5943 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
5944 ID2D1RenderTarget_Release(rt3);
5945 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1BitmapRenderTarget, (void **)&rt2);
5946 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5947 ok(rt2 == rt, "Unexpected render target\n");
5948 ID2D1BitmapRenderTarget_Release(rt2);
5949 ID2D1GdiInteropRenderTarget_Release(interop);
5951 /* See if parent target is referenced. */
5952 ID2D1HwndRenderTarget_AddRef(hwnd_rt);
5953 refcount = ID2D1HwndRenderTarget_Release(hwnd_rt);
5954 ok(refcount == 1, "Target should not have been referenced, got %lu.\n", refcount);
5956 /* Size was not specified, should match parent. */
5957 pixel_size = ID2D1HwndRenderTarget_GetPixelSize(hwnd_rt);
5958 pixel_size2 = ID2D1BitmapRenderTarget_GetPixelSize(rt);
5959 ok(!memcmp(&pixel_size, &pixel_size2, sizeof(pixel_size)), "Got target pixel size mismatch.\n");
5961 size = ID2D1HwndRenderTarget_GetSize(hwnd_rt);
5962 size2 = ID2D1BitmapRenderTarget_GetSize(rt);
5963 ok(!memcmp(&size, &size2, sizeof(size)), "Got target DIP size mismatch.\n");
5965 ID2D1HwndRenderTarget_GetDpi(hwnd_rt, dpi, dpi + 1);
5966 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
5967 ok(!memcmp(dpi, dpi2, sizeof(dpi)), "Got dpi mismatch.\n");
5969 ID2D1BitmapRenderTarget_Release(rt);
5971 /* Pixel size specified. */
5972 set_size_u(&pixel_size, 32, 32);
5973 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, &pixel_size, NULL,
5974 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
5975 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5977 pixel_size2 = ID2D1BitmapRenderTarget_GetPixelSize(rt);
5978 ok(!memcmp(&pixel_size, &pixel_size2, sizeof(pixel_size)), "Got target pixel size mismatch.\n");
5980 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
5981 ok(!memcmp(dpi, dpi2, sizeof(dpi)), "Got dpi mismatch.\n");
5983 ID2D1BitmapRenderTarget_Release(rt);
5985 /* Both pixel size and DIP size are specified. */
5986 set_size_u(&pixel_size, 128, 128);
5987 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, &size, &pixel_size, NULL,
5988 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
5989 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5991 /* Doubled pixel size dimensions with the same DIP size give doubled dpi. */
5992 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
5993 ok(dpi[0] == dpi2[0] / 2.0f && dpi[1] == dpi2[1] / 2.0f, "Got dpi mismatch.\n");
5995 ID2D1BitmapRenderTarget_Release(rt);
5997 /* DIP size is specified, fractional. */
5998 set_size_f(&size, 70.1f, 70.4f);
5999 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, &size, NULL, NULL,
6000 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
6001 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6003 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
6005 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt);
6006 ok(pixel_size.width == ceilf(size.width * dpi[0] / 96.0f)
6007 && pixel_size.height == ceilf(size.height * dpi[1] / 96.0f), "Wrong pixel size %ux%u\n",
6008 pixel_size.width, pixel_size.height);
6010 dpi[0] *= (pixel_size.width / size.width) * (96.0f / dpi[0]);
6011 dpi[1] *= (pixel_size.height / size.height) * (96.0f / dpi[1]);
6013 ok(compare_float(dpi[0], dpi2[0], 1) && compare_float(dpi[1], dpi2[1], 1), "Got dpi mismatch.\n");
6015 ID2D1HwndRenderTarget_Release(hwnd_rt);
6017 /* Check if GetBitmap() returns same instance. */
6018 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap);
6019 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6020 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap2);
6021 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6022 ok(bitmap == bitmap2, "Got different bitmap instances.\n");
6024 /* Draw something, see if bitmap instance is retained. */
6025 ID2D1BitmapRenderTarget_BeginDraw(rt);
6026 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
6027 ID2D1BitmapRenderTarget_Clear(rt, &color);
6028 hr = ID2D1BitmapRenderTarget_EndDraw(rt, NULL, NULL);
6029 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6031 ID2D1Bitmap_Release(bitmap2);
6032 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap2);
6033 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6034 ok(bitmap == bitmap2, "Got different bitmap instances.\n");
6036 ID2D1Bitmap_Release(bitmap);
6037 ID2D1Bitmap_Release(bitmap2);
6039 refcount = ID2D1BitmapRenderTarget_Release(rt);
6040 ok(!refcount, "Target should be released, got %lu.\n", refcount);
6042 DestroyWindow(hwnd_rt_desc.hwnd);
6044 /* Compatible target created from a DC target without associated HDC */
6045 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
6046 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
6047 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
6048 desc.dpiX = 192.0f;
6049 desc.dpiY = 96.0f;
6050 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
6051 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
6052 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &dc_rt);
6053 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6055 test_compatible_target_size((ID2D1RenderTarget *)dc_rt);
6057 hr = ID2D1DCRenderTarget_CreateCompatibleRenderTarget(dc_rt, NULL, NULL, NULL,
6058 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
6059 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6061 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt);
6062 ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
6064 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap);
6065 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6066 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
6067 ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
6068 ID2D1Bitmap_Release(bitmap);
6070 ID2D1BitmapRenderTarget_Release(rt);
6071 ID2D1DCRenderTarget_Release(dc_rt);
6073 ID2D1Factory_Release(factory);
6076 static void test_desktop_dpi(BOOL d3d11)
6078 ID2D1Factory *factory;
6079 float dpi_x, dpi_y;
6080 HRESULT hr;
6082 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
6083 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6085 dpi_x = dpi_y = 0.0f;
6086 ID2D1Factory_GetDesktopDpi(factory, &dpi_x, &dpi_y);
6087 ok(dpi_x > 0.0f && dpi_y > 0.0f, "Got wrong dpi %f x %f.\n", dpi_x, dpi_y);
6089 ID2D1Factory_Release(factory);
6092 static void test_stroke_style(BOOL d3d11)
6094 static const struct
6096 D2D1_DASH_STYLE dash_style;
6097 UINT32 dash_count;
6098 float dashes[6];
6100 dash_style_tests[] =
6102 {D2D1_DASH_STYLE_SOLID, 0},
6103 {D2D1_DASH_STYLE_DASH, 2, {2.0f, 2.0f}},
6104 {D2D1_DASH_STYLE_DOT, 2, {0.0f, 2.0f}},
6105 {D2D1_DASH_STYLE_DASH_DOT, 4, {2.0f, 2.0f, 0.0f, 2.0f}},
6106 {D2D1_DASH_STYLE_DASH_DOT_DOT, 6, {2.0f, 2.0f, 0.0f, 2.0f, 0.0f, 2.0f}},
6108 D2D1_STROKE_STYLE_PROPERTIES desc;
6109 ID2D1StrokeStyle *style;
6110 ID2D1Factory *factory;
6111 UINT32 count;
6112 HRESULT hr;
6113 D2D1_CAP_STYLE cap_style;
6114 D2D1_LINE_JOIN line_join;
6115 float miter_limit, dash_offset;
6116 D2D1_DASH_STYLE dash_style;
6117 unsigned int i;
6118 float dashes[2];
6120 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
6121 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6123 desc.startCap = D2D1_CAP_STYLE_SQUARE;
6124 desc.endCap = D2D1_CAP_STYLE_ROUND;
6125 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
6126 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
6127 desc.miterLimit = 1.5f;
6128 desc.dashStyle = D2D1_DASH_STYLE_DOT;
6129 desc.dashOffset = -1.0f;
6131 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
6132 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6134 cap_style = ID2D1StrokeStyle_GetStartCap(style);
6135 ok(cap_style == D2D1_CAP_STYLE_SQUARE, "Unexpected cap style %d.\n", cap_style);
6136 cap_style = ID2D1StrokeStyle_GetEndCap(style);
6137 ok(cap_style == D2D1_CAP_STYLE_ROUND, "Unexpected cap style %d.\n", cap_style);
6138 cap_style = ID2D1StrokeStyle_GetDashCap(style);
6139 ok(cap_style == D2D1_CAP_STYLE_TRIANGLE, "Unexpected cap style %d.\n", cap_style);
6140 line_join = ID2D1StrokeStyle_GetLineJoin(style);
6141 ok(line_join == D2D1_LINE_JOIN_BEVEL, "Unexpected line joind %d.\n", line_join);
6142 miter_limit = ID2D1StrokeStyle_GetMiterLimit(style);
6143 ok(miter_limit == 1.5f, "Unexpected miter limit %f.\n", miter_limit);
6144 dash_style = ID2D1StrokeStyle_GetDashStyle(style);
6145 ok(dash_style == D2D1_DASH_STYLE_DOT, "Unexpected dash style %d.\n", dash_style);
6146 dash_offset = ID2D1StrokeStyle_GetDashOffset(style);
6147 ok(dash_offset == -1.0f, "Unexpected dash offset %f.\n", dash_offset);
6149 /* Custom dash pattern, no dashes data specified. */
6150 desc.startCap = D2D1_CAP_STYLE_SQUARE;
6151 desc.endCap = D2D1_CAP_STYLE_ROUND;
6152 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
6153 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
6154 desc.miterLimit = 1.5f;
6155 desc.dashStyle = D2D1_DASH_STYLE_CUSTOM;
6156 desc.dashOffset = 0.0f;
6158 ID2D1StrokeStyle_Release(style);
6160 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
6161 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
6163 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 0, &style);
6164 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
6166 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
6167 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6168 ID2D1StrokeStyle_Release(style);
6170 /* Builtin style, dashes are specified. */
6171 desc.dashStyle = D2D1_DASH_STYLE_DOT;
6172 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
6173 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
6175 /* Invalid style. */
6176 desc.dashStyle = 100;
6177 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
6178 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
6180 /* Test returned dash pattern for builtin styles. */
6181 desc.startCap = D2D1_CAP_STYLE_SQUARE;
6182 desc.endCap = D2D1_CAP_STYLE_ROUND;
6183 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
6184 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
6185 desc.miterLimit = 1.5f;
6186 desc.dashOffset = 0.0f;
6188 for (i = 0; i < ARRAY_SIZE(dash_style_tests); ++i)
6190 float dashes[10];
6191 UINT dash_count;
6193 desc.dashStyle = dash_style_tests[i].dash_style;
6195 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
6196 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
6198 dash_count = ID2D1StrokeStyle_GetDashesCount(style);
6199 ok(dash_count == dash_style_tests[i].dash_count, "%u: unexpected dash count %u, expected %u.\n",
6200 i, dash_count, dash_style_tests[i].dash_count);
6201 ok(dash_count < ARRAY_SIZE(dashes), "%u: unexpectedly large dash count %u.\n", i, dash_count);
6202 if (dash_count == dash_style_tests[i].dash_count)
6204 unsigned int j;
6206 ID2D1StrokeStyle_GetDashes(style, dashes, dash_count);
6207 ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
6208 "%u: unexpected dash array.\n", i);
6210 /* Ask for more dashes than style actually has. */
6211 memset(dashes, 0xcc, sizeof(dashes));
6212 ID2D1StrokeStyle_GetDashes(style, dashes, ARRAY_SIZE(dashes));
6213 ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
6214 "%u: unexpected dash array.\n", i);
6216 for (j = dash_count; j < ARRAY_SIZE(dashes); ++j)
6217 ok(dashes[j] == 0.0f, "%u: unexpected dash value at %u.\n", i, j);
6220 ID2D1StrokeStyle_Release(style);
6223 /* NULL dashes array, non-zero length. */
6224 memset(&desc, 0, sizeof(desc));
6225 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 1, &style);
6226 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6228 count = ID2D1StrokeStyle_GetDashesCount(style);
6229 ok(count == 0, "Unexpected dashes count %u.\n", count);
6231 ID2D1StrokeStyle_Release(style);
6233 ID2D1Factory_Release(factory);
6236 static void test_gradient(BOOL d3d11)
6238 ID2D1GradientStopCollection *gradient;
6239 D2D1_GRADIENT_STOP stops[3], stops2[3];
6240 struct d2d1_test_context ctx;
6241 ID2D1RenderTarget *rt;
6242 D2D1_COLOR_F color;
6243 unsigned int i;
6244 UINT32 count;
6245 HRESULT hr;
6247 if (!init_test_context(&ctx, d3d11))
6248 return;
6250 rt = ctx.rt;
6251 stops2[0].position = 0.5f;
6252 set_color(&stops2[0].color, 1.0f, 1.0f, 0.0f, 1.0f);
6253 stops2[1] = stops2[0];
6254 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops2, 2, D2D1_GAMMA_2_2,
6255 D2D1_EXTEND_MODE_CLAMP, &gradient);
6256 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6258 count = ID2D1GradientStopCollection_GetGradientStopCount(gradient);
6259 ok(count == 2, "Unexpected stop count %u.\n", count);
6261 /* Request more stops than collection has. */
6262 stops[0].position = 123.4f;
6263 set_color(&stops[0].color, 1.0f, 0.5f, 0.4f, 1.0f);
6264 color = stops[0].color;
6265 stops[2] = stops[1] = stops[0];
6266 ID2D1GradientStopCollection_GetGradientStops(gradient, stops, ARRAY_SIZE(stops));
6267 ok(!memcmp(stops, stops2, sizeof(*stops) * count), "Unexpected gradient stops array.\n");
6268 for (i = count; i < ARRAY_SIZE(stops); ++i)
6270 ok(stops[i].position == 123.4f, "%u: unexpected stop position %f.\n", i, stops[i].position);
6271 ok(!memcmp(&stops[i].color, &color, sizeof(color)), "%u: unexpected stop color.\n", i);
6274 ID2D1GradientStopCollection_Release(gradient);
6276 release_test_context(&ctx);
6279 static void test_draw_geometry(BOOL d3d11)
6281 ID2D1TransformedGeometry *transformed_geometry[4];
6282 ID2D1RectangleGeometry *rect_geometry[2];
6283 D2D1_POINT_2F point = {0.0f, 0.0f};
6284 D2D1_ROUNDED_RECT rounded_rect;
6285 struct d2d1_test_context ctx;
6286 ID2D1SolidColorBrush *brush;
6287 ID2D1PathGeometry *geometry;
6288 D2D1_MATRIX_3X2_F matrix;
6289 ID2D1GeometrySink *sink;
6290 ID2D1RenderTarget *rt;
6291 ID2D1Factory *factory;
6292 D2D1_POINT_2F p0, p1;
6293 D2D1_ELLIPSE ellipse;
6294 D2D1_COLOR_F color;
6295 D2D1_RECT_F rect;
6296 HRESULT hr;
6297 BOOL match;
6299 if (!init_test_context(&ctx, d3d11))
6300 return;
6302 rt = ctx.rt;
6303 ID2D1RenderTarget_GetFactory(rt, &factory);
6305 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
6306 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
6307 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
6308 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
6309 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6311 ID2D1RenderTarget_BeginDraw(rt);
6312 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
6313 ID2D1RenderTarget_Clear(rt, &color);
6315 set_point(&p0, 40.0f, 160.0f);
6316 ID2D1RenderTarget_DrawLine(rt, p0, p0, (ID2D1Brush *)brush, 10.0f, NULL);
6317 set_point(&p0, 100.0f, 160.0f);
6318 set_point(&p1, 140.0f, 160.0f);
6319 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
6320 set_point(&p0, 200.0f, 80.0f);
6321 set_point(&p1, 200.0f, 240.0f);
6322 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
6323 set_point(&p0, 260.0f, 240.0f);
6324 set_point(&p1, 300.0f, 80.0f);
6325 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
6327 set_rect(&rect, 40.0f, 480.0f, 40.0f, 480.0f);
6328 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
6329 set_rect(&rect, 100.0f, 480.0f, 140.0f, 480.0f);
6330 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
6331 set_rect(&rect, 200.0f, 400.0f, 200.0f, 560.0f);
6332 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
6333 set_rect(&rect, 260.0f, 560.0f, 300.0f, 400.0f);
6334 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
6336 set_ellipse(&ellipse, 40.0f, 800.0f, 0.0f, 0.0f);
6337 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
6338 set_ellipse(&ellipse, 120.0f, 800.0f, 20.0f, 0.0f);
6339 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
6340 set_ellipse(&ellipse, 200.0f, 800.0f, 0.0f, 80.0f);
6341 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
6342 set_ellipse(&ellipse, 280.0f, 800.0f, 20.0f, 80.0f);
6343 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
6345 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6346 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6348 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0, "");
6349 ok(match, "Figure does not match.\n");
6350 match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0, "yGBQUFBQUFBQUFDoYQAA");
6351 ok(match, "Figure does not match.\n");
6352 match = compare_figure(&ctx, 320, 0, 160, 160, 0xff652e89, 0,
6353 "xjIUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6354 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6355 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6356 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6357 "jAEUjAEUjAEUjAEUxjIA");
6358 ok(match, "Figure does not match.\n");
6359 match = compare_figure(&ctx, 480, 0, 160, 160, 0xff652e89, 2,
6360 "zjECnQETjAEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
6361 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
6362 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
6363 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
6364 "igEVigEVigEVigEVjAETnQECzjEA");
6365 ok(match, "Figure does not match.\n");
6367 match = compare_figure(&ctx, 0, 160, 160, 160, 0xff652e89, 0, "5mAUjAEUjAEUjAEUjAEUhmIA");
6368 ok(match, "Figure does not match.\n");
6369 match = compare_figure(&ctx, 160, 160, 160, 160, 0xff652e89, 0, "vmBkPGQ8ZDxkPGTeYQAA");
6370 ok(match, "Figure does not match.\n");
6371 match = compare_figure(&ctx, 320, 160, 160, 160, 0xff652e89, 0,
6372 "5i4UjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6373 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6374 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6375 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6376 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUhjAA");
6377 ok(match, "Figure does not match.\n");
6378 match = compare_figure(&ctx, 480, 160, 160, 160, 0xff652e89, 0,
6379 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6380 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6381 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6382 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6383 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6384 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6385 ok(match, "Figure does not match.\n");
6387 match = compare_figure(&ctx, 0, 320, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6388 todo_wine ok(match, "Figure does not match.\n");
6389 match = compare_figure(&ctx, 160, 320, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6390 todo_wine ok(match, "Figure does not match.\n");
6391 match = compare_figure(&ctx, 320, 320, 160, 160, 0xff652e89, 0,
6392 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6393 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6394 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6395 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6396 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6397 todo_wine ok(match, "Figure does not match.\n");
6398 match = compare_figure(&ctx, 480, 320, 160, 160, 0xff652e89, 10,
6399 "hDAYgwEieyh1LnAybBcIF2gWDhZkFhIWYRUWFV4VGhVbFRwVWRUeFVcVIBVVFCQUUxQmFFEUKBRP"
6400 "FSgVTRUqFUwULBRLFC4USRQwFEgUMBRHFDIURhQyFEUUNBREFDQUQxQ2FEIUNhRBFDgUQBQ4FEAU"
6401 "OBQ/FDoUPhQ6FD4UOhQ+FDoUPhQ6FD0UPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6402 "FDwUPBQ8FDwUPBQ8FD0UOhQ+FDoUPhQ6FD4UOhQ+FDoUPxQ4FEAUOBRAFDgUQRQ2FEIUNhRDFDQU"
6403 "RBQ0FEUUMhRGFDIURxQwFEgUMBRJFC4USxQsFEwVKhVNFSgVTxQoFFEUJhRTFCQUVRUgFVcVHhVZ"
6404 "FRwVWxUaFV4VFhVhFhIWZBYOFmgXCBdsMnAudSh7IoMBGIQw");
6405 todo_wine ok(match, "Figure does not match.\n");
6407 ID2D1RenderTarget_BeginDraw(rt);
6408 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
6409 ID2D1RenderTarget_Clear(rt, &color);
6411 set_rounded_rect(&rounded_rect, 40.0f, 160.0f, 40.0f, 160.0f, 10.0f, 10.0f);
6412 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6413 set_rounded_rect(&rounded_rect, 100.0f, 160.0f, 140.0f, 160.0f, 10.0f, 10.0f);
6414 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6415 set_rounded_rect(&rounded_rect, 200.0f, 80.0f, 200.0f, 240.0f, 10.0f, 10.0f);
6416 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6417 set_rounded_rect(&rounded_rect, 260.0f, 240.0f, 300.0f, 80.0f, 10.0f, 10.0f);
6418 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6420 set_rounded_rect(&rounded_rect, 40.0f, 480.0f, 40.0f, 480.0f, 10.0f, 20.0f);
6421 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6422 set_rounded_rect(&rounded_rect, 100.0f, 480.0f, 140.0f, 480.0f, 10.0f, 20.0f);
6423 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6424 set_rounded_rect(&rounded_rect, 200.0f, 400.0f, 200.0f, 560.0f, 10.0f, 20.0f);
6425 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6426 set_rounded_rect(&rounded_rect, 260.0f, 560.0f, 300.0f, 400.0f, 10.0f, 20.0f);
6427 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6429 set_rounded_rect(&rounded_rect, 40.0f, 800.0f, 40.0f, 800.0f, 10.0f, 5.0f);
6430 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6431 set_rounded_rect(&rounded_rect, 100.0f, 800.0f, 140.0f, 800.0f, 10.0f, 5.0f);
6432 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6433 set_rounded_rect(&rounded_rect, 200.0f, 720.0f, 200.0f, 880.0f, 10.0f, 5.0f);
6434 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6435 set_rounded_rect(&rounded_rect, 260.0f, 880.0f, 300.0f, 720.0f, 10.0f, 5.0f);
6436 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6438 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6439 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6441 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6442 todo_wine ok(match, "Figure does not match.\n");
6443 match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6444 todo_wine ok(match, "Figure does not match.\n");
6445 match = compare_figure(&ctx, 320, 0, 160, 160, 0xff652e89, 0,
6446 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6447 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6448 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6449 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6450 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6451 todo_wine ok(match, "Figure does not match.\n");
6452 match = compare_figure(&ctx, 480, 0, 160, 160, 0xff652e89, 0,
6453 "3C4oaUZVUExYRlxCHCgcPxU4FT0UPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6454 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6455 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6456 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6457 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6458 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FD0VOBU/YEJcRlhMUFVG7S8A");
6459 todo_wine ok(match, "Figure does not match.\n");
6461 match = compare_figure(&ctx, 0, 160, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6462 todo_wine ok(match, "Figure does not match.\n");
6463 match = compare_figure(&ctx, 160, 160, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6464 todo_wine ok(match, "Figure does not match.\n");
6465 match = compare_figure(&ctx, 320, 160, 160, 160, 0xff652e89, 0,
6466 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6467 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6468 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6469 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6470 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6471 todo_wine ok(match, "Figure does not match.\n");
6472 match = compare_figure(&ctx, 480, 160, 160, 160, 0xff652e89, 8,
6473 "3C4obT5dSFRQTlRKGCgYRhYwFkMVNBVBFTYVPxU5FD4UOhQ9FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6474 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6475 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6476 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6477 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6478 "PBQ8FDwUPRQ6FD4UOhQ/FTYVQRU0FUMWMBZGWEpVTVBTSltA8C8A");
6479 todo_wine ok(match, "Figure does not match.\n");
6481 match = compare_figure(&ctx, 0, 320, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6482 todo_wine ok(match, "Figure does not match.\n");
6483 match = compare_figure(&ctx, 160, 320, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6484 todo_wine ok(match, "Figure does not match.\n");
6485 match = compare_figure(&ctx, 320, 320, 160, 160, 0xff652e89, 0,
6486 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6487 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6488 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6489 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6490 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6491 todo_wine ok(match, "Figure does not match.\n");
6492 match = compare_figure(&ctx, 480, 320, 160, 160, 0xff652e89, 0,
6493 "3C4oZU5NWERgP2I9HigePBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6494 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6495 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6496 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6497 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6498 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZD1iP2BEWE1O6S8A");
6499 todo_wine ok(match, "Figure does not match.\n");
6501 ID2D1RenderTarget_BeginDraw(rt);
6502 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
6503 ID2D1RenderTarget_Clear(rt, &color);
6505 set_rounded_rect(&rounded_rect, 40.0f, 160.0f, 40.0f, 160.0f, 1000.0f, 1000.0f);
6506 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6507 set_rounded_rect(&rounded_rect, 100.0f, 160.0f, 140.0f, 160.0f, 1000.0f, 1000.0f);
6508 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6509 set_rounded_rect(&rounded_rect, 200.0f, 80.0f, 200.0f, 240.0f, 1000.0f, 1000.0f);
6510 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6511 set_rounded_rect(&rounded_rect, 260.0f, 240.0f, 300.0f, 80.0f, 1000.0f, 1000.0f);
6512 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6514 set_rounded_rect(&rounded_rect, 40.0f, 480.0f, 40.0f, 480.0f, 10.0f, 1000.0f);
6515 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6516 set_rounded_rect(&rounded_rect, 100.0f, 480.0f, 140.0f, 480.0f, 10.0f, 1000.0f);
6517 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6518 set_rounded_rect(&rounded_rect, 200.0f, 400.0f, 200.0f, 560.0f, 10.0f, 1000.0f);
6519 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6520 set_rounded_rect(&rounded_rect, 260.0f, 560.0f, 300.0f, 400.0f, 10.0f, 1000.0f);
6521 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6523 set_rounded_rect(&rounded_rect, 40.0f, 800.0f, 40.0f, 800.0f, 1000.0f, 10.0f);
6524 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6525 set_rounded_rect(&rounded_rect, 100.0f, 800.0f, 140.0f, 800.0f, 1000.0f, 10.0f);
6526 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6527 set_rounded_rect(&rounded_rect, 200.0f, 720.0f, 200.0f, 880.0f, 1000.0f, 10.0f);
6528 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6529 set_rounded_rect(&rounded_rect, 260.0f, 880.0f, 300.0f, 720.0f, 1000.0f, 10.0f);
6530 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6532 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6533 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6535 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6536 todo_wine ok(match, "Figure does not match.\n");
6537 match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6538 todo_wine ok(match, "Figure does not match.\n");
6539 match = compare_figure(&ctx, 320, 0, 160, 160, 0xff652e89, 0,
6540 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6541 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6542 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6543 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6544 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6545 todo_wine ok(match, "Figure does not match.\n");
6546 match = compare_figure(&ctx, 480, 0, 160, 160, 0xff652e89, 16,
6547 "hDAYgwEieyh1LnAybBcIF2gWDhZkFhIWYRUWFV4WGRVbFRwVWRUeFVcVIBVVFSMUUxQmFFEVJxRP"
6548 "FSgVTRUqFUwULBRLFC4USRUvFEgUMBRHFDIURhQyFEUUNBREFDQUQxQ2FEIUNhRBFDgUQBQ4FEAU"
6549 "OBQ/FTkUPhQ6FD4UOhQ+FDoUPhQ6FD0UPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6550 "FDwUPBQ8FDwUPBQ8FD0UOhQ+FDoUPhQ6FD4UOhQ+FDoUPxQ4FEAUOBRAFDgUQRQ2FEIUNhRDFDQU"
6551 "RBQ0FEUUMhRGFDIURxQwFEgUMBRJFC4USxQsFEwVKhVNFSgVTxQoFFEUJhRTFCQUVRUgFVcVHhVZ"
6552 "FRwVWxUaFV4VFhVhFhIWZBYOFmgWChZsMnAudCp6IoMBGIQw");
6553 todo_wine ok(match, "Figure does not match.\n");
6555 match = compare_figure(&ctx, 0, 160, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6556 todo_wine ok(match, "Figure does not match.\n");
6557 match = compare_figure(&ctx, 160, 160, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6558 todo_wine ok(match, "Figure does not match.\n");
6559 match = compare_figure(&ctx, 320, 160, 160, 160, 0xff652e89, 0,
6560 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6561 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6562 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6563 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6564 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6565 todo_wine ok(match, "Figure does not match.\n");
6566 match = compare_figure(&ctx, 480, 160, 160, 160, 0xff652e89, 16,
6567 "3C4obzpjQF5EWkhXFSAVVRQkFFMUJhRRFCgUTxQqFE0VKhVMFCwUSxQuFEoULhVIFDAUSBQwFUYU"
6568 "MhRGFDIURRQ0FEQUNBRDFTQVQhQ2FEIUNhRCFDYUQRQ4FEAUOBRAFDgUQBQ4FD8UOhQ+FDoUPhQ6"
6569 "FD4UOhQ+FDoUPhQ6FD0VOxQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6570 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBU7FD0UOhQ+FDoUPhQ6FD4UOhQ+FDoUPhQ6FD8UOBRA"
6571 "FDgUQBQ4FEAUOBRBFDYUQhQ2FEIUNhRCFTQVQxQ0FEQUNBRFFDIURhQyFEYVMBVHFDAUSBUuFUkU"
6572 "LhRLFCwUTBUrFE0UKhRPFCgUURQmFFMUJBRVSldIWUZdQWI78i8A");
6573 todo_wine ok(match, "Figure does not match.\n");
6575 match = compare_figure(&ctx, 0, 320, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6576 todo_wine ok(match, "Figure does not match.\n");
6577 match = compare_figure(&ctx, 160, 320, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6578 todo_wine ok(match, "Figure does not match.\n");
6579 match = compare_figure(&ctx, 320, 320, 160, 160, 0xff652e89, 0,
6580 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6581 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6582 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6583 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6584 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6585 todo_wine ok(match, "Figure does not match.\n");
6586 match = compare_figure(&ctx, 480, 320, 160, 160, 0xff652e89, 8,
6587 "9i80ZERWUExYRV5AHCocPRY4FjwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6588 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6589 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6590 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6591 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6592 "PBQ8FDwUPBQ8FDwUPBQ8FToVPRssG0BeRFpLUFVGYzT2LwAA");
6593 todo_wine ok(match, "Figure does not match.\n");
6595 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
6596 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6597 hr = ID2D1PathGeometry_Open(geometry, &sink);
6598 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6600 set_point(&point, 40.0f, 160.0f);
6601 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6602 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6604 set_point(&point, 120.0f, 160.0f);
6605 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6606 line_to(sink, 120.0f, 160.0f);
6607 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6609 set_point(&point, 200.0f, 160.0f);
6610 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6611 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6613 set_point(&point, 280.0f, 160.0f);
6614 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6615 line_to(sink, 280.0f, 160.0f);
6616 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6618 set_point(&point, 20.0f, 480.0f);
6619 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6620 line_to(sink, 60.0f, 480.0f);
6621 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6623 set_point(&point, 120.0f, 400.0f);
6624 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6625 line_to(sink, 120.0f, 560.0f);
6626 line_to(sink, 120.0f, 400.0f);
6627 line_to(sink, 120.0f, 560.0f);
6628 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6630 set_point(&point, 180.0f, 480.0f);
6631 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6632 line_to(sink, 220.0f, 480.0f);
6633 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6635 set_point(&point, 280.0f, 400.0f);
6636 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6637 line_to(sink, 280.0f, 560.0f);
6638 line_to(sink, 280.0f, 400.0f);
6639 line_to(sink, 280.0f, 560.0f);
6640 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6642 set_point(&point, 20.0f, 880.0f);
6643 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6644 line_to(sink, 40.0f, 720.0f);
6645 line_to(sink, 60.0f, 880.0f);
6646 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6648 set_point(&point, 100.0f, 720.0f);
6649 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6650 line_to(sink, 120.0f, 880.0f);
6651 line_to(sink, 140.0f, 720.0f);
6652 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6654 set_point(&point, 180.0f, 880.0f);
6655 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6656 line_to(sink, 200.0f, 720.0f);
6657 line_to(sink, 220.0f, 880.0f);
6658 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6660 set_point(&point, 260.0f, 720.0f);
6661 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6662 line_to(sink, 280.0f, 880.0f);
6663 line_to(sink, 300.0f, 720.0f);
6664 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6666 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
6667 hr = ID2D1GeometrySink_Close(sink);
6668 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6669 ID2D1GeometrySink_Release(sink);
6671 ID2D1RenderTarget_BeginDraw(rt);
6672 ID2D1RenderTarget_Clear(rt, &color);
6673 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, 5.0f, NULL);
6674 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6675 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6676 ID2D1PathGeometry_Release(geometry);
6678 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0, "");
6679 ok(match, "Figure does not match.\n");
6680 match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0, "");
6681 ok(match, "Figure does not match.\n");
6682 match = compare_figure(&ctx, 320, 0, 160, 160, 0xff652e89, 0, "");
6683 ok(match, "Figure does not match.\n");
6684 match = compare_figure(&ctx, 480, 0, 160, 160, 0xff652e89, 0, "q2MKlgEKq2MA");
6685 todo_wine ok(match, "Figure does not match.\n");
6687 match = compare_figure(&ctx, 0, 160, 160, 160, 0xff652e89, 0, "iGNQUFCIYwAA");
6688 ok(match, "Figure does not match.\n");
6689 match = compare_figure(&ctx, 160, 160, 160, 160, 0xff652e89, 0,
6690 "qyIKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
6691 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
6692 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKQQpLCkEKSwqWAQqW"
6693 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
6694 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
6695 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQrLIwAA");
6696 ok(match, "Figure does not match.\n");
6697 match = compare_figure(&ctx, 320, 160, 160, 160, 0xff652e89, 0, "4GLAAuBi");
6698 ok(match, "Figure does not match.\n");
6699 match = compare_figure(&ctx, 480, 160, 160, 160, 0xff652e89, 0,
6700 "qyIKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
6701 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
6702 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKSwpBCksKQQqWAQqWAQqW"
6703 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
6704 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
6705 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQrLIwAA");
6706 ok(match, "Figure does not match.\n");
6708 match = compare_figure(&ctx, 0, 320, 160, 160, 0xff652e89, 0,
6709 "rycCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
6710 "jAEUiwEKAgqKAQoCCokBCgQKiAEKBAqHAQoGCoYBCgYKhQEKCAqEAQoICoMBCgoKggEKCgqBAQoM"
6711 "CoABCgwKfwoOCn4KDgp9ChAKfAoQCnsKEgp6ChIKeQoUCngKFAp3ChYKdgoWCnUKGAp0ChgKcwoa"
6712 "CnIKGgpxChwKcAocCm8KHgpuCh4KbQogCmwKIAprCiIKagoiCmkKJApoCiQKZwomCmYKJgplCigK"
6713 "ZAooCmMKKgpiCioKYQosCmAKLApfCi4KXgouCl0KMApcCjAKWwoyCloKMgpZCjQKWAo0ClcKNgpW"
6714 "CjYKVQo4ClQKOApTCjoKUgo6ClEKPApQCjwKTwo+Ck4KPgpNCkAKTApACksKQgpKCkIKSQpECkgK"
6715 "RApHCkYKozIA");
6716 ok(match, "Figure does not match.\n");
6717 match = compare_figure(&ctx, 160, 320, 160, 160, 0xff652e89, 0,
6718 "ozIKRgpHCkQKSApECkkKQgpKCkIKSwpACkwKQApNCj4KTgo+Ck8KPApQCjwKUQo6ClIKOgpTCjgK"
6719 "VAo4ClUKNgpWCjYKVwo0ClgKNApZCjIKWgoyClsKMApcCjAKXQouCl4KLgpfCiwKYAosCmEKKgpi"
6720 "CioKYwooCmQKKAplCiYKZgomCmcKJApoCiQKaQoiCmoKIgprCiAKbAogCm0KHgpuCh4KbwocCnAK"
6721 "HApxChoKcgoaCnMKGAp0ChgKdQoWCnYKFgp3ChQKeAoUCnkKEgp6ChIKewoQCnwKEAp9Cg4KfgoO"
6722 "Cn8KDAqAAQoMCoEBCgoKggEKCgqDAQoICoQBCggKhQEKBgqGAQoGCocBCgQKiAEKBAqJAQoCCooB"
6723 "CgIKiwEUjAEUjQESjgESjwEQkAEQkQEOkgEOkwEMlAEMlQEKlgEKlwEImAEImQEGmgEGmwEEnAEE"
6724 "nQECngECrycA");
6725 ok(match, "Figure does not match.\n");
6726 match = compare_figure(&ctx, 320, 320, 160, 160, 0xff652e89, 0,
6727 "rycCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
6728 "jAEUiwEKAgqKAQoCCokBCgQKiAEKBAqHAQoGCoYBCgYKhQEKCAqEAQoICoMBCgoKggEKCgqBAQoM"
6729 "CoABCgwKfwoOCn4KDgp9ChAKfAoQCnsKEgp6ChIKeQoUCngKFAp3ChYKdgoWCnUKGAp0ChgKcwoa"
6730 "CnIKGgpxChwKcAocCm8KHgpuCh4KbQogCmwKIAprCiIKagoiCmkKJApoCiQKZwomCmYKJgplCigK"
6731 "ZAooCmMKKgpiCioKYQosCmAKLApfCi4KXgouCl0KMApcCjAKWwoyCloKMgpZCjQKWAo0ClcKNgpW"
6732 "CjYKVQo4ClQKOApTCjoKUgo6ClEKPApQCjwKTwo+Ck4KPgpNCkAKTApACksKQgpKCkIKSQpECkgK"
6733 "RApHWkZagzEA");
6734 ok(match, "Figure does not match.\n");
6735 match = compare_figure(&ctx, 480, 320, 160, 160, 0xff652e89, 0,
6736 "gzFaRlpHCkQKSApECkkKQgpKCkIKSwpACkwKQApNCj4KTgo+Ck8KPApQCjwKUQo6ClIKOgpTCjgK"
6737 "VAo4ClUKNgpWCjYKVwo0ClgKNApZCjIKWgoyClsKMApcCjAKXQouCl4KLgpfCiwKYAosCmEKKgpi"
6738 "CioKYwooCmQKKAplCiYKZgomCmcKJApoCiQKaQoiCmoKIgprCiAKbAogCm0KHgpuCh4KbwocCnAK"
6739 "HApxChoKcgoaCnMKGAp0ChgKdQoWCnYKFgp3ChQKeAoUCnkKEgp6ChIKewoQCnwKEAp9Cg4KfgoO"
6740 "Cn8KDAqAAQoMCoEBCgoKggEKCgqDAQoICoQBCggKhQEKBgqGAQoGCocBCgQKiAEKBAqJAQoCCooB"
6741 "CgIKiwEUjAEUjQESjgESjwEQkAEQkQEOkgEOkwEMlAEMlQEKlgEKlwEImAEImQEGmgEGmwEEnAEE"
6742 "nQECngECrycA");
6743 ok(match, "Figure does not match.\n");
6745 set_rect(&rect, 20.0f, 80.0f, 60.0f, 240.0f);
6746 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[0]);
6747 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6749 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
6750 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[1]);
6751 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6753 set_matrix_identity(&matrix);
6754 translate_matrix(&matrix, 160.0f, 640.0f);
6755 scale_matrix(&matrix, 40.0f, 160.0f);
6756 rotate_matrix(&matrix, M_PI / -5.0f);
6757 hr = ID2D1Factory_CreateTransformedGeometry(factory,
6758 (ID2D1Geometry *)rect_geometry[1], &matrix, &transformed_geometry[0]);
6759 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6761 set_matrix_identity(&matrix);
6762 scale_matrix(&matrix, 0.5f, 1.0f);
6763 translate_matrix(&matrix, -80.0f, 0.0f);
6764 hr = ID2D1Factory_CreateTransformedGeometry(factory,
6765 (ID2D1Geometry *)transformed_geometry[0], &matrix, &transformed_geometry[1]);
6766 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6768 set_matrix_identity(&matrix);
6769 rotate_matrix(&matrix, M_PI / 2.0f);
6770 translate_matrix(&matrix, 80.0f, -320.0f);
6771 scale_matrix(&matrix, 2.0f, 0.25f);
6772 hr = ID2D1Factory_CreateTransformedGeometry(factory,
6773 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
6774 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6776 ID2D1RenderTarget_BeginDraw(rt);
6777 ID2D1RenderTarget_Clear(rt, &color);
6778 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)rect_geometry[0], (ID2D1Brush *)brush, 10.0f, NULL);
6779 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, 10.0f, NULL);
6780 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, 5.0f, NULL);
6781 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, 15.0f, NULL);
6782 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6783 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6784 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
6785 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
6786 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
6787 ID2D1RectangleGeometry_Release(rect_geometry[1]);
6788 ID2D1RectangleGeometry_Release(rect_geometry[0]);
6790 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0,
6791 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6792 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6793 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6794 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6795 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6796 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6797 ok(match, "Figure does not match.\n");
6798 match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 32,
6799 "8XYGtQIOrAIXpAIfmwIokwIwigI4gwJA+gFJ8gFR6QEzAiXhATMKJdgBMxMl0AEzGyXHATMkJb8B"
6800 "MysmtgEzNCWvATM8JaYBM0UlngEzTSWVATNWJY0BM14lhAEzZyV8M28lczN4JWszgAElYjOIASZa"
6801 "M5ABJVgtmQElWCWhASVYJaEBJVgloQElWCWhASVYJaEBJVgloQElWCWhASVYJaEBJVglmQEtWCWQ"
6802 "ATNaJogBM2IlgAEzayV4M3MlbzN8JWczhAElXjONASVWM5UBJU0zngElRTOmASU8M68BJTQztgEm"
6803 "KzO/ASUkM8cBJRsz0AElEzPYASUKM+EBJQIz6QFR8gFJ+gFAgwI4igIwkwIomwIfpAIXrAIOtQIG"
6804 "8XYA");
6805 ok(match, "Figure does not match.\n");
6806 match = compare_figure(&ctx, 0, 160, 160, 320, 0xff652e89, 32,
6807 "ujEBngECnQEDnQEEmwEFmgEHmQEHmAEIlwEKlgEKlQELlAENkwENkgEOkQEQjwERjwESjQETjAEU"
6808 "jAEKAQqKAQoCCokBCgMKiQEKBAqHAQoFCoYBCgYKhgEKBwqEAQoICoMBCgkKgwEKCgqBAQoLCoAB"
6809 "Cg0KfgsNCn4KDgp9ChAKewsQCnsKEQp6ChMKeAoUCngKFAp3ChYKdQoXCnUKGApzChkKcgoaCnIK"
6810 "GwpwChwKbwodCm4LHgptCh8KbAogCmsLIQpqCiIKaQokCmcKJQpnCiUKZgonCmQKKApkCigKYwoq"
6811 "CmEKKwphCisKYAotCl4KLgpdCy8KXAowClsKMQpaCzIKWQozClgKNApXCjYKVgo2ClUKNwpUCjkK"
6812 "Uwo5ClIKOwpQCjwKTws8Ck8KPgpNCj8KTAs/CkwKQQpKCkIKSQtCCkkKRApHCkUKRgpHCkUKRwpE"
6813 "CkgKQwpKCkIKSgpBCksKQApNCj4LTQo+Ck4KPQpQCjsLUAo7ClIKOQpTCjgLUwo4ClUKNgpWCjUK"
6814 "Vwo1ClgKMwpZCjQKWAo0ClkKMwpZCjQKWQozClkKMwpZCjQKWQozClkKMwpZCjQKWQozClkKNApY"
6815 "CjQKWQozClkKNApZCjMKWQozClkKNApZCjMKWQozClkKNApZCjMKWQo0ClgKNApZCjMKWQo0ClkK"
6816 "MwpZCjMKWQo0ClkKMwpZCjMKWQo0ClkKMwpZCjQKWAo0ClkKMwpYCjUKVwo1ClYKNgpVCjgKUws4"
6817 "ClMKOQpSCjsKUAs7ClAKPQpOCj4KTQs+Ck0KQApLCkEKSgpCCkoKQwpICkQKRwpFCkcKRgpFCkcK"
6818 "RApJCkILSQpCCkoKQQpMCj8LTAo/Ck0KPgpPCjwLTwo8ClAKOwpSCjkKUwo5ClQKNwpVCjYKVgo2"
6819 "ClcKNApYCjMKWQoyC1oKMQpbCjAKXAovC10KLgpeCi0KYAorCmEKKwphCioKYwooCmQKKApkCicK"
6820 "ZgolCmcKJQpnCiQKaQoiCmoKIQtrCiAKbAofCm0KHgtuCh0KbwocCnAKGwpyChoKcgoZCnMKGAp1"
6821 "ChcKdQoWCncKFAp4ChQKeAoTCnoKEQp7ChALewoQCn0KDgp+Cg0LfgoNCoABCgsKgQEKCgqDAQoJ"
6822 "CoMBCggKhAEKBwqGAQoGCoYBCgUKhwEKBAqJAQoDCokBCgIKigEKAQqMARSMARONARKPARGPARCR"
6823 "AQ6SAQ2TAQ2UAQuVAQqWAQqXAQiYAQeZAQeaAQWbAQSdAQOdAQKeAQG6MQAA");
6824 ok(match, "Figure does not match.\n");
6825 match = compare_figure(&ctx, 160, 160, 320, 320, 0xff652e89, 64,
6826 "82ICvQIEugIHuAIJtgIKtAINsgIPsAIRrQITrAIVqQIYpwIZpgIbowIeoQIgnwIhnQIkmwImmAIp"
6827 "lgIVARSVAhUDFJICFQUVkAIVBxSPAhUJFIwCFQwUigIVDRWHAhYPFIYCFRIUhAIVFBSBAhUWFf8B"
6828 "FRgU/gEVGhT7ARUcFfkBFR4U9wEWIBT1ARUjFPMBFSQV8AEVJxTvARUpFOwBFisU6gEVLRXoARUv"
6829 "FOYBFjEU5AEVMxXiARU1FOABFTgU3gEVOhTbARY7FdkBFT4U2AEVQBTVARZCFNMBFUQV0QEVRhTP"
6830 "ARVJFM0BFUoVygEWTBTJARVPFMcBFVEUxAEVUxXCARVVFMEBFVcUvgEVWRW8ARVbFbkBFl0UuAEV"
6831 "YBS2ARVhFbMBFWQUsgEVZhSwARVoFK0BFWoVqwEVbBSpARZuFKcBFXAVpQEVchWiARV1FKEBFXcU"
6832 "nwEVeBWcARV7FJsBFX0UmAEWfxSWARWBARWUARWDARSSARWGARSQARWHARWOARWJARWLARWMARSK"
6833 "ARWOARSHARaPARWFARWSARSEARWUARSBARWXARR/FZgBFX0VmgEUexWdARR5FZ4BFXYWoAEVdBWj"
6834 "ARRzFaUBFHAVpwEVbhWpARRtFasBFGoVrgEUaBWvARVmFbEBFGcUsgEUZxSxARVmFbEBFWYUsgEU"
6835 "ZxSyARRnFLEBFWYVsQEUZxSyARRnFLIBFGcUsQEVZhWxARRnFLIBFGcUsQEVZhWxARVmFLIBFGcU"
6836 "sgEUZxSxARVmFbEBFGcUsgEUZxSyARRmFbEBFWYVsQEUZxSyARRnFLEBFWYVsQEUZxSyARRnFLIB"
6837 "FGcUsQEVZhWxARRnFLIBFGcUsgEUZhWxARVmFbEBFGcUsgEUZxSxARVmFa8BFWgUrgEVahSrARVt"
6838 "FKkBFW4VpwEVcBSlARVzFKMBFXQVoAEWdhWeARV5FJ0BFXsUmgEVfRWYARV/FJcBFYEBFJQBFYQB"
6839 "FJIBFYUBFY8BFocBFI4BFYoBFIwBFYsBFYkBFY4BFYcBFZABFIYBFZIBFIMBFZQBFYEBFZYBFH8W"
6840 "mAEUfRWbARR7FZwBFXgVnwEUdxWhARR1FaIBFXIVpQEVcBWnARRuFqkBFGwVqwEVahWtARRoFbAB"
6841 "FGYVsgEUZBWzARVhFbYBFGAVuAEUXRa5ARVbFbwBFVkVvgEUVxXBARRVFcIBFVMVxAEUURXHARRP"
6842 "FckBFEwWygEVShXNARRJFc8BFEYV0QEVRBXTARRCFtUBFEAV2AEUPhXZARU7FtsBFDoV3gEUOBXg"
6843 "ARQ1FeIBFTMV5AEUMRbmARQvFegBFS0V6gEUKxbsARQpFe8BFCcV8AEVJBXzARQjFfUBFCAW9wEU"
6844 "HhX5ARUcFfsBFBoV/gEUGBX/ARUWFYECFBQVhAIUEhWGAhQPFocCFQ0VigIUDBWMAhQJFY8CFAcV"
6845 "kAIVBRWSAhQDFZUCFAEVlgIpmAImmwIknQIhnwIgoQIeowIbpgIZpwIYqQIVrAITrQIRsAIPsgIN"
6846 "tAIKtgIJuAIHugIEvQIC82IA");
6847 ok(match, "Figure does not match.\n");
6849 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
6850 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6851 hr = ID2D1PathGeometry_Open(geometry, &sink);
6852 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6854 set_point(&point, 20.0f, 80.0f);
6855 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6856 quadratic_to(sink, 40.0f, 80.0f, 60.0f, 80.0f);
6857 quadratic_to(sink, 60.0f, 160.0f, 60.0f, 240.0f);
6858 quadratic_to(sink, 40.0f, 240.0f, 20.0f, 240.0f);
6859 quadratic_to(sink, 20.0f, 160.0f, 20.0f, 80.0f);
6860 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6862 set_point(&point, 100.0f, 80.0f);
6863 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6864 quadratic_to(sink, 105.0f, 80.0f, 140.0f, 80.0f);
6865 quadratic_to(sink, 140.0f, 100.0f, 140.0f, 240.0f);
6866 quadratic_to(sink, 135.0f, 240.0f, 100.0f, 240.0f);
6867 quadratic_to(sink, 100.0f, 220.0f, 100.0f, 80.0f);
6868 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6870 set_point(&point, 180.0f, 80.0f);
6871 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6872 quadratic_to(sink, 215.0f, 80.0f, 220.0f, 80.0f);
6873 quadratic_to(sink, 220.0f, 220.0f, 220.0f, 240.0f);
6874 quadratic_to(sink, 185.0f, 240.0f, 180.0f, 240.0f);
6875 quadratic_to(sink, 180.0f, 100.0f, 180.0f, 80.0f);
6876 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6878 set_point(&point, 260.0f, 80.0f);
6879 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6880 quadratic_to(sink, 280.0f, 80.0f, 300.0f, 80.0f);
6881 quadratic_to(sink, 300.0f, 160.0f, 300.0f, 240.0f);
6882 quadratic_to(sink, 280.0f, 240.0f, 260.0f, 240.0f);
6883 quadratic_to(sink, 260.0f, 160.0f, 260.0f, 80.0f);
6884 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6886 set_point(&point, 20.0f, 400.0f);
6887 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6888 quadratic_to(sink, 40.0f, 420.0f, 60.0f, 400.0f);
6889 quadratic_to(sink, 55.0f, 480.0f, 60.0f, 560.0f);
6890 quadratic_to(sink, 40.0f, 540.0f, 20.0f, 560.0f);
6891 quadratic_to(sink, 25.0f, 480.0f, 20.0f, 400.0f);
6892 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6894 set_point(&point, 100.0f, 400.0f);
6895 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6896 quadratic_to(sink, 105.0f, 420.0f, 140.0f, 400.0f);
6897 quadratic_to(sink, 135.0f, 420.0f, 140.0f, 560.0f);
6898 quadratic_to(sink, 135.0f, 540.0f, 100.0f, 560.0f);
6899 quadratic_to(sink, 105.0f, 540.0f, 100.0f, 400.0f);
6900 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6902 set_point(&point, 180.0f, 400.0f);
6903 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6904 quadratic_to(sink, 215.0f, 420.0f, 220.0f, 400.0f);
6905 quadratic_to(sink, 215.0f, 540.0f, 220.0f, 560.0f);
6906 quadratic_to(sink, 185.0f, 540.0f, 180.0f, 560.0f);
6907 quadratic_to(sink, 185.0f, 420.0f, 180.0f, 400.0f);
6908 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6910 set_point(&point, 260.0f, 400.0f);
6911 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6912 quadratic_to(sink, 280.0f, 420.0f, 300.0f, 400.0f);
6913 quadratic_to(sink, 295.0f, 480.0f, 300.0f, 560.0f);
6914 quadratic_to(sink, 280.0f, 540.0f, 260.0f, 560.0f);
6915 quadratic_to(sink, 265.0f, 480.0f, 260.0f, 400.0f);
6916 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6918 set_point(&point, 20.0f, 720.0f);
6919 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6920 quadratic_to(sink, 40.0f, 700.0f, 60.0f, 720.0f);
6921 quadratic_to(sink, 65.0f, 800.0f, 60.0f, 880.0f);
6922 quadratic_to(sink, 40.0f, 900.0f, 20.0f, 880.0f);
6923 quadratic_to(sink, 15.0f, 800.0f, 20.0f, 720.0f);
6924 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6926 set_point(&point, 100.0f, 720.0f);
6927 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6928 quadratic_to(sink, 105.0f, 700.0f, 140.0f, 720.0f);
6929 quadratic_to(sink, 145.0f, 740.0f, 140.0f, 880.0f);
6930 quadratic_to(sink, 135.0f, 900.0f, 100.0f, 880.0f);
6931 quadratic_to(sink, 95.0f, 860.0f, 100.0f, 720.0f);
6932 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6934 set_point(&point, 180.0f, 720.0f);
6935 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6936 quadratic_to(sink, 215.0f, 700.0f, 220.0f, 720.0f);
6937 quadratic_to(sink, 225.0f, 860.0f, 220.0f, 880.0f);
6938 quadratic_to(sink, 185.0f, 900.0f, 180.0f, 880.0f);
6939 quadratic_to(sink, 175.0f, 740.0f, 180.0f, 720.0f);
6940 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6942 set_point(&point, 260.0f, 720.0f);
6943 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6944 quadratic_to(sink, 280.0f, 700.0f, 300.0f, 720.0f);
6945 quadratic_to(sink, 305.0f, 800.0f, 300.0f, 880.0f);
6946 quadratic_to(sink, 280.0f, 900.0f, 260.0f, 880.0f);
6947 quadratic_to(sink, 255.0f, 800.0f, 260.0f, 720.0f);
6948 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6950 hr = ID2D1GeometrySink_Close(sink);
6951 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6952 ID2D1GeometrySink_Release(sink);
6954 ID2D1RenderTarget_BeginDraw(rt);
6955 ID2D1RenderTarget_Clear(rt, &color);
6956 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, 10.0f, NULL);
6957 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6958 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
6959 ID2D1PathGeometry_Release(geometry);
6961 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0,
6962 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6963 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6964 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6965 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6966 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6967 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6968 ok(match, "Figure does not match.\n");
6969 match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0,
6970 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6971 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6972 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6973 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6974 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6975 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6976 ok(match, "Figure does not match.\n");
6977 match = compare_figure(&ctx, 320, 0, 160, 160, 0xff652e89, 0,
6978 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6979 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6980 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6981 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6982 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6983 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6984 ok(match, "Figure does not match.\n");
6985 match = compare_figure(&ctx, 480, 0, 160, 160, 0xff652e89, 0,
6986 "yC5aRlpGWjxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6987 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6988 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6989 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6990 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6991 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6992 ok(match, "Figure does not match.\n");
6994 match = compare_figure(&ctx, 0, 160, 160, 160, 0xff652e89, 64,
6995 "3SoDYAM6B1gHOgtQCzoPSA87EkASPBc2FzwcLBw8IiAiPWI+Yj5iPhQBOAEUPhQKJgoUPxQ4FEAU"
6996 "OBRAFDgUQBQ4FEAUOBRBFDYUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRDFDQURBQ0FEQUNBREFDQURBQ0"
6997 "FEQUNBREFDQURBQ0FEQUNBREFDQURRQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIU"
6998 "RhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRG"
6999 "FDIURRQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEMUNhRCFDYUQhQ2FEIU"
7000 "NhRCFDYUQhQ2FEEUOBRAFDgUQBQ4FEAUOBRAFDgUPxQKJgoUPhQBOAEUPmI+Yj5iPSIgIjwcLBw8"
7001 "FzYXPBJAEjsPSA86C1ALOgdYBzoDYAPdKgAA");
7002 ok(match, "Figure does not match.\n");
7003 match = compare_figure(&ctx, 160, 160, 160, 160, 0xff652e89, 1024,
7004 "uxUBnwECngEDnQEEnAEFmwEGmwEGmgEHmQEImAEJlwEKlgELlQEMlQEMlAENkwEOkgEPkQEQkAER"
7005 "VQQ2Ek0KOBJFEDkTPRY6FDUcOxUrJDwYHi09Yj5iP2BAQwkUQDgUFEAUOBRAFDcUQRQ3FEEUNxRC"
7006 "FDYUQhQ2FEIUNhRCFDUUQxQ1FEMUNRRDFDUUQxQ1FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQU"
7007 "NBREFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQ0"
7008 "FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQ0FEQUNBREFDQU"
7009 "RBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRDFDUUQxQ1FEMUNRRDFDUUQhQ2FEIUNhRC"
7010 "FDYUQhQ3FEEUNxRBFDcUQBQ4FEAUFDhAFAlDQGA/Yj5iPS0eGDwkKxU7HDUUOhY9EzkQRRI4Ck0S"
7011 "NgRVEZABEJEBD5IBDpMBDZQBDJUBDJUBC5YBCpcBCZgBCJkBB5oBBpsBBpsBBZwBBJ0BA54BAp8B"
7012 "AbsV");
7013 ok(match, "Figure does not match.\n");
7014 match = compare_figure(&ctx, 320, 160, 160, 160, 0xff652e89, 1024,
7015 "pBYBngECnQEDnAEEmwEFmgEGmQEGmQEHmAEIlwEJlgEKlQELlAEMkwEMkwENkgEOkQEPkAEQNgRV"
7016 "ETcKTRI4EEUSOhY9EzscNRQ8JCsVPS0eGD5iPmI/YEAUCUNAFBQ4QBQ4FEEUNxRBFDcUQRQ3FEEU"
7017 "NhRCFDYUQhQ2FEMUNRRDFDUUQxQ1FEMUNRRDFDUUQxQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0"
7018 "FEQUNBREFDQURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxREFDQU"
7019 "RBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxREFDQURBQ0FEQUNBRE"
7020 "FDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQUQxQ1FEMUNRRDFDUUQxQ1FEMUNRRDFDYUQhQ2FEIU"
7021 "NhRBFDcUQRQ3FEEUNxRBFDgUQDgUFEBDCRRAYD9iPmI+GB4tPRUrJDwUNRw7Ez0WOhJFEDgSTQo3"
7022 "EVUENhCQAQ+RAQ6SAQ2TAQyTAQyUAQuVAQqWAQmXAQiYAQeZAQaZAQaaAQWbAQScAQOdAQKeAQGk"
7023 "FgAA");
7024 ok(match, "Figure does not match.\n");
7025 match = compare_figure(&ctx, 480, 160, 160, 160, 0xff652e89, 64,
7026 "wCsDmQEHlQELkQEPSwJAEkgLNhc8HCwcPCIgIj1iPmI+Yj4UATgBFD4UCiYKFD8UOBRAFDgUQBQ4"
7027 "FEAUOBRAFDgUQRQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDYUQxQ0FEQUNBREFDQURBQ0FEQUNBREFDQU"
7028 "RBQ0FEQUNBREFDQURBQ0FEUUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRG"
7029 "FDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEUU"
7030 "NBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBRDFDYUQhQ2FEIUNhRCFDYUQhQ2"
7031 "FEIUNhRBFDgUQBQ4FEAUOBRAFDgUQBQ4FD8UCiYKFD4UATgBFD5iPmI+Yj0iICI8HCwcPBc2FzwS"
7032 "QBI7D0gPOgtQCzoHWAc6A2AD3SoA");
7033 ok(match, "Figure does not match.\n");
7035 match = compare_figure(&ctx, 0, 320, 160, 160, 0xff652e89, 64,
7036 "3SkmcThiRFdOTVhEICAgPhwsHDwXNhc8FDwUOxQ+FDoUPhQ6FD4UOhQ+FDoUPhQ5FEAUOBRAFDgU"
7037 "QBQ4FEAUOBRAFDcUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDUURBQ0FEQUNBREFDQURBQ0FEQUNBRE"
7038 "FDQURBQ0FEQUNBREFDQURBQzFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYU"
7039 "MhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQz"
7040 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRCFDYUQhQ2FEIUNhRCFDYU"
7041 "QhQ2FEIUNxRAFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPhQ6FD4UOhQ+FDsUPBQ8FzYXPBws"
7042 "HD4gICBEWE1OV0RiOHEm3SkA");
7043 ok(match, "Figure does not match.\n");
7044 match = compare_figure(&ctx, 160, 320, 160, 160, 0xff652e89, 1024,
7045 "zykoczhkRVhQTlpEFx4tPRUrJDwUNRw7FDwVOxQ+FDoUPhQ5FEAUOBRAFDgUQBQ4FEAUOBRBFDcU"
7046 "QRQ3FEEUNhRCFDYUQhQ2FEIUNhRDFDUUQxQ1FEMUNRRDFDUUQxQ0FEQUNBREFDQURBQ0FEQUNBRE"
7047 "FDQURBQ0FEQUNBREFDQURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUU"
7048 "MxRFFDMURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURBQ0"
7049 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEMUNRRDFDUUQxQ1FEMUNRRDFDYU"
7050 "QhQ2FEIUNhRCFDYUQRQ3FEEUNxRBFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDsVPBQ7HDUUPCQr"
7051 "FT0tHhdEWk5QWEVkOHMozykA");
7052 ok(match, "Figure does not match.\n");
7053 match = compare_figure(&ctx, 320, 320, 160, 160, 0xff652e89, 1024,
7054 "6SkobThfRVNQSFpALR4XPSQrFTscNRQ7FTwUOhQ+FDoUPhQ5FEAUOBRAFDgUQBQ4FEAUNxRBFDcU"
7055 "QRQ3FEEUNxRCFDYUQhQ2FEIUNRRDFDUUQxQ1FEMUNRRDFDUUQxQ1FEQUNBREFDQURBQ0FEQUNBRE"
7056 "FDQURBQ0FEQUNBREFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUU"
7057 "MxRFFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDQURBQ0"
7058 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ1FEMUNRRDFDUUQxQ1FEMUNRRDFDUU"
7059 "QhQ2FEIUNhRCFDcUQRQ3FEEUNxRBFDcUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPBU7FDUcOxUr"
7060 "JD0XHi1AWkhQU0VfOG0o6SkA");
7061 ok(match, "Figure does not match.\n");
7062 match = compare_figure(&ctx, 480, 320, 160, 160, 0xff652e89, 64,
7063 "3SkmcThiRFdOTVhGHiAgRhQsHDwXNhc8FDwUOxQ+FDoUPhQ6FD4UOhQ+FDoUPhQ5FEAUOBRAFDgU"
7064 "QBQ4FEAUOBRAFDcUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDUURBQ0FEQUNBREFDQURBQ0FEQUNBRE"
7065 "FDQURBQ0FEQUNBREFDQURBQzFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYU"
7066 "MhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQz"
7067 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRCFDYUQhQ2FEIUNhRCFDYU"
7068 "QhQ2FEIUNxRAFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPhQ6FD4UOhQ+FDsUPBQ8FzYXPBws"
7069 "HD4gICBEWE1OV0RiOHEm3SkA");
7070 ok(match, "Figure does not match.\n");
7072 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7073 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7074 hr = ID2D1PathGeometry_Open(geometry, &sink);
7075 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7077 set_point(&point, -0.402914f, 0.915514f);
7078 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
7079 quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
7080 quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f);
7081 quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f);
7082 quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f);
7083 quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f);
7084 quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f);
7085 quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f);
7086 quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f);
7087 quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f);
7088 quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f);
7089 quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f);
7090 quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f);
7091 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7093 hr = ID2D1GeometrySink_Close(sink);
7094 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7095 ID2D1GeometrySink_Release(sink);
7097 set_matrix_identity(&matrix);
7098 translate_matrix(&matrix, 40.0f, 160.0f);
7099 scale_matrix(&matrix, 20.0f, 80.0f);
7100 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7101 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]);
7102 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7104 set_matrix_identity(&matrix);
7105 translate_matrix(&matrix, 160.0f, 640.0f);
7106 scale_matrix(&matrix, 40.0f, 160.0f);
7107 rotate_matrix(&matrix, M_PI / -5.0f);
7108 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7109 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]);
7110 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7111 ID2D1PathGeometry_Release(geometry);
7113 set_matrix_identity(&matrix);
7114 scale_matrix(&matrix, 0.5f, 1.0f);
7115 translate_matrix(&matrix, -80.0f, 0.0f);
7116 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7117 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
7118 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7120 set_matrix_identity(&matrix);
7121 rotate_matrix(&matrix, M_PI / 2.0f);
7122 translate_matrix(&matrix, 80.0f, -320.0f);
7123 scale_matrix(&matrix, 2.0f, 0.25f);
7124 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7125 (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]);
7126 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7128 ID2D1RenderTarget_BeginDraw(rt);
7129 ID2D1RenderTarget_Clear(rt, &color);
7130 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, 2.0f, NULL);
7131 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, 10.0f, NULL);
7132 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, 5.0f, NULL);
7133 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[3], (ID2D1Brush *)brush, 15.0f, NULL);
7134 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7135 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7136 ID2D1TransformedGeometry_Release(transformed_geometry[3]);
7137 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
7138 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
7139 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
7141 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 128,
7142 "yjIJkQEHBwaIAQUSBYMBBBYEggEEFgSCAQQWBIIBBBYEggEEFgSCAQQWBIIBBBYEggEEFgSCAQQW"
7143 "BIIBBBYEggEEFgSDAQQVBIMBBBUEgwEEFQSDAQQVBIMBBBUEgwEEFQSDAQQVBIMBBBUEgwEEFQSD"
7144 "AQQVBIQBBBQEhAEEFASEAQQTBIUBBBMEhQEEEwSFAQQTBIUBBBMEhQEEEwSGAQQSBIYBBBIEhgEE"
7145 "EgSGAQQSBIYBBBIEhgEEEgSGAQQRBIgBBBAEiAEEEASIAQQQBIkBBA4EigEEDgSLAQQMBIwBBAwE"
7146 "jQEECgSOAQQJBJABBAgEkAEFBgSSAQQGBJMBBAQElAEEBASVAQQDBJUBBAIElwEEAQSXAQiZAQeZ"
7147 "AQaaAQaaAQaaAQabAQWbAQWbAQWbAQWaAQeZAQeZAQeZAQiXAQQBBJYBBAMElQEEAwWRAQUGBY0B"
7148 "BQwFhwEFEgSCAQUXBYABBBoFfgUYBIIBBhEFiAEUpTEA");
7149 ok(match, "Figure does not match.\n");
7150 match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 512,
7151 "yJIBArkCDa4CGKMCIZoCK5ECM4gCO4ECQ/gBS/EBUesBLAYl5QEsDiPeASwWIdkBLBwh0wEsISHO"
7152 "ASsgKMsBKR4vyAEnHDPIASUaNMsBIxg1mQEFMCIUN54BCygiDzijAREhIgY9qAEYGWGuAR4RXbMB"
7153 "JAhbuQGAAcABesYBc84Ba9YBTvQBP4MCOIoCNI4CM5ACMZICL5QCLZYCK5kCKJsCJ54CI6MCHq8C"
7154 "EraSAQAA");
7155 ok(match, "Figure does not match.\n");
7156 match = compare_figure(&ctx, 0, 160, 160, 320, 0xff652e89, 512,
7157 "xWkCmwEFmAEJlQELlAENkgEOkQEPjwESjQETjAEVigELAQqJAQsCCogBCwQKhwEKBQqGAQoGCoYB"
7158 "CgcKhAEKCAqEAQoIC4IBCgoKggEKCgqBAQoMCoABCgwKfwoNCn8KDgp9Cg8KfQoPCnwKEQp7ChEK"
7159 "egoSCnoKEwp4ChQKeAoUCncLFQp2ChYKdgoWCnYKFwp2ChYKdgoWCncKFgp2ChYKdgoWCncKFQt2"
7160 "ChYKdwoVCncKFQp4ChUKdwoVCncKFQp4ChUKdwoVCngKFAp4ChUKeAoUCngKFAp4CxMKeQoUCngK"
7161 "FAp5ChMKeQoUCnkKEwp5ChMKegoSC3kKEwp6ChIKegoSCnoLEgp6ChIKegoSCnsKEQp7ChEKfAoQ"
7162 "CnwKEAp9Cg8KfQoPCn4KDgp+Cg4KfwoOCn4KDgp/Cg0KfwoNCoABCgwKgAEKDAqBAQoLCoEBCgsK"
7163 "gQELCgqCAQoKCoIBCwkKgwEKCQqDAQoJCoQBCggKhAEKCQqEAQsHCoUBCwYKhgELBQqHAQsECogB"
7164 "CwMKiQELAgqLAQoBCowBFI0BE44BE44BEo8BEZABEJEBD5IBDpMBDpMBDZMBDZQBDJQBDZQBDJQB"
7165 "DBUCfgwSBH4MEQV/DA4GgAEMDAiAAQ0KCYEBDAgLgQENBQ2BAQ0EDoIBDQEPgwEdgwEdgwEdgwEc"
7166 "hAEKAgQCCoUBCgYKhgEKBgqGAQoFC4YBCgUKhwEKBAqIAQoECogBCgMKiQEKAwqIAQoDCokBCgMK"
7167 "iQEKAgqJAQoCCooBCgIKiQEKAgqKAQoBCosBCgEKigEKAQqLARSMARSLARSMAROMARONARKOARGO"
7168 "ARGPARCQAQ6RAQ2YAQTEZAAA");
7169 ok(match, "Figure does not match.\n");
7170 match = compare_figure(&ctx, 160, 160, 320, 320, 0xff652e89, 1024,
7171 "ytABA7gCCbICD60CFKkCF6cCGqMCHqACIZ0CJJoCJpgCKZUCFgIUkgIWBBWPAhYHFI4CFQoUjAIV"
7172 "DBSKAhUNFYgCFQ8UhwIVERSFAhUTFIMCFRQVgQIUFxSAAhQZFP4BFBoV/AEUHBT7ARQeFPkBFB8V"
7173 "9wEUIRT2ARQjFPQBFSMV8gEVJRTxARUnFPABFCgV7gEUKhTtARQsFOwBFCwV7AEULBTsARUsFOwB"
7174 "FSsV7AEULBTtARQsFO0BFCsU7QEVKxTtARUqFe0BFSoU7gEUKxTuARQqFe4BFCoU7wEUKhTuARUp"
7175 "FO8BFSkU7wEVKBXvARUoFPABFCkU8AEUKBTxARQoFPEBFCcV8QEUJxTxARUnFPEBFSYU8gEVJhTy"
7176 "ARUlFfIBFSUU8wEUJRXzARQlFPQBFCUU9AEUJBT1ARQkFPUBFCMU9gEUIhT2ARUhFPcBFSAU+AEV"
7177 "HxT5ARUeFPoBFR4U+gEVHRT7ARUcFPwBFRsU/QEVGhT+ARUZFP8BFBkUgAIUGBSBAhQXFIICFBcU"
7178 "ggIUFhSDAhQVFIQCFBQUhQIUExSGAhQSFIcCFBIUhwIUERSIAhUPFIkCFg0UigIXCxSNAhYJFI8C"
7179 "FggUkAIXBRSSAhcDFJQCFwEUlgIrlwIpmgImnAIkngIjnwIhoQIfowIepAIcpgIbpgIaqAIZqAIZ"
7180 "qAIYKwP7ARgnBf0BGCMI/QEZHgz+ARgbD/8BGBcSgAIYEhaAAhoNGIICGggcgwIaBB+DAjyEAjyF"
7181 "AjqGAjmIAjiIAiECFIkCFAIIBBSKAhQNFIsCFAwUjAIUCxSNAhQKFI4CFAkUjwIUBxWQAhQGFZEC"
7182 "FAUVkQIUBRWRAhQFFZECFQMVkwIUAxWTAhQDFZMCFAIVlAIVARWVAiqVAimWAimWAiiYAiaZAiaZ"
7183 "AiWaAiScAiKdAiGeAh+hAhyjAhmuAg3GxgEA");
7184 ok(match, "Figure does not match.\n");
7186 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7187 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7188 hr = ID2D1PathGeometry_Open(geometry, &sink);
7189 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7191 set_point(&point, 20.0f, 80.0f);
7192 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
7193 quadratic_to(sink, 20.0f, 160.0f, 60.0f, 160.0f);
7194 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7196 set_point(&point, 100.0f, 80.0f);
7197 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
7198 quadratic_to(sink, 100.0f, 160.0f, 140.0f, 160.0f);
7199 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7201 hr = ID2D1GeometrySink_Close(sink);
7202 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7203 ID2D1GeometrySink_Release(sink);
7205 ID2D1RenderTarget_BeginDraw(rt);
7206 ID2D1RenderTarget_Clear(rt, &color);
7207 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, 10.0f, NULL);
7208 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7209 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7210 ID2D1PathGeometry_Release(geometry);
7212 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 32,
7213 "3iUCngEEnAEGmgEImAEKlgEMlAEOkgEQkAESjgEUjAEWigEYiAEahgEchAEeggEggQEhfyN9JXsn"
7214 "eih4KnYUAhZ1FAMWcxQFFnIUBhZwFQcWbxQJFm4UChZsFQsWaxUMFmoVDRZpFQ4WaBUPFmcVEBZm"
7215 "FREWZhURFmUVEhZkFhIWZBYSFmQXERZkFxEWZBgQFmQaDhZlGwwWZh0JFmchBBZpOWw2bzN0Lnsn"
7216 "2mEA");
7217 ok(match, "Figure does not match.\n");
7219 match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 32,
7220 "njIUjAEUjAEUjAEUjAEUjAEUjQEUjAEUjAEUjAEUjQEUjAEUjAEUjQEUjAEUjQEUjAEVjAEUjQEU"
7221 "jAEVjAEVjAEVjAEVjAEVjAEVjAEVjQEVjAEVjAEWjAEWjAEXiwEXiwEYigEaiQEbiAEdhgEhgwEz"
7222 "ci53KX4ihwEZ6GEA");
7223 ok(match, "Figure does not match.\n");
7225 ID2D1SolidColorBrush_Release(brush);
7226 ID2D1Factory_Release(factory);
7227 release_test_context(&ctx);
7230 static void test_fill_geometry(BOOL d3d11)
7232 ID2D1TransformedGeometry *transformed_geometry[4];
7233 ID2D1RectangleGeometry *rect_geometry[2];
7234 D2D1_POINT_2F point = {0.0f, 0.0f};
7235 D2D1_ROUNDED_RECT rounded_rect;
7236 struct d2d1_test_context ctx;
7237 ID2D1SolidColorBrush *brush;
7238 ID2D1PathGeometry *geometry;
7239 D2D1_MATRIX_3X2_F matrix;
7240 ID2D1GeometrySink *sink;
7241 ID2D1RenderTarget *rt;
7242 ID2D1Factory *factory;
7243 D2D1_ELLIPSE ellipse;
7244 D2D1_COLOR_F color;
7245 D2D1_RECT_F rect;
7246 HRESULT hr;
7247 BOOL match;
7249 if (!init_test_context(&ctx, d3d11))
7250 return;
7252 rt = ctx.rt;
7253 ID2D1RenderTarget_GetFactory(rt, &factory);
7255 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
7256 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
7257 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
7258 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
7259 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7261 ID2D1RenderTarget_BeginDraw(rt);
7262 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
7263 ID2D1RenderTarget_Clear(rt, &color);
7265 set_rect(&rect, 40.0f, 480.0f, 40.0f, 480.0f);
7266 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
7267 set_rect(&rect, 100.0f, 480.0f, 140.0f, 480.0f);
7268 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
7269 set_rect(&rect, 200.0f, 400.0f, 200.0f, 560.0f);
7270 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
7271 set_rect(&rect, 260.0f, 560.0f, 300.0f, 400.0f);
7272 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
7274 set_ellipse(&ellipse, 40.0f, 800.0f, 0.0f, 0.0f);
7275 ID2D1RenderTarget_FillEllipse(rt, &ellipse, (ID2D1Brush *)brush);
7276 set_ellipse(&ellipse, 120.0f, 800.0f, 20.0f, 0.0f);
7277 ID2D1RenderTarget_FillEllipse(rt, &ellipse, (ID2D1Brush *)brush);
7278 set_ellipse(&ellipse, 200.0f, 800.0f, 0.0f, 80.0f);
7279 ID2D1RenderTarget_FillEllipse(rt, &ellipse, (ID2D1Brush *)brush);
7280 set_ellipse(&ellipse, 280.0f, 800.0f, 20.0f, 80.0f);
7281 ID2D1RenderTarget_FillEllipse(rt, &ellipse, (ID2D1Brush *)brush);
7283 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7284 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7286 match = compare_figure(&ctx, 0, 160, 160, 160, 0xff652e89, 0, "gMgB");
7287 ok(match, "Figure does not match.\n");
7288 match = compare_figure(&ctx, 160, 160, 160, 160, 0xff652e89, 0, "gMgB");
7289 ok(match, "Figure does not match.\n");
7290 match = compare_figure(&ctx, 320, 160, 160, 160, 0xff652e89, 0, "gMgB");
7291 ok(match, "Figure does not match.\n");
7292 match = compare_figure(&ctx, 480, 160, 160, 160, 0xff652e89, 0,
7293 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7294 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7295 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7296 ok(match, "Figure does not match.\n");
7298 match = compare_figure(&ctx, 0, 320, 160, 160, 0xff652e89, 0, "gMgB");
7299 ok(match, "Figure does not match.\n");
7300 match = compare_figure(&ctx, 160, 320, 160, 160, 0xff652e89, 0, "gMgB");
7301 ok(match, "Figure does not match.\n");
7302 match = compare_figure(&ctx, 320, 320, 160, 160, 0xff652e89, 0, "gMgB");
7303 ok(match, "Figure does not match.\n");
7304 match = compare_figure(&ctx, 480, 320, 160, 160, 0xff652e89, 8,
7305 "yjIMjwEWhwEcggEgfiR6KHYscy5xMG40azZpOGc6ZTxjPmI+YUBfQl1EXERbRlpGWUhYSFdKVkpV"
7306 "TFRMVExTTlJOUk5STlJOUVBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUU5STlJOUk5STlNMVExUTFVK"
7307 "VkpXSFhIWUZaRltEXERdQl9AYT5iPmM8ZTpnOGk2azRuMHEucyx2KHokfiCCARyHARaPAQzKMgAA");
7308 ok(match, "Figure does not match.\n");
7310 ID2D1RenderTarget_BeginDraw(rt);
7311 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
7312 ID2D1RenderTarget_Clear(rt, &color);
7314 set_rounded_rect(&rounded_rect, 40.0f, 160.0f, 40.0f, 160.0f, 10.0f, 10.0f);
7315 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7316 set_rounded_rect(&rounded_rect, 100.0f, 160.0f, 140.0f, 160.0f, 10.0f, 10.0f);
7317 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7318 set_rounded_rect(&rounded_rect, 200.0f, 80.0f, 200.0f, 240.0f, 10.0f, 10.0f);
7319 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7320 set_rounded_rect(&rounded_rect, 260.0f, 240.0f, 300.0f, 80.0f, 10.0f, 10.0f);
7321 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7323 set_rounded_rect(&rounded_rect, 40.0f, 480.0f, 40.0f, 480.0f, 10.0f, 20.0f);
7324 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7325 set_rounded_rect(&rounded_rect, 100.0f, 480.0f, 140.0f, 480.0f, 10.0f, 20.0f);
7326 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7327 set_rounded_rect(&rounded_rect, 200.0f, 400.0f, 200.0f, 560.0f, 10.0f, 20.0f);
7328 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7329 set_rounded_rect(&rounded_rect, 260.0f, 560.0f, 300.0f, 400.0f, 10.0f, 20.0f);
7330 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7332 set_rounded_rect(&rounded_rect, 40.0f, 800.0f, 40.0f, 800.0f, 10.0f, 5.0f);
7333 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7334 set_rounded_rect(&rounded_rect, 100.0f, 800.0f, 140.0f, 800.0f, 10.0f, 5.0f);
7335 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7336 set_rounded_rect(&rounded_rect, 200.0f, 720.0f, 200.0f, 880.0f, 10.0f, 5.0f);
7337 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7338 set_rounded_rect(&rounded_rect, 260.0f, 880.0f, 300.0f, 720.0f, 10.0f, 5.0f);
7339 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7341 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7342 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7344 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0, "gMgB");
7345 ok(match, "Figure does not match.\n");
7346 match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0, "gMgB");
7347 ok(match, "Figure does not match.\n");
7348 match = compare_figure(&ctx, 320, 0, 160, 160, 0xff652e89, 0, "gMgB");
7349 ok(match, "Figure does not match.\n");
7350 match = compare_figure(&ctx, 480, 0, 160, 160, 0xff652e89, 0,
7351 "szI6YURZSlROUVBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7352 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7353 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUU5USllEYTqzMgAA");
7354 ok(match, "Figure does not match.\n");
7356 match = compare_figure(&ctx, 0, 160, 160, 160, 0xff652e89, 0, "gMgB");
7357 ok(match, "Figure does not match.\n");
7358 match = compare_figure(&ctx, 160, 160, 160, 160, 0xff652e89, 0, "gMgB");
7359 ok(match, "Figure does not match.\n");
7360 match = compare_figure(&ctx, 320, 160, 160, 160, 0xff652e89, 0, "gMgB");
7361 ok(match, "Figure does not match.\n");
7362 match = compare_figure(&ctx, 480, 160, 160, 160, 0xff652e89, 2,
7363 "tjI0aDxhQlxGWEpVTFNOUk5RUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7364 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7365 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFFOUk5TTFVKWEZcQmA+ZzS2MgAA");
7366 ok(match, "Figure does not match.\n");
7368 match = compare_figure(&ctx, 0, 320, 160, 160, 0xff652e89, 0, "gMgB");
7369 ok(match, "Figure does not match.\n");
7370 match = compare_figure(&ctx, 160, 320, 160, 160, 0xff652e89, 0, "gMgB");
7371 ok(match, "Figure does not match.\n");
7372 match = compare_figure(&ctx, 320, 320, 160, 160, 0xff652e89, 0, "gMgB");
7373 ok(match, "Figure does not match.\n");
7374 match = compare_figure(&ctx, 480, 320, 160, 160, 0xff652e89, 0,
7375 "sDJAWkxSUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7376 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7377 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFJMWkCwMgAA");
7378 ok(match, "Figure does not match.\n");
7380 ID2D1RenderTarget_BeginDraw(rt);
7381 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
7382 ID2D1RenderTarget_Clear(rt, &color);
7384 set_rounded_rect(&rounded_rect, 40.0f, 160.0f, 40.0f, 160.0f, 1000.0f, 1000.0f);
7385 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7386 set_rounded_rect(&rounded_rect, 100.0f, 160.0f, 140.0f, 160.0f, 1000.0f, 1000.0f);
7387 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7388 set_rounded_rect(&rounded_rect, 200.0f, 80.0f, 200.0f, 240.0f, 1000.0f, 1000.0f);
7389 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7390 set_rounded_rect(&rounded_rect, 260.0f, 240.0f, 300.0f, 80.0f, 1000.0f, 1000.0f);
7391 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7393 set_rounded_rect(&rounded_rect, 40.0f, 480.0f, 40.0f, 480.0f, 10.0f, 1000.0f);
7394 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7395 set_rounded_rect(&rounded_rect, 100.0f, 480.0f, 140.0f, 480.0f, 10.0f, 1000.0f);
7396 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7397 set_rounded_rect(&rounded_rect, 200.0f, 400.0f, 200.0f, 560.0f, 10.0f, 1000.0f);
7398 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7399 set_rounded_rect(&rounded_rect, 260.0f, 560.0f, 300.0f, 400.0f, 10.0f, 1000.0f);
7400 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7402 set_rounded_rect(&rounded_rect, 40.0f, 800.0f, 40.0f, 800.0f, 1000.0f, 10.0f);
7403 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7404 set_rounded_rect(&rounded_rect, 100.0f, 800.0f, 140.0f, 800.0f, 1000.0f, 10.0f);
7405 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7406 set_rounded_rect(&rounded_rect, 200.0f, 720.0f, 200.0f, 880.0f, 1000.0f, 10.0f);
7407 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7408 set_rounded_rect(&rounded_rect, 260.0f, 880.0f, 300.0f, 720.0f, 1000.0f, 10.0f);
7409 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
7411 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7412 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7414 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0, "gMgB");
7415 ok(match, "Figure does not match.\n");
7416 match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0, "gMgB");
7417 ok(match, "Figure does not match.\n");
7418 match = compare_figure(&ctx, 320, 0, 160, 160, 0xff652e89, 0, "gMgB");
7419 ok(match, "Figure does not match.\n");
7420 match = compare_figure(&ctx, 480, 0, 160, 160, 0xff652e89, 10,
7421 "yjIMjwEWhwEcggEgfiR6KHYscy5xMG40azZpOGc6ZTxjPmI+YUBfQl1EXERbRlpGWUhYSFdKVkpV"
7422 "TFRMVExTTlJOUk5STlJOUVBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUU5STlJOUk5STlNMVExUTFVK"
7423 "VkpXSFhIWUZaRltEXERdQl9AYT5iPmM8ZTpnOGk2azRuMHEucyx2KHokfiCCARyHARaPAQzKMgAA");
7424 ok(match, "Figure does not match.\n");
7426 match = compare_figure(&ctx, 0, 160, 160, 160, 0xff652e89, 0, "gMgB");
7427 ok(match, "Figure does not match.\n");
7428 match = compare_figure(&ctx, 160, 160, 160, 160, 0xff652e89, 0, "gMgB");
7429 ok(match, "Figure does not match.\n");
7430 match = compare_figure(&ctx, 320, 160, 160, 160, 0xff652e89, 0, "gMgB");
7431 ok(match, "Figure does not match.\n");
7432 match = compare_figure(&ctx, 480, 160, 160, 160, 0xff652e89, 10,
7433 "uTIucDJsNmk4ZzplPGM+YUBgQF9CXkJdRFxEW0ZaRllIWEhXSlZKVkpWSlVMVExUTFRMU05STlJO"
7434 "Uk5STlJOUk9QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFFPUU5STlJOUk5STlJOU0xU"
7435 "TFRMVExVSlZKVkpWSldIWEhZRlpGW0RcRF1CXkJfQGBAYT5jPGU6ZzhpNmwycC65MgAA");
7436 ok(match, "Figure does not match.\n");
7438 match = compare_figure(&ctx, 0, 320, 160, 160, 0xff652e89, 0, "gMgB");
7439 ok(match, "Figure does not match.\n");
7440 match = compare_figure(&ctx, 160, 320, 160, 160, 0xff652e89, 0, "gMgB");
7441 ok(match, "Figure does not match.\n");
7442 match = compare_figure(&ctx, 320, 320, 160, 160, 0xff652e89, 0, "gMgB");
7443 ok(match, "Figure does not match.\n");
7444 match = compare_figure(&ctx, 480, 320, 160, 160, 0xff652e89, 10,
7445 "vzIiczhhRldMUlBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7446 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7447 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUkxXRmA6cSS+MgAA");
7448 ok(match, "Figure does not match.\n");
7450 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7451 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7452 hr = ID2D1PathGeometry_Open(geometry, &sink);
7453 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7455 set_point(&point, 40.0f, 160.0f);
7456 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7457 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7459 set_point(&point, 120.0f, 160.0f);
7460 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7461 line_to(sink, 120.0f, 160.0f);
7462 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7464 set_point(&point, 200.0f, 160.0f);
7465 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7466 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7468 set_point(&point, 280.0f, 160.0f);
7469 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7470 line_to(sink, 280.0f, 160.0f);
7471 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7473 set_point(&point, 20.0f, 480.0f);
7474 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7475 line_to(sink, 60.0f, 480.0f);
7476 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7478 set_point(&point, 120.0f, 400.0f);
7479 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7480 line_to(sink, 120.0f, 560.0f);
7481 line_to(sink, 120.0f, 400.0f);
7482 line_to(sink, 120.0f, 560.0f);
7483 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7485 set_point(&point, 180.0f, 480.0f);
7486 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7487 line_to(sink, 220.0f, 480.0f);
7488 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7490 set_point(&point, 280.0f, 400.0f);
7491 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7492 line_to(sink, 280.0f, 560.0f);
7493 line_to(sink, 280.0f, 400.0f);
7494 line_to(sink, 280.0f, 560.0f);
7495 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7497 set_point(&point, 20.0f, 880.0f);
7498 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7499 line_to(sink, 40.0f, 720.0f);
7500 line_to(sink, 60.0f, 880.0f);
7501 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7503 set_point(&point, 100.0f, 720.0f);
7504 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7505 line_to(sink, 120.0f, 880.0f);
7506 line_to(sink, 140.0f, 720.0f);
7507 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7509 set_point(&point, 180.0f, 880.0f);
7510 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7511 line_to(sink, 200.0f, 720.0f);
7512 line_to(sink, 220.0f, 880.0f);
7513 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7515 set_point(&point, 260.0f, 720.0f);
7516 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7517 line_to(sink, 280.0f, 880.0f);
7518 line_to(sink, 300.0f, 720.0f);
7519 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7521 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
7522 hr = ID2D1GeometrySink_Close(sink);
7523 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7524 ID2D1GeometrySink_Release(sink);
7526 ID2D1RenderTarget_BeginDraw(rt);
7527 ID2D1RenderTarget_Clear(rt, &color);
7528 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
7529 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7530 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7531 ID2D1PathGeometry_Release(geometry);
7533 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0, "gMgB");
7534 ok(match, "Figure does not match.\n");
7535 match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0, "gMgB");
7536 ok(match, "Figure does not match.\n");
7537 match = compare_figure(&ctx, 320, 0, 160, 160, 0xff652e89, 0, "gMgB");
7538 ok(match, "Figure does not match.\n");
7539 match = compare_figure(&ctx, 480, 0, 160, 160, 0xff652e89, 0, "gMgB");
7540 ok(match, "Figure does not match.\n");
7542 match = compare_figure(&ctx, 0, 160, 160, 160, 0xff652e89, 0, "gMgB");
7543 ok(match, "Figure does not match.\n");
7544 match = compare_figure(&ctx, 160, 160, 160, 160, 0xff652e89, 0, "gMgB");
7545 ok(match, "Figure does not match.\n");
7546 match = compare_figure(&ctx, 320, 160, 160, 160, 0xff652e89, 0, "gMgB");
7547 ok(match, "Figure does not match.\n");
7548 match = compare_figure(&ctx, 480, 160, 160, 160, 0xff652e89, 0, "gMgB");
7549 ok(match, "Figure does not match.\n");
7551 match = compare_figure(&ctx, 0, 320, 160, 160, 0xff652e89, 0,
7552 "7zMCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
7553 "jAEUiwEWigEWiQEYiAEYhwEahgEahQEchAEcgwEeggEegQEggAEgfyJ+In0kfCR7JnomeSh4KHcq"
7554 "dip1LHQscy5yLnEwcDBvMm4ybTRsNGs2ajZpOGg4ZzpmOmU8ZDxjPmI+YUBgQF9CXkJdRFxEW0Za"
7555 "RllIWEhXSlZKVUxUTFNOUk5RUKgy");
7556 ok(match, "Figure does not match.\n");
7557 match = compare_figure(&ctx, 160, 320, 160, 160, 0xff652e89, 0,
7558 "qDJQUU5STlNMVExVSlZKV0hYSFlGWkZbRFxEXUJeQl9AYEBhPmI+YzxkPGU6ZjpnOGg4aTZqNms0"
7559 "bDRtMm4ybzBwMHEuci5zLHQsdSp2KncoeCh5JnomeyR8JH0ifiJ/IIABIIEBHoIBHoMBHIQBHIUB"
7560 "GoYBGocBGIgBGIkBFooBFosBFIwBFI0BEo4BEo8BEJABEJEBDpIBDpMBDJQBDJUBCpYBCpcBCJgB"
7561 "CJkBBpoBBpsBBJwBBJ0BAp4BAu8z");
7562 ok(match, "Figure does not match.\n");
7563 match = compare_figure(&ctx, 320, 320, 160, 160, 0xff652e89, 0,
7564 "7zMCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
7565 "jAEUiwEWigEWiQEYiAEYhwEahgEahQEchAEcgwEeggEegQEggAEgfyJ+In0kfCR7JnomeSh4KHcq"
7566 "dip1LHQscy5yLnEwcDBvMm4ybTRsNGs2ajZpOGg4ZzpmOmU8ZDxjPmI+YUBgQF9CXkJdRFxEW0Za"
7567 "RllIWEhXSlZKVUxUTFNOUk5RUKgy");
7568 ok(match, "Figure does not match.\n");
7569 match = compare_figure(&ctx, 480, 320, 160, 160, 0xff652e89, 0,
7570 "qDJQUU5STlNMVExVSlZKV0hYSFlGWkZbRFxEXUJeQl9AYEBhPmI+YzxkPGU6ZjpnOGg4aTZqNms0"
7571 "bDRtMm4ybzBwMHEuci5zLHQsdSp2KncoeCh5JnomeyR8JH0ifiJ/IIABIIEBHoIBHoMBHIQBHIUB"
7572 "GoYBGocBGIgBGIkBFooBFosBFIwBFI0BEo4BEo8BEJABEJEBDpIBDpMBDJQBDJUBCpYBCpcBCJgB"
7573 "CJkBBpoBBpsBBJwBBJ0BAp4BAu8z");
7574 ok(match, "Figure does not match.\n");
7576 set_rect(&rect, 20.0f, 80.0f, 60.0f, 240.0f);
7577 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[0]);
7578 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7580 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
7581 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[1]);
7582 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7584 set_matrix_identity(&matrix);
7585 translate_matrix(&matrix, 160.0f, 640.0f);
7586 scale_matrix(&matrix, 40.0f, 160.0f);
7587 rotate_matrix(&matrix, M_PI / -5.0f);
7588 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7589 (ID2D1Geometry *)rect_geometry[1], &matrix, &transformed_geometry[0]);
7590 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7592 set_matrix_identity(&matrix);
7593 scale_matrix(&matrix, 0.5f, 1.0f);
7594 translate_matrix(&matrix, -80.0f, 0.0f);
7595 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7596 (ID2D1Geometry *)transformed_geometry[0], &matrix, &transformed_geometry[1]);
7597 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7599 set_matrix_identity(&matrix);
7600 rotate_matrix(&matrix, M_PI / 2.0f);
7601 translate_matrix(&matrix, 80.0f, -320.0f);
7602 scale_matrix(&matrix, 2.0f, 0.25f);
7603 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7604 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
7605 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7607 ID2D1RenderTarget_BeginDraw(rt);
7608 ID2D1RenderTarget_Clear(rt, &color);
7609 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)rect_geometry[0], (ID2D1Brush *)brush, NULL);
7610 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, NULL);
7611 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, NULL);
7612 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, NULL);
7613 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7614 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7615 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
7616 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
7617 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
7618 ID2D1RectangleGeometry_Release(rect_geometry[1]);
7619 ID2D1RectangleGeometry_Release(rect_geometry[0]);
7621 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0,
7622 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7623 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7624 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7625 ok(match, "Figure does not match.\n");
7626 match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 32,
7627 "sIMBA7cCDK8CFKYCHZ4CJJYCLY4CNYUCPv0BRvQBT+wBV+MBYNsBaNIBccoBecEBgQG6AYkBsQGS"
7628 "AakBmgGgAaMBmAGrAY8BtAGHAbwBfsUBfcYBfcYBfcUBfsUBfcYBfcYBfcYBfcYBfcUBfr0BhgG0"
7629 "AY8BrAGXAaMBoAGbAagBkgGwAYsBuAGCAcEBeskBcdIBadoBYOMBWOsBT/QBR/wBPoUCNowCLpUC"
7630 "Jp0CHaYCFa4CDLcCBK+DAQAA");
7631 ok(match, "Figure does not match.\n");
7632 match = compare_figure(&ctx, 0, 160, 160, 320, 0xff652e89, 32,
7633 "+D0BngEDnQEDnAEEmwEGmgEGmQEHmAEJlwEJlgELlAEMkwENkwEOkQEPkAEQkAERjgESjQETjQEU"
7634 "iwEVigEXiQEXiAEYhwEahgEahQEbhAEdggEeggEegQEgfyF/In0jfCR8JXomeSd5KHcpdip2K3Qs"
7635 "cy5xL3EvcDFuMm4ybTRrNWs1ajdoOGg5ZjplO2U8Yz1iPmFAYEBfQV5DXUNcRVpGWkZZSFdJV0lW"
7636 "S1RMVExTTlFPUFFPUU5STVRMVEtVSldJV0hYR1pGWkVcQ11CXkJfQGA/YT9iPWM+Yj5jPWM+Yz1j"
7637 "PWM+Yz1jPmI+Yz1jPmI+Yz1jPmM9Yz1jPmM9Yz5iPmM9Yz5iPmM9Yz5jPWM9Yz5jPWM+Yj5jPWM+"
7638 "Yj5jPWI/YT9gQF9CXkJdRFtFW0VaR1hIV0lXSlVLVExUTVJOUVBQUE9RTlNNU0xUS1ZKVklXSFlG"
7639 "WkZaRVxDXUNeQV9AYEBhPmI9Yz1kO2U6ZjpnOGg3ajVrNWs0bTJuMm4xcC9xL3Eucyx0LHUqdil3"
7640 "KXgneSZ6JXwkfCN9In8hfyCBAR6CAR6CAR2EARuFARuFARqHARiIAReJAReKARWLARSNARONARKO"
7641 "ARGQARCQAQ+RAQ6TAQ2TAQyUAQuWAQqWAQmYAQeZAQaaAQabAQScAQOdAQOeAQH4PQAA");
7642 ok(match, "Figure does not match.\n");
7643 match = compare_figure(&ctx, 160, 160, 320, 320, 0xff652e89, 32,
7644 "sXkBvgIDvAIEugIHuAIJtgILswINsgIPrwISrQITrAIVqQIYpwIapQIbowIeoQIgngIjnAIkmwIm"
7645 "mAIplgIqlQIskgIvkAIxjQIzjAI1igI3hwI5hgI7hAI9gQJA/wFB/QFE+wFG+QFI9gFK9QFM8wFO"
7646 "8AFQ7wFS7AFV6gFX6AFY5gFb5AFd4gFf3wFh3gFj2wFm2QFn2AFp1QFs0wFu0QFvzwFyzQF0ygF3"
7647 "yAF4xwF6xAF9wgF+wAGBAb4BgwG8AYUBuQGHAbgBiQG2AYsBswGOAbEBjwGvAZIBrQGUAasBlQGp"
7648 "AZgBpwGaAaUBnAGiAZ4BoQGgAZ4BowGcAaUBmgGmAZgBqQGWAasBlAGsAZIBrwGQAbEBjQG0AYsB"
7649 "tQGKAbcBhwG6AYUBvAGDAb0BgQHAAX/CAXzEAXvGAXvGAXvGAXvFAXvGAXvGAXvGAXvFAXvGAXvG"
7650 "AXvFAXvGAXvGAXvGAXvFAXvGAXvGAXvFAXzFAXvGAXvGAXvFAXvGAXvGAXvGAXvFAXvGAXvGAXvF"
7651 "AXzFAXvGAXvGAXvFAXvGAXvGAXvGAXvEAXzCAX/AAYEBvgGCAbwBhQG6AYcBtwGKAbUBiwG0AY0B"
7652 "sQGQAa8BkgGtAZMBqwGWAakBmAGmAZoBpQGcAaMBngGgAaEBngGiAZ0BpAGaAacBmAGpAZUBqwGU"
7653 "Aa0BkgGvAY8BsQGOAbMBjAG1AYkBuAGHAbkBhQG8AYMBvgGBAcABfsIBfcQBe8YBeMgBd8oBdM0B"
7654 "cs8BcNABbtMBbNUBatcBZ9kBZtsBY94BYd8BYOEBXeQBW+YBWOgBV+oBVewBUu8BUPABT/IBTPUB"
7655 "SvYBSPkBRvsBRP0BQf8BQIECPoMCO4YCOYcCN4oCNYwCM40CMZACL5ICLZQCKpYCKZgCJpsCJJ0C"
7656 "Ip4CIKECHqMCHKQCGqcCGKkCFawCE60CEq8CD7ICDbMCDLUCCbgCB7oCBLwCA74CAbF5");
7657 ok(match, "Figure does not match.\n");
7659 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7660 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7661 hr = ID2D1PathGeometry_Open(geometry, &sink);
7662 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7664 set_point(&point, 20.0f, 80.0f);
7665 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7666 quadratic_to(sink, 40.0f, 80.0f, 60.0f, 80.0f);
7667 quadratic_to(sink, 60.0f, 160.0f, 60.0f, 240.0f);
7668 quadratic_to(sink, 40.0f, 240.0f, 20.0f, 240.0f);
7669 quadratic_to(sink, 20.0f, 160.0f, 20.0f, 80.0f);
7670 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7672 set_point(&point, 100.0f, 80.0f);
7673 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7674 quadratic_to(sink, 105.0f, 80.0f, 140.0f, 80.0f);
7675 quadratic_to(sink, 140.0f, 100.0f, 140.0f, 240.0f);
7676 quadratic_to(sink, 135.0f, 240.0f, 100.0f, 240.0f);
7677 quadratic_to(sink, 100.0f, 220.0f, 100.0f, 80.0f);
7678 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7680 set_point(&point, 180.0f, 80.0f);
7681 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7682 quadratic_to(sink, 215.0f, 80.0f, 220.0f, 80.0f);
7683 quadratic_to(sink, 220.0f, 220.0f, 220.0f, 240.0f);
7684 quadratic_to(sink, 185.0f, 240.0f, 180.0f, 240.0f);
7685 quadratic_to(sink, 180.0f, 100.0f, 180.0f, 80.0f);
7686 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7688 set_point(&point, 260.0f, 80.0f);
7689 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7690 quadratic_to(sink, 280.0f, 80.0f, 300.0f, 80.0f);
7691 quadratic_to(sink, 300.0f, 160.0f, 300.0f, 240.0f);
7692 quadratic_to(sink, 280.0f, 240.0f, 260.0f, 240.0f);
7693 quadratic_to(sink, 260.0f, 160.0f, 260.0f, 80.0f);
7694 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7696 set_point(&point, 20.0f, 400.0f);
7697 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7698 quadratic_to(sink, 40.0f, 420.0f, 60.0f, 400.0f);
7699 quadratic_to(sink, 55.0f, 480.0f, 60.0f, 560.0f);
7700 quadratic_to(sink, 40.0f, 540.0f, 20.0f, 560.0f);
7701 quadratic_to(sink, 25.0f, 480.0f, 20.0f, 400.0f);
7702 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7704 set_point(&point, 100.0f, 400.0f);
7705 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7706 quadratic_to(sink, 105.0f, 420.0f, 140.0f, 400.0f);
7707 quadratic_to(sink, 135.0f, 420.0f, 140.0f, 560.0f);
7708 quadratic_to(sink, 135.0f, 540.0f, 100.0f, 560.0f);
7709 quadratic_to(sink, 105.0f, 540.0f, 100.0f, 400.0f);
7710 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7712 set_point(&point, 180.0f, 400.0f);
7713 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7714 quadratic_to(sink, 215.0f, 420.0f, 220.0f, 400.0f);
7715 quadratic_to(sink, 215.0f, 540.0f, 220.0f, 560.0f);
7716 quadratic_to(sink, 185.0f, 540.0f, 180.0f, 560.0f);
7717 quadratic_to(sink, 185.0f, 420.0f, 180.0f, 400.0f);
7718 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7720 set_point(&point, 260.0f, 400.0f);
7721 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7722 quadratic_to(sink, 280.0f, 420.0f, 300.0f, 400.0f);
7723 quadratic_to(sink, 295.0f, 480.0f, 300.0f, 560.0f);
7724 quadratic_to(sink, 280.0f, 540.0f, 260.0f, 560.0f);
7725 quadratic_to(sink, 265.0f, 480.0f, 260.0f, 400.0f);
7726 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7728 set_point(&point, 20.0f, 720.0f);
7729 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7730 quadratic_to(sink, 40.0f, 700.0f, 60.0f, 720.0f);
7731 quadratic_to(sink, 65.0f, 800.0f, 60.0f, 880.0f);
7732 quadratic_to(sink, 40.0f, 900.0f, 20.0f, 880.0f);
7733 quadratic_to(sink, 15.0f, 800.0f, 20.0f, 720.0f);
7734 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7736 set_point(&point, 100.0f, 720.0f);
7737 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7738 quadratic_to(sink, 105.0f, 700.0f, 140.0f, 720.0f);
7739 quadratic_to(sink, 145.0f, 740.0f, 140.0f, 880.0f);
7740 quadratic_to(sink, 135.0f, 900.0f, 100.0f, 880.0f);
7741 quadratic_to(sink, 95.0f, 860.0f, 100.0f, 720.0f);
7742 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7744 set_point(&point, 180.0f, 720.0f);
7745 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7746 quadratic_to(sink, 215.0f, 700.0f, 220.0f, 720.0f);
7747 quadratic_to(sink, 225.0f, 860.0f, 220.0f, 880.0f);
7748 quadratic_to(sink, 185.0f, 900.0f, 180.0f, 880.0f);
7749 quadratic_to(sink, 175.0f, 740.0f, 180.0f, 720.0f);
7750 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7752 set_point(&point, 260.0f, 720.0f);
7753 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7754 quadratic_to(sink, 280.0f, 700.0f, 300.0f, 720.0f);
7755 quadratic_to(sink, 305.0f, 800.0f, 300.0f, 880.0f);
7756 quadratic_to(sink, 280.0f, 900.0f, 260.0f, 880.0f);
7757 quadratic_to(sink, 255.0f, 800.0f, 260.0f, 720.0f);
7758 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7760 hr = ID2D1GeometrySink_Close(sink);
7761 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7762 ID2D1GeometrySink_Release(sink);
7764 ID2D1RenderTarget_BeginDraw(rt);
7765 ID2D1RenderTarget_Clear(rt, &color);
7766 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
7767 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7768 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7769 ID2D1PathGeometry_Release(geometry);
7771 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0,
7772 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7773 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7774 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7775 ok(match, "Figure does not match.\n");
7776 match = compare_figure(&ctx, 160, 0, 160, 160, 0xff652e89, 0,
7777 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7778 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7779 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7780 match = compare_figure(&ctx, 320, 0, 160, 160, 0xff652e89, 0,
7781 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7782 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7783 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7784 ok(match, "Figure does not match.\n");
7785 match = compare_figure(&ctx, 480, 0, 160, 160, 0xff652e89, 0,
7786 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7787 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7788 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7789 ok(match, "Figure does not match.\n");
7791 match = compare_figure(&ctx, 0, 160, 160, 160, 0xff652e89, 16,
7792 "qDICTAJQB0IHUQs4C1IRLBFSGxgbUk5STlNMVExUTFRMVExVSlZKVkpWSlZKVkpXSFhIWEhYSFhI"
7793 "WEhYSFhIWEhYSFlGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZa"
7794 "RllIWEhYSFhIWEhYSFhIWEhYSFhIV0pWSlZKVkpWSlZKVUxUTFRMVExUTFNOUk5SGxgbUhEsEVIL"
7795 "OAtRB0IHUAJMAqgy");
7796 ok(match, "Figure does not match.\n");
7797 match = compare_figure(&ctx, 160, 160, 160, 160, 0xff652e89, 16,
7798 "qDIBSwRQAkMKUQQ5EVIIKxtTDRkmVExUTFRMVEtVS1VLVkpWSlZKVklXSVdJV0lXSVhIWEhYSFhI"
7799 "WEhYSFhIWEhYSFhIWUdZR1lHWUdZR1lHWUdZR1lHWUdZSFhIWUdZR1lHWUdZR1lHWUdZR1lHWUdZ"
7800 "SFhIWEhYSFhIWEhYSFhIWEhYSFhJV0lXSVdJV0lWSlZKVkpWS1VLVUtUTFRMVExUJhkNUxsrCFIR"
7801 "OQRRCkMCUARLAagy");
7802 ok(match, "Figure does not match.\n");
7803 match = compare_figure(&ctx, 320, 160, 160, 160, 0xff652e89, 16,
7804 "qDIESwFRCkMCUhE5BFIbKwhTJhkNVExUTFRMVUtVS1VLVUpWSlZKV0lXSVdJV0lXSVdIWEhYSFhI"
7805 "WEhYSFhIWEhYSFhIWEdZR1lHWUdZR1lHWUdZR1lHWUdYSFhIWEdZR1lHWUdZR1lHWUdZR1lHWUdY"
7806 "SFhIWEhYSFhIWEhYSFhIWEhYSFdJV0lXSVdJV0lXSlZKVkpVS1VLVUtVTFRMVExUDRkmUwgrG1IE"
7807 "ORFSAkMKUQFLBKgy");
7808 ok(match, "Figure does not match.\n");
7809 match = compare_figure(&ctx, 480, 160, 160, 160, 0xff652e89, 16,
7810 "qDICTAJQB0IHUQs4C1IRLBFSGxgbUk5STlNMVExUTFRMVExVSlZKVkpWSlZKVkpXSFhIWEhYSFhI"
7811 "WEhYSFhIWEhYSFlGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZa"
7812 "RllIWEhYSFhIWEhYSFhIWEhYSFhIV0pWSlZKVkpWSlZKVUxUTFRMVExUTFNOUk5SGxgbUhEsEVIL"
7813 "OAtRB0IHUAJMAqgy");
7814 ok(match, "Figure does not match.\n");
7816 match = compare_figure(&ctx, 0, 320, 160, 160, 0xff652e89, 16,
7817 "pCwYfixuOGNCWUxSUFBQT1JOUk5STlJOUk1UTFRMVExUTFRLVkpWSlZKVkpWSlZJWEhYSFhIWEhY"
7818 "SFhIWEhYSFhIWEdaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpG"
7819 "WkdYSFhIWEhYSFhIWEhYSFhIWEhYSVZKVkpWSlZKVkpWS1RMVExUTFRMVE1STlJOUk5STlJPUFBQ"
7820 "UkxZQmM4bix+GKQs");
7821 ok(match, "Figure does not match.\n");
7822 match = compare_figure(&ctx, 160, 320, 160, 160, 0xff652e89, 16,
7823 "liwZgQErcTllQ1xLVFBQUU9STlJNVExUTFRMVExVS1VLVUpWSlZKVkpXSVdJV0lXSVdIWEhYSFhI"
7824 "WEhYSFhIWEhYSFhIWEdZR1lHWUdZR1lHWUdZR1lHWUdZR1hIWEdZR1lHWUdZR1lHWUdZR1lHWUdZ"
7825 "R1hIWEhYSFhIWEhYSFhIWEhYSFhIV0lXSVdJV0lXSlZKVkpWSlVLVUtVTFRMVExUTFRNUk5ST1FQ"
7826 "UFRLXENlOXErgQEZliwA");
7827 ok(match, "Figure does not match.\n");
7828 match = compare_figure(&ctx, 320, 320, 160, 160, 0xff652e89, 16,
7829 "sSwZeytrOV9DVktRUE9RTlJOUk1UTFRMVExUS1VLVUtVS1ZKVkpWSVdJV0lXSVdJV0lYSFhIWEhY"
7830 "SFhIWEhYSFhIWEhYSFlHWUdZR1lHWUdZR1lHWUdZR1lIWEhYSFlHWUdZR1lHWUdZR1lHWUdZR1lI"
7831 "WEhYSFhIWEhYSFhIWEhYSFhIWElXSVdJV0lXSVdJVkpWSlZLVUtVS1VLVExUTFRMVE1STlJOUU9Q"
7832 "UUtWQ185ayt7GbEs");
7833 ok(match, "Figure does not match.\n");
7834 match = compare_figure(&ctx, 480, 320, 160, 160, 0xff652e89, 16,
7835 "pCwYfixuOGNCWUxSUFBQT1JOUk5STlJOUk1UTFRMVExUTFRLVkpWSlZKVkpWSlZJWEhYSFhIWEhY"
7836 "SFhIWEhYSFhIWEdaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpG"
7837 "WkdYSFhIWEhYSFhIWEhYSFhIWEhYSVZKVkpWSlZKVkpWS1RMVExUTFRMVE1STlJOUk5STlJPUFBQ"
7838 "UkxZQmM4bix+GKQs");
7839 ok(match, "Figure does not match.\n");
7841 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7842 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7843 hr = ID2D1PathGeometry_Open(geometry, &sink);
7844 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7846 set_point(&point, -0.402914f, 0.915514f);
7847 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7848 quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
7849 quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f);
7850 quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f);
7851 quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f);
7852 quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f);
7853 quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f);
7854 quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f);
7855 quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f);
7856 quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f);
7857 quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f);
7858 quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f);
7859 quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f);
7860 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7862 hr = ID2D1GeometrySink_Close(sink);
7863 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7864 ID2D1GeometrySink_Release(sink);
7866 set_matrix_identity(&matrix);
7867 translate_matrix(&matrix, 40.0f, 160.0f);
7868 scale_matrix(&matrix, 20.0f, 80.0f);
7869 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7870 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]);
7871 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7873 set_matrix_identity(&matrix);
7874 translate_matrix(&matrix, 160.0f, 640.0f);
7875 scale_matrix(&matrix, 40.0f, 160.0f);
7876 rotate_matrix(&matrix, M_PI / -5.0f);
7877 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7878 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]);
7879 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7880 ID2D1PathGeometry_Release(geometry);
7882 set_matrix_identity(&matrix);
7883 scale_matrix(&matrix, 0.5f, 1.0f);
7884 translate_matrix(&matrix, -80.0f, 0.0f);
7885 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7886 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
7887 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7889 set_matrix_identity(&matrix);
7890 rotate_matrix(&matrix, M_PI / 2.0f);
7891 translate_matrix(&matrix, 80.0f, -320.0f);
7892 scale_matrix(&matrix, 2.0f, 0.25f);
7893 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7894 (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]);
7895 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7897 ID2D1RenderTarget_BeginDraw(rt);
7898 ID2D1RenderTarget_Clear(rt, &color);
7899 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, NULL);
7900 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, NULL);
7901 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, NULL);
7902 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[3], (ID2D1Brush *)brush, NULL);
7903 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7904 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7905 ID2D1TransformedGeometry_Release(transformed_geometry[3]);
7906 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
7907 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
7908 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
7910 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 32,
7911 "6DMNjgEWiAEahgEahgEahgEahgEahgEahgEahgEahgEahgEahgEahwEZhwEZhwEZhwEZhwEZhwEZ"
7912 "hwEZhwEZhwEZiAEYiAEYiAEYiAEYiAEXiQEXiQEXiQEXigEWigEWigEWigEWigEWigEWigEWiwEU"
7913 "jAEUjAEUjAEUjQESjgESjwEQkAEQkQEOkgENlAEMlQEKlgEKlwEImAEImQEHmQEGmwEFmwEEnQED"
7914 "nQECngECngECnwEBnwEBnwEBnwEBnwEBnwECnQEDnQEDnQEEmwEFmgEHmQEHlwELkQERjAEXhgEd"
7915 "hAEfgwEchgEXjwEMqTEA");
7916 ok(match, "Figure does not match.\n");
7917 match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 32,
7918 "h58BBrYCDq0CF6QCIJwCKJMCMIwCNoUCPf8BQ/kBSPQBTu4BTe8BTPEBSfUBRvgBQf0BPYECOYUC"
7919 "NIoCMI4CK+UBAS0W/AEHIwiPAgsaBZcCEAwIngIepAIaqAIWrAITsAIRsgIPtQIMtwILugIHwAIB"
7920 "ypwB");
7921 ok(match, "Figure does not match.\n");
7922 match = compare_figure(&ctx, 0, 160, 160, 320, 0xff652e89, 32,
7923 "wW4DnAEEmwEFmgEHmAEIlwEKlQELlAEMkwEOkQEPkAEQkAERjgESjgETjAEUjAEUiwEWigEWiQEX"
7924 "iQEYhwEZhwEZhgEbhQEbhAEchAEdggEeggEeggEfgAEggAEggAEhgAEggAEggQEggAEggAEggQEg"
7925 "gAEggQEfgQEfggEfgQEfgQEfggEfgQEfggEeggEfggEeggEegwEdgwEeggEegwEdgwEegwEdgwEd"
7926 "hAEchAEdhAEchAEchAEdhAEchAEchQEbhQEbhgEahgEahwEZhwEZiAEYiAEYiQEYiAEYiQEXiQEX"
7927 "igEWigEWiwEViwEViwEVjAEUjAEUjQETjQETjgESjgETjgESjwERkAEQkQEPkwENlAEMlQELlgEK"
7928 "lwEKlwEJmAEImQEHmgEGmwEFnAEEnQEEnQEDnQEDngECngEDngECngECnwECngECnwECngECngED"
7929 "ngECEgGLAQMQAosBAw4EjAEDCwaMAQQJBo0BBQYIjQEHAgqNARKOARKPARCQARCQARCQAQ+RAQ6S"
7930 "AQ6SAQ2TAQ2SAQ2TAQ2TAQyTAQyUAQyUAQuUAQuVAQuUAQuVAQqWAQmWAQqWAQmXAQiXAQiYAQeY"
7931 "AQeZAQWbAQSDZwAA");
7932 ok(match, "Figure does not match.\n");
7933 match = compare_figure(&ctx, 160, 160, 320, 320, 0xff652e89, 32,
7934 "g90BBLkCCLYCC7ICDrACEa0CFKoCF6cCGqQCHKMCHqECIJ8CIpwCJJsCJpkCKJcCKZYCK5QCLZIC"
7935 "L5ACMI8CMo0CNIsCNYoCN4gCOYcCOYYCO4QCPYICPoECQIACQYACQIECQIACQIECQIECQIECP4IC"
7936 "P4ICP4ECP4ICP4ICPoMCPoMCPoMCPYQCPYMCPYQCPYQCPYQCPIUCPIUCPIUCO4YCO4YCOoYCO4YC"
7937 "OocCOocCOocCOYgCOYgCOIkCOIkCN4oCNosCNYwCNI0CM44CMo4CM44CMo8CMZACMJECL5ICLpMC"
7938 "LZQCLJUCK5YCK5YCKpcCKZgCKJkCJ5oCJpsCJpsCJZwCJJ4CIqACIKICH6MCHaUCG6cCGakCF6wC"
7939 "Fa0CE68CEbECD7MCDrQCDLYCCrgCCbkCB7sCBrsCBbwCBbwCBL0CBL0CBL0CBL0CA70CBL0CBL0C"
7940 "BLwCBSUBlgIFIQSXAgYbCJcCBxcKmQIIEQ6ZAgoMEJoCDQUTnAIknAIjnQIingIhnwIgoAIfoQIe"
7941 "ogIdowIcpAIbpQIapQIZpgIZpgIZpwIYpwIXqAIXqAIXqQIVqgIVqgIUqwITrQISrQIRrgIQsAIO"
7942 "sQIMswILtQIIhs4B");
7943 ok(match, "Figure does not match.\n");
7945 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7946 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7947 hr = ID2D1PathGeometry_Open(geometry, &sink);
7948 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7950 set_point(&point, -0.402914f, 0.915514f);
7951 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
7952 quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
7953 quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f);
7954 quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f);
7955 quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f);
7956 quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f);
7957 quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f);
7958 quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f);
7959 quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f);
7960 quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f);
7961 quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f);
7962 quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f);
7963 quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f);
7964 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7966 hr = ID2D1GeometrySink_Close(sink);
7967 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7968 ID2D1GeometrySink_Release(sink);
7970 set_matrix_identity(&matrix);
7971 translate_matrix(&matrix, 40.0f, 160.0f);
7972 scale_matrix(&matrix, 20.0f, 80.0f);
7973 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7974 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]);
7975 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7977 set_matrix_identity(&matrix);
7978 translate_matrix(&matrix, 160.0f, 640.0f);
7979 scale_matrix(&matrix, 40.0f, 160.0f);
7980 rotate_matrix(&matrix, M_PI / -5.0f);
7981 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7982 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]);
7983 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7984 ID2D1PathGeometry_Release(geometry);
7986 set_matrix_identity(&matrix);
7987 scale_matrix(&matrix, 0.5f, 1.0f);
7988 translate_matrix(&matrix, -80.0f, 0.0f);
7989 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7990 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
7991 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
7993 set_matrix_identity(&matrix);
7994 rotate_matrix(&matrix, M_PI / 2.0f);
7995 translate_matrix(&matrix, 80.0f, -320.0f);
7996 scale_matrix(&matrix, 2.0f, 0.25f);
7997 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7998 (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]);
7999 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8001 ID2D1RenderTarget_BeginDraw(rt);
8002 ID2D1RenderTarget_Clear(rt, &color);
8003 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, NULL);
8004 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, NULL);
8005 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, NULL);
8006 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[3], (ID2D1Brush *)brush, NULL);
8007 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
8008 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8009 ID2D1TransformedGeometry_Release(transformed_geometry[3]);
8010 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
8011 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
8012 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
8014 match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 0, "gMgB");
8015 ok(match, "Figure does not match.\n");
8016 match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 0, "gJAD");
8017 ok(match, "Figure does not match.\n");
8018 match = compare_figure(&ctx, 0, 160, 160, 320, 0xff652e89, 0, "gJAD");
8019 ok(match, "Figure does not match.\n");
8020 match = compare_figure(&ctx, 160, 160, 320, 320, 0xff652e89, 0, "gKAG");
8021 ok(match, "Figure does not match.\n");
8023 ID2D1SolidColorBrush_Release(brush);
8024 ID2D1Factory_Release(factory);
8025 release_test_context(&ctx);
8028 static void test_gdi_interop(BOOL d3d11)
8030 ID2D1GdiInteropRenderTarget *interop;
8031 D2D1_RENDER_TARGET_PROPERTIES desc;
8032 IWICImagingFactory *wic_factory;
8033 struct d2d1_test_context ctx;
8034 IWICBitmapLock *wic_lock;
8035 IWICBitmap *wic_bitmap;
8036 ID2D1RenderTarget *rt;
8037 ID2D1Factory *factory;
8038 D2D1_COLOR_F color;
8039 HRESULT hr;
8040 BOOL match;
8041 RECT rect;
8042 HDC dc;
8044 if (!init_test_context(&ctx, d3d11))
8045 return;
8047 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
8048 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8050 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
8051 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
8052 &IID_IWICImagingFactory, (void **)&wic_factory);
8053 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8054 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
8055 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
8056 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8057 IWICImagingFactory_Release(wic_factory);
8059 /* WIC target, default usage */
8060 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
8061 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
8062 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
8063 desc.dpiX = 0.0f;
8064 desc.dpiY = 0.0f;
8065 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
8066 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
8068 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory, wic_bitmap, &desc, &rt);
8069 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8071 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
8072 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8074 ID2D1RenderTarget_BeginDraw(rt);
8075 dc = (void *)0xdeadbeef;
8076 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
8077 ok(hr != S_OK, "Got unexpected hr %#lx.\n", hr);
8078 todo_wine ok(!dc, "Got unexpected DC %p.\n", dc);
8079 ID2D1GdiInteropRenderTarget_Release(interop);
8080 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
8081 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8083 ID2D1RenderTarget_Release(rt);
8085 /* WIC target, gdi compatible */
8086 desc.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
8088 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory, wic_bitmap, &desc, &rt);
8089 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8091 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
8092 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8094 ID2D1RenderTarget_BeginDraw(rt);
8095 dc = NULL;
8096 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
8097 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8098 ok(dc != NULL, "Expected NULL dc, got %p.\n", dc);
8099 ID2D1GdiInteropRenderTarget_ReleaseDC(interop, NULL);
8100 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
8101 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8103 ID2D1RenderTarget_BeginDraw(rt);
8104 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
8105 ID2D1RenderTarget_Clear(rt, &color);
8106 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
8107 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8109 match = compare_wic_bitmap(wic_bitmap, "54034063dbc1c1bb61cb60ec57e4498678dc2b13");
8110 ok(match, "Bitmap does not match.\n");
8112 /* Do solid fill using GDI */
8113 ID2D1RenderTarget_BeginDraw(rt);
8115 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
8116 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8118 SetRect(&rect, 0, 0, 16, 16);
8119 FillRect(dc, &rect, GetStockObject(BLACK_BRUSH));
8120 ID2D1GdiInteropRenderTarget_ReleaseDC(interop, NULL);
8122 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
8123 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8125 match = compare_wic_bitmap(wic_bitmap, "60cacbf3d72e1e7834203da608037b1bf83b40e8");
8126 ok(match, "Bitmap does not match.\n");
8128 /* Bitmap is locked at BeginDraw(). */
8129 hr = IWICBitmap_Lock(wic_bitmap, NULL, WICBitmapLockRead, &wic_lock);
8130 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8131 IWICBitmapLock_Release(wic_lock);
8133 ID2D1RenderTarget_BeginDraw(rt);
8134 hr = IWICBitmap_Lock(wic_bitmap, NULL, WICBitmapLockRead, &wic_lock);
8135 todo_wine ok(hr == WINCODEC_ERR_ALREADYLOCKED, "Got unexpected hr %#lx.\n", hr);
8136 if (SUCCEEDED(hr))
8137 IWICBitmapLock_Release(wic_lock);
8138 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
8139 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8141 /* Lock before BeginDraw(). */
8142 hr = IWICBitmap_Lock(wic_bitmap, NULL, WICBitmapLockRead, &wic_lock);
8143 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8144 ID2D1RenderTarget_BeginDraw(rt);
8145 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
8146 todo_wine ok(hr == WINCODEC_ERR_ALREADYLOCKED, "Got unexpected hr %#lx.\n", hr);
8147 IWICBitmapLock_Release(wic_lock);
8149 ID2D1GdiInteropRenderTarget_Release(interop);
8150 ID2D1RenderTarget_Release(rt);
8152 IWICBitmap_Release(wic_bitmap);
8153 ID2D1Factory_Release(factory);
8154 release_test_context(&ctx);
8157 static void test_layer(BOOL d3d11)
8159 ID2D1Factory *factory, *layer_factory;
8160 struct d2d1_test_context ctx;
8161 ID2D1RenderTarget *rt;
8162 ID2D1Layer *layer;
8163 D2D1_SIZE_F size;
8164 HRESULT hr;
8166 if (!init_test_context(&ctx, d3d11))
8167 return;
8169 rt = ctx.rt;
8170 ID2D1RenderTarget_GetFactory(rt, &factory);
8172 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
8173 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
8175 hr = ID2D1RenderTarget_CreateLayer(rt, NULL, &layer);
8176 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8177 ID2D1Layer_GetFactory(layer, &layer_factory);
8178 ok(layer_factory == factory, "Got unexpected layer factory %p, expected %p.\n", layer_factory, factory);
8179 ID2D1Factory_Release(layer_factory);
8180 size = ID2D1Layer_GetSize(layer);
8181 ok(size.width == 0.0f, "Got unexpected width %.8e.\n", size.width);
8182 ok(size.height == 0.0f, "Got unexpected height %.8e.\n", size.height);
8183 ID2D1Layer_Release(layer);
8185 set_size_f(&size, 800.0f, 600.0f);
8186 hr = ID2D1RenderTarget_CreateLayer(rt, &size, &layer);
8187 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8188 size = ID2D1Layer_GetSize(layer);
8189 ok(size.width == 800.0f, "Got unexpected width %.8e.\n", size.width);
8190 ok(size.height == 600.0f, "Got unexpected height %.8e.\n", size.height);
8191 ID2D1Layer_Release(layer);
8193 ID2D1Factory_Release(factory);
8194 release_test_context(&ctx);
8197 static void test_bezier_intersect(BOOL d3d11)
8199 D2D1_POINT_2F point = {0.0f, 0.0f};
8200 struct d2d1_test_context ctx;
8201 ID2D1SolidColorBrush *brush;
8202 ID2D1PathGeometry *geometry;
8203 ID2D1GeometrySink *sink;
8204 ID2D1RenderTarget *rt;
8205 ID2D1Factory *factory;
8206 D2D1_COLOR_F color;
8207 HRESULT hr;
8208 BOOL match;
8210 if (!init_test_context(&ctx, d3d11))
8211 return;
8213 rt = ctx.rt;
8214 ID2D1RenderTarget_GetFactory(rt, &factory);
8216 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
8217 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
8218 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
8219 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
8220 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8222 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
8223 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8224 hr = ID2D1PathGeometry_Open(geometry, &sink);
8225 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8227 set_point(&point, 160.0f, 720.0f);
8228 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
8229 cubic_to(sink, 119.0f, 720.0f, 83.0f, 600.0f, 80.0f, 474.0f);
8230 cubic_to(sink, 78.0f, 349.0f, 108.0f, 245.0f, 135.0f, 240.0f);
8231 cubic_to(sink, 163.0f, 235.0f, 180.0f, 318.0f, 176.0f, 370.0f);
8232 cubic_to(sink, 171.0f, 422.0f, 149.0f, 422.0f, 144.0f, 370.0f);
8233 cubic_to(sink, 140.0f, 318.0f, 157.0f, 235.0f, 185.0f, 240.0f);
8234 cubic_to(sink, 212.0f, 245.0f, 242.0f, 349.0f, 240.0f, 474.0f);
8235 cubic_to(sink, 238.0f, 600.0f, 201.0f, 720.0f, 160.0f, 720.0f);
8236 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
8238 set_point(&point, 160.0f, 240.0f);
8239 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
8240 line_to(sink, 240.0f, 240.0f);
8241 line_to(sink, 240.0f, 720.0f);
8242 line_to(sink, 160.0f, 720.0f);
8243 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
8245 hr = ID2D1GeometrySink_Close(sink);
8246 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8247 ID2D1GeometrySink_Release(sink);
8249 ID2D1RenderTarget_BeginDraw(rt);
8250 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
8251 ID2D1RenderTarget_Clear(rt, &color);
8252 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
8253 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
8254 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8255 ID2D1PathGeometry_Release(geometry);
8257 match = compare_figure(&ctx, 160, 120, 320, 240, 0xff652e89, 2048,
8258 "aRQjIxRpYiIcHCJiXSwXFyxdWTQTEzRZVTsQEDtVUkIMDEJST0cKCkdPTUsICEtNSlEFBVFKSFUD"
8259 "A1VIRlkBAVlGRFsBAVtEQlwCAlxCQFwEBFxAPl0FBV0+PF0HB108Ol4ICF46OV0KCl05N14LC143"
8260 "Nl4MDF42NF8NDV80M14PD14zMV8QEF8xMF8REV8wL18SEl8vLWATE2AtLGAUFGAsK2EUFGErKWIV"
8261 "FWIpKGIWFmIoJ2IXF2InJmIYGGImJWMYGGMlJGMZGWMkI2MaGmMjImQaGmQiIWQbG2QhIGQcHGQg"
8262 "H2UcHGUfHmUdHWUeHWYdHWYdHGcdHWccG2ceHmcbGmgeHmgaGWgfH2gZGWgfH2gZGGkfH2kYF2kg"
8263 "IGkXFmogIGoWFmogIGoWFWsgIGsVFGshIWsUE2whIWwTE2whIWwTEm0hIW0SEW4hIW4REW4hIW4R"
8264 "EG8hIW8QD3AhIXAPD3AhIXAPDnEhIXEODnEhIXEODXIhIXINDHQgIHQMDHQgIHQMC3UgIHULC3Yf"
8265 "H3YLCncfH3cKCngeHngKCXkeHnkJCXodHXoJCXscHHsJCHwcHHwICH0bG30IB38aGn8HB4ABGRmA"
8266 "AQcHgQEYGIEBBwaEARYWhAEGBoUBFRWFAQYFiAETE4gBBQWKARERigEFBYwBDw+MAQUEkAEMDJAB"
8267 "BASTAQkJkwEEBJwBnAEEA50BnQEDA50BnQEDA50BnQEDA50BnQEDAp4BngECAp4BngECAp4BngEC"
8268 "Ap4BngECAp4BngECAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwGhAaAB"
8269 "oAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGg"
8270 "AaABoAGgAaABoAGgAaABoAGhAZ8BoQGfAZ8BAQGfAZ8BAQGfAZ8BAQGfAZ8BAQGfAZ8BAQKeAZ8B"
8271 "AQKeAZ4BAgKeAZ4BAgKeAZ4BAgOdAZ4BAgOdAZ4BAgOdAZ0BAwScAZ0BAwScAZ0BAwScAZ0BAwSc"
8272 "AZwBBAWbAZwBBAWbAZwBBAWbAZsBBQaaAZsBBQaaAZoBBgeZAZoBBgeZAZoBBgeZAZkBBwiYAZkB"
8273 "BwiYAZgBCAmXAZgBCAmXAZgBCAmXAZcBCQqWAZcBCQqWAZYBCguVAZYBCguVAZUBCwyUAZUBCw2T"
8274 "AZQBDA2TAZQBDA6SAZMBDQ6SAZMBDQ+RAZIBDg+RAZIBDhCQAZEBDxCQAZABEBGPAZABEBKOAY8B"
8275 "ERONAY4BEhONAY4BEhSMAY0BExWLAYwBFBWLAYwBFBaKAYsBFReJAYoBFheJAYoBFhiIAYkBFxmH"
8276 "AYgBGBqGAYcBGRuFAYYBGhuFAYUBGxyEAYUBGx2DAYQBHB6CAYMBHR+BAYIBHiCAAYEBHyF/gAEg"
8277 "In5/ISJ+fiIjfX0jJHx8JCV7eyUmenomJ3l5Jyh4eCgpd3cpK3V2Kix0dSstc3QsLnJzLS9xci4w"
8278 "cHAwMm5vMTNtbjI0bG0zNWtrNTdpajY4aGk3OmZnOTtlZjo8ZGQ8PmJjPT9hYj5BX2BAQl5eQkRc"
8279 "XUNGWltFR1lZR0lXWEhLVVZKTVNUTE9RUk5RT1BQUk5OUlRMTFRWSkpWWUdIWFtFRVteQkNdYEBA"
8280 "YGI+PmJlOztlaDg4aGs1NWtuMjJuci4vcXUrK3V6JiZ6fiIifoMBHR2DAYsBFRWLAZUBCwuVAQAA");
8281 ok(match, "Figure does not match.\n");
8283 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
8284 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8285 hr = ID2D1PathGeometry_Open(geometry, &sink);
8286 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8288 set_point(&point, 240.0f, 720.0f);
8289 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
8290 cubic_to(sink, 152.0f, 720.0f, 80.0f, 613.0f, 80.0f, 480.0f);
8291 cubic_to(sink, 80.0f, 347.0f, 152.0f, 240.0f, 240.0f, 240.0f);
8292 cubic_to(sink, 152.0f, 339.0f, 134.0f, 528.0f, 200.0f, 660.0f);
8293 cubic_to(sink, 212.0f, 683.0f, 225.0f, 703.0f, 240.0f, 720.0f);
8294 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
8296 hr = ID2D1GeometrySink_Close(sink);
8297 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8298 ID2D1GeometrySink_Release(sink);
8300 ID2D1RenderTarget_BeginDraw(rt);
8301 ID2D1RenderTarget_Clear(rt, &color);
8302 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
8303 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
8304 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8305 ID2D1PathGeometry_Release(geometry);
8307 match = compare_figure(&ctx, 160, 120, 320, 240, 0xff652e89, 2048,
8308 "pQIZkgIrhAI5/QE/9gFH7wFO6wFS5wFW4gFb3gFf2wFi2AFl1gFn1AFp0gFszwFuzQFxywFyyQF1"
8309 "xwF2xgF4xAF5xAF6wgF8wAF+vwF+vwF/vQGBAbwBggG7AYMBugGEAbkBhQG4AYYBtwGHAbcBiAG1"
8310 "AYkBtAGKAbQBigGzAYsBswGMAbEBjQGxAY0BsQGOAa8BjwGvAZABrgGQAa4BkQGtAZEBrQGSAawB"
8311 "kgGsAZMBqwGTAasBlAGrAZQBqgGVAakBlQGqAZUBqQGWAagBlwGoAZYBqAGXAagBlwGnAZgBpwGY"
8312 "AaYBmQGmAZkBpgGZAaUBmgGlAZoBpQGaAaUBmgGkAZsBpAGbAaQBmwGkAZsBpAGcAaMBnAGjAZwB"
8313 "owGcAaMBnAGjAZ0BogGdAaIBnQGiAZ4BoQGeAaEBngGiAZ4BoQGeAaEBnwGgAZ8BoQGeAaEBnwGh"
8314 "AZ4BoQGfAaABnwGhAZ8BoAGgAaABnwGgAaABoAGfAaABoAGgAaABnwGgAaABoAGgAaABnwGgAaAB"
8315 "oAGgAaABnwGhAZ8BoQGfAaABoAGgAaABoAGfAaEBnwGhAZ8BoQGfAaEBnwGhAZ8BoQGfAaABoAGg"
8316 "AaABoAGgAaEBnwGhAZ8BoQGfAaEBnwGhAaABoAGgAaABoAGgAaABoAGgAaEBoAGgAaABoAGgAaAB"
8317 "oQGgAaABoAGgAaABoQGfAaEBoAGhAZ8BoQGfAaIBnwGhAZ8BogGfAaEBnwGiAZ8BogGeAaIBnwGi"
8318 "AZ4BogGfAaIBngGjAZ4BowGdAaMBngGjAZ4BowGdAaQBnQGkAZ0BpAGcAaUBnAGlAZwBpQGcAaUB"
8319 "mwGmAZsBpgGbAaYBmwGmAZsBpgGbAacBmgGnAZkBqAGZAagBmQGpAZgBqQGZAagBmQGpAZgBqQGY"
8320 "AaoBlwGqAZcBqwGWAasBlgGsAZUBrQGVAawBlQGtAZQBrgGUAa0BlAGuAZMBrwGTAa8BkgGwAZEB"
8321 "sQGRAbEBkAGyAZABsgGPAbMBjwG0AY4BtAGNAbUBjQG2AYwBtgGLAbgBigG4AYoBuQGJAboBhwG7"
8322 "AYcBvAGGAb0BhQG+AYQBvwGDAcABggHBAYIBwgGAAcMBf8QBfsYBfMgBe8gBesoBeMwBd80BddAB"
8323 "c9EBcdQBb9YBbNkBatsBaN0BZeEBYuQBX+gBW+0BVvEBUvUBTvwBR4QCQIoCOZgCK6oCGQIA");
8324 ok(match, "Figure does not match.\n");
8326 ID2D1SolidColorBrush_Release(brush);
8327 ID2D1Factory_Release(factory);
8328 release_test_context(&ctx);
8331 static void test_create_device(BOOL d3d11)
8333 D2D1_CREATION_PROPERTIES properties = {0};
8334 struct d2d1_test_context ctx;
8335 ID2D1Factory1 *factory;
8336 ID2D1Factory *factory2;
8337 ID2D1Device *device;
8338 ULONG refcount;
8339 HRESULT hr;
8341 if (!init_test_context(&ctx, d3d11))
8342 return;
8344 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
8346 win_skip("ID2D1Factory1 is not supported.\n");
8347 release_test_context(&ctx);
8348 return;
8351 hr = ID2D1Factory1_CreateDevice(factory, ctx.device, &device);
8352 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8354 ID2D1Device_GetFactory(device, &factory2);
8355 ok(factory2 == (ID2D1Factory *)factory, "Got unexpected factory %p, expected %p.\n", factory2, factory);
8356 ID2D1Factory_Release(factory2);
8357 ID2D1Device_Release(device);
8359 if (pD2D1CreateDevice)
8361 hr = pD2D1CreateDevice(ctx.device, NULL, &device);
8362 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8363 ID2D1Device_Release(device);
8365 hr = pD2D1CreateDevice(ctx.device, &properties, &device);
8366 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8367 ID2D1Device_Release(device);
8369 else
8370 win_skip("D2D1CreateDevice() is unavailable.\n");
8372 release_test_context(&ctx);
8374 refcount = ID2D1Factory1_Release(factory);
8375 ok(!refcount, "Factory has %lu references left.\n", refcount);
8378 #define check_rt_bitmap_surface(r, s, o) check_rt_bitmap_surface_(__LINE__, r, s, o)
8379 static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, BOOL has_surface, DWORD options)
8381 ID2D1BitmapRenderTarget *compatible_rt;
8382 D2D1_BITMAP_PROPERTIES bitmap_desc;
8383 IWICImagingFactory *wic_factory;
8384 ID2D1Bitmap *bitmap, *bitmap2;
8385 ID2D1DeviceContext *context;
8386 ID2D1DCRenderTarget *dc_rt;
8387 IWICBitmap *wic_bitmap;
8388 ID2D1Image *target;
8389 D2D1_SIZE_U size;
8390 HRESULT hr;
8392 static const DWORD bitmap_data[] =
8394 0x7f7f0000,
8397 /* Raw data bitmap. */
8398 set_size_u(&size, 1, 1);
8399 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
8400 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
8401 bitmap_desc.dpiX = 96.0f;
8402 bitmap_desc.dpiY = 96.0f;
8403 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, sizeof(*bitmap_data), &bitmap_desc, &bitmap);
8404 ok_(__FILE__, line)(hr == S_OK, "Failed to create bitmap, hr %#lx.\n", hr);
8406 check_bitmap_surface_(line, bitmap, has_surface, options);
8408 ID2D1Bitmap_Release(bitmap);
8410 /* Zero sized bitmaps. */
8411 set_size_u(&size, 0, 0);
8412 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
8413 ok_(__FILE__, line)(hr == S_OK, "Failed to create bitmap, hr %#lx.\n", hr);
8414 check_bitmap_surface_(line, bitmap, has_surface, options);
8415 ID2D1Bitmap_Release(bitmap);
8417 set_size_u(&size, 2, 0);
8418 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
8419 ok_(__FILE__, line)(hr == S_OK, "Failed to create bitmap, hr %#lx.\n", hr);
8420 check_bitmap_surface_(line, bitmap, has_surface, options);
8421 ID2D1Bitmap_Release(bitmap);
8423 set_size_u(&size, 0, 2);
8424 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
8425 ok_(__FILE__, line)(hr == S_OK, "Failed to create bitmap, hr %#lx.\n", hr);
8426 check_bitmap_surface_(line, bitmap, has_surface, options);
8427 ID2D1Bitmap_Release(bitmap);
8429 /* WIC bitmap. */
8430 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
8432 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
8433 &IID_IWICImagingFactory, (void **)&wic_factory);
8434 ok_(__FILE__, line)(hr == S_OK, "Failed to create WIC imaging factory, hr %#lx.\n", hr);
8436 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
8437 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
8438 ok_(__FILE__, line)(hr == S_OK, "Failed to create WIC bitmap, hr %#lx.\n", hr);
8439 IWICImagingFactory_Release(wic_factory);
8441 hr = ID2D1RenderTarget_CreateBitmapFromWicBitmap(rt, (IWICBitmapSource *)wic_bitmap, NULL, &bitmap);
8442 ok_(__FILE__, line)(hr == S_OK, "Failed to create bitmap from WIC source, hr %#lx.\n", hr);
8444 check_bitmap_surface_(line, bitmap, has_surface, options);
8446 ID2D1Bitmap_Release(bitmap);
8448 CoUninitialize();
8450 /* Compatible target follows its parent. */
8451 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&context);
8452 ok_(__FILE__, line)(hr == S_OK, "Failed to get device context, hr %#lx.\n", hr);
8454 dc_rt = NULL;
8455 ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DCRenderTarget, (void **)&dc_rt);
8457 bitmap = NULL;
8458 target = NULL;
8459 ID2D1DeviceContext_GetTarget(context, &target);
8460 if (target && FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
8462 ID2D1Image_Release(target);
8463 target = NULL;
8465 if (bitmap)
8467 D2D1_PIXEL_FORMAT rt_format, bitmap_format;
8469 rt_format = ID2D1RenderTarget_GetPixelFormat(rt);
8470 bitmap_format = ID2D1Bitmap_GetPixelFormat(bitmap);
8471 ok_(__FILE__, line)(!memcmp(&rt_format, &bitmap_format, sizeof(rt_format)), "Unexpected bitmap format.\n");
8473 ID2D1Bitmap_Release(bitmap);
8476 /* Pixel format is not defined until target is set, for DC target it's specified on creation. */
8477 if (target || dc_rt)
8479 ID2D1Device *device, *device2;
8480 ID2D1DeviceContext *context2;
8482 ID2D1DeviceContext_GetDevice(context, &device);
8484 hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, NULL, NULL, NULL,
8485 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &compatible_rt);
8486 ok_(__FILE__, line)(hr == S_OK, "Failed to create compatible render target, hr %#lx.\n", hr);
8488 hr = ID2D1BitmapRenderTarget_QueryInterface(compatible_rt, &IID_ID2D1DeviceContext, (void **)&context2);
8489 ok_(__FILE__, line)(hr == S_OK, "Failed to get device context, hr %#lx.\n", hr);
8491 ID2D1DeviceContext_GetDevice(context2, &device2);
8492 ok_(__FILE__, line)(device == device2, "Unexpected device.\n");
8494 ID2D1Device_Release(device);
8495 ID2D1Device_Release(device2);
8497 hr = ID2D1BitmapRenderTarget_CreateBitmap(compatible_rt, size,
8498 bitmap_data, sizeof(*bitmap_data), &bitmap_desc, &bitmap);
8499 ok_(__FILE__, line)(hr == S_OK, "Failed to create bitmap, hr %#lx.\n", hr);
8500 check_bitmap_surface_(line, bitmap, has_surface, options);
8501 ID2D1Bitmap_Release(bitmap);
8503 hr = ID2D1BitmapRenderTarget_GetBitmap(compatible_rt, &bitmap);
8504 ok_(__FILE__, line)(hr == S_OK, "Failed to get compatible target bitmap, hr %#lx.\n", hr);
8506 bitmap2 = NULL;
8507 ID2D1DeviceContext_GetTarget(context2, (ID2D1Image **)&bitmap2);
8508 ok_(__FILE__, line)(bitmap2 == bitmap, "Unexpected bitmap.\n");
8510 check_bitmap_surface_(line, bitmap, has_surface, D2D1_BITMAP_OPTIONS_TARGET);
8511 ID2D1Bitmap_Release(bitmap2);
8512 ID2D1Bitmap_Release(bitmap);
8514 ID2D1BitmapRenderTarget_Release(compatible_rt);
8515 ID2D1DeviceContext_Release(context2);
8517 else
8519 hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, NULL, NULL, NULL,
8520 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &compatible_rt);
8521 ok_(__FILE__, line)(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT, "Unexpected hr %#lx.\n", hr);
8524 ID2D1DeviceContext_Release(context);
8525 if (target)
8526 ID2D1Image_Release(target);
8527 if (dc_rt)
8528 ID2D1DCRenderTarget_Release(dc_rt);
8531 static IDXGISurface *create_surface(IDXGIDevice *dxgi_device, DXGI_FORMAT format)
8533 D3D10_TEXTURE2D_DESC texture_desc;
8534 ID3D10Texture2D *texture;
8535 ID3D10Device *d3d_device;
8536 IDXGISurface *surface;
8537 HRESULT hr;
8539 texture_desc.Width = 1;
8540 texture_desc.Height = 1;
8541 texture_desc.MipLevels = 1;
8542 texture_desc.ArraySize = 1;
8543 texture_desc.Format = format;
8544 texture_desc.SampleDesc.Count = 1;
8545 texture_desc.SampleDesc.Quality = 0;
8546 texture_desc.Usage = D3D10_USAGE_DEFAULT;
8547 texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
8548 texture_desc.CPUAccessFlags = 0;
8549 texture_desc.MiscFlags = 0;
8551 hr = IDXGIDevice_QueryInterface(dxgi_device, &IID_ID3D10Device, (void **)&d3d_device);
8552 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8554 hr = ID3D10Device_CreateTexture2D(d3d_device, &texture_desc, NULL, &texture);
8555 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8557 hr = ID3D10Texture2D_QueryInterface(texture, &IID_IDXGISurface, (void **)&surface);
8558 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8560 ID3D10Device_Release(d3d_device);
8561 ID3D10Texture2D_Release(texture);
8563 return surface;
8566 static void test_bitmap_surface(BOOL d3d11)
8568 static const struct bitmap_format_test
8570 D2D1_PIXEL_FORMAT original;
8571 D2D1_PIXEL_FORMAT result;
8572 HRESULT hr;
8574 bitmap_format_tests[] =
8576 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
8577 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED } },
8579 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
8581 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE },
8582 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
8584 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
8586 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
8588 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE },
8589 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
8591 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
8593 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
8594 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
8595 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
8596 ID2D1DeviceContext *device_context;
8597 IDXGISurface *surface2;
8598 D2D1_PIXEL_FORMAT pixel_format;
8599 struct d2d1_test_context ctx;
8600 ID2D1Factory1 *factory;
8601 ID2D1RenderTarget *rt;
8602 ID2D1Bitmap1 *bitmap;
8603 ID2D1Device *device;
8604 ID2D1Image *target;
8605 D2D1_SIZE_U size;
8606 D2D1_TAG t1, t2;
8607 unsigned int i;
8608 HRESULT hr;
8610 IWICBitmap *wic_bitmap;
8611 IWICImagingFactory *wic_factory;
8613 if (!init_test_context(&ctx, d3d11))
8614 return;
8616 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
8618 win_skip("ID2D1Factory1 is not supported.\n");
8619 release_test_context(&ctx);
8620 return;
8623 /* DXGI target */
8624 hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8625 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8627 bitmap = NULL;
8628 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8629 ok(!!bitmap, "Unexpected target.\n");
8630 check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW);
8631 ID2D1Bitmap1_Release(bitmap);
8633 check_rt_bitmap_surface(ctx.rt, TRUE, D2D1_BITMAP_OPTIONS_NONE);
8635 ID2D1DeviceContext_Release(device_context);
8637 /* Bitmap created from DXGI surface. */
8638 hr = ID2D1Factory1_CreateDevice(factory, ctx.device, &device);
8639 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8641 hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &device_context);
8642 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8644 for (i = 0; i < ARRAY_SIZE(bitmap_format_tests); ++i)
8646 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
8647 bitmap_desc.pixelFormat = bitmap_format_tests[i].original;
8648 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
8650 hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, ctx.surface, &bitmap_desc, &bitmap);
8651 todo_wine_if(bitmap_format_tests[i].hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT)
8652 ok(hr == bitmap_format_tests[i].hr, "%u: Got unexpected hr %#lx.\n", i, hr);
8654 if (SUCCEEDED(bitmap_format_tests[i].hr))
8656 pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap);
8658 ok(pixel_format.format == bitmap_format_tests[i].result.format, "%u: unexpected pixel format %#x.\n",
8659 i, pixel_format.format);
8660 ok(pixel_format.alphaMode == bitmap_format_tests[i].result.alphaMode, "%u: unexpected alpha mode %d.\n",
8661 i, pixel_format.alphaMode);
8663 ID2D1Bitmap1_Release(bitmap);
8667 /* A8 surface */
8668 surface2 = create_surface(ctx.device, DXGI_FORMAT_A8_UNORM);
8670 hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, surface2, NULL, &bitmap);
8671 ok(hr == S_OK || broken(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT) /* Win7 */,
8672 "Got unexpected hr %#lx.\n", hr);
8674 if (SUCCEEDED(hr))
8676 pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap);
8677 ok(pixel_format.alphaMode == D2D1_ALPHA_MODE_PREMULTIPLIED,
8678 "Unexpected alpha mode %#x.\n", pixel_format.alphaMode);
8680 ID2D1Bitmap1_Release(bitmap);
8683 IDXGISurface_Release(surface2);
8685 hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, ctx.surface, NULL, &bitmap);
8686 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8688 pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap);
8689 ok(pixel_format.alphaMode == D2D1_ALPHA_MODE_PREMULTIPLIED,
8690 "Unexpected alpha mode %#x.\n", pixel_format.alphaMode);
8692 check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW);
8693 check_rt_bitmap_surface((ID2D1RenderTarget *)device_context, TRUE, D2D1_BITMAP_OPTIONS_NONE);
8695 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
8696 ID2D1DeviceContext_GetTarget(device_context, &target);
8697 ok(target == (ID2D1Image *)bitmap, "Unexpected target.\n");
8699 check_rt_bitmap_surface((ID2D1RenderTarget *)device_context, TRUE, D2D1_BITMAP_OPTIONS_NONE);
8701 ID2D1Bitmap1_Release(bitmap);
8703 /* Without D2D1_BITMAP_OPTIONS_TARGET. */
8704 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
8705 bitmap_desc.pixelFormat = ID2D1DeviceContext_GetPixelFormat(device_context);
8706 size.width = size.height = 4;
8707 hr = ID2D1DeviceContext_CreateBitmap(device_context, size, NULL, 0, &bitmap_desc, &bitmap);
8708 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8709 check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_NONE);
8710 ID2D1DeviceContext_SetTags(device_context, 1, 2);
8712 ID2D1DeviceContext_BeginDraw(device_context);
8713 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
8714 hr = ID2D1DeviceContext_EndDraw(device_context, &t1, &t2);
8715 ok(hr == D2DERR_INVALID_TARGET, "Got unexpected hr %#lx.\n", hr);
8716 ok(t1 == 1 && t2 == 2, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
8718 ID2D1Bitmap1_Release(bitmap);
8720 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8721 ok(!!bitmap, "Expected target bitmap.\n");
8722 ID2D1Bitmap1_Release(bitmap);
8724 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET;
8725 hr = ID2D1DeviceContext_CreateBitmap(device_context, size, NULL, 0, &bitmap_desc, &bitmap);
8726 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8727 check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET);
8728 ID2D1DeviceContext_SetTarget(device_context, NULL);
8729 ID2D1DeviceContext_SetTags(device_context, 3, 4);
8731 ID2D1DeviceContext_BeginDraw(device_context);
8732 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
8733 hr = ID2D1DeviceContext_EndDraw(device_context, &t1, &t2);
8734 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8735 ok(!t1 && !t2, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
8737 ID2D1Bitmap1_Release(bitmap);
8739 ID2D1DeviceContext_Release(device_context);
8741 ID2D1Device_Release(device);
8743 /* DC target */
8744 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
8745 rt_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
8746 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
8747 rt_desc.dpiX = 96.0f;
8748 rt_desc.dpiY = 96.0f;
8749 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
8750 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
8751 hr = ID2D1Factory1_CreateDCRenderTarget(factory, &rt_desc, (ID2D1DCRenderTarget **)&rt);
8752 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8754 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8755 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8757 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8758 ok(!bitmap, "Unexpected target.\n");
8760 ID2D1DeviceContext_Release(device_context);
8761 ID2D1RenderTarget_Release(rt);
8763 /* HWND target */
8764 hwnd_rt_desc.hwnd = NULL;
8765 hwnd_rt_desc.pixelSize.width = 64;
8766 hwnd_rt_desc.pixelSize.height = 64;
8767 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
8768 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
8769 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
8771 hr = ID2D1Factory1_CreateHwndRenderTarget(factory, &rt_desc, &hwnd_rt_desc, (ID2D1HwndRenderTarget **)&rt);
8772 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8774 check_rt_bitmap_surface(rt, FALSE, D2D1_BITMAP_OPTIONS_NONE);
8775 ID2D1RenderTarget_Release(rt);
8776 DestroyWindow(hwnd_rt_desc.hwnd);
8778 /* WIC target */
8779 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
8781 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
8782 &IID_IWICImagingFactory, (void **)&wic_factory);
8783 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8784 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
8785 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
8786 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8787 IWICImagingFactory_Release(wic_factory);
8789 hr = ID2D1Factory1_CreateWicBitmapRenderTarget(factory, wic_bitmap, &rt_desc, &rt);
8790 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8792 check_rt_bitmap_surface(rt, FALSE, D2D1_BITMAP_OPTIONS_NONE);
8793 ID2D1RenderTarget_Release(rt);
8795 CoUninitialize();
8797 ID2D1Factory1_Release(factory);
8798 release_test_context(&ctx);
8801 static void test_device_context(BOOL d3d11)
8803 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
8804 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
8805 ID2D1DeviceContext *device_context;
8806 IDXGISurface *surface, *surface2;
8807 ID2D1Device *device, *device2;
8808 struct d2d1_test_context ctx;
8809 D2D1_BITMAP_OPTIONS options;
8810 ID2D1DCRenderTarget *dc_rt;
8811 D2D1_UNIT_MODE unit_mode;
8812 ID2D1Factory1 *factory;
8813 ID2D1RenderTarget *rt;
8814 ID2D1Bitmap1 *bitmap;
8815 ID2D1Image *target;
8816 HRESULT hr;
8817 RECT rect;
8818 HDC hdc;
8820 IWICBitmap *wic_bitmap;
8821 IWICImagingFactory *wic_factory;
8823 if (!init_test_context(&ctx, d3d11))
8824 return;
8826 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
8828 win_skip("ID2D1Factory1 is not supported.\n");
8829 release_test_context(&ctx);
8830 return;
8833 hr = ID2D1Factory1_CreateDevice(factory, ctx.device, &device);
8834 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8836 hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &device_context);
8837 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8839 ID2D1DeviceContext_GetDevice(device_context, &device2);
8840 ok(device2 == device, "Unexpected device instance.\n");
8841 ID2D1Device_Release(device2);
8843 target = (void *)0xdeadbeef;
8844 ID2D1DeviceContext_GetTarget(device_context, &target);
8845 ok(target == NULL, "Unexpected target instance %p.\n", target);
8847 unit_mode = ID2D1DeviceContext_GetUnitMode(device_context);
8848 ok(unit_mode == D2D1_UNIT_MODE_DIPS, "Unexpected unit mode %d.\n", unit_mode);
8850 ID2D1DeviceContext_Release(device_context);
8852 /* DXGI target */
8853 rt = ctx.rt;
8854 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8855 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8856 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8857 options = ID2D1Bitmap1_GetOptions(bitmap);
8858 ok(options == (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW),
8859 "Unexpected bitmap options %#x.\n", options);
8860 hr = ID2D1Bitmap1_GetSurface(bitmap, &surface2);
8861 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8862 ok(surface2 == ctx.surface, "Unexpected surface instance.\n");
8863 IDXGISurface_Release(surface2);
8865 ID2D1DeviceContext_BeginDraw(device_context);
8866 hr = ID2D1Bitmap1_GetSurface(bitmap, &surface2);
8867 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8868 ok(surface2 == ctx.surface, "Unexpected surface instance.\n");
8869 IDXGISurface_Release(surface2);
8870 ID2D1DeviceContext_EndDraw(device_context, NULL, NULL);
8871 ID2D1Bitmap1_Release(bitmap);
8873 ID2D1DeviceContext_SetTarget(device_context, NULL);
8874 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8875 ok(bitmap == NULL, "Unexpected target instance.\n");
8877 ID2D1DeviceContext_Release(device_context);
8879 /* WIC target */
8880 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
8882 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
8883 &IID_IWICImagingFactory, (void **)&wic_factory);
8884 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8885 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
8886 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
8887 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8888 IWICImagingFactory_Release(wic_factory);
8890 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
8891 rt_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
8892 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
8893 rt_desc.dpiX = 96.0f;
8894 rt_desc.dpiY = 96.0f;
8895 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
8896 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
8897 hr = ID2D1Factory1_CreateWicBitmapRenderTarget(factory, wic_bitmap, &rt_desc, &rt);
8898 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8900 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8901 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8902 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8903 options = ID2D1Bitmap1_GetOptions(bitmap);
8904 ok(options == (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW),
8905 "Unexpected bitmap options %#x.\n", options);
8906 hr = ID2D1Bitmap1_GetSurface(bitmap, &surface);
8907 todo_wine ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
8908 ID2D1Bitmap1_Release(bitmap);
8910 ID2D1DeviceContext_SetTarget(device_context, NULL);
8911 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8912 ok(bitmap == NULL, "Unexpected target instance.\n");
8914 ID2D1DeviceContext_Release(device_context);
8915 ID2D1RenderTarget_Release(rt);
8917 CoUninitialize();
8919 /* HWND target */
8920 hwnd_rt_desc.hwnd = NULL;
8921 hwnd_rt_desc.pixelSize.width = 64;
8922 hwnd_rt_desc.pixelSize.height = 64;
8923 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
8924 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
8925 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
8927 hr = ID2D1Factory1_CreateHwndRenderTarget(factory, &rt_desc, &hwnd_rt_desc, (ID2D1HwndRenderTarget **)&rt);
8928 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8930 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8931 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8932 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8933 options = ID2D1Bitmap1_GetOptions(bitmap);
8934 ok(options == (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW),
8935 "Unexpected bitmap options %#x.\n", options);
8936 hr = ID2D1Bitmap1_GetSurface(bitmap, &surface);
8937 ok(hr == D2DERR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr);
8938 ID2D1Bitmap1_Release(bitmap);
8940 ID2D1DeviceContext_SetTarget(device_context, NULL);
8941 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8942 ok(bitmap == NULL, "Unexpected target instance.\n");
8944 ID2D1DeviceContext_Release(device_context);
8945 ID2D1RenderTarget_Release(rt);
8946 DestroyWindow(hwnd_rt_desc.hwnd);
8948 /* DC target */
8949 hr = ID2D1Factory1_CreateDCRenderTarget(factory, &rt_desc, &dc_rt);
8950 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8952 hr = ID2D1DCRenderTarget_QueryInterface(dc_rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8953 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8954 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8955 ok(bitmap == NULL, "Unexpected bitmap instance.\n");
8957 hdc = CreateCompatibleDC(NULL);
8958 ok(hdc != NULL, "Failed to create an HDC.\n");
8960 create_target_dibsection(hdc, 16, 16);
8962 SetRect(&rect, 0, 0, 16, 16);
8963 hr = ID2D1DCRenderTarget_BindDC(dc_rt, hdc, &rect);
8964 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8966 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8967 options = ID2D1Bitmap1_GetOptions(bitmap);
8968 ok(options == (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE),
8969 "Unexpected bitmap options %#x.\n", options);
8970 hr = ID2D1Bitmap1_GetSurface(bitmap, &surface);
8971 ok(hr == D2DERR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr);
8972 ID2D1Bitmap1_Release(bitmap);
8974 ID2D1DeviceContext_SetTarget(device_context, NULL);
8975 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8976 ok(bitmap == NULL, "Unexpected target instance.\n");
8978 ID2D1DeviceContext_Release(device_context);
8979 ID2D1DCRenderTarget_Release(dc_rt);
8980 DeleteDC(hdc);
8982 ID2D1Device_Release(device);
8983 ID2D1Factory1_Release(factory);
8984 release_test_context(&ctx);
8987 static void test_invert_matrix(BOOL d3d11)
8989 static const struct
8991 D2D1_MATRIX_3X2_F matrix;
8992 D2D1_MATRIX_3X2_F inverse;
8993 BOOL invertible;
8995 invert_tests[] =
8997 { {{{ 0 }}}, {{{ 0 }}}, FALSE },
9000 1.0f, 2.0f,
9001 1.0f, 2.0f,
9002 4.0f, 8.0f
9003 }}},
9005 1.0f, 2.0f,
9006 1.0f, 2.0f,
9007 4.0f, 8.0f
9008 }}},
9009 FALSE
9013 2.0f, 0.0f,
9014 0.0f, 2.0f,
9015 4.0f, 8.0f
9016 }}},
9018 0.5f, -0.0f,
9019 -0.0f, 0.5f,
9020 -2.0f, -4.0f
9021 }}},
9022 TRUE
9026 2.0f, 1.0f,
9027 2.0f, 2.0f,
9028 4.0f, 8.0f
9029 }}},
9031 1.0f, -0.5f,
9032 -1.0f, 1.0f,
9033 4.0f, -6.0f
9034 }}},
9035 TRUE
9039 2.0f, 1.0f,
9040 3.0f, 1.0f,
9041 4.0f, 8.0f
9042 }}},
9044 -1.0f, 1.0f,
9045 3.0f, -2.0f,
9046 -20.0f, 12.0f
9047 }}},
9048 TRUE
9051 unsigned int i;
9053 for (i = 0; i < ARRAY_SIZE(invert_tests); ++i)
9055 D2D1_MATRIX_3X2_F m;
9056 BOOL ret;
9058 m = invert_tests[i].matrix;
9059 ret = D2D1InvertMatrix(&m);
9060 ok(ret == invert_tests[i].invertible, "%u: unexpected return value %d.\n", i, ret);
9061 ok(!memcmp(&m, &invert_tests[i].inverse, sizeof(m)),
9062 "%u: unexpected matrix value {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n", i,
9063 m._11, m._12, m._21, m._22, m._31, m._32);
9065 ret = D2D1IsMatrixInvertible(&invert_tests[i].matrix);
9066 ok(ret == invert_tests[i].invertible, "%u: unexpected return value %d.\n", i, ret);
9070 static void test_skew_matrix(BOOL d3d11)
9072 static const struct
9074 float angle_x;
9075 float angle_y;
9076 D2D1_POINT_2F center;
9077 D2D1_MATRIX_3X2_F matrix;
9079 skew_tests[] =
9081 { 0.0f, 0.0f, { 0.0f, 0.0f }, {{{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }}} },
9082 { 45.0f, 0.0f, { 0.0f, 0.0f }, {{{ 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f }}} },
9083 { 0.0f, 0.0f, { 10.0f, -3.0f }, {{{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }}} },
9084 { -45.0f, 45.0f, { 0.1f, 0.5f }, {{{ 1.0f, 1.0f, -1.0f, 1.0f, 0.5f, -0.1f }}} },
9085 { -45.0f, 45.0f, { 1.0f, 2.0f }, {{{ 1.0f, 1.0f, -1.0f, 1.0f, 2.0f, -1.0f }}} },
9086 { 45.0f, -45.0f, { 1.0f, 2.0f }, {{{ 1.0f, -1.0f, 1.0f, 1.0f, -2.0f, 1.0f }}} },
9087 { 30.0f, -60.0f, { 12.0f, -5.0f }, {{{ 1.0f, -1.7320509f, 0.577350259f, 1.0f, 2.88675117f, 20.7846107f }}} },
9089 unsigned int i;
9091 for (i = 0; i < ARRAY_SIZE(skew_tests); ++i)
9093 const D2D1_MATRIX_3X2_F *expected = &skew_tests[i].matrix;
9094 D2D1_MATRIX_3X2_F m;
9095 BOOL ret;
9097 D2D1MakeSkewMatrix(skew_tests[i].angle_x, skew_tests[i].angle_y, skew_tests[i].center, &m);
9098 ret = compare_float(m._11, expected->_11, 3) && compare_float(m._12, expected->_12, 3)
9099 && compare_float(m._21, expected->_21, 3) && compare_float(m._22, expected->_22, 3)
9100 && compare_float(m._31, expected->_31, 3) && compare_float(m._32, expected->_32, 3);
9102 ok(ret, "%u: unexpected matrix value {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}, expected "
9103 "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n", i, m._11, m._12, m._21, m._22, m._31, m._32,
9104 expected->_11, expected->_12, expected->_21, expected->_22, expected->_31, expected->_32);
9108 static ID2D1DeviceContext *create_device_context(ID2D1Factory1 *factory, IDXGIDevice *dxgi_device, BOOL d3d11)
9110 ID2D1DeviceContext *device_context;
9111 ID2D1Device *device;
9112 HRESULT hr;
9114 hr = ID2D1Factory1_CreateDevice(factory, dxgi_device, &device);
9115 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9117 hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &device_context);
9118 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9119 ID2D1Device_Release(device);
9121 return device_context;
9124 static void test_command_list(BOOL d3d11)
9126 static const DWORD bitmap_data[] =
9128 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
9130 static const D2D1_GRADIENT_STOP stops[] =
9132 {0.0f, {1.0f, 0.0f, 0.0f, 1.0f}},
9133 {0.5f, {0.0f, 1.0f, 0.0f, 1.0f}},
9134 {1.0f, {0.0f, 0.0f, 1.0f, 1.0f}},
9136 D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES radial_gradient_properties;
9137 D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES linear_gradient_properties;
9138 ID2D1DeviceContext *device_context, *device_context2;
9139 D2D1_STROKE_STYLE_PROPERTIES stroke_desc;
9140 ID2D1GradientStopCollection *gradient;
9141 D2D1_BITMAP_PROPERTIES bitmap_desc;
9142 ID2D1StrokeStyle *stroke_style;
9143 ID2D1CommandList *command_list;
9144 struct d2d1_test_context ctx;
9145 ID2D1Geometry *geometry;
9146 ID2D1Factory1 *factory;
9147 ID2D1RenderTarget *rt;
9148 D2D1_POINT_2F p0, p1;
9149 ID2D1Bitmap *bitmap;
9150 ID2D1Image *target;
9151 D2D1_COLOR_F color;
9152 ID2D1Brush *brush;
9153 D2D1_RECT_F rect;
9154 D2D_SIZE_U size;
9155 ULONG refcount;
9156 HRESULT hr;
9158 if (!init_test_context(&ctx, d3d11))
9159 return;
9161 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
9163 win_skip("ID2D1Factory1 is not supported.\n");
9164 release_test_context(&ctx);
9165 return;
9168 device_context = create_device_context(factory, ctx.device, d3d11);
9169 ok(device_context != NULL, "Failed to create device context.\n");
9171 hr = ID2D1DeviceContext_CreateCommandList(device_context, &command_list);
9172 todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9174 if (FAILED(hr))
9176 ID2D1DeviceContext_Release(device_context);
9177 ID2D1Factory1_Release(factory);
9178 return;
9181 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)command_list);
9182 ID2D1DeviceContext_BeginDraw(device_context);
9184 hr = ID2D1DeviceContext_QueryInterface(device_context, &IID_ID2D1RenderTarget, (void **)&rt);
9185 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9187 /* Test how resources are referenced by the list. */
9189 /* Bitmap. */
9190 set_size_u(&size, 4, 1);
9191 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
9192 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
9193 bitmap_desc.dpiX = 96.0f;
9194 bitmap_desc.dpiY = 96.0f;
9195 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
9196 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9198 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
9200 refcount = ID2D1Bitmap_Release(bitmap);
9201 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
9203 /* Solid color brush. */
9204 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
9205 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, (ID2D1SolidColorBrush **)&brush);
9206 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9208 set_rect(&rect, 0.0f, 0.0f, 16.0f, 16.0f);
9209 ID2D1RenderTarget_FillRectangle(rt, &rect, brush);
9211 refcount = ID2D1Brush_Release(brush);
9212 ok(refcount == 0, "Got unexpected refcount %lu.\n", refcount);
9214 /* Bitmap brush. */
9215 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
9216 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9218 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, (ID2D1BitmapBrush **)&brush);
9219 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9221 set_rect(&rect, 0.0f, 0.0f, 16.0f, 16.0f);
9222 ID2D1RenderTarget_FillRectangle(rt, &rect, brush);
9224 refcount = ID2D1Brush_Release(brush);
9225 ok(refcount == 0, "Got unexpected refcount %lu.\n", refcount);
9227 refcount = ID2D1Bitmap_Release(bitmap);
9228 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
9230 /* Linear gradient brush. */
9231 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops, ARRAY_SIZE(stops),
9232 D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &gradient);
9233 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9235 set_point(&linear_gradient_properties.startPoint, 320.0f, 0.0f);
9236 set_point(&linear_gradient_properties.endPoint, 0.0f, 960.0f);
9237 hr = ID2D1RenderTarget_CreateLinearGradientBrush(rt, &linear_gradient_properties, NULL, gradient,
9238 (ID2D1LinearGradientBrush **)&brush);
9239 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9241 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
9242 hr = ID2D1Factory1_CreateRectangleGeometry(factory, &rect, (ID2D1RectangleGeometry **)&geometry);
9243 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9245 ID2D1RenderTarget_FillGeometry(rt, geometry, brush, NULL);
9247 refcount = ID2D1Brush_Release(brush);
9248 ok(refcount == 0, "Got unexpected refcount %lu.\n", refcount);
9250 refcount = ID2D1Geometry_Release(geometry);
9251 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
9253 refcount = ID2D1GradientStopCollection_Release(gradient);
9254 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
9256 /* Radial gradient brush. */
9257 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops, ARRAY_SIZE(stops),
9258 D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &gradient);
9259 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9261 set_point(&radial_gradient_properties.center, 160.0f, 480.0f);
9262 set_point(&radial_gradient_properties.gradientOriginOffset, 40.0f, -120.0f);
9263 radial_gradient_properties.radiusX = 160.0f;
9264 radial_gradient_properties.radiusY = 480.0f;
9265 hr = ID2D1RenderTarget_CreateRadialGradientBrush(rt, &radial_gradient_properties, NULL, gradient,
9266 (ID2D1RadialGradientBrush **)&brush);
9267 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9269 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
9270 hr = ID2D1Factory1_CreateRectangleGeometry(factory, &rect, (ID2D1RectangleGeometry **)&geometry);
9271 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9273 ID2D1RenderTarget_FillGeometry(rt, geometry, brush, NULL);
9275 refcount = ID2D1Brush_Release(brush);
9276 ok(refcount == 0, "Got unexpected refcount %lu.\n", refcount);
9278 refcount = ID2D1Geometry_Release(geometry);
9279 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
9281 refcount = ID2D1GradientStopCollection_Release(gradient);
9282 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
9284 /* Geometry. */
9285 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
9286 hr = ID2D1Factory1_CreateRectangleGeometry(factory, &rect, (ID2D1RectangleGeometry **)&geometry);
9287 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9289 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
9290 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, (ID2D1SolidColorBrush **)&brush);
9291 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9293 ID2D1RenderTarget_FillGeometry(rt, geometry, brush, NULL);
9295 refcount = ID2D1Brush_Release(brush);
9296 ok(refcount == 0, "Got unexpected refcount %lu.\n", refcount);
9298 refcount = ID2D1Geometry_Release(geometry);
9299 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
9301 /* Stroke style. */
9302 stroke_desc.startCap = D2D1_CAP_STYLE_SQUARE;
9303 stroke_desc.endCap = D2D1_CAP_STYLE_ROUND;
9304 stroke_desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
9305 stroke_desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
9306 stroke_desc.miterLimit = 1.5f;
9307 stroke_desc.dashStyle = D2D1_DASH_STYLE_DOT;
9308 stroke_desc.dashOffset = -1.0f;
9310 hr = ID2D1Factory_CreateStrokeStyle((ID2D1Factory *)factory, &stroke_desc, NULL, 0, &stroke_style);
9311 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9313 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
9314 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, (ID2D1SolidColorBrush **)&brush);
9315 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9317 set_point(&p0, 100.0f, 160.0f);
9318 set_point(&p1, 140.0f, 160.0f);
9319 ID2D1RenderTarget_DrawLine(rt, p0, p1, brush, 1.0f, stroke_style);
9321 refcount = ID2D1Brush_Release(brush);
9322 ok(refcount == 0, "Got unexpected refcount %lu.\n", refcount);
9324 refcount = ID2D1StrokeStyle_Release(stroke_style);
9325 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
9327 /* Close on attached list. */
9328 ID2D1DeviceContext_GetTarget(device_context, &target);
9329 ok(target == (ID2D1Image *)command_list, "Unexpected context target.\n");
9330 ID2D1Image_Release(target);
9332 hr = ID2D1CommandList_Close(command_list);
9333 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9335 ID2D1DeviceContext_GetTarget(device_context, &target);
9336 ok(target == NULL, "Unexpected context target.\n");
9338 hr = ID2D1CommandList_Close(command_list);
9339 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
9341 ID2D1CommandList_Release(command_list);
9343 /* Close empty list. */
9344 hr = ID2D1DeviceContext_CreateCommandList(device_context, &command_list);
9345 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9347 hr = ID2D1CommandList_Close(command_list);
9348 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9350 ID2D1CommandList_Release(command_list);
9352 /* List created with different context. */
9353 device_context2 = create_device_context(factory, ctx.device, d3d11);
9354 ok(device_context2 != NULL, "Failed to create device context.\n");
9356 hr = ID2D1DeviceContext_CreateCommandList(device_context, &command_list);
9357 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9359 ID2D1DeviceContext_SetTarget(device_context2, (ID2D1Image *)command_list);
9360 ID2D1DeviceContext_GetTarget(device_context2, &target);
9361 ok(target == NULL, "Unexpected target.\n");
9363 ID2D1CommandList_Release(command_list);
9364 ID2D1DeviceContext_Release(device_context2);
9366 ID2D1RenderTarget_Release(rt);
9367 ID2D1DeviceContext_Release(device_context);
9368 ID2D1Factory1_Release(factory);
9369 release_test_context(&ctx);
9372 static void test_max_bitmap_size(BOOL d3d11)
9374 D2D1_RENDER_TARGET_PROPERTIES desc;
9375 D2D1_BITMAP_PROPERTIES bitmap_desc;
9376 IDXGISwapChain *swapchain;
9377 ID2D1Factory *factory;
9378 IDXGISurface *surface;
9379 ID2D1RenderTarget *rt;
9380 ID3D10Device1 *device;
9381 ID2D1Bitmap *bitmap;
9382 UINT32 bitmap_size;
9383 unsigned int i, j;
9384 HWND window;
9385 HRESULT hr;
9387 static const struct
9389 const char *name;
9390 DWORD type;
9392 device_types[] =
9394 { "HW", D3D10_DRIVER_TYPE_HARDWARE },
9395 { "WARP", D3D10_DRIVER_TYPE_WARP },
9396 { "REF", D3D10_DRIVER_TYPE_REFERENCE },
9398 static const struct
9400 const char *name;
9401 DWORD type;
9403 target_types[] =
9405 { "DEFAULT", D2D1_RENDER_TARGET_TYPE_DEFAULT },
9406 { "HW", D2D1_RENDER_TARGET_TYPE_HARDWARE },
9409 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
9410 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9412 for (i = 0; i < ARRAY_SIZE(device_types); ++i)
9414 if (FAILED(hr = D3D10CreateDevice1(NULL, device_types[i].type, NULL, D3D10_CREATE_DEVICE_BGRA_SUPPORT,
9415 D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
9417 skip("Failed to create %s d3d device, hr %#lx.\n", device_types[i].name, hr);
9418 continue;
9421 window = create_window();
9422 swapchain = create_d3d10_swapchain(device, window, TRUE);
9423 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
9424 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9426 for (j = 0; j < ARRAY_SIZE(target_types); ++j)
9428 D3D10_TEXTURE2D_DESC texture_desc;
9429 ID3D10Texture2D *texture;
9430 D2D1_SIZE_U size;
9432 desc.type = target_types[j].type;
9433 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
9434 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
9435 desc.dpiX = 0.0f;
9436 desc.dpiY = 0.0f;
9437 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
9438 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
9440 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
9441 ok(hr == S_OK, "%s/%s: Got unexpected hr %#lx.\n", device_types[i].name, target_types[j].name, hr);
9443 bitmap_size = ID2D1RenderTarget_GetMaximumBitmapSize(rt);
9444 ok(bitmap_size >= D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION, "%s/%s: unexpected bitmap size %u.\n",
9445 device_types[i].name, target_types[j].name, bitmap_size);
9447 bitmap_desc.dpiX = 96.0f;
9448 bitmap_desc.dpiY = 96.0f;
9449 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
9450 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
9452 size.width = bitmap_size;
9453 size.height = 1;
9454 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
9455 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9456 ID2D1Bitmap_Release(bitmap);
9458 ID2D1RenderTarget_Release(rt);
9460 texture_desc.Width = bitmap_size;
9461 texture_desc.Height = 1;
9462 texture_desc.MipLevels = 1;
9463 texture_desc.ArraySize = 1;
9464 texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
9465 texture_desc.SampleDesc.Count = 1;
9466 texture_desc.SampleDesc.Quality = 0;
9467 texture_desc.Usage = D3D10_USAGE_DEFAULT;
9468 texture_desc.BindFlags = 0;
9469 texture_desc.CPUAccessFlags = 0;
9470 texture_desc.MiscFlags = 0;
9472 hr = ID3D10Device1_CreateTexture2D(device, &texture_desc, NULL, &texture);
9473 ok(hr == S_OK || broken(hr == E_INVALIDARG && device_types[i].type == D3D10_DRIVER_TYPE_WARP) /* Vista */,
9474 "%s/%s: Got unexpected hr %#lx.\n", device_types[i].name, target_types[j].name, hr);
9475 if (SUCCEEDED(hr))
9476 ID3D10Texture2D_Release(texture);
9479 IDXGISurface_Release(surface);
9480 IDXGISwapChain_Release(swapchain);
9481 DestroyWindow(window);
9483 ID3D10Device1_Release(device);
9486 ID2D1Factory_Release(factory);
9489 static void test_dpi(BOOL d3d11)
9491 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
9492 ID2D1DeviceContext *device_context;
9493 IWICImagingFactory *wic_factory;
9494 struct d2d1_test_context ctx;
9495 ID2D1Factory1 *factory;
9496 ID2D1Bitmap1 *bitmap;
9497 float dpi_x, dpi_y;
9498 HRESULT hr;
9500 static const struct
9502 float dpi_x, dpi_y;
9503 HRESULT hr;
9505 create_dpi_tests[] =
9507 { 0.0f, 0.0f, S_OK},
9508 {192.0f, 0.0f, E_INVALIDARG},
9509 { 0.0f, 192.0f, E_INVALIDARG},
9510 {192.0f, -10.0f, E_INVALIDARG},
9511 {-10.0f, 192.0f, E_INVALIDARG},
9512 {-10.0f, -10.0f, E_INVALIDARG},
9513 { 48.0f, 96.0f, S_OK},
9514 { 96.0f, 48.0f, S_OK},
9516 static const float init_dpi_x = 60.0f, init_dpi_y = 288.0f;
9517 static const float dc_dpi_x = 120.0f, dc_dpi_y = 144.0f;
9518 unsigned int i;
9520 if (!init_test_context(&ctx, d3d11))
9521 return;
9523 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
9525 win_skip("ID2D1Factory1 is not supported.\n");
9526 release_test_context(&ctx);
9527 return;
9531 device_context = create_device_context(factory, ctx.device, d3d11);
9532 ok(!!device_context, "Failed to create device context.\n");
9534 ID2D1DeviceContext_GetDpi(device_context, &dpi_x, &dpi_y);
9535 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
9536 ok(dpi_y == 96.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
9538 /* DXGI surface */
9539 for (i = 0; i < ARRAY_SIZE(create_dpi_tests); ++i)
9541 ID2D1DeviceContext_SetDpi(device_context, init_dpi_x, init_dpi_y);
9543 bitmap_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
9544 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
9545 bitmap_desc.dpiX = create_dpi_tests[i].dpi_x;
9546 bitmap_desc.dpiY = create_dpi_tests[i].dpi_y;
9547 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
9548 bitmap_desc.colorContext = NULL;
9549 hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, ctx.surface, &bitmap_desc, &bitmap);
9550 /* Native accepts negative DPI values for DXGI surface bitmap. */
9551 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
9553 ID2D1DeviceContext_SetDpi(device_context, dc_dpi_x, dc_dpi_y);
9555 ID2D1Bitmap1_GetDpi(bitmap, &dpi_x, &dpi_y);
9556 todo_wine_if(bitmap_desc.dpiX == 0.0f)
9557 ok(dpi_x == bitmap_desc.dpiX, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n",
9558 i, dpi_x, bitmap_desc.dpiX);
9559 todo_wine_if(bitmap_desc.dpiY == 0.0f)
9560 ok(dpi_y == bitmap_desc.dpiY, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n",
9561 i, dpi_y, bitmap_desc.dpiY);
9563 ID2D1DeviceContext_BeginDraw(device_context);
9564 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
9565 hr = ID2D1DeviceContext_EndDraw(device_context, NULL, NULL);
9566 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
9568 /* Device context DPI values aren't updated by SetTarget. */
9569 ID2D1DeviceContext_GetDpi(device_context, &dpi_x, &dpi_y);
9570 ok(dpi_x == dc_dpi_x, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n", i, dpi_x, dc_dpi_x);
9571 ok(dpi_y == dc_dpi_y, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n", i, dpi_y, dc_dpi_y);
9573 ID2D1Bitmap1_Release(bitmap);
9576 /* WIC bitmap */
9577 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
9578 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
9579 &IID_IWICImagingFactory, (void **)&wic_factory);
9580 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9581 for (i = 0; i < ARRAY_SIZE(create_dpi_tests); ++i)
9583 IWICBitmapSource *wic_bitmap_src;
9584 IWICBitmap *wic_bitmap;
9586 ID2D1DeviceContext_SetDpi(device_context, init_dpi_x, init_dpi_y);
9588 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
9589 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
9590 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
9591 hr = IWICBitmap_QueryInterface(wic_bitmap, &IID_IWICBitmapSource, (void **)&wic_bitmap_src);
9592 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
9593 IWICBitmap_Release(wic_bitmap);
9595 bitmap_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
9596 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
9597 bitmap_desc.dpiX = create_dpi_tests[i].dpi_x;
9598 bitmap_desc.dpiY = create_dpi_tests[i].dpi_y;
9599 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
9600 bitmap_desc.colorContext = NULL;
9601 hr = ID2D1DeviceContext_CreateBitmapFromWicBitmap(device_context, wic_bitmap_src, &bitmap_desc, &bitmap);
9602 ok(hr == create_dpi_tests[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n",
9603 i, hr, create_dpi_tests[i].hr);
9604 IWICBitmapSource_Release(wic_bitmap_src);
9606 if (FAILED(hr))
9607 continue;
9609 ID2D1DeviceContext_SetDpi(device_context, dc_dpi_x, dc_dpi_y);
9611 ID2D1Bitmap1_GetDpi(bitmap, &dpi_x, &dpi_y);
9612 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
9614 /* Bitmap DPI values are inherited at creation time. */
9615 ok(dpi_x == init_dpi_x, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n", i, dpi_x, init_dpi_x);
9616 ok(dpi_y == init_dpi_y, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n", i, dpi_y, init_dpi_y);
9618 else
9620 ok(dpi_x == bitmap_desc.dpiX, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n",
9621 i, dpi_x, bitmap_desc.dpiX);
9622 ok(dpi_y == bitmap_desc.dpiY, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n",
9623 i, dpi_y, bitmap_desc.dpiY);
9626 ID2D1DeviceContext_BeginDraw(device_context);
9627 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
9628 hr = ID2D1DeviceContext_EndDraw(device_context, NULL, NULL);
9629 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
9631 /* Device context DPI values aren't updated by SetTarget. */
9632 ID2D1DeviceContext_GetDpi(device_context, &dpi_x, &dpi_y);
9633 ok(dpi_x == dc_dpi_x, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n", i, dpi_x, dc_dpi_x);
9634 ok(dpi_y == dc_dpi_y, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n", i, dpi_y, dc_dpi_y);
9636 ID2D1Bitmap1_Release(bitmap);
9638 IWICImagingFactory_Release(wic_factory);
9639 CoUninitialize();
9641 /* D2D bitmap */
9642 for (i = 0; i < ARRAY_SIZE(create_dpi_tests); ++i)
9644 const D2D1_SIZE_U size = {16, 16};
9646 ID2D1DeviceContext_SetDpi(device_context, init_dpi_x, init_dpi_y);
9648 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
9649 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
9650 bitmap_desc.dpiX = create_dpi_tests[i].dpi_x;
9651 bitmap_desc.dpiY = create_dpi_tests[i].dpi_y;
9652 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
9653 bitmap_desc.colorContext = NULL;
9654 hr = ID2D1DeviceContext_CreateBitmap(device_context, size, NULL, 0, &bitmap_desc, &bitmap);
9655 ok(hr == create_dpi_tests[i].hr, "Test %u: Got unexpected hr %#lx, expected %#lx.\n",
9656 i, hr, create_dpi_tests[i].hr);
9658 if (FAILED(hr))
9659 continue;
9661 ID2D1DeviceContext_SetDpi(device_context, dc_dpi_x, dc_dpi_y);
9663 ID2D1Bitmap1_GetDpi(bitmap, &dpi_x, &dpi_y);
9664 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
9666 /* Bitmap DPI values are inherited at creation time. */
9667 ok(dpi_x == init_dpi_x, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n", i, dpi_x, init_dpi_x);
9668 ok(dpi_y == init_dpi_y, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n", i, dpi_y, init_dpi_y);
9670 else
9672 ok(dpi_x == bitmap_desc.dpiX, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n",
9673 i, dpi_x, bitmap_desc.dpiX);
9674 ok(dpi_y == bitmap_desc.dpiY, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n",
9675 i, dpi_y, bitmap_desc.dpiY);
9678 ID2D1DeviceContext_BeginDraw(device_context);
9679 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
9680 hr = ID2D1DeviceContext_EndDraw(device_context, NULL, NULL);
9681 ok(hr == S_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
9683 /* Device context DPI values aren't updated by SetTarget. */
9684 ID2D1DeviceContext_GetDpi(device_context, &dpi_x, &dpi_y);
9685 ok(dpi_x == dc_dpi_x, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n", i, dpi_x, dc_dpi_x);
9686 ok(dpi_y == dc_dpi_y, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n", i, dpi_y, dc_dpi_y);
9688 ID2D1Bitmap1_Release(bitmap);
9691 ID2D1DeviceContext_SetTarget(device_context, NULL);
9692 ID2D1DeviceContext_GetDpi(device_context, &dpi_x, &dpi_y);
9693 ok(dpi_x == dc_dpi_x, "Got unexpected dpi_x %.8e, expected %.8e.\n", dpi_x, dc_dpi_x);
9694 ok(dpi_y == dc_dpi_y, "Got unexpected dpi_y %.8e, expected %.8e.\n", dpi_y, dc_dpi_y);
9696 ID2D1DeviceContext_Release(device_context);
9697 ID2D1Factory1_Release(factory);
9698 release_test_context(&ctx);
9701 static void test_unit_mode(BOOL d3d11)
9703 struct d2d1_test_context ctx;
9704 ID2D1DeviceContext *context;
9705 D2D1_UNIT_MODE unit_mode;
9706 HRESULT hr;
9708 if (!init_test_context(&ctx, d3d11))
9709 return;
9711 hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&context);
9712 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9714 unit_mode = ID2D1DeviceContext_GetUnitMode(context);
9715 ok(unit_mode == D2D1_UNIT_MODE_DIPS, "Got unexpected unit mode %#x.\n", unit_mode);
9717 ID2D1DeviceContext_SetUnitMode(context, 0xdeadbeef);
9718 unit_mode = ID2D1DeviceContext_GetUnitMode(context);
9719 ok(unit_mode == D2D1_UNIT_MODE_DIPS, "Got unexpected unit mode %#x.\n", unit_mode);
9721 ID2D1DeviceContext_SetUnitMode(context, D2D1_UNIT_MODE_PIXELS);
9722 unit_mode = ID2D1DeviceContext_GetUnitMode(context);
9723 ok(unit_mode == D2D1_UNIT_MODE_PIXELS, "Got unexpected unit mode %#x.\n", unit_mode);
9725 ID2D1DeviceContext_SetUnitMode(context, 0xdeadbeef);
9726 unit_mode = ID2D1DeviceContext_GetUnitMode(context);
9727 ok(unit_mode == D2D1_UNIT_MODE_PIXELS, "Got unexpected unit mode %#x.\n", unit_mode);
9729 ID2D1DeviceContext_Release(context);
9730 release_test_context(&ctx);
9733 static void test_wic_bitmap_format(BOOL d3d11)
9735 IWICImagingFactory *wic_factory;
9736 struct d2d1_test_context ctx;
9737 D2D1_PIXEL_FORMAT format;
9738 IWICBitmap *wic_bitmap;
9739 ID2D1RenderTarget *rt;
9740 ID2D1Bitmap *bitmap;
9741 unsigned int i;
9742 HRESULT hr;
9744 static const struct
9746 const WICPixelFormatGUID *wic;
9747 D2D1_PIXEL_FORMAT d2d;
9749 tests[] =
9751 {&GUID_WICPixelFormat32bppPBGRA, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED}},
9752 {&GUID_WICPixelFormat32bppPRGBA, {DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED}},
9753 {&GUID_WICPixelFormat32bppBGR, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE}},
9756 if (!init_test_context(&ctx, d3d11))
9757 return;
9759 rt = ctx.rt;
9760 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
9762 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
9763 &IID_IWICImagingFactory, (void **)&wic_factory);
9764 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9766 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9768 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
9769 tests[i].wic, WICBitmapCacheOnDemand, &wic_bitmap);
9770 ok(hr == S_OK, "%s: Got unexpected hr %#lx.\n", debugstr_guid(tests[i].wic), hr);
9772 hr = ID2D1RenderTarget_CreateBitmapFromWicBitmap(rt, (IWICBitmapSource *)wic_bitmap, NULL, &bitmap);
9773 ok(hr == S_OK, "%s: Got unexpected hr %#lx.\n", debugstr_guid(tests[i].wic), hr);
9775 format = ID2D1Bitmap_GetPixelFormat(bitmap);
9776 ok(format.format == tests[i].d2d.format, "%s: Got unexpected DXGI format %#x.\n",
9777 debugstr_guid(tests[i].wic), format.format);
9778 ok(format.alphaMode == tests[i].d2d.alphaMode, "%s: Got unexpected alpha mode %#x.\n",
9779 debugstr_guid(tests[i].wic), format.alphaMode);
9781 ID2D1Bitmap_Release(bitmap);
9782 IWICBitmap_Release(wic_bitmap);
9785 IWICImagingFactory_Release(wic_factory);
9786 CoUninitialize();
9787 release_test_context(&ctx);
9790 static void test_math(BOOL d3d11)
9792 float s, c, t, l;
9793 unsigned int i;
9795 static const struct
9797 float x;
9798 float s;
9799 float c;
9801 sc_data[] =
9803 {0.0f, 0.0f, 1.0f},
9804 {1.0f, 8.41470957e-001f, 5.40302277e-001f},
9805 {2.0f, 9.09297407e-001f, -4.16146845e-001f},
9806 {M_PI / 2.0f, 1.0f, -4.37113883e-008f},
9807 {M_PI, -8.74227766e-008f, -1.0f},
9810 static const struct
9812 float x;
9813 float t;
9815 t_data[] =
9817 {0.0f, 0.0f},
9818 {1.0f, 1.55740774f},
9819 {2.0f, -2.18503976f},
9820 {M_PI / 2.0f, -2.28773320e+007f},
9821 {M_PI, 8.74227766e-008f},
9824 static const struct
9826 float x;
9827 float y;
9828 float z;
9829 float l;
9831 l_data[] =
9833 {0.0f, 0.0f, 0.0f, 0.0f},
9834 {1.0f, 0.0f, 0.0f, 1.0f},
9835 {0.0f, 1.0f, 0.0f, 1.0f},
9836 {0.0f, 0.0f, 1.0f, 1.0f},
9837 {1.0f, 1.0f, 1.0f, 1.73205078f},
9838 {1.0f, 2.0f, 2.0f, 3.0f},
9839 {1.0f, 2.0f, 3.0f, 3.74165750f},
9842 if (!pD2D1SinCos || !pD2D1Tan || !pD2D1Vec3Length)
9844 win_skip("D2D1SinCos/D2D1Tan/D2D1Vec3Length not available, skipping test.\n");
9845 return;
9848 for (i = 0; i < ARRAY_SIZE(sc_data); ++i)
9850 pD2D1SinCos(sc_data[i].x, &s, &c);
9851 ok(compare_float(s, sc_data[i].s, 0),
9852 "Test %u: Got unexpected sin %.8e, expected %.8e.\n", i, s, sc_data[i].s);
9853 ok(compare_float(c, sc_data[i].c, 0),
9854 "Test %u: Got unexpected cos %.8e, expected %.8e.\n", i, c, sc_data[i].c);
9857 for (i = 0; i < ARRAY_SIZE(t_data); ++i)
9859 t = pD2D1Tan(t_data[i].x);
9860 ok(compare_float(t, t_data[i].t, 1),
9861 "Test %u: Got unexpected tan %.8e, expected %.8e.\n", i, t, t_data[i].t);
9864 for (i = 0; i < ARRAY_SIZE(l_data); ++i)
9866 l = pD2D1Vec3Length(l_data[i].x, l_data[i].y, l_data[i].z);
9867 ok(compare_float(l, l_data[i].l, 0),
9868 "Test %u: Got unexpected length %.8e, expected %.8e.\n", i, l, l_data[i].l);
9872 static void test_colour_space(BOOL d3d11)
9874 D2D1_COLOR_F src_colour, dst_colour, expected;
9875 D2D1_COLOR_SPACE src_space, dst_space;
9876 unsigned i, j, k;
9878 static const D2D1_COLOR_SPACE colour_spaces[] =
9880 D2D1_COLOR_SPACE_CUSTOM,
9881 D2D1_COLOR_SPACE_SRGB,
9882 D2D1_COLOR_SPACE_SCRGB,
9884 static struct
9886 D2D1_COLOR_F srgb;
9887 D2D1_COLOR_F scrgb;
9889 const test_data[] =
9891 {{0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}},
9892 {{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}},
9893 {{1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}},
9894 /* Samples in the non-linear region. */
9895 {{0.2f, 0.4f, 0.6f, 0.8f}, {0.0331047624f, 0.132868335f, 0.318546832f, 0.8f}},
9896 {{0.3f, 0.5f, 0.7f, 0.9f}, {0.0732389688f, 0.214041144f, 0.447988421f, 0.9f}},
9897 /* Samples in the linear region. */
9898 {{0.0002f, 0.0004f, 0.0006f, 0.0008f}, {1.54798763e-005f, 3.09597526e-005f, 4.64396289e-005f, 0.0008f}},
9899 {{0.0003f, 0.0005f, 0.0007f, 0.0009f}, {2.32198145e-005f, 3.86996908e-005f, 5.41795634e-005f, 0.0009f}},
9900 /* Out of range samples */
9901 {{-0.3f, 1.5f, -0.7f, 2.0f}, { 0.0f, 1.0f, 0.0f, 2.0f}},
9902 {{ 1.5f, -0.3f, 2.0f, -0.7f}, { 1.0f, 0.0f, 1.0f, -0.7f}},
9903 {{ 0.0f, 1.0f, 0.0f, 1.5f}, {-0.7f, 2.0f, -0.3f, 1.5f}},
9904 {{ 1.0f, 0.0f, 1.0f, -0.3f}, { 2.0f, -0.7f, 1.5f, -0.3f}},
9907 if (!pD2D1ConvertColorSpace)
9909 win_skip("D2D1ConvertColorSpace() not available, skipping test.\n");
9910 return;
9913 for (i = 0; i < ARRAY_SIZE(colour_spaces); ++i)
9915 src_space = colour_spaces[i];
9916 for (j = 0; j < ARRAY_SIZE(colour_spaces); ++j)
9918 dst_space = colour_spaces[j];
9919 for (k = 0; k < ARRAY_SIZE(test_data); ++k)
9921 if (src_space == D2D1_COLOR_SPACE_SCRGB)
9922 src_colour = test_data[k].scrgb;
9923 else
9924 src_colour = test_data[k].srgb;
9926 if (dst_space == D2D1_COLOR_SPACE_SCRGB)
9927 expected = test_data[k].scrgb;
9928 else
9929 expected = test_data[k].srgb;
9931 if (src_space == D2D1_COLOR_SPACE_CUSTOM || dst_space == D2D1_COLOR_SPACE_CUSTOM)
9933 set_color(&expected, 0.0f, 0.0f, 0.0f, 0.0f);
9935 else if (src_space != dst_space)
9937 expected.r = clamp_float(expected.r, 0.0f, 1.0f);
9938 expected.g = clamp_float(expected.g, 0.0f, 1.0f);
9939 expected.b = clamp_float(expected.b, 0.0f, 1.0f);
9942 dst_colour = pD2D1ConvertColorSpace(src_space, dst_space, &src_colour);
9943 ok(compare_colour_f(&dst_colour, expected.r, expected.g, expected.b, expected.a, 1),
9944 "Got unexpected destination colour {%.8e, %.8e, %.8e, %.8e}, "
9945 "expected destination colour {%.8e, %.8e, %.8e, %.8e} for "
9946 "source colour {%.8e, %.8e, %.8e, %.8e}, "
9947 "source colour space %#x, destination colour space %#x.\n",
9948 dst_colour.r, dst_colour.g, dst_colour.b, dst_colour.a,
9949 expected.r, expected.g, expected.b, expected.a,
9950 src_colour.r, src_colour.g, src_colour.b, src_colour.a,
9951 src_space, dst_space);
9957 static void test_geometry_group(BOOL d3d11)
9959 ID2D1Factory *factory;
9960 ID2D1GeometryGroup *group;
9961 ID2D1Geometry *geometries[2];
9962 D2D1_RECT_F rect;
9963 HRESULT hr;
9964 D2D1_MATRIX_3X2_F matrix;
9965 BOOL match;
9967 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
9968 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9970 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
9971 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, (ID2D1RectangleGeometry **)&geometries[0]);
9972 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9974 set_rect(&rect, -2.0f, -2.0f, 0.0f, 2.0f);
9975 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, (ID2D1RectangleGeometry **)&geometries[1]);
9976 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9978 hr = ID2D1Factory_CreateGeometryGroup(factory, D2D1_FILL_MODE_ALTERNATE, geometries, 2, &group);
9979 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9981 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
9982 hr = ID2D1GeometryGroup_GetBounds(group, NULL, &rect);
9983 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9984 match = compare_rect(&rect, -2.0f, -2.0f, 1.0f, 2.0f, 0);
9985 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
9986 rect.left, rect.top, rect.right, rect.bottom);
9988 set_matrix_identity(&matrix);
9989 translate_matrix(&matrix, 80.0f, 640.0f);
9990 scale_matrix(&matrix, 2.0f, 0.5f);
9991 hr = ID2D1GeometryGroup_GetBounds(group, &matrix, &rect);
9992 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
9993 match = compare_rect(&rect, 76.0f, 639.0f, 82.0f, 641.0f, 0);
9994 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
9995 rect.left, rect.top, rect.right, rect.bottom);
9997 ID2D1GeometryGroup_Release(group);
9999 ID2D1Geometry_Release(geometries[0]);
10000 ID2D1Geometry_Release(geometries[1]);
10002 ID2D1Factory_Release(factory);
10005 static DWORD WINAPI mt_factory_test_thread_func(void *param)
10007 ID2D1Multithread *multithread = param;
10009 ID2D1Multithread_Enter(multithread);
10011 return 0;
10014 static void test_mt_factory(BOOL d3d11)
10016 ID2D1Multithread *multithread;
10017 ID2D1Factory *factory;
10018 HANDLE thread;
10019 HRESULT hr;
10020 DWORD ret;
10022 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED + 1, &IID_ID2D1Factory, NULL, (void **)&factory);
10023 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
10025 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
10026 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10028 hr = ID2D1Factory_QueryInterface(factory, &IID_ID2D1Multithread, (void **)&multithread);
10029 if (hr == E_NOINTERFACE)
10031 win_skip("ID2D1Multithread is not supported.\n");
10032 ID2D1Factory_Release(factory);
10033 return;
10035 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10037 ret = ID2D1Multithread_GetMultithreadProtected(multithread);
10038 ok(!ret, "Unexpected return value.\n");
10040 ID2D1Multithread_Enter(multithread);
10041 thread = CreateThread(NULL, 0, mt_factory_test_thread_func, multithread, 0, NULL);
10042 ok(!!thread, "Failed to create a thread.\n");
10043 WaitForSingleObject(thread, INFINITE);
10044 CloseHandle(thread);
10046 ID2D1Multithread_Release(multithread);
10047 ID2D1Factory_Release(factory);
10049 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
10050 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10052 hr = ID2D1Factory_QueryInterface(factory, &IID_ID2D1Multithread, (void **)&multithread);
10053 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10055 ret = ID2D1Multithread_GetMultithreadProtected(multithread);
10056 ok(!!ret, "Unexpected return value.\n");
10058 ID2D1Multithread_Enter(multithread);
10059 thread = CreateThread(NULL, 0, mt_factory_test_thread_func, multithread, 0, NULL);
10060 ok(!!thread, "Failed to create a thread.\n");
10061 ret = WaitForSingleObject(thread, 10);
10062 ok(ret == WAIT_TIMEOUT, "Expected timeout.\n");
10063 ID2D1Multithread_Leave(multithread);
10064 WaitForSingleObject(thread, INFINITE);
10065 CloseHandle(thread);
10067 ID2D1Multithread_Release(multithread);
10069 ID2D1Factory_Release(factory);
10072 static void test_effect(BOOL d3d11)
10074 unsigned int i, j, min_inputs, max_inputs, str_size, input_count, factory_version;
10075 D2D1_BITMAP_PROPERTIES bitmap_desc;
10076 D2D1_BUFFER_PRECISION precision;
10077 ID2D1Image *image_a, *image_b;
10078 struct d2d1_test_context ctx;
10079 ID2D1DeviceContext *context;
10080 ID2D1Factory1 *factory1;
10081 ID2D1Factory2 *factory2;
10082 ID2D1Factory3 *factory3;
10083 ID2D1Bitmap *bitmap;
10084 ID2D1Effect *effect;
10085 D2D1_SIZE_U size;
10086 BYTE buffer[256];
10087 BOOL cached;
10088 CLSID clsid;
10089 HRESULT hr;
10091 const struct effect_test
10093 const CLSID *clsid;
10094 UINT32 factory_version;
10095 UINT32 default_input_count;
10096 UINT32 min_inputs;
10097 UINT32 max_inputs;
10099 effect_tests[] =
10101 {&CLSID_D2D12DAffineTransform, 1, 1, 1, 1},
10102 {&CLSID_D2D13DPerspectiveTransform, 1, 1, 1, 1},
10103 {&CLSID_D2D1Composite, 1, 2, 1, 0xffffffff},
10104 {&CLSID_D2D1Crop, 1, 1, 1, 1},
10105 {&CLSID_D2D1Shadow, 1, 1, 1, 1},
10106 {&CLSID_D2D1Grayscale, 3, 1, 1, 1},
10109 if (!init_test_context(&ctx, d3d11))
10110 return;
10112 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory1)))
10114 win_skip("ID2D1Factory1 is not supported.\n");
10115 release_test_context(&ctx);
10116 return;
10118 factory_version = 1;
10119 if (SUCCEEDED(ID2D1Factory1_QueryInterface(factory1, &IID_ID2D1Factory2, (void **)&factory2)))
10121 ID2D1Factory2_Release(factory2);
10122 factory_version = 2;
10124 if (SUCCEEDED(ID2D1Factory1_QueryInterface(factory1, &IID_ID2D1Factory3, (void **)&factory3)))
10126 ID2D1Factory3_Release(factory3);
10127 factory_version = 3;
10129 if (factory_version < 3)
10130 win_skip("ID2D1Factory%u is not supported.\n", factory_version + 1);
10132 hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&context);
10133 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10135 for (i = 0; i < ARRAY_SIZE(effect_tests); ++i)
10137 const struct effect_test *test = effect_tests + i;
10139 if (factory_version < test->factory_version)
10140 continue;
10142 winetest_push_context("Test %u", i);
10144 hr = ID2D1DeviceContext_CreateEffect(context, test->clsid, &effect);
10145 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10147 hr = ID2D1Effect_QueryInterface(effect, &IID_ID2D1Image, (void **)&image_a);
10148 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10149 ID2D1Effect_GetOutput(effect, &image_b);
10150 ok(image_b == image_a, "Got unexpected image_b %p, expected %p.\n", image_b, image_a);
10151 ID2D1Image_Release(image_b);
10152 ID2D1Image_Release(image_a);
10154 hr = ID2D1Effect_GetValue(effect, 0xdeadbeef, D2D1_PROPERTY_TYPE_CLSID, (BYTE *)&clsid, sizeof(clsid));
10155 ok(hr == D2DERR_INVALID_PROPERTY, "Got unexpected hr %#lx.\n", hr);
10157 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_CLSID, D2D1_PROPERTY_TYPE_CLSID, buffer, sizeof(clsid) + 1);
10158 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
10159 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_CLSID, D2D1_PROPERTY_TYPE_CLSID, buffer, sizeof(clsid) - 1);
10160 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
10161 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_CLSID, D2D1_PROPERTY_TYPE_CLSID, buffer, sizeof(clsid));
10162 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10164 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_DISPLAYNAME, D2D1_PROPERTY_TYPE_STRING, buffer, sizeof(buffer));
10165 todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10166 str_size = (wcslen((WCHAR *)buffer) + 1) * sizeof(WCHAR);
10167 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_DISPLAYNAME, D2D1_PROPERTY_TYPE_STRING, buffer, str_size);
10168 todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10169 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_DISPLAYNAME, D2D1_PROPERTY_TYPE_STRING, buffer, str_size - 1);
10170 todo_wine ok(hr == D2DERR_INSUFFICIENT_BUFFER, "Got unexpected hr %#lx.\n", hr);
10172 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_CLSID, 0xdeadbeef, (BYTE *)&clsid, sizeof(clsid));
10173 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
10174 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_CLSID, D2D1_PROPERTY_TYPE_UNKNOWN, (BYTE *)&clsid, sizeof(clsid));
10175 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10176 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_CLSID, D2D1_PROPERTY_TYPE_VECTOR4, (BYTE *)&clsid, sizeof(clsid));
10177 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
10178 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_CLSID, D2D1_PROPERTY_TYPE_VECTOR4, buffer, sizeof(buffer));
10179 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
10181 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_CLSID,
10182 D2D1_PROPERTY_TYPE_CLSID, (BYTE *)&clsid, sizeof(clsid));
10183 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10184 ok(IsEqualGUID(&clsid, test->clsid), "Got unexpected clsid %s, expected %s.\n",
10185 debugstr_guid(&clsid), debugstr_guid(test->clsid));
10187 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_CACHED,
10188 D2D1_PROPERTY_TYPE_BOOL, (BYTE *)&cached, sizeof(cached));
10189 todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10190 if (hr == S_OK)
10191 ok(cached == FALSE, "Got unexpected cached %d.\n", cached);
10193 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_PRECISION,
10194 D2D1_PROPERTY_TYPE_ENUM, (BYTE *)&precision, sizeof(precision));
10195 todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10196 if (hr == S_OK)
10197 ok(precision == D2D1_BUFFER_PRECISION_UNKNOWN, "Got unexpected precision %u.\n", precision);
10199 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_MIN_INPUTS,
10200 D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&min_inputs, sizeof(min_inputs));
10201 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10202 ok(min_inputs == test->min_inputs, "Got unexpected min inputs %u, expected %u.\n",
10203 min_inputs, test->min_inputs);
10205 hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_MAX_INPUTS,
10206 D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&max_inputs, sizeof(max_inputs));
10207 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10208 ok(max_inputs == test->max_inputs, "Got unexpected max inputs %u, expected %u.\n",
10209 max_inputs, test->max_inputs);
10211 input_count = ID2D1Effect_GetInputCount(effect);
10212 ok(input_count == test->default_input_count, "Got unexpected input count %u, expected %u.\n",
10213 input_count, test->default_input_count);
10215 input_count = (test->max_inputs < 16 ? test->max_inputs : 16);
10216 for (j = 0; j < input_count + 4; ++j)
10218 winetest_push_context("Input %u", j);
10219 hr = ID2D1Effect_SetInputCount(effect, j);
10220 if (j < test->min_inputs || j > test->max_inputs)
10221 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
10222 else
10223 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10224 winetest_pop_context();
10227 input_count = ID2D1Effect_GetInputCount(effect);
10228 for (j = 0; j < input_count + 4; ++j)
10230 winetest_push_context("Input %u", j);
10231 ID2D1Effect_GetInput(effect, j, &image_a);
10232 ok(image_a == NULL, "Got unexpected image_a %p.\n", image_a);
10233 winetest_pop_context();
10236 set_size_u(&size, 1, 1);
10237 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
10238 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
10239 bitmap_desc.dpiX = 96.0f;
10240 bitmap_desc.dpiY = 96.0f;
10241 hr = ID2D1RenderTarget_CreateBitmap(ctx.rt, size, NULL, 4, &bitmap_desc, &bitmap);
10242 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10244 ID2D1Effect_SetInput(effect, 0, (ID2D1Image *)bitmap, FALSE);
10245 for (j = 0; j < input_count + 4; ++j)
10247 winetest_push_context("Input %u", j);
10248 image_a = (ID2D1Image *)0xdeadbeef;
10249 ID2D1Effect_GetInput(effect, j, &image_a);
10250 if (j == 0)
10252 ok(image_a == (ID2D1Image *)bitmap, "Got unexpected image_a %p.\n", image_a);
10253 ID2D1Image_Release(image_a);
10255 else
10257 ok(image_a == NULL, "Got unexpected image_a %p.\n", image_a);
10259 winetest_pop_context();
10262 for (j = input_count; j < input_count + 4; ++j)
10264 winetest_push_context("Input %u", j);
10265 image_a = (ID2D1Image *)0xdeadbeef;
10266 ID2D1Effect_SetInput(effect, j, (ID2D1Image *)bitmap, FALSE);
10267 ID2D1Effect_GetInput(effect, j, &image_a);
10268 ok(image_a == NULL, "Got unexpected image_a %p.\n", image_a);
10269 winetest_pop_context();
10271 ID2D1Bitmap_Release(bitmap);
10273 ID2D1Effect_Release(effect);
10274 winetest_pop_context();
10277 ID2D1DeviceContext_Release(context);
10278 ID2D1Factory1_Release(factory1);
10279 release_test_context(&ctx);
10282 static void test_effect_2d_affine(BOOL d3d11)
10284 D2D1_MATRIX_3X2_F rotate, scale, skew;
10285 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
10286 D2D_RECT_F output_bounds = {0};
10287 struct d2d1_test_context ctx;
10288 ID2D1DeviceContext *context;
10289 unsigned int i, x, y, w, h;
10290 D2D1_SIZE_U input_size;
10291 ID2D1Factory1 *factory;
10292 D2D1_POINT_2F offset;
10293 ID2D1Bitmap1 *bitmap;
10294 ID2D1Effect *effect;
10295 ID2D1Image *output;
10296 BOOL match;
10297 HRESULT hr;
10299 static const DWORD image_4x4[] =
10301 0xfdcba987, 0xffff0000, 0x98765432, 0xffffffff,
10302 0x4b4b4b4b, 0x89abcdef, 0xdeadbeef, 0xabcdef01,
10303 0x7f000011, 0x40ffffff, 0x12345678, 0xaabbccdd,
10304 0x44444444, 0xff7f7f7f, 0x1221abba, 0x00000000
10306 DWORD image_16x16[16 * 16];
10308 const struct effect_2d_affine_test
10310 const DWORD *img_data;
10311 unsigned int img_width;
10312 unsigned int img_height;
10314 D2D1_MATRIX_3X2_F *matrix;
10316 D2D_RECT_F bounds;
10317 const char *figure;
10319 effect_2d_affine_tests[] =
10321 {image_4x4, 4, 4, &rotate, {-6.0f, -3.0f, 2.0f, 4.0f},
10322 "ASgBAQkBAQEBBwEBAQEBAQYBAQEBAQEHAQEBASgA"},
10323 {image_4x4, 4, 4, &scale, {-2.0f, -3.0f, 1.0f, 9.0f},
10324 "AQ8BAQEEAQEBBAEBAQQBAQEEAQEBBAEBAQQBAQEEAQEBBAEBAQQBAQEEAQEBBAEBARAA/"},
10325 {image_4x4, 4, 4, &skew, {-7.0f, -3.0f, 3.0f, 7.0f},
10326 "AS8CCwEBAQEJAQEBAQEBBwEBAQEBAQEBBgEBAQEBAQEBBwEBAQEBAQkCAj0A"},
10327 {image_16x16, 16, 16, &rotate, {-14.0f, -3.0f, 10.0f, 21.0f},
10328 "AWACGQECARcBBAEVAQYBEwEIAREBCgEPAQwBDQEOAQsBEAEJARIBBwEUAQUBARQBAQUBARIBAQcB"
10329 "ARABAQkBAQ4BAQsBAQwBAQ0BAQoBAQ8BAQgBAREBAQYBARMBAQQBARUBAQIBARcBAgEZAkUA"},
10330 {image_16x16, 16, 16, &scale, {-2.0f, -3.0f, 10.0f, 39.0f},
10331 "ASEMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQM"
10332 "BAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDCIA"},
10333 {image_16x16, 16, 16, &skew, {-19.0f, -3.0f, 15.0f, 31.0f},
10334 "AYMBAiMBAgEhAQQBHwEGAR0BCAEbAQoBGQEMARcBDgEVARABEwESAREBFAEPARYBDQEYAQsBGgEJ"
10335 "ARwBBwEeAQYBHgEHARwBCQEaAQsBGAENARYBDwEUAREBEgETARABFQEOARcBDAEZAQoBGwEIAR0B"
10336 "BgEfAQQBIQECASMChAEA"},
10339 memset(image_16x16, 0xff, sizeof(image_16x16));
10340 set_matrix_identity(&rotate);
10341 set_matrix_identity(&scale);
10342 set_matrix_identity(&skew);
10343 translate_matrix(&rotate, -2.0f, -2.0f);
10344 translate_matrix(&scale, -2.0f, -2.0f);
10345 translate_matrix(&skew, -2.0f, -2.0f);
10346 rotate_matrix(&rotate, M_PI_4);
10347 scale_matrix(&scale, 0.75f, 2.5f);
10348 skew_matrix(&skew, -1.0f, 1.0f);
10350 if (!init_test_context(&ctx, d3d11))
10351 return;
10353 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
10355 win_skip("ID2D1Factory1 is not supported.\n");
10356 release_test_context(&ctx);
10357 return;
10360 hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&context);
10361 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10363 hr = ID2D1DeviceContext_CreateEffect(context, &CLSID_D2D12DAffineTransform, &effect);
10364 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10366 for (i = 0; i < ARRAY_SIZE(effect_2d_affine_tests); ++i)
10368 const struct effect_2d_affine_test *test = &effect_2d_affine_tests[i];
10369 winetest_push_context("Test %u", i);
10371 set_size_u(&input_size, test->img_width, test->img_height);
10372 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
10373 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
10374 bitmap_desc.dpiX = 96.0f;
10375 bitmap_desc.dpiY = 96.0f;
10376 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_NONE;
10377 bitmap_desc.colorContext = NULL;
10378 hr = ID2D1DeviceContext_CreateBitmap(context, input_size, test->img_data,
10379 sizeof(*test->img_data) * test->img_width, &bitmap_desc, &bitmap);
10380 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10382 ID2D1Effect_SetInput(effect, 0, (ID2D1Image *)bitmap, FALSE);
10383 todo_wine
10384 hr = ID2D1Effect_SetValue(effect, D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX,
10385 D2D1_PROPERTY_TYPE_MATRIX_3X2, (const BYTE *)test->matrix, sizeof(*test->matrix));
10386 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10387 ID2D1Effect_GetOutput(effect, &output);
10389 ID2D1DeviceContext_GetImageLocalBounds(context, output, &output_bounds);
10390 todo_wine
10391 ok(compare_rect(&output_bounds, test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom, 1),
10392 "Got unexpected output bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10393 output_bounds.left, output_bounds.top, output_bounds.right, output_bounds.bottom,
10394 test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom);
10395 if (output_bounds.left == output_bounds.right || output_bounds.top == output_bounds.bottom)
10397 ID2D1Image_Release(output);
10398 ID2D1Bitmap1_Release(bitmap);
10399 winetest_pop_context();
10400 continue;
10403 ID2D1DeviceContext_BeginDraw(context);
10404 ID2D1DeviceContext_Clear(context, 0);
10405 offset.x = 320.0f;
10406 offset.y = 240.0f;
10407 ID2D1DeviceContext_DrawImage(context, output, &offset, NULL, 0, 0);
10408 hr = ID2D1DeviceContext_EndDraw(context, NULL, NULL);
10409 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10411 x = offset.x + output_bounds.left - 2.0f;
10412 y = offset.y + output_bounds.top - 2.0f;
10413 w = (output_bounds.right - output_bounds.left) + 4.0f;
10414 h = (output_bounds.bottom - output_bounds.top) + 4.0f;
10415 match = compare_figure(&ctx, x, y, w, h, 0xff652e89, 0, test->figure);
10416 todo_wine
10417 ok(match, "Figure does not match.\n");
10419 ID2D1Image_Release(output);
10420 ID2D1Bitmap1_Release(bitmap);
10421 winetest_pop_context();
10424 ID2D1Effect_Release(effect);
10425 ID2D1DeviceContext_Release(context);
10426 ID2D1Factory1_Release(factory);
10427 release_test_context(&ctx);
10430 static void test_effect_crop(BOOL d3d11)
10432 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
10433 struct d2d1_test_context ctx;
10434 ID2D1DeviceContext *context;
10435 D2D_RECT_F output_bounds;
10436 D2D1_SIZE_U input_size;
10437 ID2D1Factory1 *factory;
10438 ID2D1Bitmap1 *bitmap;
10439 DWORD image[16 * 16];
10440 ID2D1Effect *effect;
10441 ID2D1Image *output;
10442 unsigned int i;
10443 HRESULT hr;
10445 const struct crop_effect_test
10447 D2D_VECTOR_4F crop_rect; /* {x: left, y: top, z: right, w: bottom} */
10448 D2D_RECT_F bounds;
10450 crop_effect_tests[] =
10452 {{0.0f, 0.0f, 8.0f, 8.0f}, {0.0f, 0.0f, 8.0f, 8.0f}},
10453 {{4.0f, 4.0f, 8.0f, 8.0f}, {4.0f, 4.0f, 8.0f, 8.0f}},
10454 {{10.0f, 10.0f, 20.0f, 20.0f}, {10.0f, 10.0f, 16.0f, 16.0f}},
10455 {{-10.0f, 10.0f, 20.0f, 12.0f}, {0.0f, 10.0f, 16.0f, 12.0f}},
10456 {{3.0f, -2.0f, 5.0f, 1.0f}, {3.0f, 0.0f, 5.0f, 1.0f}},
10457 {{-1.0f, -1.0f, 20.0f, 20.0f}, {0.0f, 0.0f, 16.0f, 16.0f}},
10458 {{-5.0f, -5.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}},
10460 memset(image, 0xff, sizeof(image));
10462 if (!init_test_context(&ctx, d3d11))
10463 return;
10465 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
10467 win_skip("ID2D1Factory1 is not supported.\n");
10468 release_test_context(&ctx);
10469 return;
10472 hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&context);
10473 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10475 hr = ID2D1DeviceContext_CreateEffect(context, &CLSID_D2D1Crop, &effect);
10476 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10478 for (i = 0; i < ARRAY_SIZE(crop_effect_tests); ++i)
10480 const struct crop_effect_test *test = &crop_effect_tests[i];
10481 winetest_push_context("Test %u", i);
10483 set_size_u(&input_size, 16, 16);
10484 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
10485 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
10486 bitmap_desc.dpiX = 96.0f;
10487 bitmap_desc.dpiY = 96.0f;
10488 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_NONE;
10489 bitmap_desc.colorContext = NULL;
10490 hr = ID2D1DeviceContext_CreateBitmap(context, input_size, image,
10491 sizeof(*image) * 16, &bitmap_desc, &bitmap);
10492 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10494 ID2D1Effect_SetInput(effect, 0, (ID2D1Image *)bitmap, FALSE);
10495 hr = ID2D1Effect_SetValue(effect, D2D1_CROP_PROP_RECT, D2D1_PROPERTY_TYPE_VECTOR4,
10496 (const BYTE *)&test->crop_rect, sizeof(test->crop_rect));
10497 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10498 ID2D1Effect_GetOutput(effect, &output);
10500 set_rect(&output_bounds, -1.0f, -1.0f, -1.0f, -1.0f);
10501 ID2D1DeviceContext_GetImageLocalBounds(context, output, &output_bounds);
10502 todo_wine
10503 ok(compare_rect(&output_bounds, test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom, 0),
10504 "Got unexpected output bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10505 output_bounds.left, output_bounds.top, output_bounds.right, output_bounds.bottom,
10506 test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom);
10508 ID2D1Image_Release(output);
10509 ID2D1Bitmap1_Release(bitmap);
10510 winetest_pop_context();
10513 ID2D1Effect_Release(effect);
10514 ID2D1DeviceContext_Release(context);
10515 ID2D1Factory1_Release(factory);
10516 release_test_context(&ctx);
10519 static void test_effect_grayscale(BOOL d3d11)
10521 DWORD colour, expected_colour, luminance;
10522 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
10523 struct d2d1_test_context ctx;
10524 struct resource_readback rb;
10525 ID2D1DeviceContext *context;
10526 D2D1_SIZE_U input_size;
10527 ID2D1Factory3 *factory;
10528 ID2D1Bitmap1 *bitmap;
10529 ID2D1Effect *effect;
10530 ID2D1Image *output;
10531 unsigned int i;
10532 HRESULT hr;
10534 const DWORD test_pixels[] = {0xffffffff, 0x12345678, 0x89abcdef, 0x77777777, 0xdeadbeef};
10536 if (!init_test_context(&ctx, d3d11))
10537 return;
10539 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory3, NULL, (void **)&factory)))
10541 win_skip("ID2D1Factory3 is not supported.\n");
10542 release_test_context(&ctx);
10543 return;
10546 hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&context);
10547 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10549 hr = ID2D1DeviceContext_CreateEffect(context, &CLSID_D2D1Grayscale, &effect);
10550 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10552 for (i = 0; i < ARRAY_SIZE(test_pixels); ++i)
10554 DWORD pixel = test_pixels[i];
10555 winetest_push_context("Test %u", i);
10557 set_size_u(&input_size, 1, 1);
10558 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
10559 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
10560 bitmap_desc.dpiX = 96.0f;
10561 bitmap_desc.dpiY = 96.0f;
10562 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_NONE;
10563 bitmap_desc.colorContext = NULL;
10564 hr = ID2D1DeviceContext_CreateBitmap(context, input_size, &pixel, sizeof(pixel), &bitmap_desc, &bitmap);
10565 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10567 ID2D1Effect_SetInput(effect, 0, (ID2D1Image *)bitmap, FALSE);
10568 ID2D1Effect_GetOutput(effect, &output);
10570 ID2D1DeviceContext_BeginDraw(context);
10571 ID2D1DeviceContext_Clear(context, 0);
10572 ID2D1DeviceContext_DrawImage(context, output, NULL, NULL, 0, 0);
10573 hr = ID2D1DeviceContext_EndDraw(context, NULL, NULL);
10574 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10576 get_surface_readback(&ctx, &rb);
10577 colour = get_readback_colour(&rb, 0, 0);
10578 luminance = (DWORD)(0.299f * ((pixel >> 16) & 0xff)
10579 + 0.587f * ((pixel >> 8) & 0xff)
10580 + 0.114f * ((pixel >> 0) & 0xff) + 0.5f);
10581 expected_colour = (pixel & 0xff000000) | (luminance << 16) | (luminance << 8) | luminance;
10582 todo_wine ok(compare_colour(colour, expected_colour, 1),
10583 "Got unexpected colour %#lx, expected %#lx.\n", colour, expected_colour);
10584 release_resource_readback(&rb);
10586 ID2D1Image_Release(output);
10587 ID2D1Bitmap1_Release(bitmap);
10588 winetest_pop_context();
10591 ID2D1Effect_Release(effect);
10592 ID2D1DeviceContext_Release(context);
10593 ID2D1Factory3_Release(factory);
10594 release_test_context(&ctx);
10597 static void test_stroke_contains_point(BOOL d3d11)
10599 ID2D1TransformedGeometry *transformed_geometry;
10600 ID2D1RectangleGeometry *rectangle;
10601 D2D1_MATRIX_3X2_F matrix;
10602 ID2D1GeometrySink *sink;
10603 ID2D1PathGeometry *path;
10604 ID2D1Factory *factory;
10605 D2D1_POINT_2F point;
10606 D2D1_RECT_F rect;
10607 unsigned int i;
10608 BOOL contains;
10609 HRESULT hr;
10611 static const struct contains_point_test
10613 D2D1_MATRIX_3X2_F transform;
10614 D2D1_POINT_2F point;
10615 float tolerance;
10616 float stroke_width;
10617 BOOL matrix;
10618 BOOL contains;
10620 rectangle_tests[] =
10622 /* 0. Stroked area hittesting. Edge. */
10623 {{{{0.0f}}}, { 0.4f, 10.0f}, 0.0f, 1.0f, FALSE, TRUE},
10624 {{{{0.0f}}}, { 0.5f, 10.0f}, 0.0f, 1.0f, FALSE, FALSE},
10625 {{{{0.0f}}}, { 0.6f, 10.0f}, 0.0f, 1.0f, FALSE, FALSE},
10627 /* 3. Negative tolerance. */
10628 {{{{0.0f}}}, {-0.6f, 10.0f}, -1.0f, 1.0f, FALSE, TRUE},
10629 {{{{0.0f}}}, { 0.6f, 10.0f}, -1.0f, 1.0f, FALSE, TRUE},
10630 {{{{0.0f}}}, { 1.4f, 10.0f}, -1.0f, 1.0f, FALSE, TRUE},
10631 {{{{0.0f}}}, { 1.5f, 10.0f}, -1.0f, 1.0f, FALSE, FALSE},
10633 /* 7. Within tolerance limit around corner. */
10634 {{{{0.0f}}}, {-D2D1_DEFAULT_FLATTENING_TOLERANCE - 1.00f, 0.0f}, 0.0f, 2.0f, FALSE, FALSE},
10635 {{{{0.0f}}}, {-D2D1_DEFAULT_FLATTENING_TOLERANCE - 1.01f, 0.0f}, 0.0f, 2.0f, FALSE, FALSE},
10636 {{{{0.0f}}}, {-D2D1_DEFAULT_FLATTENING_TOLERANCE, -D2D1_DEFAULT_FLATTENING_TOLERANCE},
10637 0.0f, 2.0f, FALSE, TRUE},
10638 {{{{0.0f}}}, {-D2D1_DEFAULT_FLATTENING_TOLERANCE, -D2D1_DEFAULT_FLATTENING_TOLERANCE - 1.01f},
10639 0.0f, 2.0f, FALSE, FALSE},
10641 /* 11. Center point. */
10642 {{{{0.0f}}}, { 5.0f, 10.0f}, 0.0f, 1.0f, FALSE, FALSE},
10644 /* 12. Center point, large stroke width. */
10645 {{{{0.0f}}}, { 5.0f, 10.0f}, 0.0f, 100.0f, FALSE, TRUE},
10647 /* 13. Center point, large tolerance. */
10648 {{{{0.0f}}}, { 5.0f, 10.0f}, 50.0f, 10.0f, FALSE, TRUE},
10650 /* With transformation matrix. */
10652 /* 14. */
10653 {{{{0.0f, 0.0f, 0.0f, 1.0f}}}, {0.1f, 10.0f}, 0.0f, 1.0f, TRUE, FALSE},
10654 {{{{0.0f, 0.0f, 0.0f, 1.0f}}}, {5.0f, 10.0f}, 5.0f, 1.0f, TRUE, FALSE},
10655 {{{{0.0f, 0.0f, 0.0f, 1.0f}}}, {4.9f, 10.0f}, 5.0f, 1.0f, TRUE, TRUE},
10656 {{{{0.0f, 0.0f, 0.0f, 1.0f}}}, {5.0f, 10.0f}, -5.0f, 1.0f, TRUE, FALSE},
10657 {{{{0.0f, 0.0f, 0.0f, 1.0f}}}, {4.9f, 10.0f}, -5.0f, 1.0f, TRUE, TRUE},
10659 /* 19. */
10660 {{{{1.0f, 0.0f, 0.0f, 1.0f}}}, {0.0f, 10.0f}, 0.0f, 1.0f, TRUE, TRUE},
10661 {{{{1.0f, 0.0f, 0.0f, 1.0f}}}, {0.1f, 10.0f}, 0.0f, 1.0f, TRUE, TRUE},
10662 {{{{1.0f, 0.0f, 0.0f, 1.0f}}}, {0.5f, 10.0f}, 0.0f, 1.0f, TRUE, FALSE},
10663 {{{{1.0f, 0.0f, 0.0f, 1.0f}}}, {0.0f, 10.0f}, 1.0f, 1.0f, TRUE, TRUE},
10664 {{{{1.0f, 0.0f, 0.0f, 1.0f}}}, {0.59f, 10.0f}, 1.0f, 1.0f, TRUE, TRUE},
10665 {{{{1.0f, 0.0f, 0.0f, 1.0f}}}, {-0.59f, 10.0f}, 1.0f, 1.0f, TRUE, TRUE},
10666 {{{{1.0f, 0.0f, 0.0f, 1.0f}}}, {0.59f, 10.0f}, -1.0f, 1.0f, TRUE, TRUE},
10667 {{{{1.0f, 0.0f, 0.0f, 1.0f}}}, {-0.59f, 10.0f}, -1.0f, 1.0f, TRUE, TRUE},
10669 /* 27. */
10670 {{{{1.0f, 1.0f, 0.0f, 1.0f}}}, {5.0f, 4.4f}, 0.0f, 1.0f, TRUE, FALSE},
10671 {{{{1.0f, 1.0f, 0.0f, 1.0f}}}, {5.0f, 4.6f}, 0.0f, 1.0f, TRUE, TRUE},
10672 {{{{1.0f, 1.0f, 0.0f, 1.0f}}}, {5.0f, 5.4f}, 0.0f, 1.0f, TRUE, TRUE},
10673 {{{{1.0f, 1.0f, 0.0f, 1.0f}}}, {5.0f, 5.6f}, 0.0f, 1.0f, TRUE, FALSE},
10675 /* 31. */
10676 {{{{1.0f, 1.0f, 0.0f, 1.0f}}}, {5.0f, 6.9f}, 1.0f, 1.0f, TRUE, TRUE},
10677 {{{{1.0f, 1.0f, 0.0f, 1.0f}}}, {5.0f, 7.0f}, 1.0f, 1.0f, TRUE, FALSE},
10679 /* 33. Offset matrix */
10680 {{{{1.0f, 0.0f, 0.0f, 1.0f, -11.0f, 0.0f}}}, { 5.0f, 20.0f}, 0.0f, 1.0f, TRUE, FALSE},
10681 {{{{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 21.0f}}}, {10.0f, 10.0f}, 0.0f, 1.0f, TRUE, FALSE},
10682 {{{{1.0f, 0.0f, 0.0f, 1.0f, 11.0f, 0.0f}}}, { 5.0f, 0.0f}, 0.0f, 1.0f, TRUE, FALSE},
10683 {{{{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -21.0f}}}, { 0.0f, 10.0f}, 0.0f, 1.0f, TRUE, FALSE},
10684 {{{{1.0f, 0.0f, 0.0f, 1.0f, -11.0f, 0.0f}}}, {-6.0f, 20.0f}, 0.0f, 1.0f, TRUE, TRUE},
10685 {{{{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 21.0f}}}, {10.0f, 31.0f}, 0.0f, 1.0f, TRUE, TRUE},
10686 {{{{1.0f, 0.0f, 0.0f, 1.0f, 11.0f, 0.0f}}}, {16.0f, 0.0f}, 0.0f, 1.0f, TRUE, TRUE},
10687 {{{{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -21.0f}}}, { 0.0f, -11.0f}, 0.0f, 1.0f, TRUE, TRUE},
10689 path_tests[] =
10691 /* 0. Stroked area hittesting. Edge. */
10692 {{{{0.0f}}}, {160.0f, 600.0f}, 0.0f, 1.0f, FALSE, FALSE},
10693 {{{{0.0f}}}, {239.24f, 600.0f}, 0.0f, 1.0f, FALSE, FALSE},
10694 {{{{0.0f}}}, {239.26f, 600.0f}, 0.0f, 1.0f, FALSE, TRUE},
10695 {{{{0.0f}}}, {240.74f, 600.0f}, 0.0f, 1.0f, FALSE, TRUE},
10696 {{{{0.0f}}}, {240.76f, 600.0f}, 0.0f, 1.0f, FALSE, FALSE},
10698 /* 5. Negative tolerance. */
10699 {{{{0.0f}}}, {239.24f, 600.0f}, -1.0f, 1.0f, FALSE, FALSE},
10700 {{{{0.0f}}}, {239.26f, 600.0f}, -1.0f, 1.0f, FALSE, TRUE},
10701 {{{{0.0f}}}, {240.74f, 600.0f}, -1.0f, 1.0f, FALSE, TRUE},
10702 {{{{0.0f}}}, {240.76f, 600.0f}, -1.0f, 1.0f, FALSE, FALSE},
10704 /* 9. Less than default tolerance. */
10705 {{{{0.0f}}}, {239.39f, 600.0f}, 0.1f, 1.0f, FALSE, FALSE},
10706 {{{{0.0f}}}, {239.41f, 600.0f}, 0.1f, 1.0f, FALSE, TRUE},
10707 {{{{0.0f}}}, {240.59f, 600.0f}, 0.1f, 1.0f, FALSE, TRUE},
10708 {{{{0.0f}}}, {240.61f, 600.0f}, 0.1f, 1.0f, FALSE, FALSE},
10710 /* 13. Curves. */
10711 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {170.0f, 418.6f}, 0.0f, 1.0f, TRUE, TRUE},
10712 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {170.0f, 420.1f}, 0.0f, 1.0f, TRUE, FALSE},
10713 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {170.0f, 417.7f}, 0.0f, 1.0f, TRUE, FALSE},
10714 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, { 89.5f, 485.3f}, 0.1f, 1.0f, TRUE, TRUE},
10715 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, { 90.5f, 485.3f}, 0.1f, 1.0f, TRUE, TRUE},
10716 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, { 91.5f, 485.3f}, 0.1f, 1.0f, TRUE, FALSE},
10717 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, { 89.0f, 485.3f}, 0.1f, 1.0f, TRUE, FALSE},
10718 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {167.0f, 729.8f}, 0.0f, 1.0f, TRUE, TRUE},
10719 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {167.0f, 728.6f}, 0.0f, 1.0f, TRUE, FALSE},
10720 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {167.0f, 731.0f}, 0.0f, 1.0f, TRUE, FALSE},
10721 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {173.0f, 729.8f}, 0.0f, 1.0f, TRUE, TRUE},
10722 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {173.0f, 728.6f}, 0.0f, 1.0f, TRUE, FALSE},
10723 {{{{1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f}}}, {173.0f, 731.0f}, 0.0f, 1.0f, TRUE, FALSE},
10725 /* 26. A curve where the control points project beyond the endpoints
10726 * onto the line through the endpoints. */
10727 {{{{0.0f}}}, {306.97f, 791.67f}, 0.0f, 1.0f, FALSE, FALSE},
10728 {{{{0.0f}}}, {307.27f, 791.67f}, 0.0f, 1.0f, FALSE, TRUE},
10729 {{{{0.0f}}}, {308.47f, 791.67f}, 0.0f, 1.0f, FALSE, TRUE},
10730 {{{{0.0f}}}, {308.77f, 791.67f}, 0.0f, 1.0f, FALSE, FALSE},
10732 {{{{0.0f}}}, {350.00f, 824.10f}, 0.0f, 1.0f, FALSE, FALSE},
10733 {{{{0.0f}}}, {350.00f, 824.40f}, 0.0f, 1.0f, FALSE, TRUE},
10734 {{{{0.0f}}}, {350.00f, 825.60f}, 0.0f, 1.0f, FALSE, TRUE},
10735 {{{{0.0f}}}, {350.00f, 825.90f}, 0.0f, 1.0f, FALSE, FALSE},
10737 {{{{0.0f}}}, {391.23f, 791.67f}, 0.0f, 1.0f, FALSE, FALSE},
10738 {{{{0.0f}}}, {391.53f, 791.67f}, 0.0f, 1.0f, FALSE, TRUE},
10739 {{{{0.0f}}}, {392.73f, 791.67f}, 0.0f, 1.0f, FALSE, TRUE},
10740 {{{{0.0f}}}, {393.03f, 791.67f}, 0.0f, 1.0f, FALSE, FALSE},
10742 /* 38. A curve where the endpoints coincide. */
10743 {{{{0.0f}}}, {570.23f, 799.77f}, 0.0f, 1.0f, FALSE, FALSE},
10744 {{{{0.0f}}}, {570.53f, 799.77f}, 0.0f, 1.0f, FALSE, TRUE},
10745 {{{{0.0f}}}, {571.73f, 799.77f}, 0.0f, 1.0f, FALSE, TRUE},
10746 {{{{0.0f}}}, {572.03f, 799.77f}, 0.0f, 1.0f, FALSE, FALSE},
10748 {{{{0.0f}}}, {600.00f, 824.10f}, 0.0f, 1.0f, FALSE, FALSE},
10749 {{{{0.0f}}}, {600.00f, 824.40f}, 0.0f, 1.0f, FALSE, TRUE},
10750 {{{{0.0f}}}, {600.00f, 825.60f}, 0.0f, 1.0f, FALSE, TRUE},
10751 {{{{0.0f}}}, {600.00f, 825.90f}, 0.0f, 1.0f, FALSE, FALSE},
10753 {{{{0.0f}}}, {627.97f, 799.77f}, 0.0f, 1.0f, FALSE, FALSE},
10754 {{{{0.0f}}}, {628.27f, 799.77f}, 0.0f, 1.0f, FALSE, TRUE},
10755 {{{{0.0f}}}, {629.47f, 799.77f}, 0.0f, 1.0f, FALSE, TRUE},
10756 {{{{0.0f}}}, {629.77f, 799.77f}, 0.0f, 1.0f, FALSE, FALSE},
10758 /* 50. A curve with coinciding endpoints, as well as coinciding
10759 * control points. */
10760 {{{{0.0f}}}, {825.00f, 800.00f}, 0.0f, 1.0f, FALSE, TRUE},
10761 {{{{0.0f}}}, {861.00f, 824.00f}, 0.0f, 1.0f, FALSE, TRUE},
10762 {{{{0.0f}}}, {861.00f, 826.00f}, 0.0f, 1.0f, FALSE, FALSE},
10763 {{{{0.0f}}}, {862.50f, 825.00f}, 0.0f, 1.0f, FALSE, TRUE},
10764 {{{{0.0f}}}, {864.00f, 824.00f}, 0.0f, 1.0f, FALSE, FALSE},
10765 {{{{0.0f}}}, {864.00f, 826.00f}, 0.0f, 1.0f, FALSE, FALSE},
10767 /* 56. Shear transforms. */
10768 {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, { 837.2f, 600.0f}, 0.1f, 5.0f, TRUE, FALSE},
10769 {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, { 837.5f, 600.0f}, 0.1f, 5.0f, TRUE, TRUE},
10770 {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, {1186.3f, 791.7f}, 0.1f, 5.0f, TRUE, TRUE},
10771 {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, {1186.6f, 791.7f}, 0.1f, 5.0f, TRUE, FALSE},
10772 {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, {1425.0f, 827.3f}, 0.1f, 5.0f, TRUE, TRUE},
10773 {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, {1425.0f, 827.6f}, 0.1f, 5.0f, TRUE, FALSE},
10774 {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, {1620.1f, 800.0f}, 0.1f, 5.0f, TRUE, FALSE},
10775 {{{{1.0f, 0.0f, 1.0f, 1.0f}}}, {1620.4f, 800.0f}, 0.1f, 5.0f, TRUE, TRUE},
10777 transformed_tests[] =
10779 /* 0. Stroked area hittesting. Edge. Tolerance is 0.0f */
10780 {{{{0.0f}}}, {0.74f, 2.5f}, 0.0f, 1.0f, FALSE, TRUE},
10781 {{{{0.0f}}}, {0.75f, 2.5f}, 0.0f, 1.0f, FALSE, FALSE},
10783 /* 2. Stroked area hittesting. Edge. Tolerance is negative */
10784 {{{{0.0f}}}, {0.74f, 2.5f}, -1.0f, 1.0f, FALSE, TRUE},
10785 {{{{0.0f}}}, {0.75f, 2.5f}, -1.0f, 1.0f, FALSE, FALSE},
10787 /* 4. Stroked area hittesting. Edge. Tolerance is close to zero */
10788 {{{{0.0f}}}, {0.501f, 2.5f}, 0.001f, 1.0f, FALSE, TRUE},
10789 {{{{0.0f}}}, {0.502f, 2.5f}, 0.001f, 1.0f, FALSE, FALSE},
10791 /* 6. Stroked area hittesting. Edge. Tolerance is D2D1_DEFAULT_FLATTENING_TOLERANCE */
10792 {{{{0.0f}}}, {0.74f, 2.5f}, 0.25f, 1.0f, FALSE, TRUE},
10793 {{{{0.0f}}}, {0.75f, 2.5f}, 0.25f, 1.0f, FALSE, FALSE},
10796 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
10797 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10799 set_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f);
10800 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rectangle);
10801 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10802 for (i = 0; i < ARRAY_SIZE(rectangle_tests); ++i)
10804 const struct contains_point_test *test = &rectangle_tests[i];
10806 winetest_push_context("Test %u", i);
10808 contains = !test->contains;
10809 hr = ID2D1RectangleGeometry_StrokeContainsPoint(rectangle, test->point, test->stroke_width,
10810 NULL, test->matrix ? &test->transform : NULL, test->tolerance, &contains);
10811 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10812 ok(contains == test->contains, "Got unexpected result %#x.\n", contains);
10814 winetest_pop_context();
10816 ID2D1RectangleGeometry_Release(rectangle);
10818 hr = ID2D1Factory_CreatePathGeometry(factory, &path);
10819 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10820 hr = ID2D1PathGeometry_Open(path, &sink);
10821 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10823 /* A limaçon. */
10824 set_point(&point, 160.0f, 720.0f);
10825 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
10826 cubic_to(sink, 119.0f, 720.0f, 83.0f, 600.0f, 80.0f, 474.0f);
10827 cubic_to(sink, 78.0f, 349.0f, 108.0f, 245.0f, 135.0f, 240.0f);
10828 cubic_to(sink, 163.0f, 235.0f, 180.0f, 318.0f, 176.0f, 370.0f);
10829 cubic_to(sink, 171.0f, 422.0f, 149.0f, 422.0f, 144.0f, 370.0f);
10830 cubic_to(sink, 140.0f, 318.0f, 157.0f, 235.0f, 185.0f, 240.0f);
10831 cubic_to(sink, 212.0f, 245.0f, 242.0f, 349.0f, 240.0f, 474.0f);
10832 cubic_to(sink, 238.0f, 600.0f, 201.0f, 720.0f, 160.0f, 720.0f);
10833 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
10835 /* Some straight lines. */
10836 set_point(&point, 160.0f, 240.0f);
10837 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
10838 line_to(sink, 240.0f, 240.0f);
10839 line_to(sink, 240.0f, 720.0f);
10840 line_to(sink, 160.0f, 720.0f);
10841 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
10843 /* Projected control points extending beyond the line segment through the
10844 * endpoints. */
10845 set_point(&point, 325.0f, 750.0f);
10846 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
10847 cubic_to(sink, 250.0f, 850.0f, 450.0f, 850.0f, 375.0f, 750.0f);
10848 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
10850 /* Coinciding endpoints. */
10851 set_point(&point, 600.0f, 750.0f);
10852 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
10853 cubic_to(sink, 500.0f, 850.0f, 700.0f, 850.0f, 600.0f, 750.0f);
10854 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
10856 /* Coinciding endpoints, as well as coinciding control points. */
10857 set_point(&point, 750.0f, 750.0f);
10858 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
10859 cubic_to(sink, 900.0f, 850.0f, 900.0f, 850.0f, 750.0f, 750.0f);
10860 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
10862 hr = ID2D1GeometrySink_Close(sink);
10863 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10864 ID2D1GeometrySink_Release(sink);
10866 for (i = 0; i < ARRAY_SIZE(path_tests); ++i)
10868 const struct contains_point_test *test = &path_tests[i];
10870 winetest_push_context("Test %u", i);
10872 contains = !test->contains;
10873 hr = ID2D1PathGeometry_StrokeContainsPoint(path, test->point, test->stroke_width,
10874 NULL, test->matrix ? &test->transform : NULL, test->tolerance, &contains);
10875 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10876 ok(contains == test->contains, "Got unexpected result %#x.\n", contains);
10878 winetest_pop_context();
10881 ID2D1PathGeometry_Release(path);
10883 set_rect(&rect, 0.0f, 0.0f, 5.0f, 5.0f);
10884 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rectangle);
10885 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10886 set_matrix_identity(&matrix);
10887 scale_matrix(&matrix, 2.0f, 4.0f);
10888 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)rectangle, &matrix,
10889 &transformed_geometry);
10890 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10892 for (i = 0; i < ARRAY_SIZE(transformed_tests); ++i)
10894 const struct contains_point_test *test = &transformed_tests[i];
10896 winetest_push_context("Test %u", i);
10898 contains = !test->contains;
10899 hr = ID2D1TransformedGeometry_StrokeContainsPoint(transformed_geometry, test->point,
10900 test->stroke_width, NULL, test->matrix ? &test->transform : NULL, test->tolerance,
10901 &contains);
10902 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10903 ok(contains == test->contains, "Got unexpected result %#x.\n", contains);
10905 winetest_pop_context();
10907 ID2D1TransformedGeometry_Release(transformed_geometry);
10908 ID2D1RectangleGeometry_Release(rectangle);
10910 ID2D1Factory_Release(factory);
10913 static void test_image_bounds(BOOL d3d11)
10915 D2D1_BITMAP_PROPERTIES bitmap_desc;
10916 struct d2d1_test_context ctx;
10917 ID2D1DeviceContext *context;
10918 D2D1_UNIT_MODE unit_mode;
10919 ID2D1Factory1 *factory;
10920 ID2D1Bitmap *bitmap;
10921 float dpi_x, dpi_y;
10922 D2D_RECT_F bounds;
10923 D2D1_SIZE_F size;
10924 unsigned int i;
10925 HRESULT hr;
10927 const struct bitmap_bounds_test
10929 float dpi_x;
10930 float dpi_y;
10931 D2D_SIZE_U pixel_size;
10933 bitmap_bounds_tests[] =
10935 {96.0f, 96.0f, {100, 100}},
10936 {48.0f, 48.0f, {100, 100}},
10937 {192.0f, 192.0f, {100, 100}},
10938 {96.0f, 10.0f, {100, 100}},
10939 {50.0f, 100.0f, {100, 100}},
10940 {150.0f, 150.0f, {100, 100}},
10941 {48.0f, 48.0f, {1, 1}},
10942 {192.0f, 192.0f, {1, 1}},
10945 if (!init_test_context(&ctx, d3d11))
10946 return;
10948 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
10950 win_skip("ID2D1Factory1 is not supported.\n");
10951 release_test_context(&ctx);
10952 return;
10955 hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&context);
10956 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10958 for (i = 0; i < ARRAY_SIZE(bitmap_bounds_tests); ++i)
10960 const struct bitmap_bounds_test *test = &bitmap_bounds_tests[i];
10961 winetest_push_context("Test %u", i);
10963 bitmap_desc.dpiX = test->dpi_x;
10964 bitmap_desc.dpiY = test->dpi_y;
10965 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
10966 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
10967 hr = ID2D1RenderTarget_CreateBitmap(ctx.rt, test->pixel_size, NULL, 0, &bitmap_desc, &bitmap);
10968 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
10970 set_rect(&bounds, 0.0f, 0.0f, 0.0f, 0.0f);
10971 size = ID2D1Bitmap_GetSize(bitmap);
10972 ID2D1DeviceContext_GetImageLocalBounds(context, (ID2D1Image *)bitmap, &bounds);
10973 ok(compare_rect(&bounds, 0.0f, 0.0f, size.width, size.height, 0),
10974 "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10975 bounds.left, bounds.top, bounds.right, bounds.bottom, 0.0f, 0.0f, size.width, size.height);
10977 /* Test bitmap local bounds after changing context dpi */
10978 ID2D1DeviceContext_GetDpi(context, &dpi_x, &dpi_y);
10979 ID2D1DeviceContext_SetDpi(context, dpi_x * 2.0f, dpi_y * 2.0f);
10980 ID2D1DeviceContext_GetImageLocalBounds(context, (ID2D1Image *)bitmap, &bounds);
10981 ok(compare_rect(&bounds, 0.0f, 0.0f, size.width, size.height, 0),
10982 "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10983 bounds.left, bounds.top, bounds.right, bounds.bottom, 0.0f, 0.0f, size.width, size.height);
10984 ID2D1DeviceContext_SetDpi(context, dpi_x, dpi_y);
10986 /* Test bitmap local bounds after changing context unit mode */
10987 unit_mode = ID2D1DeviceContext_GetUnitMode(context);
10988 ok(unit_mode == D2D1_UNIT_MODE_DIPS, "Got unexpected unit mode %#x.\n", unit_mode);
10989 ID2D1DeviceContext_SetUnitMode(context, D2D1_UNIT_MODE_PIXELS);
10990 ID2D1DeviceContext_GetImageLocalBounds(context, (ID2D1Image *)bitmap, &bounds);
10991 ok(compare_rect(&bounds, 0.0f, 0.0f, test->pixel_size.width, test->pixel_size.height, 0),
10992 "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10993 bounds.left, bounds.top, bounds.right, bounds.bottom, 0.0f, 0.0f,
10994 (float)test->pixel_size.width, (float)test->pixel_size.height);
10995 ID2D1DeviceContext_SetUnitMode(context, unit_mode);
10997 ID2D1Bitmap_Release(bitmap);
10998 winetest_pop_context();
11001 ID2D1DeviceContext_Release(context);
11002 ID2D1Factory1_Release(factory);
11003 release_test_context(&ctx);
11006 START_TEST(d2d1)
11008 HMODULE d2d1_dll = GetModuleHandleA("d2d1.dll");
11009 unsigned int argc, i;
11010 char **argv;
11012 pD2D1CreateDevice = (void *)GetProcAddress(d2d1_dll, "D2D1CreateDevice");
11013 pD2D1SinCos = (void *)GetProcAddress(d2d1_dll, "D2D1SinCos");
11014 pD2D1Tan = (void *)GetProcAddress(d2d1_dll, "D2D1Tan");
11015 pD2D1Vec3Length = (void *)GetProcAddress(d2d1_dll, "D2D1Vec3Length");
11016 pD2D1ConvertColorSpace = (void *)GetProcAddress(d2d1_dll, "D2D1ConvertColorSpace");
11018 use_mt = !getenv("WINETEST_NO_MT_D3D");
11019 /* Some host drivers (MacOS, Mesa radeonsi) never unmap memory even when
11020 * requested. When using the chunk allocator, running the tests with more
11021 * than one thread can exceed the 32-bit virtual address space. */
11022 if (sizeof(void *) == 4 && !strcmp(winetest_platform, "wine"))
11023 use_mt = FALSE;
11025 argc = winetest_get_mainargs(&argv);
11026 for (i = 2; i < argc; ++i)
11028 if (!strcmp(argv[i], "--single"))
11029 use_mt = FALSE;
11032 queue_test(test_clip);
11033 queue_test(test_state_block);
11034 queue_test(test_color_brush);
11035 queue_test(test_bitmap_brush);
11036 queue_test(test_image_brush);
11037 queue_test(test_linear_brush);
11038 queue_test(test_radial_brush);
11039 queue_test(test_path_geometry);
11040 queue_d3d10_test(test_rectangle_geometry);
11041 queue_d3d10_test(test_rounded_rectangle_geometry);
11042 queue_test(test_bitmap_formats);
11043 queue_test(test_alpha_mode);
11044 queue_test(test_shared_bitmap);
11045 queue_test(test_bitmap_updates);
11046 queue_test(test_opacity_brush);
11047 queue_test(test_create_target);
11048 queue_test(test_draw_text_layout);
11049 queue_test(test_dc_target);
11050 queue_test(test_hwnd_target);
11051 queue_test(test_bitmap_target);
11052 queue_d3d10_test(test_desktop_dpi);
11053 queue_d3d10_test(test_stroke_style);
11054 queue_test(test_gradient);
11055 queue_test(test_draw_geometry);
11056 queue_test(test_fill_geometry);
11057 queue_test(test_gdi_interop);
11058 queue_test(test_layer);
11059 queue_test(test_bezier_intersect);
11060 queue_test(test_create_device);
11061 queue_test(test_bitmap_surface);
11062 queue_test(test_device_context);
11063 queue_d3d10_test(test_invert_matrix);
11064 queue_d3d10_test(test_skew_matrix);
11065 queue_test(test_command_list);
11066 queue_d3d10_test(test_max_bitmap_size);
11067 queue_test(test_dpi);
11068 queue_test(test_unit_mode);
11069 queue_test(test_wic_bitmap_format);
11070 queue_d3d10_test(test_math);
11071 queue_d3d10_test(test_colour_space);
11072 queue_test(test_geometry_group);
11073 queue_test(test_mt_factory);
11074 queue_test(test_effect);
11075 queue_test(test_effect_2d_affine);
11076 queue_test(test_effect_crop);
11077 queue_test(test_effect_grayscale);
11078 queue_d3d10_test(test_stroke_contains_point);
11079 queue_test(test_image_bounds);
11081 run_queued_tests();