d2d1: Skip empty source rectangle for ID2D1RenderTarget_DrawBitmap().
[wine.git] / dlls / d2d1 / tests / d2d1.c
blob19bb94530c29c386788b7a5204f40cef059fedae
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_1.h"
24 #include "wincrypt.h"
25 #include "wine/test.h"
26 #include "initguid.h"
27 #include "dwrite.h"
28 #include "wincodec.h"
29 #include "wine/heap.h"
31 static HRESULT (WINAPI *pD2D1CreateDevice)(IDXGIDevice *dxgi_device,
32 const D2D1_CREATION_PROPERTIES *properties, ID2D1Device **device);
34 static BOOL use_mt = TRUE;
36 static struct test_entry
38 void (*test)(void);
39 } *mt_tests;
40 size_t mt_tests_size, mt_test_count;
42 struct resource_readback
44 ID3D10Resource *resource;
45 D3D10_MAPPED_TEXTURE2D map_desc;
46 unsigned int width, height;
49 struct figure
51 unsigned int *spans;
52 unsigned int spans_size;
53 unsigned int span_count;
56 struct geometry_sink
58 ID2D1SimplifiedGeometrySink ID2D1SimplifiedGeometrySink_iface;
60 struct geometry_figure
62 D2D1_FIGURE_BEGIN begin;
63 D2D1_FIGURE_END end;
64 D2D1_POINT_2F start_point;
65 struct geometry_segment
67 enum
69 SEGMENT_BEZIER,
70 SEGMENT_LINE,
71 } type;
72 union
74 D2D1_BEZIER_SEGMENT bezier;
75 D2D1_POINT_2F line;
76 } u;
77 DWORD flags;
78 } *segments;
79 unsigned int segments_size;
80 unsigned int segment_count;
81 } *figures;
82 unsigned int figures_size;
83 unsigned int figure_count;
85 D2D1_FILL_MODE fill_mode;
86 DWORD segment_flags;
87 BOOL closed;
90 struct expected_geometry_figure
92 D2D1_FIGURE_BEGIN begin;
93 D2D1_FIGURE_END end;
94 D2D1_POINT_2F start_point;
95 unsigned int segment_count;
96 const struct geometry_segment *segments;
99 static void queue_test(void (*test)(void))
101 if (mt_test_count >= mt_tests_size)
103 mt_tests_size = max(16, mt_tests_size * 2);
104 mt_tests = heap_realloc(mt_tests, mt_tests_size * sizeof(*mt_tests));
106 mt_tests[mt_test_count++].test = test;
109 static DWORD WINAPI thread_func(void *ctx)
111 LONG *i = ctx, j;
113 while (*i < mt_test_count)
115 j = *i;
116 if (InterlockedCompareExchange(i, j + 1, j) == j)
117 mt_tests[j].test();
120 return 0;
123 static void run_queued_tests(void)
125 unsigned int thread_count, i;
126 HANDLE *threads;
127 SYSTEM_INFO si;
128 LONG test_idx;
130 if (!use_mt)
132 for (i = 0; i < mt_test_count; ++i)
134 mt_tests[i].test();
137 return;
140 GetSystemInfo(&si);
141 thread_count = si.dwNumberOfProcessors;
142 threads = heap_calloc(thread_count, sizeof(*threads));
143 for (i = 0, test_idx = 0; i < thread_count; ++i)
145 threads[i] = CreateThread(NULL, 0, thread_func, &test_idx, 0, NULL);
146 ok(!!threads[i], "Failed to create thread %u.\n", i);
148 WaitForMultipleObjects(thread_count, threads, TRUE, INFINITE);
149 for (i = 0; i < thread_count; ++i)
151 CloseHandle(threads[i]);
153 heap_free(threads);
156 static void set_point(D2D1_POINT_2F *point, float x, float y)
158 point->x = x;
159 point->y = y;
162 static void set_quadratic(D2D1_QUADRATIC_BEZIER_SEGMENT *quadratic, float x1, float y1, float x2, float y2)
164 quadratic->point1.x = x1;
165 quadratic->point1.y = y1;
166 quadratic->point2.x = x2;
167 quadratic->point2.y = y2;
170 static void set_rect(D2D1_RECT_F *rect, float left, float top, float right, float bottom)
172 rect->left = left;
173 rect->top = top;
174 rect->right = right;
175 rect->bottom = bottom;
178 static void set_rounded_rect(D2D1_ROUNDED_RECT *rect, float left, float top, float right, float bottom,
179 float radius_x, float radius_y)
181 set_rect(&rect->rect, left, top, right, bottom);
182 rect->radiusX = radius_x;
183 rect->radiusY = radius_y;
186 static void set_rect_u(D2D1_RECT_U *rect, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
188 rect->left = left;
189 rect->top = top;
190 rect->right = right;
191 rect->bottom = bottom;
194 static void set_ellipse(D2D1_ELLIPSE *ellipse, float x, float y, float rx, float ry)
196 set_point(&ellipse->point, x, y);
197 ellipse->radiusX = rx;
198 ellipse->radiusY = ry;
201 static void set_color(D2D1_COLOR_F *color, float r, float g, float b, float a)
203 color->r = r;
204 color->g = g;
205 color->b = b;
206 color->a = a;
209 static void set_size_u(D2D1_SIZE_U *size, unsigned int w, unsigned int h)
211 size->width = w;
212 size->height = h;
215 static void set_size_f(D2D1_SIZE_F *size, float w, float h)
217 size->width = w;
218 size->height = h;
221 static void set_matrix_identity(D2D1_MATRIX_3X2_F *matrix)
223 matrix->_11 = 1.0f;
224 matrix->_12 = 0.0f;
225 matrix->_21 = 0.0f;
226 matrix->_22 = 1.0f;
227 matrix->_31 = 0.0f;
228 matrix->_32 = 0.0f;
231 static void rotate_matrix(D2D1_MATRIX_3X2_F *matrix, float theta)
233 float sin_theta, cos_theta, tmp_11, tmp_12;
235 sin_theta = sinf(theta);
236 cos_theta = cosf(theta);
237 tmp_11 = matrix->_11;
238 tmp_12 = matrix->_12;
240 matrix->_11 = cos_theta * tmp_11 + sin_theta * matrix->_21;
241 matrix->_12 = cos_theta * tmp_12 + sin_theta * matrix->_22;
242 matrix->_21 = -sin_theta * tmp_11 + cos_theta * matrix->_21;
243 matrix->_22 = -sin_theta * tmp_12 + cos_theta * matrix->_22;
246 static void skew_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
248 float tmp_11, tmp_12;
250 tmp_11 = matrix->_11;
251 tmp_12 = matrix->_12;
253 matrix->_11 += y * matrix->_21;
254 matrix->_12 += y * matrix->_22;
255 matrix->_21 += x * tmp_11;
256 matrix->_22 += x * tmp_12;
259 static void scale_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
261 matrix->_11 *= x;
262 matrix->_12 *= x;
263 matrix->_21 *= y;
264 matrix->_22 *= y;
267 static void translate_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
269 matrix->_31 += x * matrix->_11 + y * matrix->_21;
270 matrix->_32 += x * matrix->_12 + y * matrix->_22;
273 static void line_to(ID2D1GeometrySink *sink, float x, float y)
275 D2D1_POINT_2F point;
277 set_point(&point, x, y);
278 ID2D1GeometrySink_AddLine(sink, point);
281 static void quadratic_to(ID2D1GeometrySink *sink, float x1, float y1, float x2, float y2)
283 D2D1_QUADRATIC_BEZIER_SEGMENT quadratic;
285 set_quadratic(&quadratic, x1, y1, x2, y2);
286 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
289 static void cubic_to(ID2D1GeometrySink *sink, float x1, float y1, float x2, float y2, float x3, float y3)
291 D2D1_BEZIER_SEGMENT b;
293 b.point1.x = x1;
294 b.point1.y = y1;
295 b.point2.x = x2;
296 b.point2.y = y2;
297 b.point3.x = x3;
298 b.point3.y = y3;
299 ID2D1GeometrySink_AddBezier(sink, &b);
302 static void get_surface_readback(IDXGISurface *surface, struct resource_readback *rb)
304 D3D10_TEXTURE2D_DESC texture_desc;
305 DXGI_SURFACE_DESC surface_desc;
306 ID3D10Resource *src_resource;
307 ID3D10Device *device;
308 HRESULT hr;
310 hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
311 ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
312 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
313 ok(SUCCEEDED(hr), "Failed to query resource interface, hr %#x.\n", hr);
315 hr = IDXGISurface_GetDesc(surface, &surface_desc);
316 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
317 texture_desc.Width = surface_desc.Width;
318 texture_desc.Height = surface_desc.Height;
319 texture_desc.MipLevels = 1;
320 texture_desc.ArraySize = 1;
321 texture_desc.Format = surface_desc.Format;
322 texture_desc.SampleDesc = surface_desc.SampleDesc;
323 texture_desc.Usage = D3D10_USAGE_STAGING;
324 texture_desc.BindFlags = 0;
325 texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
326 texture_desc.MiscFlags = 0;
327 hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D10Texture2D **)&rb->resource);
328 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
330 rb->width = texture_desc.Width;
331 rb->height = texture_desc.Height;
333 ID3D10Device_CopyResource(device, rb->resource, src_resource);
334 ID3D10Resource_Release(src_resource);
335 ID3D10Device_Release(device);
337 hr = ID3D10Texture2D_Map((ID3D10Texture2D *)rb->resource, 0, D3D10_MAP_READ, 0, &rb->map_desc);
338 ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr);
341 static void release_resource_readback(struct resource_readback *rb)
343 ID3D10Texture2D_Unmap((ID3D10Texture2D *)rb->resource, 0);
344 ID3D10Resource_Release(rb->resource);
347 static DWORD get_readback_colour(struct resource_readback *rb, unsigned int x, unsigned int y)
349 return ((DWORD *)((BYTE *)rb->map_desc.pData + y * rb->map_desc.RowPitch))[x];
352 static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
354 unsigned int diff = x > y ? x - y : y - x;
356 return diff <= max_diff;
359 static BOOL compare_colour(DWORD c1, DWORD c2, BYTE max_diff)
361 return compare_uint(c1 & 0xff, c2 & 0xff, max_diff)
362 && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff)
363 && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff)
364 && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
367 static BOOL compare_float(float f, float g, unsigned int ulps)
369 int x = *(int *)&f;
370 int y = *(int *)&g;
372 if (x < 0)
373 x = INT_MIN - x;
374 if (y < 0)
375 y = INT_MIN - y;
377 if (abs(x - y) > ulps)
378 return FALSE;
380 return TRUE;
383 static BOOL compare_point(const D2D1_POINT_2F *point, float x, float y, unsigned int ulps)
385 return compare_float(point->x, x, ulps)
386 && compare_float(point->y, y, ulps);
389 static BOOL compare_rect(const D2D1_RECT_F *rect, float left, float top, float right, float bottom, unsigned int ulps)
391 return compare_float(rect->left, left, ulps)
392 && compare_float(rect->top, top, ulps)
393 && compare_float(rect->right, right, ulps)
394 && compare_float(rect->bottom, bottom, ulps);
397 static BOOL compare_bezier_segment(const D2D1_BEZIER_SEGMENT *b, float x1, float y1,
398 float x2, float y2, float x3, float y3, unsigned int ulps)
400 return compare_point(&b->point1, x1, y1, ulps)
401 && compare_point(&b->point2, x2, y2, ulps)
402 && compare_point(&b->point3, x3, y3, ulps);
405 static BOOL compare_sha1(void *data, unsigned int pitch, unsigned int bpp,
406 unsigned int w, unsigned int h, const char *ref_sha1)
408 static const char hex_chars[] = "0123456789abcdef";
409 HCRYPTPROV provider;
410 BYTE hash_data[20];
411 HCRYPTHASH hash;
412 unsigned int i;
413 char sha1[41];
414 BOOL ret;
416 ret = CryptAcquireContextW(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
417 ok(ret, "Failed to acquire crypt context.\n");
418 ret = CryptCreateHash(provider, CALG_SHA1, 0, 0, &hash);
419 ok(ret, "Failed to create hash.\n");
421 for (i = 0; i < h; ++i)
423 if (!(ret = CryptHashData(hash, (BYTE *)data + pitch * i, w * bpp, 0)))
424 break;
426 ok(ret, "Failed to hash data.\n");
428 i = sizeof(hash_data);
429 ret = CryptGetHashParam(hash, HP_HASHVAL, hash_data, &i, 0);
430 ok(ret, "Failed to get hash value.\n");
431 ok(i == sizeof(hash_data), "Got unexpected hash size %u.\n", i);
433 ret = CryptDestroyHash(hash);
434 ok(ret, "Failed to destroy hash.\n");
435 ret = CryptReleaseContext(provider, 0);
436 ok(ret, "Failed to release crypt context.\n");
438 for (i = 0; i < 20; ++i)
440 sha1[i * 2] = hex_chars[hash_data[i] >> 4];
441 sha1[i * 2 + 1] = hex_chars[hash_data[i] & 0xf];
443 sha1[40] = 0;
445 return !strcmp(ref_sha1, (char *)sha1);
448 static BOOL compare_surface(IDXGISurface *surface, const char *ref_sha1)
450 struct resource_readback rb;
451 BOOL ret;
453 get_surface_readback(surface, &rb);
454 ret = compare_sha1(rb.map_desc.pData, rb.map_desc.RowPitch, 4,
455 rb.width, rb.height, ref_sha1);
456 release_resource_readback(&rb);
458 return ret;
461 static BOOL compare_wic_bitmap(IWICBitmap *bitmap, const char *ref_sha1)
463 UINT stride, width, height, buffer_size;
464 IWICBitmapLock *lock;
465 BYTE *data;
466 HRESULT hr;
467 BOOL ret;
469 hr = IWICBitmap_Lock(bitmap, NULL, WICBitmapLockRead, &lock);
470 ok(SUCCEEDED(hr), "Failed to lock bitmap, hr %#x.\n", hr);
472 hr = IWICBitmapLock_GetDataPointer(lock, &buffer_size, &data);
473 ok(SUCCEEDED(hr), "Failed to get bitmap data, hr %#x.\n", hr);
475 hr = IWICBitmapLock_GetStride(lock, &stride);
476 ok(SUCCEEDED(hr), "Failed to get bitmap stride, hr %#x.\n", hr);
478 hr = IWICBitmapLock_GetSize(lock, &width, &height);
479 ok(SUCCEEDED(hr), "Failed to get bitmap size, hr %#x.\n", hr);
481 ret = compare_sha1(data, stride, 4, width, height, ref_sha1);
483 IWICBitmapLock_Release(lock);
485 return ret;
488 static void serialize_figure(struct figure *figure)
490 static const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
491 unsigned int i, j, k, span;
492 char output[76];
493 char t[3];
494 char *p;
496 for (i = 0, j = 0, k = 0, p = output; i < figure->span_count; ++i)
498 span = figure->spans[i];
499 while (span)
501 t[j] = span & 0x7f;
502 if (span > 0x7f)
503 t[j] |= 0x80;
504 span >>= 7;
505 if (++j == 3)
507 p[0] = lookup[(t[0] & 0xfc) >> 2];
508 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
509 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
510 p[3] = lookup[t[2] & 0x3f];
511 p += 4;
512 if (++k == 19)
514 trace("%.76s\n", output);
515 p = output;
516 k = 0;
518 j = 0;
522 if (j)
524 for (i = j; i < 3; ++i)
525 t[i] = 0;
526 p[0] = lookup[(t[0] & 0xfc) >> 2];
527 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
528 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
529 p[3] = lookup[t[2] & 0x3f];
530 ++k;
532 if (k)
533 trace("%.*s\n", k * 4, output);
536 static void figure_add_span(struct figure *figure, unsigned int span)
538 if (figure->span_count == figure->spans_size)
540 figure->spans_size *= 2;
541 figure->spans = HeapReAlloc(GetProcessHeap(), 0, figure->spans,
542 figure->spans_size * sizeof(*figure->spans));
545 figure->spans[figure->span_count++] = span;
548 static void deserialize_span(struct figure *figure, unsigned int *current, unsigned int *shift, unsigned int c)
550 *current |= (c & 0x7f) << *shift;
551 if (c & 0x80)
553 *shift += 7;
554 return;
557 if (*current)
558 figure_add_span(figure, *current);
559 *current = 0;
560 *shift = 0;
563 static void deserialize_figure(struct figure *figure, const BYTE *s)
565 static const BYTE lookup[] =
567 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
568 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
569 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
570 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
571 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
572 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
573 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
574 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
576 unsigned int current = 0, shift = 0;
577 const BYTE *ptr;
578 BYTE x, y;
580 figure->span_count = 0;
581 figure->spans_size = 64;
582 figure->spans = HeapAlloc(GetProcessHeap(), 0, figure->spans_size * sizeof(*figure->spans));
584 for (ptr = s; *ptr; ptr += 4)
586 x = lookup[ptr[0]];
587 y = lookup[ptr[1]];
588 deserialize_span(figure, &current, &shift, ((x & 0x3f) << 2) | ((y & 0x3f) >> 4));
589 x = lookup[ptr[2]];
590 deserialize_span(figure, &current, &shift, ((y & 0x0f) << 4) | ((x & 0x3f) >> 2));
591 y = lookup[ptr[3]];
592 deserialize_span(figure, &current, &shift, ((x & 0x03) << 6) | (y & 0x3f));
596 static void read_figure(struct figure *figure, BYTE *data, unsigned int pitch,
597 unsigned int x, unsigned int y, unsigned int w, unsigned int h, DWORD prev)
599 unsigned int i, j, span;
601 figure->span_count = 0;
602 for (i = 0, span = 0; i < h; ++i)
604 const DWORD *row = (DWORD *)&data[(y + i) * pitch + x * 4];
605 for (j = 0; j < w; ++j, ++span)
607 if ((i || j) && prev != row[j])
609 figure_add_span(figure, span);
610 prev = row[j];
611 span = 0;
615 if (span)
616 figure_add_span(figure, span);
619 static BOOL compare_figure(IDXGISurface *surface, unsigned int x, unsigned int y,
620 unsigned int w, unsigned int h, DWORD prev, unsigned int max_diff, const char *ref)
622 struct figure ref_figure, figure;
623 unsigned int i, j, span, diff;
624 struct resource_readback rb;
626 get_surface_readback(surface, &rb);
628 figure.span_count = 0;
629 figure.spans_size = 64;
630 figure.spans = HeapAlloc(GetProcessHeap(), 0, figure.spans_size * sizeof(*figure.spans));
632 read_figure(&figure, rb.map_desc.pData, rb.map_desc.RowPitch, x, y, w, h, prev);
634 deserialize_figure(&ref_figure, (BYTE *)ref);
635 span = w * h;
636 for (i = 0; i < ref_figure.span_count; ++i)
638 span -= ref_figure.spans[i];
640 if (span)
641 figure_add_span(&ref_figure, span);
643 for (i = 0, j = 0, diff = 0; i < figure.span_count && j < ref_figure.span_count;)
645 if (figure.spans[i] == ref_figure.spans[j])
647 if ((i ^ j) & 1)
648 diff += ref_figure.spans[j];
649 ++i;
650 ++j;
652 else if (figure.spans[i] > ref_figure.spans[j])
654 if ((i ^ j) & 1)
655 diff += ref_figure.spans[j];
656 figure.spans[i] -= ref_figure.spans[j];
657 ++j;
659 else
661 if ((i ^ j) & 1)
662 diff += figure.spans[i];
663 ref_figure.spans[j] -= figure.spans[i];
664 ++i;
667 if (diff > max_diff)
669 trace("diff %u > max_diff %u.\n", diff, max_diff);
670 read_figure(&figure, rb.map_desc.pData, rb.map_desc.RowPitch, x, y, w, h, prev);
671 serialize_figure(&figure);
674 HeapFree(GetProcessHeap(), 0, ref_figure.spans);
675 HeapFree(GetProcessHeap(), 0, figure.spans);
676 release_resource_readback(&rb);
678 return diff <= max_diff;
681 static ID3D10Device1 *create_device(void)
683 ID3D10Device1 *device;
685 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL,
686 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
687 return device;
688 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_WARP, NULL,
689 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
690 return device;
691 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL,
692 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
693 return device;
695 return NULL;
698 static HWND create_window(void)
700 RECT r = {0, 0, 640, 480};
702 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
704 return CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
705 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
708 static IDXGISwapChain *create_swapchain(ID3D10Device1 *device, HWND window, BOOL windowed)
710 IDXGISwapChain *swapchain;
711 DXGI_SWAP_CHAIN_DESC desc;
712 IDXGIDevice *dxgi_device;
713 IDXGIAdapter *adapter;
714 IDXGIFactory *factory;
715 HRESULT hr;
717 hr = ID3D10Device1_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
718 ok(SUCCEEDED(hr), "Failed to get DXGI device, hr %#x.\n", hr);
719 hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter);
720 ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr);
721 IDXGIDevice_Release(dxgi_device);
722 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
723 ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr);
724 IDXGIAdapter_Release(adapter);
726 desc.BufferDesc.Width = 640;
727 desc.BufferDesc.Height = 480;
728 desc.BufferDesc.RefreshRate.Numerator = 60;
729 desc.BufferDesc.RefreshRate.Denominator = 1;
730 desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
731 desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
732 desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
733 desc.SampleDesc.Count = 1;
734 desc.SampleDesc.Quality = 0;
735 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
736 desc.BufferCount = 1;
737 desc.OutputWindow = window;
738 desc.Windowed = windowed;
739 desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
740 desc.Flags = 0;
742 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &desc, &swapchain);
743 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
744 IDXGIFactory_Release(factory);
746 return swapchain;
749 static ID2D1RenderTarget *create_render_target_desc(IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
751 ID2D1RenderTarget *render_target;
752 ID2D1Factory *factory;
753 HRESULT hr;
755 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
756 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
757 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, desc, &render_target);
758 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
759 ID2D1Factory_Release(factory);
761 return render_target;
764 static ID2D1RenderTarget *create_render_target(IDXGISurface *surface)
766 D2D1_RENDER_TARGET_PROPERTIES desc;
768 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
769 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
770 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
771 desc.dpiX = 0.0f;
772 desc.dpiY = 0.0f;
773 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
774 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
776 return create_render_target_desc(surface, &desc);
779 #define check_bitmap_surface(b, s, o) check_bitmap_surface_(__LINE__, b, s, o)
780 static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL has_surface, DWORD expected_options)
782 D2D1_BITMAP_OPTIONS options;
783 IDXGISurface *surface;
784 ID2D1Bitmap1 *bitmap1;
785 HRESULT hr;
787 hr = ID2D1Bitmap_QueryInterface(bitmap, &IID_ID2D1Bitmap1, (void **)&bitmap1);
788 if (FAILED(hr))
789 return;
791 options = ID2D1Bitmap1_GetOptions(bitmap1);
792 ok_(__FILE__, line)(options == expected_options, "Unexpected bitmap options %#x, expected %#x.\n",
793 options, expected_options);
795 surface = (void *)0xdeadbeef;
796 hr = ID2D1Bitmap1_GetSurface(bitmap1, &surface);
797 if (has_surface)
799 D3D10_TEXTURE2D_DESC desc;
800 ID3D10Texture2D *texture;
801 D2D1_SIZE_U pixel_size;
802 DWORD bind_flags = 0;
804 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get bitmap surface, hr %#x.\n", hr);
805 ok_(__FILE__, line)(!!surface, "Expected surface instance.\n");
807 /* Correlate with resource configuration. */
808 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Texture2D, (void **)&texture);
809 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get texture pointer, hr %#x.\n", hr);
811 ID3D10Texture2D_GetDesc(texture, &desc);
812 ok_(__FILE__, line)(desc.Usage == 0, "Unexpected usage %#x.\n", desc.Usage);
814 if (options & D2D1_BITMAP_OPTIONS_TARGET)
815 bind_flags |= D3D10_BIND_RENDER_TARGET;
816 if (!(options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW))
817 bind_flags |= D3D10_BIND_SHADER_RESOURCE;
819 ok_(__FILE__, line)(desc.BindFlags == bind_flags, "Unexpected bind flags %#x for bitmap options %#x.\n",
820 desc.BindFlags, options);
821 ok_(__FILE__, line)(!desc.CPUAccessFlags, "Unexpected cpu access flags %#x.\n", desc.CPUAccessFlags);
822 ok_(__FILE__, line)(!desc.MiscFlags, "Unexpected misc flags %#x.\n", desc.MiscFlags);
824 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
825 if (!pixel_size.width || !pixel_size.height)
826 pixel_size.width = pixel_size.height = 1;
827 ok_(__FILE__, line)(desc.Width == pixel_size.width, "Got width %u, expected %u.\n",
828 desc.Width, pixel_size.width);
829 ok_(__FILE__, line)(desc.Height == pixel_size.height, "Got height %u, expected %u.\n",
830 desc.Height, pixel_size.height);
832 ID3D10Texture2D_Release(texture);
834 IDXGISurface_Release(surface);
836 else
838 ok_(__FILE__, line)(hr == D2DERR_INVALID_CALL, "Unexpected hr %#x.\n", hr);
839 ok_(__FILE__, line)(!surface, "Unexpected surface instance.\n");
842 ID2D1Bitmap1_Release(bitmap1);
845 static inline struct geometry_sink *impl_from_ID2D1SimplifiedGeometrySink(ID2D1SimplifiedGeometrySink *iface)
847 return CONTAINING_RECORD(iface, struct geometry_sink, ID2D1SimplifiedGeometrySink_iface);
850 static HRESULT STDMETHODCALLTYPE geometry_sink_QueryInterface(ID2D1SimplifiedGeometrySink *iface,
851 REFIID iid, void **out)
853 if (IsEqualGUID(iid, &IID_ID2D1SimplifiedGeometrySink)
854 || IsEqualGUID(iid, &IID_IUnknown))
856 *out = iface;
857 return S_OK;
860 *out = NULL;
861 return E_NOINTERFACE;
864 static ULONG STDMETHODCALLTYPE geometry_sink_AddRef(ID2D1SimplifiedGeometrySink *iface)
866 return 0;
869 static ULONG STDMETHODCALLTYPE geometry_sink_Release(ID2D1SimplifiedGeometrySink *iface)
871 return 0;
874 static void STDMETHODCALLTYPE geometry_sink_SetFillMode(ID2D1SimplifiedGeometrySink *iface, D2D1_FILL_MODE mode)
876 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
878 sink->fill_mode = mode;
881 static void STDMETHODCALLTYPE geometry_sink_SetSegmentFlags(ID2D1SimplifiedGeometrySink *iface,
882 D2D1_PATH_SEGMENT flags)
884 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
886 sink->segment_flags = flags;
889 static void STDMETHODCALLTYPE geometry_sink_BeginFigure(ID2D1SimplifiedGeometrySink *iface,
890 D2D1_POINT_2F start_point, D2D1_FIGURE_BEGIN figure_begin)
892 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
893 struct geometry_figure *figure;
895 if (sink->figure_count == sink->figures_size)
897 sink->figures_size *= 2;
898 sink->figures = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sink->figures,
899 sink->figures_size * sizeof(*sink->figures));
901 figure = &sink->figures[sink->figure_count++];
903 figure->begin = figure_begin;
904 figure->start_point = start_point;
905 figure->segments_size = 4;
906 figure->segments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
907 figure->segments_size * sizeof(*figure->segments));
910 static struct geometry_segment *geometry_figure_add_segment(struct geometry_figure *figure)
912 if (figure->segment_count == figure->segments_size)
914 figure->segments_size *= 2;
915 figure->segments = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, figure->segments,
916 figure->segments_size * sizeof(*figure->segments));
918 return &figure->segments[figure->segment_count++];
921 static void STDMETHODCALLTYPE geometry_sink_AddLines(ID2D1SimplifiedGeometrySink *iface,
922 const D2D1_POINT_2F *points, UINT32 count)
924 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
925 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
926 struct geometry_segment *segment;
927 unsigned int i;
929 for (i = 0; i < count; ++i)
931 segment = geometry_figure_add_segment(figure);
932 segment->type = SEGMENT_LINE;
933 segment->u.line = points[i];
934 segment->flags = sink->segment_flags;
938 static void STDMETHODCALLTYPE geometry_sink_AddBeziers(ID2D1SimplifiedGeometrySink *iface,
939 const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
941 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
942 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
943 struct geometry_segment *segment;
944 unsigned int i;
946 for (i = 0; i < count; ++i)
948 segment = geometry_figure_add_segment(figure);
949 segment->type = SEGMENT_BEZIER;
950 segment->u.bezier = beziers[i];
951 segment->flags = sink->segment_flags;
955 static void STDMETHODCALLTYPE geometry_sink_EndFigure(ID2D1SimplifiedGeometrySink *iface,
956 D2D1_FIGURE_END figure_end)
958 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
959 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
961 figure->end = figure_end;
964 static HRESULT STDMETHODCALLTYPE geometry_sink_Close(ID2D1SimplifiedGeometrySink *iface)
966 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
968 sink->closed = TRUE;
970 return S_OK;
973 static const struct ID2D1SimplifiedGeometrySinkVtbl geometry_sink_vtbl =
975 geometry_sink_QueryInterface,
976 geometry_sink_AddRef,
977 geometry_sink_Release,
978 geometry_sink_SetFillMode,
979 geometry_sink_SetSegmentFlags,
980 geometry_sink_BeginFigure,
981 geometry_sink_AddLines,
982 geometry_sink_AddBeziers,
983 geometry_sink_EndFigure,
984 geometry_sink_Close,
987 static void geometry_sink_init(struct geometry_sink *sink)
989 memset(sink, 0, sizeof(*sink));
990 sink->ID2D1SimplifiedGeometrySink_iface.lpVtbl = &geometry_sink_vtbl;
991 sink->figures_size = 4;
992 sink->figures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
993 sink->figures_size * sizeof(*sink->figures));
996 static void geometry_sink_cleanup(struct geometry_sink *sink)
998 unsigned int i;
1000 for (i = 0; i < sink->figure_count; ++i)
1002 HeapFree(GetProcessHeap(), 0, sink->figures[i].segments);
1004 HeapFree(GetProcessHeap(), 0, sink->figures);
1007 #define geometry_sink_check(a, b, c, d, e) geometry_sink_check_(__LINE__, a, b, c, d, e)
1008 static void geometry_sink_check_(unsigned int line, const struct geometry_sink *sink, D2D1_FILL_MODE fill_mode,
1009 unsigned int figure_count, const struct expected_geometry_figure *expected_figures, unsigned int ulps)
1011 const struct geometry_segment *segment, *expected_segment;
1012 const struct expected_geometry_figure *expected_figure;
1013 const struct geometry_figure *figure;
1014 unsigned int i, j;
1015 BOOL match;
1017 ok_(__FILE__, line)(sink->fill_mode == fill_mode,
1018 "Got unexpected fill mode %#x.\n", sink->fill_mode);
1019 ok_(__FILE__, line)(sink->figure_count == figure_count,
1020 "Got unexpected figure count %u, expected %u.\n", sink->figure_count, figure_count);
1021 ok_(__FILE__, line)(!sink->closed, "Sink is closed.\n");
1023 for (i = 0; i < figure_count; ++i)
1025 expected_figure = &expected_figures[i];
1026 figure = &sink->figures[i];
1028 ok_(__FILE__, line)(figure->begin == expected_figure->begin,
1029 "Got unexpected figure %u begin %#x, expected %#x.\n",
1030 i, figure->begin, expected_figure->begin);
1031 ok_(__FILE__, line)(figure->end == expected_figure->end,
1032 "Got unexpected figure %u end %#x, expected %#x.\n",
1033 i, figure->end, expected_figure->end);
1034 match = compare_point(&figure->start_point,
1035 expected_figure->start_point.x, expected_figure->start_point.y, ulps);
1036 ok_(__FILE__, line)(match, "Got unexpected figure %u start point {%.8e, %.8e}, expected {%.8e, %.8e}.\n",
1037 i, figure->start_point.x, figure->start_point.y,
1038 expected_figure->start_point.x, expected_figure->start_point.y);
1039 ok_(__FILE__, line)(figure->segment_count == expected_figure->segment_count,
1040 "Got unexpected figure %u segment count %u, expected %u.\n",
1041 i, figure->segment_count, expected_figure->segment_count);
1043 for (j = 0; j < figure->segment_count; ++j)
1045 expected_segment = &expected_figure->segments[j];
1046 segment = &figure->segments[j];
1047 ok_(__FILE__, line)(segment->type == expected_segment->type,
1048 "Got unexpected figure %u, segment %u type %#x, expected %#x.\n",
1049 i, j, segment->type, expected_segment->type);
1050 ok_(__FILE__, line)(segment->flags == expected_segment->flags,
1051 "Got unexpected figure %u, segment %u flags %#x, expected %#x.\n",
1052 i, j, segment->flags, expected_segment->flags);
1053 switch (segment->type)
1055 case SEGMENT_LINE:
1056 match = compare_point(&segment->u.line,
1057 expected_segment->u.line.x, expected_segment->u.line.y, ulps);
1058 ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u {%.8e, %.8e}, "
1059 "expected {%.8e, %.8e}.\n",
1060 i, j, segment->u.line.x, segment->u.line.y,
1061 expected_segment->u.line.x, expected_segment->u.line.y);
1062 break;
1064 case SEGMENT_BEZIER:
1065 match = compare_bezier_segment(&segment->u.bezier,
1066 expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
1067 expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
1068 expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y,
1069 ulps);
1070 ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u "
1071 "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}, "
1072 "expected {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1073 i, j, segment->u.bezier.point1.x, segment->u.bezier.point1.y,
1074 segment->u.bezier.point2.x, segment->u.bezier.point2.y,
1075 segment->u.bezier.point3.x, segment->u.bezier.point3.y,
1076 expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
1077 expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
1078 expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y);
1079 break;
1085 static void test_clip(void)
1087 IDXGISwapChain *swapchain;
1088 D2D1_MATRIX_3X2_F matrix;
1089 D2D1_SIZE_U pixel_size;
1090 ID2D1RenderTarget *rt;
1091 ID3D10Device1 *device;
1092 IDXGISurface *surface;
1093 D2D1_POINT_2F point;
1094 D2D1_COLOR_F color;
1095 float dpi_x, dpi_y;
1096 D2D1_RECT_F rect;
1097 D2D1_SIZE_F size;
1098 HWND window;
1099 HRESULT hr;
1100 BOOL match;
1101 static const D2D1_MATRIX_3X2_F identity =
1103 1.0f, 0.0f,
1104 0.0f, 1.0f,
1105 0.0f, 0.0f,
1106 }}};
1108 if (!(device = create_device()))
1110 skip("Failed to create device, skipping tests.\n");
1111 return;
1113 window = create_window();
1114 swapchain = create_swapchain(device, window, TRUE);
1115 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1116 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1117 rt = create_render_target(surface);
1118 ok(!!rt, "Failed to create render target.\n");
1120 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1121 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1122 ok(dpi_y == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
1123 size = ID2D1RenderTarget_GetSize(rt);
1124 ok(size.width == 640.0f, "Got unexpected width %.8e.\n", size.width);
1125 ok(size.height == 480.0f, "Got unexpected height %.8e.\n", size.height);
1126 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
1127 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
1128 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
1130 ID2D1RenderTarget_GetTransform(rt, &matrix);
1131 ok(!memcmp(&matrix, &identity, sizeof(matrix)),
1132 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1133 matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32);
1135 ID2D1RenderTarget_BeginDraw(rt);
1137 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
1138 ID2D1RenderTarget_Clear(rt, &color);
1140 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
1141 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1142 ok(dpi_x == 48.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1143 ok(dpi_y == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
1144 size = ID2D1RenderTarget_GetSize(rt);
1145 ok(size.width == 1280.0f, "Got unexpected width %.8e.\n", size.width);
1146 ok(size.height == 240.0f, "Got unexpected height %.8e.\n", size.height);
1147 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
1148 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
1149 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
1151 /* The effective clip rect is the intersection of all currently pushed
1152 * clip rects. Clip rects are in DIPs. */
1153 set_rect(&rect, 0.0f, 0.0f, 1280.0f, 80.0f);
1154 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1155 set_rect(&rect, 0.0f, 0.0f, 426.0f, 240.0f);
1156 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1158 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
1159 ID2D1RenderTarget_Clear(rt, &color);
1160 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1161 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1163 ID2D1RenderTarget_SetDpi(rt, 0.0f, 0.0f);
1164 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1165 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1166 ok(dpi_y == 96.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1168 ID2D1RenderTarget_SetDpi(rt, 192.0f, 192.0f);
1169 ID2D1RenderTarget_SetDpi(rt, 0.0f, 96.0f);
1170 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1171 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1172 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1174 ID2D1RenderTarget_SetDpi(rt, -10.0f, 96.0f);
1175 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1176 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1177 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1179 ID2D1RenderTarget_SetDpi(rt, 96.0f, -10.0f);
1180 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1181 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1182 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1184 ID2D1RenderTarget_SetDpi(rt, 96.0f, 0.0f);
1185 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1186 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1187 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1189 ID2D1RenderTarget_SetDpi(rt, 96.0f, 96.0f);
1191 /* Transformations apply to clip rects, the effective clip rect is the
1192 * (axis-aligned) bounding box of the transformed clip rect. */
1193 set_point(&point, 320.0f, 240.0f);
1194 D2D1MakeRotateMatrix(30.0f, point, &matrix);
1195 ID2D1RenderTarget_SetTransform(rt, &matrix);
1196 set_rect(&rect, 215.0f, 208.0f, 425.0f, 272.0f);
1197 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1198 set_color(&color, 1.0f, 1.0f, 1.0f, 1.0f);
1199 ID2D1RenderTarget_Clear(rt, &color);
1200 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1202 /* Transformations are applied when pushing the clip rect, transformations
1203 * set afterwards have no effect on the current clip rect. This includes
1204 * SetDpi(). */
1205 ID2D1RenderTarget_SetTransform(rt, &identity);
1206 set_rect(&rect, 427.0f, 320.0f, 640.0f, 480.0f);
1207 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1208 ID2D1RenderTarget_SetTransform(rt, &matrix);
1209 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
1210 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
1211 ID2D1RenderTarget_Clear(rt, &color);
1212 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1214 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1215 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1216 match = compare_surface(surface, "035a44d4198d6e422e9de6185b5b2c2bac5e33c9");
1217 ok(match, "Surface does not match.\n");
1219 /* Fractional clip rectangle coordinates, aliased mode. */
1220 set_matrix_identity(&matrix);
1221 ID2D1RenderTarget_SetTransform(rt, &matrix);
1222 ID2D1RenderTarget_SetDpi(rt, 96.0f, 96.0f);
1224 ID2D1RenderTarget_BeginDraw(rt);
1226 set_color(&color, 0.0f, 0.0f, 0.0f, 1.0f);
1227 ID2D1RenderTarget_Clear(rt, &color);
1229 scale_matrix(&matrix, 2.0f, 2.0f);
1230 ID2D1RenderTarget_SetTransform(rt, &matrix);
1231 set_rect(&rect, 0.0f, 0.5f, 200.0f, 100.5f);
1232 set_color(&color, 1.0f, 0.0f, 1.0f, 1.0f);
1233 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1234 ID2D1RenderTarget_Clear(rt, &color);
1235 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1237 set_matrix_identity(&matrix);
1238 ID2D1RenderTarget_SetTransform(rt, &matrix);
1239 set_rect(&rect, 0.0f, 0.5f, 100.0f, 200.5f);
1240 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
1241 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1242 ID2D1RenderTarget_Clear(rt, &color);
1243 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1245 ID2D1RenderTarget_SetTransform(rt, &matrix);
1246 set_rect(&rect, 0.5f, 250.0f, 100.5f, 300.0f);
1247 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
1248 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1249 ID2D1RenderTarget_Clear(rt, &color);
1250 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1252 translate_matrix(&matrix, 0.1f, 0.0f);
1253 ID2D1RenderTarget_SetTransform(rt, &matrix);
1254 set_rect(&rect, 110.0f, 250.25f, 150.0f, 300.25f);
1255 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
1256 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1257 ID2D1RenderTarget_Clear(rt, &color);
1258 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1260 set_rect(&rect, 160.0f, 250.75f, 200.0f, 300.75f);
1261 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1262 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1263 ID2D1RenderTarget_Clear(rt, &color);
1264 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1266 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
1267 set_rect(&rect, 160.25f, 0.0f, 200.25f, 100.0f);
1268 set_color(&color, 1.0f, 0.0f, 1.0f, 1.0f);
1269 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1270 ID2D1RenderTarget_Clear(rt, &color);
1271 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1273 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1274 set_rect(&rect, 160.75f, 100.0f, 200.75f, 120.0f);
1275 set_color(&color, 0.0f, 1.0f, 1.0f, 1.0f);
1276 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1277 ID2D1RenderTarget_Clear(rt, &color);
1278 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1280 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1281 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1282 match = compare_surface(surface, "cb418ec4a7c8407b5e36db06fc6292a06bb8476c");
1283 ok(match, "Surface does not match.\n");
1285 ID2D1RenderTarget_Release(rt);
1286 IDXGISurface_Release(surface);
1287 IDXGISwapChain_Release(swapchain);
1288 ID3D10Device1_Release(device);
1289 DestroyWindow(window);
1292 static void test_state_block(void)
1294 IDWriteRenderingParams *text_rendering_params1, *text_rendering_params2;
1295 D2D1_DRAWING_STATE_DESCRIPTION drawing_state;
1296 ID2D1DrawingStateBlock *state_block;
1297 IDWriteFactory *dwrite_factory;
1298 IDXGISwapChain *swapchain;
1299 ID2D1Factory1 *factory1;
1300 ID2D1RenderTarget *rt;
1301 ID3D10Device1 *device;
1302 IDXGISurface *surface;
1303 ID2D1Factory *factory;
1304 ULONG refcount;
1305 HWND window;
1306 HRESULT hr;
1307 static const D2D1_MATRIX_3X2_F identity =
1309 1.0f, 0.0f,
1310 0.0f, 1.0f,
1311 0.0f, 0.0f,
1312 }}};
1313 static const D2D1_MATRIX_3X2_F transform1 =
1315 1.0f, 2.0f,
1316 3.0f, 4.0f,
1317 5.0f, 6.0f,
1318 }}};
1319 static const D2D1_MATRIX_3X2_F transform2 =
1321 7.0f, 8.0f,
1322 9.0f, 10.0f,
1323 11.0f, 12.0f,
1324 }}};
1326 if (!(device = create_device()))
1328 skip("Failed to create device, skipping tests.\n");
1329 return;
1331 window = create_window();
1332 swapchain = create_swapchain(device, window, TRUE);
1333 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1334 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1335 rt = create_render_target(surface);
1336 ok(!!rt, "Failed to create render target.\n");
1337 ID2D1RenderTarget_GetFactory(rt, &factory);
1338 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
1339 ok(SUCCEEDED(hr), "Failed to create dwrite factory, hr %#x.\n", hr);
1340 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &text_rendering_params1);
1341 ok(SUCCEEDED(hr), "Failed to create dwrite rendering params, hr %#x.\n", hr);
1342 IDWriteFactory_Release(dwrite_factory);
1344 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1345 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1346 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1347 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1348 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
1349 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1350 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1351 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %s:%s.\n",
1352 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1353 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1354 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
1355 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1356 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1357 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1358 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1359 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1361 hr = ID2D1Factory_CreateDrawingStateBlock(factory, NULL, NULL, &state_block);
1362 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
1363 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1364 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1365 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1366 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
1367 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1368 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %s:%s.\n",
1369 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1370 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
1371 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1372 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1373 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1374 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1375 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1376 ID2D1DrawingStateBlock_Release(state_block);
1378 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
1379 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
1380 drawing_state.tag1 = 0xdead;
1381 drawing_state.tag2 = 0xbeef;
1382 drawing_state.transform = transform1;
1383 hr = ID2D1Factory_CreateDrawingStateBlock(factory, &drawing_state, text_rendering_params1, &state_block);
1384 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
1386 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1387 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1388 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1389 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
1390 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1391 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %s:%s.\n",
1392 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1393 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1394 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1395 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1396 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1397 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1398 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1399 text_rendering_params2, text_rendering_params1);
1400 IDWriteRenderingParams_Release(text_rendering_params2);
1402 ID2D1RenderTarget_RestoreDrawingState(rt, state_block);
1404 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1405 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1406 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1407 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1408 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
1409 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1410 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1411 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %s:%s.\n",
1412 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1413 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1414 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1415 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1416 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1417 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1418 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1419 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1420 text_rendering_params2, text_rendering_params1);
1421 IDWriteRenderingParams_Release(text_rendering_params2);
1423 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
1424 ID2D1RenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
1425 ID2D1RenderTarget_SetTags(rt, 1, 2);
1426 ID2D1RenderTarget_SetTransform(rt, &transform2);
1427 ID2D1RenderTarget_SetTextRenderingParams(rt, NULL);
1429 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1430 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1431 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1432 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1433 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
1434 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1435 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1436 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %s:%s.\n",
1437 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1438 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1439 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
1440 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1441 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1442 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1443 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1444 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1446 ID2D1RenderTarget_SaveDrawingState(rt, state_block);
1448 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1449 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1450 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1451 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
1452 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1453 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %s:%s.\n",
1454 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1455 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
1456 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1457 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1458 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1459 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1460 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1462 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
1463 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1464 drawing_state.tag1 = 3;
1465 drawing_state.tag2 = 4;
1466 drawing_state.transform = transform1;
1467 ID2D1DrawingStateBlock_SetDescription(state_block, &drawing_state);
1468 ID2D1DrawingStateBlock_SetTextRenderingParams(state_block, text_rendering_params1);
1470 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1471 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1472 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1473 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE,
1474 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1475 ok(drawing_state.tag1 == 3 && drawing_state.tag2 == 4, "Got unexpected tags %s:%s.\n",
1476 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1477 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1478 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1479 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1480 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1481 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1482 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1483 text_rendering_params2, text_rendering_params1);
1484 IDWriteRenderingParams_Release(text_rendering_params2);
1486 if (SUCCEEDED(ID2D1Factory_QueryInterface(factory, &IID_ID2D1Factory1, (void **)&factory1)))
1488 D2D1_DRAWING_STATE_DESCRIPTION1 drawing_state1;
1489 ID2D1DrawingStateBlock1 *state_block1;
1491 hr = ID2D1DrawingStateBlock_QueryInterface(state_block, &IID_ID2D1DrawingStateBlock1, (void **)&state_block1);
1492 ok(SUCCEEDED(hr), "Failed to get ID2D1DrawingStateBlock1 interface, hr %#x.\n", hr);
1494 ID2D1DrawingStateBlock1_GetDescription(state_block1, &drawing_state1);
1495 ok(drawing_state1.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1496 "Got unexpected antialias mode %#x.\n", drawing_state1.antialiasMode);
1497 ok(drawing_state1.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE,
1498 "Got unexpected text antialias mode %#x.\n", drawing_state1.textAntialiasMode);
1499 ok(drawing_state1.tag1 == 3 && drawing_state1.tag2 == 4, "Got unexpected tags %s:%s.\n",
1500 wine_dbgstr_longlong(drawing_state1.tag1), wine_dbgstr_longlong(drawing_state1.tag2));
1501 ok(!memcmp(&drawing_state1.transform, &transform1, sizeof(drawing_state1.transform)),
1502 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1503 drawing_state1.transform._11, drawing_state1.transform._12, drawing_state1.transform._21,
1504 drawing_state1.transform._22, drawing_state1.transform._31, drawing_state1.transform._32);
1505 ok(drawing_state1.primitiveBlend == D2D1_PRIMITIVE_BLEND_SOURCE_OVER,
1506 "Got unexpected primitive blend mode %#x.\n", drawing_state1.primitiveBlend);
1507 ok(drawing_state1.unitMode == D2D1_UNIT_MODE_DIPS, "Got unexpected unit mode %#x.\n", drawing_state1.unitMode);
1508 ID2D1DrawingStateBlock1_GetTextRenderingParams(state_block1, &text_rendering_params2);
1509 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1510 text_rendering_params2, text_rendering_params1);
1511 IDWriteRenderingParams_Release(text_rendering_params2);
1513 drawing_state1.primitiveBlend = D2D1_PRIMITIVE_BLEND_COPY;
1514 drawing_state1.unitMode = D2D1_UNIT_MODE_PIXELS;
1515 ID2D1DrawingStateBlock1_SetDescription(state_block1, &drawing_state1);
1516 ID2D1DrawingStateBlock1_GetDescription(state_block1, &drawing_state1);
1517 ok(drawing_state1.primitiveBlend == D2D1_PRIMITIVE_BLEND_COPY,
1518 "Got unexpected primitive blend mode %#x.\n", drawing_state1.primitiveBlend);
1519 ok(drawing_state1.unitMode == D2D1_UNIT_MODE_PIXELS,
1520 "Got unexpected unit mode %#x.\n", drawing_state1.unitMode);
1522 ID2D1DrawingStateBlock_SetDescription(state_block, &drawing_state);
1523 ID2D1DrawingStateBlock1_GetDescription(state_block1, &drawing_state1);
1524 ok(drawing_state1.primitiveBlend == D2D1_PRIMITIVE_BLEND_COPY,
1525 "Got unexpected primitive blend mode %#x.\n", drawing_state1.primitiveBlend);
1526 ok(drawing_state1.unitMode == D2D1_UNIT_MODE_PIXELS,
1527 "Got unexpected unit mode %#x.\n", drawing_state1.unitMode);
1529 ID2D1DrawingStateBlock1_Release(state_block1);
1531 hr = ID2D1Factory1_CreateDrawingStateBlock(factory1, NULL, NULL, &state_block1);
1532 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
1533 ID2D1DrawingStateBlock1_GetDescription(state_block1, &drawing_state1);
1534 ok(drawing_state1.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1535 "Got unexpected antialias mode %#x.\n", drawing_state1.antialiasMode);
1536 ok(drawing_state1.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
1537 "Got unexpected text antialias mode %#x.\n", drawing_state1.textAntialiasMode);
1538 ok(drawing_state1.tag1 == 0 && drawing_state1.tag2 == 0, "Got unexpected tags %s:%s.\n",
1539 wine_dbgstr_longlong(drawing_state1.tag1), wine_dbgstr_longlong(drawing_state1.tag2));
1540 ok(!memcmp(&drawing_state1.transform, &identity, sizeof(drawing_state1.transform)),
1541 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1542 drawing_state1.transform._11, drawing_state1.transform._12, drawing_state1.transform._21,
1543 drawing_state1.transform._22, drawing_state1.transform._31, drawing_state1.transform._32);
1544 ok(drawing_state1.primitiveBlend == D2D1_PRIMITIVE_BLEND_SOURCE_OVER,
1545 "Got unexpected primitive blend mode %#x.\n", drawing_state1.primitiveBlend);
1546 ok(drawing_state1.unitMode == D2D1_UNIT_MODE_DIPS, "Got unexpected unit mode %#x.\n", drawing_state1.unitMode);
1547 ID2D1DrawingStateBlock1_GetTextRenderingParams(state_block1, &text_rendering_params2);
1548 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1549 ID2D1DrawingStateBlock1_Release(state_block1);
1551 ID2D1Factory1_Release(factory1);
1554 ID2D1DrawingStateBlock_Release(state_block);
1556 refcount = IDWriteRenderingParams_Release(text_rendering_params1);
1557 ok(!refcount, "Rendering params %u references left.\n", refcount);
1558 ID2D1Factory_Release(factory);
1559 ID2D1RenderTarget_Release(rt);
1560 IDXGISurface_Release(surface);
1561 IDXGISwapChain_Release(swapchain);
1562 ID3D10Device1_Release(device);
1563 DestroyWindow(window);
1566 static void test_color_brush(void)
1568 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1569 D2D1_BRUSH_PROPERTIES brush_desc;
1570 D2D1_COLOR_F color, tmp_color;
1571 ID2D1SolidColorBrush *brush;
1572 IDXGISwapChain *swapchain;
1573 ID2D1RenderTarget *rt;
1574 ID3D10Device1 *device;
1575 IDXGISurface *surface;
1576 D2D1_RECT_F rect;
1577 float opacity;
1578 HWND window;
1579 HRESULT hr;
1580 BOOL match;
1582 if (!(device = create_device()))
1584 skip("Failed to create device, skipping tests.\n");
1585 return;
1587 window = create_window();
1588 swapchain = create_swapchain(device, window, TRUE);
1589 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1590 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1591 rt = create_render_target(surface);
1592 ok(!!rt, "Failed to create render target.\n");
1594 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1595 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1597 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
1598 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
1599 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1600 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
1601 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
1602 set_matrix_identity(&matrix);
1603 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
1604 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1605 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1606 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1607 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1608 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
1609 ok(!memcmp(&tmp_color, &color, sizeof(color)),
1610 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
1611 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
1612 ID2D1SolidColorBrush_Release(brush);
1614 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
1615 brush_desc.opacity = 0.3f;
1616 set_matrix_identity(&matrix);
1617 scale_matrix(&matrix, 2.0f, 2.0f);
1618 brush_desc.transform = matrix;
1619 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, &brush_desc, &brush);
1620 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1621 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
1622 ok(opacity == 0.3f, "Got unexpected opacity %.8e.\n", opacity);
1623 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
1624 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1625 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1626 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1627 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1628 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
1629 ok(!memcmp(&tmp_color, &color, sizeof(color)),
1630 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
1631 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
1633 ID2D1RenderTarget_BeginDraw(rt);
1635 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1636 ID2D1RenderTarget_Clear(rt, &color);
1638 ID2D1SolidColorBrush_SetOpacity(brush, 1.0f);
1639 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
1640 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
1642 set_matrix_identity(&matrix);
1643 scale_matrix(&matrix, 0.5f, 2.0f);
1644 translate_matrix(&matrix, 320.0f, 240.0f);
1645 rotate_matrix(&matrix, M_PI / 4.0f);
1646 ID2D1RenderTarget_SetTransform(rt, &matrix);
1647 set_color(&color, 1.0f, 0.0f, 0.0f, 0.625f);
1648 ID2D1SolidColorBrush_SetColor(brush, &color);
1649 ID2D1SolidColorBrush_SetOpacity(brush, 0.75f);
1650 set_rect(&rect, -80.0f, -60.0f, 80.0f, 60.0f);
1651 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
1653 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1654 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1655 match = compare_surface(surface, "6d1218fca5e21fb7e287b3a439d60dbc251f5ceb");
1656 ok(match, "Surface does not match.\n");
1658 ID2D1SolidColorBrush_Release(brush);
1659 ID2D1RenderTarget_Release(rt);
1660 IDXGISurface_Release(surface);
1661 IDXGISwapChain_Release(swapchain);
1662 ID3D10Device1_Release(device);
1663 DestroyWindow(window);
1666 static void test_bitmap_brush(void)
1668 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode;
1669 ID2D1TransformedGeometry *transformed_geometry;
1670 ID2D1RectangleGeometry *rectangle_geometry;
1671 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1672 D2D1_BITMAP_PROPERTIES bitmap_desc;
1673 ID2D1Bitmap *bitmap, *tmp_bitmap;
1674 D2D1_RECT_F src_rect, dst_rect;
1675 D2D1_EXTEND_MODE extend_mode;
1676 IDXGISwapChain *swapchain;
1677 ID2D1BitmapBrush1 *brush1;
1678 ID2D1BitmapBrush *brush;
1679 D2D1_SIZE_F image_size;
1680 ID2D1RenderTarget *rt;
1681 ID3D10Device1 *device;
1682 IDXGISurface *surface;
1683 ID2D1Factory *factory;
1684 D2D1_COLOR_F color;
1685 ID2D1Image *image;
1686 D2D1_SIZE_U size;
1687 unsigned int i;
1688 ULONG refcount;
1689 float opacity;
1690 HWND window;
1691 HRESULT hr;
1692 BOOL match;
1694 static const struct
1696 D2D1_EXTEND_MODE extend_mode_x;
1697 D2D1_EXTEND_MODE extend_mode_y;
1698 float translate_x;
1699 float translate_y;
1700 D2D1_RECT_F rect;
1702 extend_mode_tests[] =
1704 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_MIRROR, -7.0f, 1.0f, {-4.0f, 0.0f, -8.0f, 4.0f}},
1705 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_MIRROR, -3.0f, 1.0f, {-4.0f, 4.0f, 0.0f, 0.0f}},
1706 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_MIRROR, 1.0f, 1.0f, { 4.0f, 0.0f, 0.0f, 4.0f}},
1707 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_WRAP, -7.0f, 5.0f, {-8.0f, 8.0f, -4.0f, 4.0f}},
1708 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP, -3.0f, 5.0f, { 0.0f, 4.0f, -4.0f, 8.0f}},
1709 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_WRAP, 1.0f, 5.0f, { 0.0f, 8.0f, 4.0f, 4.0f}},
1710 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_CLAMP, -7.0f, 9.0f, {-4.0f, 8.0f, -8.0f, 12.0f}},
1711 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, -3.0f, 9.0f, {-4.0f, 12.0f, 0.0f, 8.0f}},
1712 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_CLAMP, 1.0f, 9.0f, { 4.0f, 8.0f, 0.0f, 12.0f}},
1714 static const DWORD bitmap_data[] =
1716 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
1717 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
1718 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
1719 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
1722 if (!(device = create_device()))
1724 skip("Failed to create device, skipping tests.\n");
1725 return;
1727 window = create_window();
1728 swapchain = create_swapchain(device, window, TRUE);
1729 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1730 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1731 rt = create_render_target(surface);
1732 ok(!!rt, "Failed to create render target.\n");
1734 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1735 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1737 set_size_u(&size, 4, 4);
1738 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1739 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1740 bitmap_desc.dpiX = 96.0f;
1741 bitmap_desc.dpiY = 96.0f;
1742 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1743 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1744 image_size = ID2D1Bitmap_GetSize(bitmap);
1746 hr = ID2D1Bitmap_QueryInterface(bitmap, &IID_ID2D1Image, (void **)&image);
1747 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Vista */, "Failed to get ID2D1Image, hr %#x.\n", hr);
1748 if (hr == S_OK)
1749 ID2D1Image_Release(image);
1751 /* Creating a brush with a NULL bitmap crashes on Vista, but works fine on
1752 * Windows 7+. */
1753 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1754 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1755 ID2D1BitmapBrush_GetBitmap(brush, &tmp_bitmap);
1756 ok(tmp_bitmap == bitmap, "Got unexpected bitmap %p, expected %p.\n", tmp_bitmap, bitmap);
1757 ID2D1Bitmap_Release(tmp_bitmap);
1758 opacity = ID2D1BitmapBrush_GetOpacity(brush);
1759 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
1760 set_matrix_identity(&matrix);
1761 ID2D1BitmapBrush_GetTransform(brush, &tmp_matrix);
1762 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1763 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1764 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1765 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1766 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1767 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1768 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1769 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1770 interpolation_mode = ID2D1BitmapBrush_GetInterpolationMode(brush);
1771 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
1772 "Got unexpected interpolation mode %#x.\n", interpolation_mode);
1773 ID2D1BitmapBrush_Release(brush);
1775 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1776 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1777 set_matrix_identity(&matrix);
1778 translate_matrix(&matrix, 40.0f, 120.0f);
1779 scale_matrix(&matrix, 20.0f, 60.0f);
1780 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1781 ID2D1BitmapBrush_SetInterpolationMode(brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1783 ID2D1RenderTarget_BeginDraw(rt);
1785 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1786 ID2D1RenderTarget_Clear(rt, &color);
1788 set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
1789 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1791 set_matrix_identity(&matrix);
1792 scale_matrix(&matrix, 0.5f, 2.0f);
1793 translate_matrix(&matrix, 320.0f, 240.0f);
1794 rotate_matrix(&matrix, M_PI / 4.0f);
1795 ID2D1RenderTarget_SetTransform(rt, &matrix);
1796 set_matrix_identity(&matrix);
1797 translate_matrix(&matrix, -80.0f, -60.0f);
1798 scale_matrix(&matrix, 64.0f, 32.0f);
1799 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1800 ID2D1BitmapBrush_SetOpacity(brush, 0.75f);
1801 set_rect(&dst_rect, -80.0f, -60.0f, 80.0f, 60.0f);
1802 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1804 set_matrix_identity(&matrix);
1805 translate_matrix(&matrix, 200.0f, 120.0f);
1806 scale_matrix(&matrix, 20.0f, 60.0f);
1807 ID2D1RenderTarget_SetTransform(rt, &matrix);
1808 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f,
1809 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1810 set_rect(&dst_rect, -4.0f, 12.0f, -8.0f, 8.0f);
1811 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 0.75f,
1812 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1813 set_rect(&dst_rect, 0.0f, 8.0f, 4.0f, 12.0f);
1814 set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
1815 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1816 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1817 set_rect(&dst_rect, 4.0f, 12.0f, 12.0f, 20.0f);
1818 set_rect(&src_rect, 0.0f, 0.0f, image_size.width * 2, image_size.height * 2);
1819 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1820 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1821 set_rect(&dst_rect, 4.0f, 8.0f, 12.0f, 12.0f);
1822 set_rect(&src_rect, image_size.width / 2, image_size.height / 2, image_size.width, image_size.height);
1823 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1824 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1825 set_rect(&dst_rect, 0.0f, 4.0f, 4.0f, 8.0f);
1826 set_rect(&src_rect, image_size.width, 0.0f, 0.0f, image_size.height);
1827 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1828 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1830 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1831 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1832 match = compare_surface(surface, "f5d039c280fa33ba05496c9883192a34108efbbe");
1833 ok(match, "Surface does not match.\n");
1835 /* Invalid interpolation mode. */
1836 ID2D1RenderTarget_BeginDraw(rt);
1838 set_rect(&dst_rect, 4.0f, 8.0f, 8.0f, 12.0f);
1839 set_rect(&src_rect, 0.0f, 1.0f, image_size.width, 1.0f);
1840 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1841 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1843 set_rect(&dst_rect, 1.0f, 8.0f, 4.0f, 12.0f);
1844 set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
1845 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1846 D2D1_BITMAP_INTERPOLATION_MODE_LINEAR + 1, &src_rect);
1848 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1849 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1850 match = compare_surface(surface, "f5d039c280fa33ba05496c9883192a34108efbbe");
1851 ok(match, "Surface does not match.\n");
1853 ID2D1RenderTarget_BeginDraw(rt);
1854 ID2D1RenderTarget_Clear(rt, &color);
1856 set_rect(&src_rect, image_size.width, 0.0f, 0.0f, image_size.height);
1857 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 1.0f,
1858 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1860 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1861 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1862 match = compare_surface(surface, "59043096393570ad800dbcbfdd644394b79493bd");
1863 ok(match, "Surface does not match.\n");
1865 ID2D1RenderTarget_BeginDraw(rt);
1867 ID2D1RenderTarget_Clear(rt, &color);
1869 ID2D1BitmapBrush_SetOpacity(brush, 1.0f);
1870 for (i = 0; i < ARRAY_SIZE(extend_mode_tests); ++i)
1872 ID2D1BitmapBrush_SetExtendModeX(brush, extend_mode_tests[i].extend_mode_x);
1873 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1874 ok(extend_mode == extend_mode_tests[i].extend_mode_x,
1875 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1876 i, extend_mode, extend_mode_tests[i].extend_mode_x);
1877 ID2D1BitmapBrush_SetExtendModeY(brush, extend_mode_tests[i].extend_mode_y);
1878 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1879 ok(extend_mode == extend_mode_tests[i].extend_mode_y,
1880 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1881 i, extend_mode, extend_mode_tests[i].extend_mode_y);
1882 set_matrix_identity(&matrix);
1883 translate_matrix(&matrix, extend_mode_tests[i].translate_x, extend_mode_tests[i].translate_y);
1884 scale_matrix(&matrix, 0.5f, 0.5f);
1885 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1886 ID2D1RenderTarget_FillRectangle(rt, &extend_mode_tests[i].rect, (ID2D1Brush *)brush);
1889 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1890 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1891 match = compare_surface(surface, "b4b775afecdae2d26642001f4faff73663bb8b31");
1892 ok(match, "Surface does not match.\n");
1894 ID2D1Bitmap_Release(bitmap);
1895 bitmap_desc.dpiX = 96.0f / 20.0f;
1896 bitmap_desc.dpiY = 96.0f / 60.0f;
1897 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1898 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1899 ID2D1BitmapBrush_SetBitmap(brush, bitmap);
1901 ID2D1RenderTarget_BeginDraw(rt);
1903 ID2D1RenderTarget_Clear(rt, &color);
1905 set_matrix_identity(&matrix);
1906 translate_matrix(&matrix, 40.0f, 120.0f);
1907 skew_matrix(&matrix, 0.125f, 2.0f);
1908 ID2D1RenderTarget_SetTransform(rt, &matrix);
1909 set_matrix_identity(&matrix);
1910 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1911 set_rect(&dst_rect, 0.0f, 0.0f, 80.0f, 240.0f);
1912 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1914 ID2D1RenderTarget_GetFactory(rt, &factory);
1916 set_rect(&dst_rect, -1.0f, -1.0f, 1.0f, 1.0f);
1917 hr = ID2D1Factory_CreateRectangleGeometry(factory, &dst_rect, &rectangle_geometry);
1918 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
1920 set_matrix_identity(&matrix);
1921 translate_matrix(&matrix, 240.0f, 720.0f);
1922 scale_matrix(&matrix, 40.0f, 120.0f);
1923 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)rectangle_geometry,
1924 &matrix, &transformed_geometry);
1925 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
1926 ID2D1RectangleGeometry_Release(rectangle_geometry);
1928 set_matrix_identity(&matrix);
1929 ID2D1RenderTarget_SetTransform(rt, &matrix);
1930 set_matrix_identity(&matrix);
1931 translate_matrix(&matrix, 200.0f, 600.0f);
1932 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1933 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1934 ID2D1TransformedGeometry_Release(transformed_geometry);
1936 ID2D1Factory_Release(factory);
1938 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1939 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1940 match = compare_surface(surface, "cf7b90ba7b139fdfbe9347e1907d635cfb4ed197");
1941 ok(match, "Surface does not match.\n");
1943 if (SUCCEEDED(ID2D1BitmapBrush_QueryInterface(brush, &IID_ID2D1BitmapBrush1, (void **)&brush1)))
1945 D2D1_INTERPOLATION_MODE interpolation_mode1;
1947 interpolation_mode = ID2D1BitmapBrush1_GetInterpolationMode(brush1);
1948 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
1949 "Unexpected interpolation mode %#x.\n", interpolation_mode);
1951 interpolation_mode1 = ID2D1BitmapBrush1_GetInterpolationMode1(brush1);
1952 ok(interpolation_mode1 == D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
1953 "Unexpected interpolation mode %#x.\n", interpolation_mode1);
1955 ID2D1BitmapBrush1_SetInterpolationMode1(brush1, D2D1_INTERPOLATION_MODE_CUBIC);
1956 interpolation_mode = ID2D1BitmapBrush1_GetInterpolationMode(brush1);
1957 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
1958 "Unexpected interpolation mode %#x.\n", interpolation_mode);
1960 interpolation_mode1 = ID2D1BitmapBrush1_GetInterpolationMode1(brush1);
1961 ok(interpolation_mode1 == D2D1_INTERPOLATION_MODE_CUBIC,
1962 "Unexpected interpolation mode %#x.\n", interpolation_mode1);
1964 ID2D1BitmapBrush1_SetInterpolationMode1(brush1, 100);
1965 interpolation_mode1 = ID2D1BitmapBrush1_GetInterpolationMode1(brush1);
1966 ok(interpolation_mode1 == D2D1_INTERPOLATION_MODE_CUBIC,
1967 "Unexpected interpolation mode %#x.\n", interpolation_mode1);
1969 ID2D1BitmapBrush1_SetInterpolationMode(brush1, 100);
1970 interpolation_mode1 = ID2D1BitmapBrush1_GetInterpolationMode1(brush1);
1971 ok(interpolation_mode1 == D2D1_INTERPOLATION_MODE_CUBIC,
1972 "Unexpected interpolation mode %#x.\n", interpolation_mode1);
1974 ID2D1BitmapBrush1_SetInterpolationMode(brush1, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1975 interpolation_mode = ID2D1BitmapBrush1_GetInterpolationMode(brush1);
1976 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
1977 "Unexpected interpolation mode %#x.\n", interpolation_mode);
1979 interpolation_mode1 = ID2D1BitmapBrush1_GetInterpolationMode1(brush1);
1980 ok(interpolation_mode1 == D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
1981 "Unexpected interpolation mode %#x.\n", interpolation_mode1);
1983 ID2D1BitmapBrush1_Release(brush1);
1986 ID2D1BitmapBrush_Release(brush);
1987 refcount = ID2D1Bitmap_Release(bitmap);
1988 ok(!refcount, "Bitmap has %u references left.\n", refcount);
1989 ID2D1RenderTarget_Release(rt);
1990 IDXGISurface_Release(surface);
1991 IDXGISwapChain_Release(swapchain);
1992 ID3D10Device1_Release(device);
1993 DestroyWindow(window);
1996 static void test_linear_brush(void)
1998 D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES gradient_properties;
1999 ID2D1GradientStopCollection *gradient, *tmp_gradient;
2000 ID2D1TransformedGeometry *transformed_geometry;
2001 ID2D1RectangleGeometry *rectangle_geometry;
2002 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
2003 ID2D1LinearGradientBrush *brush;
2004 struct resource_readback rb;
2005 IDXGISwapChain *swapchain;
2006 ID2D1RenderTarget *rt;
2007 ID3D10Device1 *device;
2008 IDXGISurface *surface;
2009 ID2D1Factory *factory;
2010 D2D1_COLOR_F colour;
2011 D2D1_POINT_2F p;
2012 unsigned int i;
2013 ULONG refcount;
2014 D2D1_RECT_F r;
2015 float opacity;
2016 HWND window;
2017 HRESULT hr;
2019 static const D2D1_GRADIENT_STOP stops[] =
2021 {0.0f, {1.0f, 0.0f, 0.0f, 1.0f}},
2022 {0.5f, {0.0f, 1.0f, 0.0f, 1.0f}},
2023 {1.0f, {0.0f, 0.0f, 1.0f, 1.0f}},
2025 static const struct
2027 unsigned int x, y;
2028 DWORD colour;
2030 test1[] =
2032 {80, 80, 0xff857a00}, {240, 80, 0xff926d00}, {400, 80, 0xff9f6000}, {560, 80, 0xffac5300},
2033 {80, 240, 0xff00eb14}, {240, 240, 0xff00f807}, {400, 240, 0xff06f900}, {560, 240, 0xff13ec00},
2034 {80, 400, 0xff0053ac}, {240, 400, 0xff005fa0}, {400, 400, 0xff006c93}, {560, 400, 0xff007986},
2036 test2[] =
2038 { 40, 30, 0xff005ba4}, {120, 30, 0xffffffff}, { 40, 60, 0xffffffff}, { 80, 60, 0xff00b44b},
2039 {120, 60, 0xff006c93}, {200, 60, 0xffffffff}, { 40, 90, 0xffffffff}, {120, 90, 0xff0ef100},
2040 {160, 90, 0xff00c53a}, {200, 90, 0xffffffff}, { 80, 120, 0xffffffff}, {120, 120, 0xffaf5000},
2041 {160, 120, 0xff679800}, {200, 120, 0xff1fe000}, {240, 120, 0xffffffff}, {160, 150, 0xffffffff},
2042 {200, 150, 0xffc03e00}, {240, 150, 0xffffffff}, {280, 150, 0xffffffff}, {320, 150, 0xffffffff},
2043 {240, 180, 0xffffffff}, {280, 180, 0xffff4040}, {320, 180, 0xffff4040}, {380, 180, 0xffffffff},
2044 {200, 210, 0xffffffff}, {240, 210, 0xffa99640}, {280, 210, 0xffb28d40}, {320, 210, 0xffbb8440},
2045 {360, 210, 0xffc47b40}, {400, 210, 0xffffffff}, {200, 240, 0xffffffff}, {280, 240, 0xff41fe40},
2046 {320, 240, 0xff49f540}, {360, 240, 0xff52ec40}, {440, 240, 0xffffffff}, {240, 270, 0xffffffff},
2047 {280, 270, 0xff408eb0}, {320, 270, 0xff4097a7}, {360, 270, 0xff40a19e}, {440, 270, 0xffffffff},
2048 {280, 300, 0xffffffff}, {320, 300, 0xff4040ff}, {360, 300, 0xff4040ff}, {400, 300, 0xff406ad4},
2049 {440, 300, 0xff4061de}, {480, 300, 0xff4057e7}, {520, 300, 0xff404ef1}, {280, 330, 0xffffffff},
2050 {360, 330, 0xffffffff}, {400, 330, 0xff40c17e}, {440, 330, 0xff40b788}, {480, 330, 0xff40ae91},
2051 {520, 330, 0xff40a49b}, {400, 360, 0xff57e740}, {440, 360, 0xff4ef140}, {480, 360, 0xff44fb40},
2052 {520, 360, 0xff40fa45}, {400, 390, 0xffae9140}, {440, 390, 0xffa49b40}, {480, 390, 0xff9aa540},
2053 {520, 390, 0xff90ae40},
2056 if (!(device = create_device()))
2058 skip("Failed to create device, skipping tests.\n");
2059 return;
2061 window = create_window();
2062 swapchain = create_swapchain(device, window, TRUE);
2063 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2064 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2065 rt = create_render_target(surface);
2066 ok(!!rt, "Failed to create render target.\n");
2068 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
2069 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2071 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops, ARRAY_SIZE(stops),
2072 D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &gradient);
2073 ok(SUCCEEDED(hr), "Failed to create stop collection, hr %#x.\n", hr);
2075 set_point(&gradient_properties.startPoint, 320.0f, 0.0f);
2076 set_point(&gradient_properties.endPoint, 0.0f, 960.0f);
2077 hr = ID2D1RenderTarget_CreateLinearGradientBrush(rt, &gradient_properties, NULL, gradient, &brush);
2078 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2080 opacity = ID2D1LinearGradientBrush_GetOpacity(brush);
2081 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
2082 set_matrix_identity(&matrix);
2083 ID2D1LinearGradientBrush_GetTransform(brush, &tmp_matrix);
2084 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
2085 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2086 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
2087 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
2088 p = ID2D1LinearGradientBrush_GetStartPoint(brush);
2089 ok(compare_point(&p, 320.0f, 0.0f, 0), "Got unexpected start point {%.8e, %.8e}.\n", p.x, p.y);
2090 p = ID2D1LinearGradientBrush_GetEndPoint(brush);
2091 ok(compare_point(&p, 0.0f, 960.0f, 0), "Got unexpected end point {%.8e, %.8e}.\n", p.x, p.y);
2092 ID2D1LinearGradientBrush_GetGradientStopCollection(brush, &tmp_gradient);
2093 ok(tmp_gradient == gradient, "Got unexpected gradient %p, expected %p.\n", tmp_gradient, gradient);
2094 ID2D1GradientStopCollection_Release(tmp_gradient);
2096 ID2D1RenderTarget_BeginDraw(rt);
2098 set_color(&colour, 1.0f, 1.0f, 1.0f, 1.0f);
2099 ID2D1RenderTarget_Clear(rt, &colour);
2101 set_rect(&r, 0.0f, 0.0f, 320.0f, 960.0f);
2102 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2104 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2105 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2107 get_surface_readback(surface, &rb);
2108 for (i = 0; i < ARRAY_SIZE(test1); ++i)
2110 DWORD colour;
2112 colour = get_readback_colour(&rb, test1[i].x, test1[i].y);
2113 ok(compare_colour(colour, test1[i].colour, 1),
2114 "Got unexpected colour 0x%08x at position {%u, %u}.\n",
2115 colour, test1[i].x, test1[i].y);
2117 release_resource_readback(&rb);
2119 ID2D1RenderTarget_BeginDraw(rt);
2121 ID2D1RenderTarget_Clear(rt, &colour);
2123 set_matrix_identity(&matrix);
2124 skew_matrix(&matrix, 0.2146f, 1.575f);
2125 ID2D1RenderTarget_SetTransform(rt, &matrix);
2127 set_matrix_identity(&matrix);
2128 translate_matrix(&matrix, 0.0f, 240.0f);
2129 scale_matrix(&matrix, 0.25f, -0.25f);
2130 ID2D1LinearGradientBrush_SetTransform(brush, &matrix);
2132 set_rect(&r, 0.0f, 0.0f, 80.0f, 240.0f);
2133 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2135 set_matrix_identity(&matrix);
2136 scale_matrix(&matrix, 0.5f, 2.0f);
2137 translate_matrix(&matrix, 320.0f, 240.0f);
2138 rotate_matrix(&matrix, M_PI / 4.0f);
2139 ID2D1RenderTarget_SetTransform(rt, &matrix);
2141 set_matrix_identity(&matrix);
2142 translate_matrix(&matrix, 0.0f, -50.0f);
2143 scale_matrix(&matrix, 0.1f, 0.1f);
2144 rotate_matrix(&matrix, -M_PI / 3.0f);
2145 ID2D1LinearGradientBrush_SetTransform(brush, &matrix);
2147 ID2D1LinearGradientBrush_SetOpacity(brush, 0.75f);
2148 set_rect(&r, -80.0f, -60.0f, 80.0f, 60.0f);
2149 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2151 ID2D1RenderTarget_GetFactory(rt, &factory);
2153 set_rect(&r, -1.0f, -1.0f, 1.0f, 1.0f);
2154 hr = ID2D1Factory_CreateRectangleGeometry(factory, &r, &rectangle_geometry);
2155 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2157 set_matrix_identity(&matrix);
2158 translate_matrix(&matrix, 228.5f, 714.0f);
2159 scale_matrix(&matrix, 40.0f, 120.0f);
2160 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)rectangle_geometry,
2161 &matrix, &transformed_geometry);
2162 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2163 ID2D1RectangleGeometry_Release(rectangle_geometry);
2165 set_matrix_identity(&matrix);
2166 ID2D1RenderTarget_SetTransform(rt, &matrix);
2167 ID2D1LinearGradientBrush_SetTransform(brush, &matrix);
2168 set_point(&p, 188.5f, 834.0f);
2169 ID2D1LinearGradientBrush_SetStartPoint(brush, p);
2170 set_point(&p, 268.5f, 594.0f);
2171 ID2D1LinearGradientBrush_SetEndPoint(brush, p);
2172 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2173 ID2D1TransformedGeometry_Release(transformed_geometry);
2175 ID2D1Factory_Release(factory);
2177 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2178 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2180 get_surface_readback(surface, &rb);
2181 for (i = 0; i < ARRAY_SIZE(test2); ++i)
2183 DWORD colour;
2185 colour = get_readback_colour(&rb, test2[i].x, test2[i].y);
2186 ok(compare_colour(colour, test2[i].colour, 1),
2187 "Got unexpected colour 0x%08x at position {%u, %u}.\n",
2188 colour, test2[i].x, test2[i].y);
2190 release_resource_readback(&rb);
2192 ID2D1LinearGradientBrush_Release(brush);
2193 refcount = ID2D1GradientStopCollection_Release(gradient);
2194 ok(!refcount, "Gradient has %u references left.\n", refcount);
2195 ID2D1RenderTarget_Release(rt);
2196 IDXGISurface_Release(surface);
2197 IDXGISwapChain_Release(swapchain);
2198 ID3D10Device1_Release(device);
2199 DestroyWindow(window);
2202 static void test_radial_brush(void)
2204 D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES gradient_properties;
2205 ID2D1GradientStopCollection *gradient, *tmp_gradient;
2206 ID2D1TransformedGeometry *transformed_geometry;
2207 ID2D1RectangleGeometry *rectangle_geometry;
2208 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
2209 ID2D1RadialGradientBrush *brush;
2210 struct resource_readback rb;
2211 IDXGISwapChain *swapchain;
2212 ID2D1RenderTarget *rt;
2213 ID3D10Device1 *device;
2214 IDXGISurface *surface;
2215 ID2D1Factory *factory;
2216 D2D1_COLOR_F colour;
2217 D2D1_POINT_2F p;
2218 unsigned int i;
2219 ULONG refcount;
2220 D2D1_RECT_F r;
2221 HWND window;
2222 HRESULT hr;
2223 float f;
2225 static const D2D1_GRADIENT_STOP stops[] =
2227 {0.0f, {1.0f, 0.0f, 0.0f, 1.0f}},
2228 {0.5f, {0.0f, 1.0f, 0.0f, 1.0f}},
2229 {1.0f, {0.0f, 0.0f, 1.0f, 1.0f}},
2231 static const struct
2233 unsigned int x, y;
2234 DWORD colour;
2236 test1[] =
2238 {80, 80, 0xff0000ff}, {240, 80, 0xff00a857}, {400, 80, 0xff00d728}, {560, 80, 0xff0000ff},
2239 {80, 240, 0xff006699}, {240, 240, 0xff29d600}, {400, 240, 0xff966900}, {560, 240, 0xff00a55a},
2240 {80, 400, 0xff0000ff}, {240, 400, 0xff006e91}, {400, 400, 0xff007d82}, {560, 400, 0xff0000ff},
2242 test2[] =
2244 { 40, 30, 0xff000df2}, {120, 30, 0xffffffff}, { 40, 60, 0xffffffff}, { 80, 60, 0xff00b04f},
2245 {120, 60, 0xff007689}, {200, 60, 0xffffffff}, { 40, 90, 0xffffffff}, {120, 90, 0xff47b800},
2246 {160, 90, 0xff00c13e}, {200, 90, 0xffffffff}, { 80, 120, 0xffffffff}, {120, 120, 0xff0000ff},
2247 {160, 120, 0xff6f9000}, {200, 120, 0xff00718e}, {240, 120, 0xffffffff}, {160, 150, 0xffffffff},
2248 {200, 150, 0xff00609f}, {240, 150, 0xffffffff}, {280, 150, 0xffffffff}, {320, 150, 0xffffffff},
2249 {240, 180, 0xffffffff}, {280, 180, 0xff4040ff}, {320, 180, 0xff40b788}, {380, 180, 0xffffffff},
2250 {200, 210, 0xffffffff}, {240, 210, 0xff4040ff}, {280, 210, 0xff4040ff}, {320, 210, 0xff76c940},
2251 {360, 210, 0xff40cc73}, {400, 210, 0xffffffff}, {200, 240, 0xffffffff}, {280, 240, 0xff4061de},
2252 {320, 240, 0xff9fa040}, {360, 240, 0xff404af5}, {440, 240, 0xffffffff}, {240, 270, 0xffffffff},
2253 {280, 270, 0xff40aa95}, {320, 270, 0xff4ef140}, {360, 270, 0xff4040ff}, {440, 270, 0xffffffff},
2254 {280, 300, 0xffffffff}, {320, 300, 0xff4093ac}, {360, 300, 0xff4040ff}, {400, 300, 0xff4040ff},
2255 {440, 300, 0xff404af5}, {480, 300, 0xff4045fa}, {520, 300, 0xff4040ff}, {280, 330, 0xffffffff},
2256 {360, 330, 0xffffffff}, {400, 330, 0xff4069d6}, {440, 330, 0xff40c579}, {480, 330, 0xff40e956},
2257 {520, 330, 0xff4072cd}, {400, 360, 0xff408ab4}, {440, 360, 0xff49f540}, {480, 360, 0xffb98640},
2258 {520, 360, 0xff40dc62}, {400, 390, 0xff405ee1}, {440, 390, 0xff40d56a}, {480, 390, 0xff62dd40},
2259 {520, 390, 0xff4059e6},
2262 if (!(device = create_device()))
2264 skip("Failed to create device, skipping tests.\n");
2265 return;
2267 window = create_window();
2268 swapchain = create_swapchain(device, window, TRUE);
2269 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2270 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2271 rt = create_render_target(surface);
2272 ok(!!rt, "Failed to create render target.\n");
2274 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
2275 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2277 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops, ARRAY_SIZE(stops),
2278 D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &gradient);
2279 ok(SUCCEEDED(hr), "Failed to create stop collection, hr %#x.\n", hr);
2281 set_point(&gradient_properties.center, 160.0f, 480.0f);
2282 set_point(&gradient_properties.gradientOriginOffset, 40.0f, -120.0f);
2283 gradient_properties.radiusX = 160.0f;
2284 gradient_properties.radiusY = 480.0f;
2285 hr = ID2D1RenderTarget_CreateRadialGradientBrush(rt, &gradient_properties, NULL, gradient, &brush);
2286 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2288 f = ID2D1RadialGradientBrush_GetOpacity(brush);
2289 ok(f == 1.0f, "Got unexpected opacity %.8e.\n", f);
2290 set_matrix_identity(&matrix);
2291 ID2D1RadialGradientBrush_GetTransform(brush, &tmp_matrix);
2292 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
2293 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2294 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
2295 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
2296 p = ID2D1RadialGradientBrush_GetCenter(brush);
2297 ok(compare_point(&p, 160.0f, 480.0f, 0), "Got unexpected center {%.8e, %.8e}.\n", p.x, p.y);
2298 p = ID2D1RadialGradientBrush_GetGradientOriginOffset(brush);
2299 ok(compare_point(&p, 40.0f, -120.0f, 0), "Got unexpected origin offset {%.8e, %.8e}.\n", p.x, p.y);
2300 f = ID2D1RadialGradientBrush_GetRadiusX(brush);
2301 ok(compare_float(f, 160.0f, 0), "Got unexpected x-radius %.8e.\n", f);
2302 f = ID2D1RadialGradientBrush_GetRadiusY(brush);
2303 ok(compare_float(f, 480.0f, 0), "Got unexpected y-radius %.8e.\n", f);
2304 ID2D1RadialGradientBrush_GetGradientStopCollection(brush, &tmp_gradient);
2305 ok(tmp_gradient == gradient, "Got unexpected gradient %p, expected %p.\n", tmp_gradient, gradient);
2306 ID2D1GradientStopCollection_Release(tmp_gradient);
2308 ID2D1RenderTarget_BeginDraw(rt);
2310 set_color(&colour, 1.0f, 1.0f, 1.0f, 1.0f);
2311 ID2D1RenderTarget_Clear(rt, &colour);
2313 set_rect(&r, 0.0f, 0.0f, 320.0f, 960.0f);
2314 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2316 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2317 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2319 get_surface_readback(surface, &rb);
2320 for (i = 0; i < ARRAY_SIZE(test1); ++i)
2322 DWORD colour;
2324 colour = get_readback_colour(&rb, test1[i].x, test1[i].y);
2325 ok(compare_colour(colour, test1[i].colour, 1),
2326 "Got unexpected colour 0x%08x at position {%u, %u}.\n",
2327 colour, test1[i].x, test1[i].y);
2329 release_resource_readback(&rb);
2331 ID2D1RenderTarget_BeginDraw(rt);
2333 ID2D1RenderTarget_Clear(rt, &colour);
2335 set_matrix_identity(&matrix);
2336 skew_matrix(&matrix, 0.2146f, 1.575f);
2337 ID2D1RenderTarget_SetTransform(rt, &matrix);
2339 set_matrix_identity(&matrix);
2340 translate_matrix(&matrix, 0.0f, 240.0f);
2341 scale_matrix(&matrix, 0.25f, -0.25f);
2342 ID2D1RadialGradientBrush_SetTransform(brush, &matrix);
2344 set_rect(&r, 0.0f, 0.0f, 80.0f, 240.0f);
2345 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2347 set_matrix_identity(&matrix);
2348 scale_matrix(&matrix, 0.5f, 2.0f);
2349 translate_matrix(&matrix, 320.0f, 240.0f);
2350 rotate_matrix(&matrix, M_PI / 4.0f);
2351 ID2D1RenderTarget_SetTransform(rt, &matrix);
2353 set_matrix_identity(&matrix);
2354 translate_matrix(&matrix, -75.0f, -50.0f);
2355 scale_matrix(&matrix, 0.15f, 0.5f);
2356 rotate_matrix(&matrix, -M_PI / 3.0f);
2357 ID2D1RadialGradientBrush_SetTransform(brush, &matrix);
2359 ID2D1RadialGradientBrush_SetOpacity(brush, 0.75f);
2360 set_rect(&r, -80.0f, -60.0f, 80.0f, 60.0f);
2361 ID2D1RenderTarget_FillRectangle(rt, &r, (ID2D1Brush *)brush);
2363 ID2D1RenderTarget_GetFactory(rt, &factory);
2365 set_rect(&r, -1.0f, -1.0f, 1.0f, 1.0f);
2366 hr = ID2D1Factory_CreateRectangleGeometry(factory, &r, &rectangle_geometry);
2367 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2369 set_matrix_identity(&matrix);
2370 translate_matrix(&matrix, 228.5f, 714.0f);
2371 scale_matrix(&matrix, 40.0f, 120.0f);
2372 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)rectangle_geometry,
2373 &matrix, &transformed_geometry);
2374 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2375 ID2D1RectangleGeometry_Release(rectangle_geometry);
2377 set_matrix_identity(&matrix);
2378 ID2D1RenderTarget_SetTransform(rt, &matrix);
2379 ID2D1RadialGradientBrush_SetTransform(brush, &matrix);
2380 set_point(&p, 228.5f, 714.0f);
2381 ID2D1RadialGradientBrush_SetCenter(brush, p);
2382 ID2D1RadialGradientBrush_SetRadiusX(brush, -40.0f);
2383 ID2D1RadialGradientBrush_SetRadiusY(brush, 120.0f);
2384 set_point(&p, 20.0f, 30.0f);
2385 ID2D1RadialGradientBrush_SetGradientOriginOffset(brush, p);
2386 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2387 ID2D1TransformedGeometry_Release(transformed_geometry);
2389 ID2D1Factory_Release(factory);
2391 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2392 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2394 get_surface_readback(surface, &rb);
2395 for (i = 0; i < ARRAY_SIZE(test2); ++i)
2397 DWORD colour;
2399 colour = get_readback_colour(&rb, test2[i].x, test2[i].y);
2400 ok(compare_colour(colour, test2[i].colour, 1),
2401 "Got unexpected colour 0x%08x at position {%u, %u}.\n",
2402 colour, test2[i].x, test2[i].y);
2404 release_resource_readback(&rb);
2406 ID2D1RadialGradientBrush_Release(brush);
2407 refcount = ID2D1GradientStopCollection_Release(gradient);
2408 ok(!refcount, "Gradient has %u references left.\n", refcount);
2409 ID2D1RenderTarget_Release(rt);
2410 IDXGISurface_Release(surface);
2411 IDXGISwapChain_Release(swapchain);
2412 ID3D10Device1_Release(device);
2413 DestroyWindow(window);
2416 static void fill_geometry_sink(ID2D1GeometrySink *sink, unsigned int hollow_count)
2418 D2D1_FIGURE_BEGIN begin;
2419 unsigned int idx = 0;
2420 D2D1_POINT_2F point;
2422 set_point(&point, 15.0f, 20.0f);
2423 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2424 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2425 line_to(sink, 55.0f, 20.0f);
2426 line_to(sink, 55.0f, 220.0f);
2427 line_to(sink, 25.0f, 220.0f);
2428 line_to(sink, 25.0f, 100.0f);
2429 line_to(sink, 75.0f, 100.0f);
2430 line_to(sink, 75.0f, 300.0f);
2431 line_to(sink, 5.0f, 300.0f);
2432 line_to(sink, 5.0f, 60.0f);
2433 line_to(sink, 45.0f, 60.0f);
2434 line_to(sink, 45.0f, 180.0f);
2435 line_to(sink, 35.0f, 180.0f);
2436 line_to(sink, 35.0f, 140.0f);
2437 line_to(sink, 65.0f, 140.0f);
2438 line_to(sink, 65.0f, 260.0f);
2439 line_to(sink, 15.0f, 260.0f);
2440 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2442 set_point(&point, 155.0f, 300.0f);
2443 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2444 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2445 line_to(sink, 155.0f, 160.0f);
2446 line_to(sink, 85.0f, 160.0f);
2447 line_to(sink, 85.0f, 300.0f);
2448 line_to(sink, 120.0f, 300.0f);
2449 line_to(sink, 120.0f, 20.0f);
2450 line_to(sink, 155.0f, 20.0f);
2451 line_to(sink, 155.0f, 160.0f);
2452 line_to(sink, 85.0f, 160.0f);
2453 line_to(sink, 85.0f, 20.0f);
2454 line_to(sink, 120.0f, 20.0f);
2455 line_to(sink, 120.0f, 300.0f);
2456 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2458 set_point(&point, 165.0f, 20.0f);
2459 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2460 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2461 line_to(sink, 165.0f, 300.0f);
2462 line_to(sink, 235.0f, 300.0f);
2463 line_to(sink, 235.0f, 20.0f);
2464 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2465 set_point(&point, 225.0f, 60.0f);
2466 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2467 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2468 line_to(sink, 225.0f, 260.0f);
2469 line_to(sink, 175.0f, 260.0f);
2470 line_to(sink, 175.0f, 60.0f);
2471 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2472 set_point(&point, 215.0f, 220.0f);
2473 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2474 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2475 line_to(sink, 185.0f, 220.0f);
2476 line_to(sink, 185.0f, 100.0f);
2477 line_to(sink, 215.0f, 100.0f);
2478 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2479 set_point(&point, 195.0f, 180.0f);
2480 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2481 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2482 line_to(sink, 205.0f, 180.0f);
2483 line_to(sink, 205.0f, 140.0f);
2484 line_to(sink, 195.0f, 140.0f);
2485 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2488 static void fill_geometry_sink_bezier(ID2D1GeometrySink *sink, unsigned int hollow_count)
2490 D2D1_FIGURE_BEGIN begin;
2491 unsigned int idx = 0;
2492 D2D1_POINT_2F point;
2494 set_point(&point, 5.0f, 160.0f);
2495 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2496 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2497 quadratic_to(sink, 40.0f, 160.0f, 40.0f, 20.0f);
2498 quadratic_to(sink, 40.0f, 160.0f, 75.0f, 160.0f);
2499 quadratic_to(sink, 40.0f, 160.0f, 40.0f, 300.0f);
2500 quadratic_to(sink, 40.0f, 160.0f, 5.0f, 160.0f);
2501 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2503 set_point(&point, 20.0f, 160.0f);
2504 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2505 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2506 quadratic_to(sink, 20.0f, 80.0f, 40.0f, 80.0f);
2507 quadratic_to(sink, 60.0f, 80.0f, 60.0f, 160.0f);
2508 quadratic_to(sink, 60.0f, 240.0f, 40.0f, 240.0f);
2509 quadratic_to(sink, 20.0f, 240.0f, 20.0f, 160.0f);
2510 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2512 set_point(&point, 5.0f, 612.0f);
2513 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2514 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2515 quadratic_to(sink, 40.0f, 612.0f, 40.0f, 752.0f);
2516 quadratic_to(sink, 40.0f, 612.0f, 75.0f, 612.0f);
2517 quadratic_to(sink, 40.0f, 612.0f, 40.0f, 472.0f);
2518 quadratic_to(sink, 40.0f, 612.0f, 5.0f, 612.0f);
2519 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2521 set_point(&point, 20.0f, 612.0f);
2522 begin = idx++ < hollow_count ? D2D1_FIGURE_BEGIN_HOLLOW : D2D1_FIGURE_BEGIN_FILLED;
2523 ID2D1GeometrySink_BeginFigure(sink, point, begin);
2524 quadratic_to(sink, 20.0f, 692.0f, 40.0f, 692.0f);
2525 quadratic_to(sink, 60.0f, 692.0f, 60.0f, 612.0f);
2526 quadratic_to(sink, 60.0f, 532.0f, 40.0f, 532.0f);
2527 quadratic_to(sink, 20.0f, 532.0f, 20.0f, 612.0f);
2528 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2531 static void test_path_geometry(void)
2533 ID2D1TransformedGeometry *transformed_geometry;
2534 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
2535 ID2D1GeometrySink *sink, *tmp_sink;
2536 struct geometry_sink simplify_sink;
2537 D2D1_POINT_2F point = {0.0f, 0.0f};
2538 ID2D1SolidColorBrush *brush;
2539 ID2D1PathGeometry *geometry;
2540 ID2D1Geometry *tmp_geometry;
2541 IDXGISwapChain *swapchain;
2542 ID2D1RenderTarget *rt;
2543 ID3D10Device1 *device;
2544 IDXGISurface *surface;
2545 ID2D1Factory *factory;
2546 BOOL match, contains;
2547 D2D1_COLOR_F color;
2548 D2D1_RECT_F rect;
2549 ULONG refcount;
2550 UINT32 count;
2551 HWND window;
2552 HRESULT hr;
2554 static const struct geometry_segment expected_segments[] =
2556 /* Figure 0. */
2557 {SEGMENT_LINE, {{{ 55.0f, 20.0f}}}},
2558 {SEGMENT_LINE, {{{ 55.0f, 220.0f}}}},
2559 {SEGMENT_LINE, {{{ 25.0f, 220.0f}}}},
2560 {SEGMENT_LINE, {{{ 25.0f, 100.0f}}}},
2561 {SEGMENT_LINE, {{{ 75.0f, 100.0f}}}},
2562 {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}},
2563 {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}},
2564 {SEGMENT_LINE, {{{ 5.0f, 60.0f}}}},
2565 {SEGMENT_LINE, {{{ 45.0f, 60.0f}}}},
2566 {SEGMENT_LINE, {{{ 45.0f, 180.0f}}}},
2567 {SEGMENT_LINE, {{{ 35.0f, 180.0f}}}},
2568 {SEGMENT_LINE, {{{ 35.0f, 140.0f}}}},
2569 {SEGMENT_LINE, {{{ 65.0f, 140.0f}}}},
2570 {SEGMENT_LINE, {{{ 65.0f, 260.0f}}}},
2571 {SEGMENT_LINE, {{{ 15.0f, 260.0f}}}},
2572 /* Figure 1. */
2573 {SEGMENT_LINE, {{{155.0f, 160.0f}}}},
2574 {SEGMENT_LINE, {{{ 85.0f, 160.0f}}}},
2575 {SEGMENT_LINE, {{{ 85.0f, 300.0f}}}},
2576 {SEGMENT_LINE, {{{120.0f, 300.0f}}}},
2577 {SEGMENT_LINE, {{{120.0f, 20.0f}}}},
2578 {SEGMENT_LINE, {{{155.0f, 20.0f}}}},
2579 {SEGMENT_LINE, {{{155.0f, 160.0f}}}},
2580 {SEGMENT_LINE, {{{ 85.0f, 160.0f}}}},
2581 {SEGMENT_LINE, {{{ 85.0f, 20.0f}}}},
2582 {SEGMENT_LINE, {{{120.0f, 20.0f}}}},
2583 {SEGMENT_LINE, {{{120.0f, 300.0f}}}},
2584 /* Figure 2. */
2585 {SEGMENT_LINE, {{{165.0f, 300.0f}}}},
2586 {SEGMENT_LINE, {{{235.0f, 300.0f}}}},
2587 {SEGMENT_LINE, {{{235.0f, 20.0f}}}},
2588 /* Figure 3. */
2589 {SEGMENT_LINE, {{{225.0f, 260.0f}}}},
2590 {SEGMENT_LINE, {{{175.0f, 260.0f}}}},
2591 {SEGMENT_LINE, {{{175.0f, 60.0f}}}},
2592 /* Figure 4. */
2593 {SEGMENT_LINE, {{{185.0f, 220.0f}}}},
2594 {SEGMENT_LINE, {{{185.0f, 100.0f}}}},
2595 {SEGMENT_LINE, {{{215.0f, 100.0f}}}},
2596 /* Figure 5. */
2597 {SEGMENT_LINE, {{{205.0f, 180.0f}}}},
2598 {SEGMENT_LINE, {{{205.0f, 140.0f}}}},
2599 {SEGMENT_LINE, {{{195.0f, 140.0f}}}},
2600 /* Figure 6. */
2601 {SEGMENT_LINE, {{{135.0f, 620.0f}}}},
2602 {SEGMENT_LINE, {{{135.0f, 420.0f}}}},
2603 {SEGMENT_LINE, {{{105.0f, 420.0f}}}},
2604 {SEGMENT_LINE, {{{105.0f, 540.0f}}}},
2605 {SEGMENT_LINE, {{{155.0f, 540.0f}}}},
2606 {SEGMENT_LINE, {{{155.0f, 340.0f}}}},
2607 {SEGMENT_LINE, {{{ 85.0f, 340.0f}}}},
2608 {SEGMENT_LINE, {{{ 85.0f, 580.0f}}}},
2609 {SEGMENT_LINE, {{{125.0f, 580.0f}}}},
2610 {SEGMENT_LINE, {{{125.0f, 460.0f}}}},
2611 {SEGMENT_LINE, {{{115.0f, 460.0f}}}},
2612 {SEGMENT_LINE, {{{115.0f, 500.0f}}}},
2613 {SEGMENT_LINE, {{{145.0f, 500.0f}}}},
2614 {SEGMENT_LINE, {{{145.0f, 380.0f}}}},
2615 {SEGMENT_LINE, {{{ 95.0f, 380.0f}}}},
2616 /* Figure 7. */
2617 {SEGMENT_LINE, {{{235.0f, 480.0f}}}},
2618 {SEGMENT_LINE, {{{165.0f, 480.0f}}}},
2619 {SEGMENT_LINE, {{{165.0f, 340.0f}}}},
2620 {SEGMENT_LINE, {{{200.0f, 340.0f}}}},
2621 {SEGMENT_LINE, {{{200.0f, 620.0f}}}},
2622 {SEGMENT_LINE, {{{235.0f, 620.0f}}}},
2623 {SEGMENT_LINE, {{{235.0f, 480.0f}}}},
2624 {SEGMENT_LINE, {{{165.0f, 480.0f}}}},
2625 {SEGMENT_LINE, {{{165.0f, 620.0f}}}},
2626 {SEGMENT_LINE, {{{200.0f, 620.0f}}}},
2627 {SEGMENT_LINE, {{{200.0f, 340.0f}}}},
2628 /* Figure 8. */
2629 {SEGMENT_LINE, {{{245.0f, 340.0f}}}},
2630 {SEGMENT_LINE, {{{315.0f, 340.0f}}}},
2631 {SEGMENT_LINE, {{{315.0f, 620.0f}}}},
2632 /* Figure 9. */
2633 {SEGMENT_LINE, {{{305.0f, 380.0f}}}},
2634 {SEGMENT_LINE, {{{255.0f, 380.0f}}}},
2635 {SEGMENT_LINE, {{{255.0f, 580.0f}}}},
2636 /* Figure 10. */
2637 {SEGMENT_LINE, {{{265.0f, 420.0f}}}},
2638 {SEGMENT_LINE, {{{265.0f, 540.0f}}}},
2639 {SEGMENT_LINE, {{{295.0f, 540.0f}}}},
2640 /* Figure 11. */
2641 {SEGMENT_LINE, {{{285.0f, 460.0f}}}},
2642 {SEGMENT_LINE, {{{285.0f, 500.0f}}}},
2643 {SEGMENT_LINE, {{{275.0f, 500.0f}}}},
2644 /* Figure 12. */
2645 {SEGMENT_BEZIER, {{{2.83333340e+01f, 1.60000000e+02f},
2646 {4.00000000e+01f, 1.13333336e+02f},
2647 {4.00000000e+01f, 2.00000000e+01f}}}},
2648 {SEGMENT_BEZIER, {{{4.00000000e+01f, 1.13333336e+02f},
2649 {5.16666641e+01f, 1.60000000e+02f},
2650 {7.50000000e+01f, 1.60000000e+02f}}}},
2651 {SEGMENT_BEZIER, {{{5.16666641e+01f, 1.60000000e+02f},
2652 {4.00000000e+01f, 2.06666656e+02f},
2653 {4.00000000e+01f, 3.00000000e+02f}}}},
2654 {SEGMENT_BEZIER, {{{4.00000000e+01f, 2.06666656e+02f},
2655 {2.83333340e+01f, 1.60000000e+02f},
2656 {5.00000000e+00f, 1.60000000e+02f}}}},
2657 /* Figure 13. */
2658 {SEGMENT_BEZIER, {{{2.00000000e+01f, 1.06666664e+02f},
2659 {2.66666660e+01f, 8.00000000e+01f},
2660 {4.00000000e+01f, 8.00000000e+01f}}}},
2661 {SEGMENT_BEZIER, {{{5.33333321e+01f, 8.00000000e+01f},
2662 {6.00000000e+01f, 1.06666664e+02f},
2663 {6.00000000e+01f, 1.60000000e+02f}}}},
2664 {SEGMENT_BEZIER, {{{6.00000000e+01f, 2.13333328e+02f},
2665 {5.33333321e+01f, 2.40000000e+02f},
2666 {4.00000000e+01f, 2.40000000e+02f}}}},
2667 {SEGMENT_BEZIER, {{{2.66666660e+01f, 2.40000000e+02f},
2668 {2.00000000e+01f, 2.13333328e+02f},
2669 {2.00000000e+01f, 1.60000000e+02f}}}},
2670 /* Figure 14. */
2671 {SEGMENT_BEZIER, {{{2.83333340e+01f, 6.12000000e+02f},
2672 {4.00000000e+01f, 6.58666687e+02f},
2673 {4.00000000e+01f, 7.52000000e+02f}}}},
2674 {SEGMENT_BEZIER, {{{4.00000000e+01f, 6.58666687e+02f},
2675 {5.16666641e+01f, 6.12000000e+02f},
2676 {7.50000000e+01f, 6.12000000e+02f}}}},
2677 {SEGMENT_BEZIER, {{{5.16666641e+01f, 6.12000000e+02f},
2678 {4.00000000e+01f, 5.65333313e+02f},
2679 {4.00000000e+01f, 4.72000000e+02f}}}},
2680 {SEGMENT_BEZIER, {{{4.00000000e+01f, 5.65333313e+02f},
2681 {2.83333340e+01f, 6.12000000e+02f},
2682 {5.00000000e+00f, 6.12000000e+02f}}}},
2683 /* Figure 15. */
2684 {SEGMENT_BEZIER, {{{2.00000000e+01f, 6.65333313e+02f},
2685 {2.66666660e+01f, 6.92000000e+02f},
2686 {4.00000000e+01f, 6.92000000e+02f}}}},
2687 {SEGMENT_BEZIER, {{{5.33333321e+01f, 6.92000000e+02f},
2688 {6.00000000e+01f, 6.65333313e+02f},
2689 {6.00000000e+01f, 6.12000000e+02f}}}},
2690 {SEGMENT_BEZIER, {{{6.00000000e+01f, 5.58666687e+02f},
2691 {5.33333321e+01f, 5.32000000e+02f},
2692 {4.00000000e+01f, 5.32000000e+02f}}}},
2693 {SEGMENT_BEZIER, {{{2.66666660e+01f, 5.32000000e+02f},
2694 {2.00000000e+01f, 5.58666687e+02f},
2695 {2.00000000e+01f, 6.12000000e+02f}}}},
2696 /* Figure 16. */
2697 {SEGMENT_BEZIER, {{{1.91750427e+02f, 1.27275856e+02f},
2698 {2.08249573e+02f, 1.27275856e+02f},
2699 {2.24748734e+02f, 6.12792168e+01f}}}},
2700 {SEGMENT_BEZIER, {{{2.08249573e+02f, 1.27275856e+02f},
2701 {2.08249573e+02f, 1.93272476e+02f},
2702 {2.24748734e+02f, 2.59269104e+02f}}}},
2703 {SEGMENT_BEZIER, {{{2.08249573e+02f, 1.93272476e+02f},
2704 {1.91750427e+02f, 1.93272476e+02f},
2705 {1.75251266e+02f, 2.59269104e+02f}}}},
2706 {SEGMENT_BEZIER, {{{1.91750427e+02f, 1.93272476e+02f},
2707 {1.91750427e+02f, 1.27275856e+02f},
2708 {1.75251266e+02f, 6.12792168e+01f}}}},
2709 /* Figure 17. */
2710 {SEGMENT_BEZIER, {{{1.95285950e+02f, 6.59932632e+01f},
2711 {2.04714050e+02f, 6.59932632e+01f},
2712 {2.14142136e+02f, 1.03705627e+02f}}}},
2713 {SEGMENT_BEZIER, {{{2.23570221e+02f, 1.41417984e+02f},
2714 {2.23570221e+02f, 1.79130356e+02f},
2715 {2.14142136e+02f, 2.16842712e+02f}}}},
2716 {SEGMENT_BEZIER, {{{2.04714050e+02f, 2.54555069e+02f},
2717 {1.95285950e+02f, 2.54555069e+02f},
2718 {1.85857864e+02f, 2.16842712e+02f}}}},
2719 {SEGMENT_BEZIER, {{{1.76429779e+02f, 1.79130356e+02f},
2720 {1.76429779e+02f, 1.41417984e+02f},
2721 {1.85857864e+02f, 1.03705627e+02f}}}},
2722 /* Figure 18. */
2723 {SEGMENT_BEZIER, {{{1.11847351e+02f, 4.46888092e+02f},
2724 {1.11847351e+02f, 5.12884705e+02f},
2725 {9.53481979e+01f, 5.78881348e+02f}}}},
2726 {SEGMENT_BEZIER, {{{1.11847351e+02f, 5.12884705e+02f},
2727 {1.28346512e+02f, 5.12884705e+02f},
2728 {1.44845673e+02f, 5.78881348e+02f}}}},
2729 {SEGMENT_BEZIER, {{{1.28346512e+02f, 5.12884705e+02f},
2730 {1.28346512e+02f, 4.46888092e+02f},
2731 {1.44845673e+02f, 3.80891479e+02f}}}},
2732 {SEGMENT_BEZIER, {{{1.28346512e+02f, 4.46888092e+02f},
2733 {1.11847351e+02f, 4.46888092e+02f},
2734 {9.53481979e+01f, 3.80891479e+02f}}}},
2735 /* Figure 19. */
2736 {SEGMENT_BEZIER, {{{9.65267105e+01f, 4.61030243e+02f},
2737 {9.65267105e+01f, 4.98742584e+02f},
2738 {1.05954803e+02f, 5.36454956e+02f}}}},
2739 {SEGMENT_BEZIER, {{{1.15382889e+02f, 5.74167297e+02f},
2740 {1.24810982e+02f, 5.74167297e+02f},
2741 {1.34239075e+02f, 5.36454956e+02f}}}},
2742 {SEGMENT_BEZIER, {{{1.43667160e+02f, 4.98742584e+02f},
2743 {1.43667160e+02f, 4.61030243e+02f},
2744 {1.34239075e+02f, 4.23317871e+02f}}}},
2745 {SEGMENT_BEZIER, {{{1.24810982e+02f, 3.85605499e+02f},
2746 {1.15382889e+02f, 3.85605499e+02f},
2747 {1.05954803e+02f, 4.23317871e+02f}}}},
2748 /* Figure 20. */
2749 {SEGMENT_LINE, {{{ 40.0f, 20.0f}}}},
2750 {SEGMENT_LINE, {{{ 75.0f, 160.0f}}}},
2751 {SEGMENT_LINE, {{{ 40.0f, 300.0f}}}},
2752 {SEGMENT_LINE, {{{ 5.0f, 160.0f}}}},
2753 /* Figure 21. */
2754 {SEGMENT_LINE, {{{ 40.0f, 80.0f}}}},
2755 {SEGMENT_LINE, {{{ 60.0f, 160.0f}}}},
2756 {SEGMENT_LINE, {{{ 40.0f, 240.0f}}}},
2757 {SEGMENT_LINE, {{{ 20.0f, 160.0f}}}},
2758 /* Figure 22. */
2759 {SEGMENT_LINE, {{{ 40.0f, 752.0f}}}},
2760 {SEGMENT_LINE, {{{ 75.0f, 612.0f}}}},
2761 {SEGMENT_LINE, {{{ 40.0f, 472.0f}}}},
2762 {SEGMENT_LINE, {{{ 5.0f, 612.0f}}}},
2763 /* Figure 23. */
2764 {SEGMENT_LINE, {{{ 40.0f, 692.0f}}}},
2765 {SEGMENT_LINE, {{{ 60.0f, 612.0f}}}},
2766 {SEGMENT_LINE, {{{ 40.0f, 532.0f}}}},
2767 {SEGMENT_LINE, {{{ 20.0f, 612.0f}}}},
2768 /* Figure 24. */
2769 {SEGMENT_LINE, {{{2.03125019e+01f, 1.51250000e+02f}}}},
2770 {SEGMENT_LINE, {{{3.12500019e+01f, 1.25000008e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2771 {SEGMENT_LINE, {{{3.78125000e+01f, 8.12500076e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2772 {SEGMENT_LINE, {{{4.00000000e+01f, 2.00000000e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2773 {SEGMENT_LINE, {{{4.21875000e+01f, 8.12500076e+01f}}}},
2774 {SEGMENT_LINE, {{{4.87500000e+01f, 1.25000008e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2775 {SEGMENT_LINE, {{{5.96875000e+01f, 1.51250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2776 {SEGMENT_LINE, {{{7.50000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2777 {SEGMENT_LINE, {{{5.96875000e+01f, 1.68750000e+02f}}}},
2778 {SEGMENT_LINE, {{{4.87500000e+01f, 1.95000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2779 {SEGMENT_LINE, {{{4.21875000e+01f, 2.38750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2780 {SEGMENT_LINE, {{{4.00000000e+01f, 3.00000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2781 {SEGMENT_LINE, {{{3.78125000e+01f, 2.38750000e+02f}}}},
2782 {SEGMENT_LINE, {{{3.12500019e+01f, 1.95000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2783 {SEGMENT_LINE, {{{2.03125019e+01f, 1.68750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2784 {SEGMENT_LINE, {{{5.00000000e+00f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2785 /* Figure 25. */
2786 {SEGMENT_LINE, {{{2.50000000e+01f, 1.00000000e+02f}}}},
2787 {SEGMENT_LINE, {{{4.00000000e+01f, 8.00000000e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2788 {SEGMENT_LINE, {{{5.50000000e+01f, 1.00000000e+02f}}}},
2789 {SEGMENT_LINE, {{{6.00000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2790 {SEGMENT_LINE, {{{5.50000000e+01f, 2.20000000e+02f}}}},
2791 {SEGMENT_LINE, {{{4.00000000e+01f, 2.40000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2792 {SEGMENT_LINE, {{{2.50000000e+01f, 2.20000000e+02f}}}},
2793 {SEGMENT_LINE, {{{2.00000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2794 /* Figure 26. */
2795 {SEGMENT_LINE, {{{2.03125019e+01f, 6.20750000e+02f}}}},
2796 {SEGMENT_LINE, {{{3.12500019e+01f, 6.47000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2797 {SEGMENT_LINE, {{{3.78125000e+01f, 6.90750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2798 {SEGMENT_LINE, {{{4.00000000e+01f, 7.52000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2799 {SEGMENT_LINE, {{{4.21875000e+01f, 6.90750000e+02f}}}},
2800 {SEGMENT_LINE, {{{4.87500000e+01f, 6.47000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2801 {SEGMENT_LINE, {{{5.96875000e+01f, 6.20750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2802 {SEGMENT_LINE, {{{7.50000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2803 {SEGMENT_LINE, {{{5.96875000e+01f, 6.03250000e+02f}}}},
2804 {SEGMENT_LINE, {{{4.87500000e+01f, 5.77000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2805 {SEGMENT_LINE, {{{4.21875000e+01f, 5.33250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2806 {SEGMENT_LINE, {{{4.00000000e+01f, 4.72000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2807 {SEGMENT_LINE, {{{3.78125000e+01f, 5.33250000e+02f}}}},
2808 {SEGMENT_LINE, {{{3.12500019e+01f, 5.77000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2809 {SEGMENT_LINE, {{{2.03125019e+01f, 6.03250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2810 {SEGMENT_LINE, {{{5.00000000e+00f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2811 /* Figure 27. */
2812 {SEGMENT_LINE, {{{2.50000000e+01f, 6.72000000e+02f}}}},
2813 {SEGMENT_LINE, {{{4.00000000e+01f, 6.92000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2814 {SEGMENT_LINE, {{{5.50000000e+01f, 6.72000000e+02f}}}},
2815 {SEGMENT_LINE, {{{6.00000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2816 {SEGMENT_LINE, {{{5.50000000e+01f, 5.52000000e+02f}}}},
2817 {SEGMENT_LINE, {{{4.00000000e+01f, 5.32000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2818 {SEGMENT_LINE, {{{2.50000000e+01f, 5.52000000e+02f}}}},
2819 {SEGMENT_LINE, {{{2.00000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2820 /* Figure 28. */
2821 {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}},
2822 {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}},
2824 static const struct expected_geometry_figure expected_figures[] =
2826 /* 0 */
2827 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 15.0f, 20.0f}, 15, &expected_segments[0]},
2828 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {155.0f, 300.0f}, 11, &expected_segments[15]},
2829 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {165.0f, 20.0f}, 3, &expected_segments[26]},
2830 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {225.0f, 60.0f}, 3, &expected_segments[29]},
2831 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {215.0f, 220.0f}, 3, &expected_segments[32]},
2832 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {195.0f, 180.0f}, 3, &expected_segments[35]},
2833 /* 6 */
2834 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 95.0f, 620.0f}, 15, &expected_segments[38]},
2835 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {235.0f, 340.0f}, 11, &expected_segments[53]},
2836 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {245.0f, 620.0f}, 3, &expected_segments[64]},
2837 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {305.0f, 580.0f}, 3, &expected_segments[67]},
2838 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {295.0f, 420.0f}, 3, &expected_segments[70]},
2839 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {275.0f, 460.0f}, 3, &expected_segments[73]},
2840 /* 12 */
2841 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 4, &expected_segments[76]},
2842 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 4, &expected_segments[80]},
2843 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 4, &expected_segments[84]},
2844 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 4, &expected_segments[88]},
2845 /* 16 */
2846 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
2847 {1.75251266e+02f, 6.12792168e+01f}, 4, &expected_segments[92]},
2848 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
2849 {1.85857864e+02f, 1.03705627e+02f}, 4, &expected_segments[96]},
2850 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
2851 {9.53481979e+01f, 3.80891479e+02f}, 4, &expected_segments[100]},
2852 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
2853 {1.05954803e+02f, 4.23317871e+02f}, 4, &expected_segments[104]},
2854 /* 20 */
2855 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 4, &expected_segments[108]},
2856 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 4, &expected_segments[112]},
2857 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 4, &expected_segments[116]},
2858 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 4, &expected_segments[120]},
2859 /* 24 */
2860 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 16, &expected_segments[124]},
2861 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 8, &expected_segments[140]},
2862 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 16, &expected_segments[148]},
2863 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 8, &expected_segments[164]},
2864 /* 28 */
2865 {D2D1_FIGURE_BEGIN_HOLLOW, D2D1_FIGURE_END_OPEN, { 40.0f, 20.0f}, 2, &expected_segments[172]},
2868 if (!(device = create_device()))
2870 skip("Failed to create device, skipping tests.\n");
2871 return;
2873 window = create_window();
2874 swapchain = create_swapchain(device, window, TRUE);
2875 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2876 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2877 rt = create_render_target(surface);
2878 ok(!!rt, "Failed to create render target.\n");
2879 ID2D1RenderTarget_GetFactory(rt, &factory);
2881 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
2882 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2883 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
2884 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
2885 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2887 /* Close() when closed. */
2888 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2889 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2890 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2891 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2892 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2893 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2894 hr = ID2D1PathGeometry_Open(geometry, &sink);
2895 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2896 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2897 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2898 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2899 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2900 hr = ID2D1GeometrySink_Close(sink);
2901 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2902 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2903 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2904 ok(!count, "Got unexpected figure count %u.\n", count);
2905 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2906 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2907 ok(!count, "Got unexpected segment count %u.\n", count);
2908 hr = ID2D1GeometrySink_Close(sink);
2909 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2910 ID2D1GeometrySink_Release(sink);
2911 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2912 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2913 ok(!count, "Got unexpected figure count %u.\n", count);
2914 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2915 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2916 ok(!count, "Got unexpected segment count %u.\n", count);
2917 ID2D1PathGeometry_Release(geometry);
2919 /* Open() when closed. */
2920 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2921 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2922 hr = ID2D1PathGeometry_Open(geometry, &sink);
2923 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2924 hr = ID2D1GeometrySink_Close(sink);
2925 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2926 ID2D1GeometrySink_Release(sink);
2927 hr = ID2D1PathGeometry_Open(geometry, &sink);
2928 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2929 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2930 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2931 ok(!count, "Got unexpected figure count %u.\n", count);
2932 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2933 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2934 ok(!count, "Got unexpected segment count %u.\n", count);
2935 ID2D1PathGeometry_Release(geometry);
2937 /* Open() when open. */
2938 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2939 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2940 hr = ID2D1PathGeometry_Open(geometry, &sink);
2941 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2942 hr = ID2D1PathGeometry_Open(geometry, &tmp_sink);
2943 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2944 hr = ID2D1GeometrySink_Close(sink);
2945 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2946 ID2D1GeometrySink_Release(sink);
2947 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2948 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2949 ok(!count, "Got unexpected figure count %u.\n", count);
2950 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2951 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2952 ok(!count, "Got unexpected segment count %u.\n", count);
2953 ID2D1PathGeometry_Release(geometry);
2955 /* BeginFigure() without EndFigure(). */
2956 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2957 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2958 hr = ID2D1PathGeometry_Open(geometry, &sink);
2959 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2960 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2961 hr = ID2D1GeometrySink_Close(sink);
2962 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2963 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2964 hr = ID2D1GeometrySink_Close(sink);
2965 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2966 ID2D1GeometrySink_Release(sink);
2967 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2968 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2969 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2970 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2971 ID2D1PathGeometry_Release(geometry);
2973 /* EndFigure() without BeginFigure(). */
2974 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2975 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2976 hr = ID2D1PathGeometry_Open(geometry, &sink);
2977 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2978 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2979 hr = ID2D1GeometrySink_Close(sink);
2980 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2981 ID2D1GeometrySink_Release(sink);
2982 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2983 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2984 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2985 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2986 ID2D1PathGeometry_Release(geometry);
2988 /* BeginFigure()/EndFigure() mismatch. */
2989 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2990 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2991 hr = ID2D1PathGeometry_Open(geometry, &sink);
2992 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2993 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2994 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2995 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2996 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2997 hr = ID2D1GeometrySink_Close(sink);
2998 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2999 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3000 hr = ID2D1GeometrySink_Close(sink);
3001 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
3002 ID2D1GeometrySink_Release(sink);
3003 ID2D1PathGeometry_Release(geometry);
3005 /* AddLine() outside BeginFigure()/EndFigure(). */
3006 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3007 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3008 hr = ID2D1PathGeometry_Open(geometry, &sink);
3009 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3010 ID2D1GeometrySink_AddLine(sink, point);
3011 hr = ID2D1GeometrySink_Close(sink);
3012 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
3013 ID2D1GeometrySink_AddLine(sink, point);
3014 ID2D1GeometrySink_Release(sink);
3015 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3016 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
3017 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3018 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
3019 ID2D1PathGeometry_Release(geometry);
3021 /* Empty figure. */
3022 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3023 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3024 hr = ID2D1PathGeometry_Open(geometry, &sink);
3025 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3026 set_point(&point, 123.0f, 456.0f);
3027 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
3028 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3029 hr = ID2D1GeometrySink_Close(sink);
3030 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3031 ID2D1GeometrySink_Release(sink);
3032 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3033 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
3034 ok(count == 1, "Got unexpected figure count %u.\n", count);
3035 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3036 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
3037 ok(count == 1, "Got unexpected segment count %u.\n", count);
3039 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3040 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3041 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3042 match = compare_rect(&rect, 123.0f, 456.0f, 123.0f, 456.0f, 0);
3043 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3044 rect.left, rect.top, rect.right, rect.bottom);
3046 set_matrix_identity(&matrix);
3047 translate_matrix(&matrix, 80.0f, 640.0f);
3048 scale_matrix(&matrix, 2.0f, 0.5f);
3049 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3050 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3051 match = compare_rect(&rect, 326.0f, 868.0f, 326.0f, 868.0f, 0);
3052 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3053 rect.left, rect.top, rect.right, rect.bottom);
3055 ID2D1PathGeometry_Release(geometry);
3057 /* Close right after Open(). */
3058 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3059 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3061 /* Not open yet. */
3062 set_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f);
3063 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3064 ok(hr == D2DERR_WRONG_STATE, "Unexpected hr %#x.\n", hr);
3065 match = compare_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0);
3066 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3067 rect.left, rect.top, rect.right, rect.bottom);
3069 hr = ID2D1PathGeometry_Open(geometry, &sink);
3070 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3072 /* Open, not closed. */
3073 set_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f);
3074 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3075 ok(hr == D2DERR_WRONG_STATE, "Unexpected hr %#x.\n", hr);
3076 match = compare_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0);
3077 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3078 rect.left, rect.top, rect.right, rect.bottom);
3080 hr = ID2D1GeometrySink_Close(sink);
3081 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3082 ID2D1GeometrySink_Release(sink);
3083 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3084 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
3085 ok(count == 0, "Got unexpected figure count %u.\n", count);
3086 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3087 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
3088 ok(count == 0, "Got unexpected segment count %u.\n", count);
3090 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3091 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3092 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3093 ok(rect.left > rect.right && rect.top > rect.bottom,
3094 "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom);
3096 set_matrix_identity(&matrix);
3097 translate_matrix(&matrix, 10.0f, 20.0f);
3098 scale_matrix(&matrix, 10.0f, 20.0f);
3099 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3100 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3101 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3102 ok(rect.left > rect.right && rect.top > rect.bottom,
3103 "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom);
3105 ID2D1PathGeometry_Release(geometry);
3107 /* GetBounds() with bezier segments. */
3108 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3109 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3110 hr = ID2D1PathGeometry_Open(geometry, &sink);
3111 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3112 fill_geometry_sink_bezier(sink, 0);
3113 hr = ID2D1GeometrySink_Close(sink);
3114 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3115 ID2D1GeometrySink_Release(sink);
3117 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3118 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3119 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3120 match = compare_rect(&rect, 5.0f, 20.0f, 75.0f, 752.0f, 0);
3121 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3122 rect.left, rect.top, rect.right, rect.bottom);
3124 set_matrix_identity(&matrix);
3125 translate_matrix(&matrix, 80.0f, 640.0f);
3126 scale_matrix(&matrix, 2.0f, 0.5f);
3127 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3128 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3129 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3130 match = compare_rect(&rect, 90.0f, 650.0f, 230.0f, 1016.0f, 0);
3131 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3132 rect.left, rect.top, rect.right, rect.bottom);
3134 ID2D1PathGeometry_Release(geometry);
3136 /* GetBounds() with bezier segments and some hollow components. */
3137 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3138 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3139 hr = ID2D1PathGeometry_Open(geometry, &sink);
3140 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3141 fill_geometry_sink_bezier(sink, 2);
3142 hr = ID2D1GeometrySink_Close(sink);
3143 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3144 ID2D1GeometrySink_Release(sink);
3146 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3147 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3148 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3149 match = compare_rect(&rect, 5.0f, 472.0f, 75.0f, 752.0f, 0);
3150 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3151 rect.left, rect.top, rect.right, rect.bottom);
3153 set_matrix_identity(&matrix);
3154 translate_matrix(&matrix, 80.0f, 640.0f);
3155 scale_matrix(&matrix, 2.0f, 0.5f);
3156 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3157 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3158 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3159 match = compare_rect(&rect, 90.0f, 876.0f, 230.0f, 1016.0f, 0);
3160 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3161 rect.left, rect.top, rect.right, rect.bottom);
3163 ID2D1PathGeometry_Release(geometry);
3165 /* GetBounds() with bezier segments and all hollow components. */
3166 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3167 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3168 hr = ID2D1PathGeometry_Open(geometry, &sink);
3169 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3170 fill_geometry_sink_bezier(sink, 4);
3171 hr = ID2D1GeometrySink_Close(sink);
3172 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3173 ID2D1GeometrySink_Release(sink);
3175 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3176 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3177 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3178 match = compare_rect(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0);
3179 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3180 rect.left, rect.top, rect.right, rect.bottom);
3182 set_matrix_identity(&matrix);
3183 translate_matrix(&matrix, 80.0f, 640.0f);
3184 scale_matrix(&matrix, 2.0f, 0.5f);
3185 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3186 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3187 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3188 match = compare_rect(&rect, INFINITY, INFINITY, FLT_MAX, FLT_MAX, 0);
3189 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3190 rect.left, rect.top, rect.right, rect.bottom);
3192 ID2D1PathGeometry_Release(geometry);
3194 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3195 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3196 hr = ID2D1PathGeometry_Open(geometry, &sink);
3197 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3198 /* The fillmode that's used is the last one set before the sink is closed. */
3199 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
3200 fill_geometry_sink(sink, 0);
3201 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
3202 hr = ID2D1GeometrySink_Close(sink);
3203 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3204 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3205 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
3206 ok(count == 6, "Got unexpected figure count %u.\n", count);
3207 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3208 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
3209 /* Intersections don't create extra segments. */
3210 ok(count == 44, "Got unexpected segment count %u.\n", count);
3211 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
3212 ID2D1GeometrySink_Release(sink);
3214 geometry_sink_init(&simplify_sink);
3215 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3216 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3217 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3218 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[0], 0);
3219 geometry_sink_cleanup(&simplify_sink);
3220 geometry_sink_init(&simplify_sink);
3221 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3222 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3223 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3224 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[0], 0);
3225 geometry_sink_cleanup(&simplify_sink);
3227 set_matrix_identity(&matrix);
3228 translate_matrix(&matrix, 80.0f, 640.0f);
3229 scale_matrix(&matrix, 1.0f, -1.0f);
3230 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
3231 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
3233 geometry_sink_init(&simplify_sink);
3234 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3235 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3236 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3237 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[6], 0);
3238 geometry_sink_cleanup(&simplify_sink);
3240 ID2D1TransformedGeometry_GetSourceGeometry(transformed_geometry, &tmp_geometry);
3241 ok(tmp_geometry == (ID2D1Geometry *)geometry,
3242 "Got unexpected source geometry %p, expected %p.\n", tmp_geometry, geometry);
3243 ID2D1TransformedGeometry_GetTransform(transformed_geometry, &tmp_matrix);
3244 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
3245 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
3246 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
3247 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
3248 geometry_sink_init(&simplify_sink);
3249 hr = ID2D1Geometry_Simplify(tmp_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3250 &tmp_matrix, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3251 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3252 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[6], 0);
3253 geometry_sink_cleanup(&simplify_sink);
3254 ID2D1Geometry_Release(tmp_geometry);
3256 ID2D1RenderTarget_BeginDraw(rt);
3257 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
3258 ID2D1RenderTarget_Clear(rt, &color);
3259 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
3260 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
3261 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3262 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3263 match = compare_surface(surface, "3aace1b22aae111cb577614fed16e4eb1650dba5");
3264 ok(match, "Surface does not match.\n");
3266 /* Edge test. */
3267 set_point(&point, 94.0f, 620.0f);
3268 contains = TRUE;
3269 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, NULL, 0.0f, &contains);
3270 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
3271 ok(!contains, "Got unexpected contains %#x.\n", contains);
3273 set_point(&point, 95.0f, 620.0f);
3274 contains = FALSE;
3275 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, NULL, 0.0f, &contains);
3276 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
3277 ok(contains == TRUE, "Got unexpected contains %#x.\n", contains);
3279 /* With transformation matrix. */
3280 set_matrix_identity(&matrix);
3281 translate_matrix(&matrix, -10.0f, 0.0f);
3282 set_point(&point, 85.0f, 620.0f);
3283 contains = FALSE;
3284 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, &matrix, 0.0f, &contains);
3285 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
3286 ok(contains == TRUE, "Got unexpected contains %#x.\n", contains);
3288 ID2D1TransformedGeometry_Release(transformed_geometry);
3289 ID2D1PathGeometry_Release(geometry);
3291 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3292 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3293 hr = ID2D1PathGeometry_Open(geometry, &sink);
3294 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3295 fill_geometry_sink(sink, 0);
3296 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
3297 hr = ID2D1GeometrySink_Close(sink);
3298 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3299 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3300 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
3301 ok(count == 6, "Got unexpected figure count %u.\n", count);
3302 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3303 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
3304 ok(count == 44, "Got unexpected segment count %u.\n", count);
3305 ID2D1GeometrySink_Release(sink);
3307 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3308 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
3309 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3310 match = compare_rect(&rect, 5.0f, 20.0f, 235.0f, 300.0f, 0);
3311 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3312 rect.left, rect.top, rect.right, rect.bottom);
3314 set_matrix_identity(&matrix);
3315 translate_matrix(&matrix, 100.0f, 50.0f);
3316 scale_matrix(&matrix, 2.0f, 1.5f);
3317 rotate_matrix(&matrix, M_PI / 4.0f);
3318 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3319 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
3320 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
3321 match = compare_rect(&rect, -3.17192993e+02f, 8.71231079e+01f, 4.04055908e+02f, 6.17453125e+02f, 1);
3322 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3323 rect.left, rect.top, rect.right, rect.bottom);
3325 geometry_sink_init(&simplify_sink);
3326 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3327 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3328 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3329 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 6, &expected_figures[0], 0);
3330 geometry_sink_cleanup(&simplify_sink);
3332 set_matrix_identity(&matrix);
3333 translate_matrix(&matrix, 320.0f, 320.0f);
3334 scale_matrix(&matrix, -1.0f, 1.0f);
3335 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
3336 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
3338 ID2D1RenderTarget_BeginDraw(rt);
3339 ID2D1RenderTarget_Clear(rt, &color);
3340 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
3341 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
3342 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3343 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3344 match = compare_surface(surface, "bfb40a1f007694fa07dbd3b854f3f5d9c3e1d76b");
3345 ok(match, "Surface does not match.\n");
3346 ID2D1TransformedGeometry_Release(transformed_geometry);
3347 ID2D1PathGeometry_Release(geometry);
3349 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3350 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3351 hr = ID2D1PathGeometry_Open(geometry, &sink);
3352 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3353 fill_geometry_sink_bezier(sink, 0);
3354 hr = ID2D1GeometrySink_Close(sink);
3355 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3356 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3357 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
3358 ok(count == 4, "Got unexpected figure count %u.\n", count);
3359 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3360 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
3361 ok(count == 20, "Got unexpected segment count %u.\n", count);
3362 ID2D1GeometrySink_Release(sink);
3364 geometry_sink_init(&simplify_sink);
3365 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3366 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3367 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3368 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[12], 1);
3369 geometry_sink_cleanup(&simplify_sink);
3370 geometry_sink_init(&simplify_sink);
3371 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3372 NULL, 100.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3373 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3374 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[20], 1);
3375 geometry_sink_cleanup(&simplify_sink);
3376 geometry_sink_init(&simplify_sink);
3377 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3378 NULL, 10.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3379 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3380 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[24], 1);
3381 geometry_sink_cleanup(&simplify_sink);
3383 set_matrix_identity(&matrix);
3384 scale_matrix(&matrix, 0.5f, 2.0f);
3385 translate_matrix(&matrix, 400.0f, -33.0f);
3386 rotate_matrix(&matrix, M_PI / 4.0f);
3387 scale_matrix(&matrix, 2.0f, 0.5f);
3388 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
3389 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
3391 geometry_sink_init(&simplify_sink);
3392 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3393 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3394 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3395 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[16], 4);
3396 geometry_sink_cleanup(&simplify_sink);
3398 ID2D1RenderTarget_BeginDraw(rt);
3399 ID2D1RenderTarget_Clear(rt, &color);
3400 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
3401 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
3402 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3403 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3404 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
3405 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
3406 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
3407 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
3408 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
3409 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
3410 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
3411 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
3412 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
3413 ok(match, "Figure does not match.\n");
3414 match = compare_figure(surface, 0, 226, 160, 160, 0xff652e89, 64,
3415 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
3416 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
3417 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
3418 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
3419 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
3420 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
3421 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
3422 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
3423 ok(match, "Figure does not match.\n");
3424 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
3425 "gVQBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQEjDCMB7AECHhQeAu0BAxoYGgPvAQMWHhYD8QEDFCAU"
3426 "A/MBBBAkEAT0AQUOJw0F9QEGCioKBvcBBggsCAb4AQgFLgUI+QEJATIBCfsBCAIwAgj8AQcFLAUH"
3427 "/QEFCCgIBf4BBAwiDAT/AQIQHBAClwISlwIBPgGAAgI8Av8BAzwD/QEEPAT7AQY6BvkBBzoH+AEI"
3428 "OAj3AQk4CfYBCTgK9AELNgvzAQw2DPIBDDYM8QEONA7wAQ40DvABDjQO7wEPNA/uAQ80D+4BEDIQ"
3429 "7QERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewB"
3430 "ETIR7AERMhHsAREyEe0BEDIQ7gEQMw/uAQ80D+4BDzQP7wEONA7wAQ40DvEBDDYM8gEMNgzzAQs2"
3431 "C/QBCzcK9QEJOAn3AQg4CfcBBzoH+QEGOgb7AQU6BfwBBDwE/QEDPAP/AQE+AZkCDpkCAhIYEgKA"
3432 "AgMNIA0D/wEFCSYJBf4BBgYqBgf8AQgDLgMI+wFG+gEIAzADCPkBBwYuBgf3AQYKKgoG9gEFDCgM"
3433 "BfUBBBAlDwTzAQQSIhIE8QEDFh4WA/ABAhkaGQLvAQIcFhwC7QECIBAgAusBASgEKAHpAQFWAecB"
3434 "AVgB5QEBWgHAAgHhUgAA");
3435 ok(match, "Figure does not match.\n");
3436 match = compare_figure(surface, 160, 160, 320, 160, 0xff652e89, 64,
3437 "/VUB5QEBWAHnAQFWAekBAVQB6wECIQ8hAe0BAh0VHQLuAQIZGhkD7wEDFh4WA/EBBBMhEwPzAQQQ"
3438 "JQ8F9AEFDCgNBfUBBgoqCgb3AQcHLQcG+QEIBC8ECPkBPAEJ+wEIAy8CCP0BBgYrBQf9AQUJJgkF"
3439 "/wEDDSANBP8BAhEaEQKYAhAXAYACAT4BgAICPQL+AQM8BPwBBTsE+wEGOgb6AQc5B/gBCDgJ9gEJ"
3440 "OAn2AQo3CvQBCzcK8wEMNgzyAQ01DPIBDTUN8AEONA7wAQ40D+4BDzQP7gEQMw/uARAzEO0BEDIR"
3441 "7AERMhHsAREyEewBETIR7AERMhLrAREyEusBETIS6wERMhLrAREyEusBETIS6wERMhHsAREyEewB"
3442 "ETIR7QEQMhHtARAzEO0BEDMP7gEPNA/vAQ40D+8BDjQO8QENNQ3xAQ01DPMBCzYM8wELNwr1AQo3"
3443 "CvUBCTgJ9wEIOAn4AQc5B/kBBjoG+wEFOwT9AQM8BP4BAj0C/wEBPgGYAhAXAYACAhEaEQKAAgMN"
3444 "IA0E/gEFCSYJBf4BBgYrBQf8AQgDLwII+wE8AQn6AQgELwQI+AEHBy0HBvcBBgoqCgb2AQUNJw0F"
3445 "9AEEECQQBfIBBBMhEwPxAQMWHhYD8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB"
3446 "wAIBwlYA");
3447 ok(match, "Figure does not match.\n");
3448 ID2D1TransformedGeometry_Release(transformed_geometry);
3449 ID2D1PathGeometry_Release(geometry);
3451 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3452 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3453 hr = ID2D1PathGeometry_Open(geometry, &sink);
3454 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3455 fill_geometry_sink_bezier(sink, 0);
3456 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
3457 hr = ID2D1GeometrySink_Close(sink);
3458 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3459 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3460 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
3461 ok(count == 4, "Got unexpected figure count %u.\n", count);
3462 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3463 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
3464 ok(count == 20, "Got unexpected segment count %u.\n", count);
3465 ID2D1GeometrySink_Release(sink);
3467 geometry_sink_init(&simplify_sink);
3468 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3469 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3470 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3471 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[12], 1);
3472 geometry_sink_cleanup(&simplify_sink);
3473 geometry_sink_init(&simplify_sink);
3474 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3475 NULL, 100.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3476 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3477 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[20], 1);
3478 geometry_sink_cleanup(&simplify_sink);
3479 geometry_sink_init(&simplify_sink);
3480 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3481 NULL, 10.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3482 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3483 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[24], 1);
3484 geometry_sink_cleanup(&simplify_sink);
3486 set_matrix_identity(&matrix);
3487 scale_matrix(&matrix, 0.5f, 2.0f);
3488 translate_matrix(&matrix, 127.0f, 80.0f);
3489 rotate_matrix(&matrix, M_PI / -4.0f);
3490 scale_matrix(&matrix, 2.0f, 0.5f);
3491 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
3492 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
3494 ID2D1RenderTarget_BeginDraw(rt);
3495 ID2D1RenderTarget_Clear(rt, &color);
3496 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
3497 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
3498 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3499 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3500 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
3501 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
3502 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
3503 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
3504 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
3505 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
3506 ok(match, "Figure does not match.\n");
3507 match = compare_figure(surface, 0, 226, 160, 160, 0xff652e89, 64,
3508 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
3509 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
3510 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
3511 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
3512 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
3513 ok(match, "Figure does not match.\n");
3514 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
3515 "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQIhDiIB7QECHRUdAu4BAhkaGQPvAQMWHhYD8QEEEyET"
3516 "A/MBBBAkEAT1AQUMKA0F9QEGCioKBvcBBwctBwb5AQgELwQI+QEJATIBCfsBRP0BQ/0BQv8BQf8B"
3517 "QIECP4ACQIACQf4BQ/wBRPsBRvoBR/gBSPcBSvYBS/QBTPMBTvIBTvIBT/ABUPABUe4BUu4BUu4B"
3518 "U+0BU+wBVOwBVOwBVOwBVOwBVesBVesBVesBVesBVOwBVOwBVOwBVO0BU+0BU+0BUu4BUu8BUe8B"
3519 "UPEBT/EBTvIBTvMBTPUBS/UBSvcBSfcBSPkBRvsBRP0BQ/4BQf8BQIECP4ACQIACQf4BQv4BQ/wB"
3520 "RPsBCQEyAQn6AQgELwQI+AEHBy0GB/cBBgoqCgb2AQUMKA0F9AEEECUPBPMBBBIiEwPxAQMWHhYD"
3521 "8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB5QEBWgHAAgEA");
3522 ok(match, "Figure does not match.\n");
3523 match = compare_figure(surface, 160, 160, 320, 160, 0xff652e89, 64,
3524 "gVQBXAHjAQFaAeUBAVgB5wEBVgHpAQEpAikB6wECIBAgAu0BAhwWHALvAQIZGhkC8AEDFh4WA/EB"
3525 "BBIiEgTzAQQPJRAE9QEFDCgMBfYBBgoqCgb3AQcGLgYH+QEIAzADCPoBRvsBRPwBRP0BQv8BQIAC"
3526 "QIECPoECQP8BQv0BRPwBRPsBRvkBSPgBSPcBSvUBTPQBTPMBTvIBTvEBUPABUO8BUu4BUu4BUu4B"
3527 "Uu0BVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVO0BUu4BUu4BUu8BUPAB"
3528 "UPABUPEBTvIBTvMBTPQBS/YBSvcBSPgBSPkBRvsBRP0BQv8BQIACQIECPoECQP8BQv4BQv0BRPwB"
3529 "RPsBCQEyAQn5AQgFLgUI+AEGCCwIBvcBBgoqCgb1AQUNJw4F9AEEECQQBPMBAxQgFAPxAQMWHhYD"
3530 "7wEDGhgaA+0BAh4UHgLsAQEjDCMB6wEBVAHpAQFWAecBAVgB5QEBWgGiVQAA");
3531 ok(match, "Figure does not match.\n");
3532 ID2D1TransformedGeometry_Release(transformed_geometry);
3533 ID2D1PathGeometry_Release(geometry);
3535 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3536 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3537 hr = ID2D1PathGeometry_Open(geometry, &sink);
3538 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3540 set_point(&point, 40.0f, 20.0f);
3541 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
3542 line_to(sink, 75.0f, 300.0f);
3543 line_to(sink, 5.0f, 300.0f);
3544 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3546 set_point(&point, 40.0f, 290.0f);
3547 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
3548 line_to(sink, 55.0f, 160.0f);
3549 line_to(sink, 25.0f, 160.0f);
3550 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
3552 hr = ID2D1GeometrySink_Close(sink);
3553 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3554 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
3555 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
3556 ok(count == 2, "Got unexpected figure count %u.\n", count);
3557 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3558 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
3559 ok(count == 6, "Got unexpected segment count %u.\n", count);
3560 ID2D1GeometrySink_Release(sink);
3562 ID2D1RenderTarget_BeginDraw(rt);
3563 ID2D1RenderTarget_Clear(rt, &color);
3564 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
3565 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3566 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3567 match = compare_surface(surface, "a875e68e0cb9c055927b1b50b879f90b24e38470");
3568 ok(match, "Surface does not match.\n");
3569 ID2D1PathGeometry_Release(geometry);
3571 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
3572 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
3573 hr = ID2D1PathGeometry_Open(geometry, &sink);
3574 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
3575 set_point(&point, 40.0f, 20.0f);
3576 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
3577 line_to(sink, 75.0f, 300.0f);
3578 line_to(sink, 5.0f, 300.0f);
3579 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
3580 hr = ID2D1GeometrySink_Close(sink);
3581 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
3582 ID2D1GeometrySink_Release(sink);
3583 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
3584 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
3585 ok(count == 2, "Got unexpected segment count %u.\n", count);
3587 geometry_sink_init(&simplify_sink);
3588 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3589 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
3590 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3591 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[28], 1);
3592 geometry_sink_cleanup(&simplify_sink);
3594 ID2D1PathGeometry_Release(geometry);
3596 ID2D1SolidColorBrush_Release(brush);
3597 ID2D1RenderTarget_Release(rt);
3598 refcount = ID2D1Factory_Release(factory);
3599 ok(!refcount, "Factory has %u references left.\n", refcount);
3600 IDXGISurface_Release(surface);
3601 IDXGISwapChain_Release(swapchain);
3602 ID3D10Device1_Release(device);
3603 DestroyWindow(window);
3606 static void test_rectangle_geometry(void)
3608 ID2D1TransformedGeometry *transformed_geometry;
3609 ID2D1RectangleGeometry *geometry;
3610 struct geometry_sink sink;
3611 D2D1_MATRIX_3X2_F matrix;
3612 D2D1_RECT_F rect, rect2;
3613 ID2D1Factory *factory;
3614 D2D1_POINT_2F point;
3615 BOOL contains;
3616 HRESULT hr;
3617 BOOL match;
3619 static const struct geometry_segment expected_segments[] =
3621 /* Figure 0. */
3622 {SEGMENT_LINE, {{{10.0f, 0.0f}}}},
3623 {SEGMENT_LINE, {{{10.0f, 20.0f}}}},
3624 {SEGMENT_LINE, {{{ 0.0f, 20.0f}}}},
3625 /* Figure 1. */
3626 {SEGMENT_LINE, {{{4.42705116e+01f, 1.82442951e+01f}}}},
3627 {SEGMENT_LINE, {{{7.95376282e+01f, 5.06049728e+01f}}}},
3628 {SEGMENT_LINE, {{{5.52671127e+01f, 6.23606796e+01f}}}},
3629 /* Figure 2. */
3630 {SEGMENT_LINE, {{{25.0f, 15.0f}}}},
3631 {SEGMENT_LINE, {{{25.0f, 55.0f}}}},
3632 {SEGMENT_LINE, {{{25.0f, 55.0f}}}},
3633 /* Figure 3. */
3634 {SEGMENT_LINE, {{{35.0f, 45.0f}}}},
3635 {SEGMENT_LINE, {{{35.0f, 45.0f}}}},
3636 {SEGMENT_LINE, {{{30.0f, 45.0f}}}},
3637 /* Figure 4. */
3638 {SEGMENT_LINE, {{{ 1.07179585e+01f, 2.23205078e+02f}}}},
3639 {SEGMENT_LINE, {{{-5.85640755e+01f, 2.73205078e+02f}}}},
3640 {SEGMENT_LINE, {{{-7.85640717e+01f, 2.29903809e+02f}}}},
3641 /* Figure 5. */
3642 {SEGMENT_LINE, {{{40.0f, 20.0f}}}},
3643 {SEGMENT_LINE, {{{40.0f, 40.0f}}}},
3644 {SEGMENT_LINE, {{{30.0f, 40.0f}}}},
3645 /* Figure 6. */
3646 {SEGMENT_LINE, {{{ 2.14359169e+01f, 0.0f}}}},
3647 {SEGMENT_LINE, {{{-1.17128151e+02f, 0.0f}}}},
3648 {SEGMENT_LINE, {{{-1.57128143e+02f, 0.0f}}}},
3649 /* Figure 7. */
3650 {SEGMENT_LINE, {{{0.0f, 1.11602539e+02f}}}},
3651 {SEGMENT_LINE, {{{0.0f, 1.36602539e+02f}}}},
3652 {SEGMENT_LINE, {{{0.0f, 1.14951904e+02f}}}},
3654 static const struct expected_geometry_figure expected_figures[] =
3656 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 0.0f, 0.0f}, 3, &expected_segments[0]},
3657 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {20.0f, 30.0f}, 3, &expected_segments[3]},
3658 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {25.0f, 15.0f}, 3, &expected_segments[6]},
3659 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {30.0f, 45.0f}, 3, &expected_segments[9]},
3660 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {-9.28203964e+00f, 1.79903809e+02f},
3661 3, &expected_segments[12]},
3662 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {30.0f, 20.0f}, 3, &expected_segments[15]},
3663 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {-1.85640793e+01f, 0.0f}, 3, &expected_segments[18]},
3664 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {0.0f, 8.99519043e+01f}, 3, &expected_segments[21]},
3667 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
3668 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3670 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
3671 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3672 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
3673 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
3674 match = compare_rect(&rect2, 0.0f, 0.0f, 0.0f, 0.0f, 0);
3675 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3676 rect2.left, rect2.top, rect2.right, rect2.bottom);
3677 ID2D1RectangleGeometry_Release(geometry);
3679 set_rect(&rect, 50.0f, 0.0f, 40.0f, 100.0f);
3680 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3681 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
3682 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
3683 match = compare_rect(&rect2, 50.0f, 0.0f, 40.0f, 100.0f, 0);
3684 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3685 rect2.left, rect2.top, rect2.right, rect2.bottom);
3686 ID2D1RectangleGeometry_Release(geometry);
3688 set_rect(&rect, 0.0f, 100.0f, 40.0f, 50.0f);
3689 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3690 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
3691 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
3692 match = compare_rect(&rect2, 0.0f, 100.0f, 40.0f, 50.0f, 0);
3693 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3694 rect2.left, rect2.top, rect2.right, rect2.bottom);
3695 ID2D1RectangleGeometry_Release(geometry);
3697 set_rect(&rect, 50.0f, 100.0f, 40.0f, 50.0f);
3698 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3699 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
3700 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
3701 match = compare_rect(&rect2, 50.0f, 100.0f, 40.0f, 50.0f, 0);
3702 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
3703 rect2.left, rect2.top, rect2.right, rect2.bottom);
3704 ID2D1RectangleGeometry_Release(geometry);
3706 set_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f);
3707 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3708 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
3710 /* Edge. */
3711 contains = FALSE;
3712 set_point(&point, 0.0f, 0.0f);
3713 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
3714 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
3715 ok(!!contains, "Got wrong hit test result %d.\n", contains);
3717 /* Within tolerance limit around corner. */
3718 contains = TRUE;
3719 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE, 0.0f);
3720 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
3721 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
3722 ok(!contains, "Got wrong hit test result %d.\n", contains);
3724 contains = FALSE;
3725 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE + 0.01f, 0.0f);
3726 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
3727 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
3728 ok(!!contains, "Got wrong hit test result %d.\n", contains);
3730 contains = TRUE;
3731 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE - 0.01f, 0.0f);
3732 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
3733 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
3734 ok(!contains, "Got wrong hit test result %d.\n", contains);
3736 contains = TRUE;
3737 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE, -D2D1_DEFAULT_FLATTENING_TOLERANCE);
3738 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
3739 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
3740 ok(!contains, "Got wrong hit test result %d.\n", contains);
3742 /* Inside. */
3743 contains = FALSE;
3744 set_point(&point, 5.0f, 5.0f);
3745 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
3746 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
3747 ok(!!contains, "Got wrong hit test result %d.\n", contains);
3749 /* Test GetBounds() and Simplify(). */
3750 hr = ID2D1RectangleGeometry_GetBounds(geometry, NULL, &rect);
3751 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3752 match = compare_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f, 0);
3753 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3754 rect.left, rect.top, rect.right, rect.bottom);
3755 geometry_sink_init(&sink);
3756 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3757 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3758 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3759 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[0], 0);
3760 geometry_sink_cleanup(&sink);
3761 geometry_sink_init(&sink);
3762 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3763 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3764 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3765 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[0], 0);
3766 geometry_sink_cleanup(&sink);
3768 set_matrix_identity(&matrix);
3769 translate_matrix(&matrix, 20.0f, 30.0f);
3770 scale_matrix(&matrix, 3.0f, 2.0f);
3771 rotate_matrix(&matrix, M_PI / -5.0f);
3772 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
3773 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3774 match = compare_rect(&rect, 2.00000000e+01f, 1.82442951e+01f, 7.95376282e+01f, 6.23606796e+01f, 0);
3775 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3776 rect.left, rect.top, rect.right, rect.bottom);
3777 geometry_sink_init(&sink);
3778 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3779 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3780 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3781 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[1], 1);
3782 geometry_sink_cleanup(&sink);
3784 set_matrix_identity(&matrix);
3785 translate_matrix(&matrix, 25.0f, 15.0f);
3786 scale_matrix(&matrix, 0.0f, 2.0f);
3787 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
3788 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3789 match = compare_rect(&rect, 25.0f, 15.0f, 25.0f, 55.0f, 0);
3790 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3791 rect.left, rect.top, rect.right, rect.bottom);
3792 geometry_sink_init(&sink);
3793 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3794 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3795 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3796 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[2], 0);
3797 geometry_sink_cleanup(&sink);
3799 set_matrix_identity(&matrix);
3800 translate_matrix(&matrix, 30.0f, 45.0f);
3801 scale_matrix(&matrix, 0.5f, 0.0f);
3802 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
3803 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3804 match = compare_rect(&rect, 30.0f, 45.0f, 35.0f, 45.0f, 0);
3805 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3806 rect.left, rect.top, rect.right, rect.bottom);
3807 geometry_sink_init(&sink);
3808 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3809 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3810 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3811 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[3], 0);
3812 geometry_sink_cleanup(&sink);
3814 set_matrix_identity(&matrix);
3815 scale_matrix(&matrix, 4.0f, 5.0f);
3816 rotate_matrix(&matrix, M_PI / 3.0f);
3817 translate_matrix(&matrix, 30.0f, 20.0f);
3818 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
3819 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
3821 ID2D1TransformedGeometry_GetBounds(transformed_geometry, NULL, &rect);
3822 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3823 match = compare_rect(&rect, -7.85640717e+01f, 1.79903809e+02f, 1.07179594e+01f, 2.73205078e+02f, 1);
3824 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3825 rect.left, rect.top, rect.right, rect.bottom);
3826 geometry_sink_init(&sink);
3827 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3828 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3829 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3830 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[4], 1);
3831 geometry_sink_cleanup(&sink);
3832 geometry_sink_init(&sink);
3833 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3834 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3835 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3836 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[4], 1);
3837 geometry_sink_cleanup(&sink);
3839 set_matrix_identity(&matrix);
3840 rotate_matrix(&matrix, M_PI / -3.0f);
3841 scale_matrix(&matrix, 0.25f, 0.2f);
3842 ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
3843 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3844 match = compare_rect(&rect, 30.0f, 20.0f, 40.0f, 40.0f, 2);
3845 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3846 rect.left, rect.top, rect.right, rect.bottom);
3847 geometry_sink_init(&sink);
3848 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3849 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3850 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3851 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[5], 4);
3852 geometry_sink_cleanup(&sink);
3854 set_matrix_identity(&matrix);
3855 scale_matrix(&matrix, 2.0f, 0.0f);
3856 ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
3857 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3858 match = compare_rect(&rect, -1.57128143e+02f, 0.00000000e+00f, 2.14359188e+01f, 0.00000000e+00f, 1);
3859 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3860 rect.left, rect.top, rect.right, rect.bottom);
3861 geometry_sink_init(&sink);
3862 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3863 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3864 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3865 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[6], 1);
3866 geometry_sink_cleanup(&sink);
3868 set_matrix_identity(&matrix);
3869 scale_matrix(&matrix, 0.0f, 0.5f);
3870 ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
3871 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3872 match = compare_rect(&rect, 0.00000000e+00f, 8.99519043e+01f, 0.00000000e+00, 1.36602539e+02f, 1);
3873 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3874 rect.left, rect.top, rect.right, rect.bottom);
3875 geometry_sink_init(&sink);
3876 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3877 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3878 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3879 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[7], 1);
3880 geometry_sink_cleanup(&sink);
3882 ID2D1TransformedGeometry_Release(transformed_geometry);
3883 ID2D1RectangleGeometry_Release(geometry);
3884 ID2D1Factory_Release(factory);
3887 static void test_rounded_rectangle_geometry(void)
3889 ID2D1RoundedRectangleGeometry *geometry;
3890 D2D1_ROUNDED_RECT rect, rect2;
3891 ID2D1Factory *factory;
3892 HRESULT hr;
3894 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
3895 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3897 set_rounded_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
3898 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
3899 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
3901 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
3902 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
3903 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
3904 ID2D1RoundedRectangleGeometry_Release(geometry);
3906 /* X radius larger than half width. */
3907 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 30.0f, 5.0f);
3908 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
3909 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
3910 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
3911 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
3912 ID2D1RoundedRectangleGeometry_Release(geometry);
3914 /* Y radius larger than half height. */
3915 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 5.0f, 30.0f);
3916 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
3917 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
3918 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
3919 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
3920 ID2D1RoundedRectangleGeometry_Release(geometry);
3922 /* Both exceed rectangle size. */
3923 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 30.0f, 25.0f);
3924 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
3925 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
3926 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
3927 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
3928 ID2D1RoundedRectangleGeometry_Release(geometry);
3930 ID2D1Factory_Release(factory);
3933 static void test_bitmap_formats(void)
3935 D2D1_BITMAP_PROPERTIES bitmap_desc;
3936 IDXGISwapChain *swapchain;
3937 D2D1_SIZE_U size = {4, 4};
3938 ID2D1RenderTarget *rt;
3939 ID3D10Device1 *device;
3940 IDXGISurface *surface;
3941 ID2D1Bitmap *bitmap;
3942 unsigned int i, j;
3943 HWND window;
3944 HRESULT hr;
3946 static const struct
3948 DXGI_FORMAT format;
3949 DWORD mask;
3951 bitmap_formats[] =
3953 {DXGI_FORMAT_R32G32B32A32_FLOAT, 0x8a},
3954 {DXGI_FORMAT_R16G16B16A16_FLOAT, 0x8a},
3955 {DXGI_FORMAT_R16G16B16A16_UNORM, 0x8a},
3956 {DXGI_FORMAT_R8G8B8A8_TYPELESS, 0x00},
3957 {DXGI_FORMAT_R8G8B8A8_UNORM, 0x0a},
3958 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0x8a},
3959 {DXGI_FORMAT_R8G8B8A8_UINT, 0x00},
3960 {DXGI_FORMAT_R8G8B8A8_SNORM, 0x00},
3961 {DXGI_FORMAT_R8G8B8A8_SINT, 0x00},
3962 {DXGI_FORMAT_A8_UNORM, 0x06},
3963 {DXGI_FORMAT_B8G8R8A8_UNORM, 0x0a},
3964 {DXGI_FORMAT_B8G8R8X8_UNORM, 0x88},
3965 {DXGI_FORMAT_B8G8R8A8_TYPELESS, 0x00},
3966 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 0x8a},
3969 if (!(device = create_device()))
3971 skip("Failed to create device, skipping tests.\n");
3972 return;
3974 window = create_window();
3975 swapchain = create_swapchain(device, window, TRUE);
3976 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3977 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3978 rt = create_render_target(surface);
3979 ok(!!rt, "Failed to create render target.\n");
3981 bitmap_desc.dpiX = 96.0f;
3982 bitmap_desc.dpiY = 96.0f;
3983 for (i = 0; i < ARRAY_SIZE(bitmap_formats); ++i)
3985 for (j = 0; j < 4; ++j)
3987 if ((bitmap_formats[i].mask & (0x80 | (1u << j))) == (0x80 | (1u << j)))
3988 continue;
3990 bitmap_desc.pixelFormat.format = bitmap_formats[i].format;
3991 bitmap_desc.pixelFormat.alphaMode = j;
3992 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
3993 if (bitmap_formats[i].mask & (1u << j))
3994 ok(hr == S_OK, "Got unexpected hr %#x, for format %#x/%#x.\n",
3995 hr, bitmap_formats[i].format, j);
3996 else
3997 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x, for format %#x/%#x.\n",
3998 hr, bitmap_formats[i].format, j);
3999 if (SUCCEEDED(hr))
4000 ID2D1Bitmap_Release(bitmap);
4004 ID2D1RenderTarget_Release(rt);
4005 IDXGISurface_Release(surface);
4006 IDXGISwapChain_Release(swapchain);
4007 ID3D10Device1_Release(device);
4008 DestroyWindow(window);
4011 static void test_alpha_mode(void)
4013 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
4014 D2D1_BITMAP_PROPERTIES bitmap_desc;
4015 ID2D1SolidColorBrush *color_brush;
4016 ID2D1BitmapBrush *bitmap_brush;
4017 IDXGISwapChain *swapchain;
4018 ID2D1RenderTarget *rt;
4019 ID3D10Device1 *device;
4020 IDXGISurface *surface;
4021 ID2D1Bitmap *bitmap;
4022 D2D1_COLOR_F color;
4023 D2D1_RECT_F rect;
4024 D2D1_SIZE_U size;
4025 ULONG refcount;
4026 HWND window;
4027 HRESULT hr;
4028 BOOL match;
4030 static const DWORD bitmap_data[] =
4032 0x7f7f0000, 0x7f7f7f00, 0x7f007f00, 0x7f007f7f,
4033 0x7f00007f, 0x7f7f007f, 0x7f000000, 0x7f404040,
4034 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f000000,
4035 0x7f7f7f7f, 0x7f000000, 0x7f000000, 0x7f000000,
4038 if (!(device = create_device()))
4040 skip("Failed to create device, skipping tests.\n");
4041 return;
4043 window = create_window();
4044 swapchain = create_swapchain(device, window, TRUE);
4045 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
4046 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4047 rt = create_render_target(surface);
4048 ok(!!rt, "Failed to create render target.\n");
4050 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4052 set_size_u(&size, 4, 4);
4053 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4054 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
4055 bitmap_desc.dpiX = 96.0f / 40.0f;
4056 bitmap_desc.dpiY = 96.0f / 30.0f;
4057 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
4058 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4060 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
4061 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4062 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
4063 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
4064 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
4066 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
4067 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
4068 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4070 ID2D1RenderTarget_BeginDraw(rt);
4071 ID2D1RenderTarget_Clear(rt, NULL);
4072 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4073 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4074 match = compare_surface(surface, "48c41aff3a130a17ee210866b2ab7d36763934d5");
4075 ok(match, "Surface does not match.\n");
4077 ID2D1RenderTarget_BeginDraw(rt);
4078 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
4079 ID2D1RenderTarget_Clear(rt, &color);
4080 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4081 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4082 match = compare_surface(surface, "6487e683730fb5a77c1911388d00b04664c5c4e4");
4083 ok(match, "Surface does not match.\n");
4085 ID2D1RenderTarget_BeginDraw(rt);
4086 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
4087 ID2D1RenderTarget_Clear(rt, &color);
4088 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4089 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4090 match = compare_surface(surface, "7a35ba09e43cbaf591388ff1ef8de56157630c98");
4091 ok(match, "Surface does not match.\n");
4093 ID2D1RenderTarget_BeginDraw(rt);
4095 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
4096 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4097 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
4098 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
4099 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4100 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
4101 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
4102 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4104 ID2D1Bitmap_Release(bitmap);
4105 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4106 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
4107 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4108 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
4110 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
4111 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
4112 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4113 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
4114 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
4115 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4116 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
4117 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
4118 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4120 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
4121 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4122 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
4123 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
4124 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4125 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
4126 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
4127 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4129 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4130 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4131 match = compare_surface(surface, "14f8ac64b70966c7c3c6281c59aaecdb17c3b16a");
4132 ok(match, "Surface does not match.\n");
4134 ID2D1RenderTarget_Release(rt);
4135 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4136 rt_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
4137 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
4138 rt_desc.dpiX = 0.0f;
4139 rt_desc.dpiY = 0.0f;
4140 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4141 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4142 rt = create_render_target_desc(surface, &rt_desc);
4143 ok(!!rt, "Failed to create render target.\n");
4145 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4147 ID2D1Bitmap_Release(bitmap);
4148 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
4149 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
4150 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4151 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
4153 ID2D1BitmapBrush_Release(bitmap_brush);
4154 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
4155 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4156 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
4157 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
4158 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
4160 ID2D1SolidColorBrush_Release(color_brush);
4161 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
4162 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
4163 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4165 ID2D1RenderTarget_BeginDraw(rt);
4166 ID2D1RenderTarget_Clear(rt, NULL);
4167 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4168 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4169 match = compare_surface(surface, "b44510bf2d2e61a8d7c0ad862de49a471f1fd13f");
4170 ok(match, "Surface does not match.\n");
4172 ID2D1RenderTarget_BeginDraw(rt);
4173 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
4174 ID2D1RenderTarget_Clear(rt, &color);
4175 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4176 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4177 match = compare_surface(surface, "2184f4a9198fc1de09ac85301b7a03eebadd9b81");
4178 ok(match, "Surface does not match.\n");
4180 ID2D1RenderTarget_BeginDraw(rt);
4181 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
4182 ID2D1RenderTarget_Clear(rt, &color);
4183 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4184 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4185 match = compare_surface(surface, "6527ec83b4039c895b50f9b3e144fe0cf90d1889");
4186 ok(match, "Surface does not match.\n");
4188 ID2D1RenderTarget_BeginDraw(rt);
4190 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
4191 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4192 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
4193 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
4194 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4195 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
4196 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
4197 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4199 ID2D1Bitmap_Release(bitmap);
4200 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4201 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
4202 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4203 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
4205 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
4206 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
4207 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4208 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
4209 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
4210 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4211 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
4212 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
4213 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4215 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
4216 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4217 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
4218 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
4219 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4220 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
4221 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
4222 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4224 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4225 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4226 match = compare_surface(surface, "465f5a3190d7bde408b3206b4be939fb22f8a3d6");
4227 ok(match, "Surface does not match.\n");
4229 refcount = ID2D1Bitmap_Release(bitmap);
4230 ok(refcount == 1, "Bitmap has %u references left.\n", refcount);
4231 ID2D1SolidColorBrush_Release(color_brush);
4232 ID2D1BitmapBrush_Release(bitmap_brush);
4233 ID2D1RenderTarget_Release(rt);
4234 IDXGISurface_Release(surface);
4235 IDXGISwapChain_Release(swapchain);
4236 ID3D10Device1_Release(device);
4237 DestroyWindow(window);
4240 static void test_shared_bitmap(void)
4242 IDXGISwapChain *swapchain1, *swapchain2;
4243 IWICBitmap *wic_bitmap1, *wic_bitmap2;
4244 ID2D1GdiInteropRenderTarget *interop;
4245 D2D1_RENDER_TARGET_PROPERTIES desc;
4246 D2D1_BITMAP_PROPERTIES bitmap_desc;
4247 ID2D1RenderTarget *rt1, *rt2, *rt3;
4248 IDXGISurface *surface1, *surface2;
4249 ID2D1Factory *factory1, *factory2;
4250 ID3D10Device1 *device1, *device2;
4251 IWICImagingFactory *wic_factory;
4252 ID2D1Bitmap *bitmap1, *bitmap2;
4253 DXGI_SURFACE_DESC surface_desc;
4254 D2D1_PIXEL_FORMAT pixel_format;
4255 D2D1_SIZE_U size = {4, 4};
4256 IDXGISurface1 *surface3;
4257 HWND window1, window2;
4258 HRESULT hr;
4260 if (!(device1 = create_device()))
4262 skip("Failed to create device, skipping tests.\n");
4263 return;
4266 window1 = create_window();
4267 window2 = create_window();
4268 swapchain1 = create_swapchain(device1, window1, TRUE);
4269 swapchain2 = create_swapchain(device1, window2, TRUE);
4270 hr = IDXGISwapChain_GetBuffer(swapchain1, 0, &IID_IDXGISurface, (void **)&surface1);
4271 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4272 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
4273 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4275 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
4276 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
4277 &IID_IWICImagingFactory, (void **)&wic_factory);
4278 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
4279 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
4280 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap1);
4281 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4282 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
4283 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap2);
4284 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4285 IWICImagingFactory_Release(wic_factory);
4287 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4288 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
4289 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4290 desc.dpiX = 0.0f;
4291 desc.dpiY = 0.0f;
4292 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4293 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4295 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4296 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4297 bitmap_desc.dpiX = 96.0f;
4298 bitmap_desc.dpiY = 96.0f;
4300 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory1);
4301 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4302 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
4303 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4305 /* DXGI surface render targets with the same device and factory. */
4306 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface1, &desc, &rt1);
4307 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4308 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
4309 check_bitmap_surface(bitmap1, TRUE, 0);
4310 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4312 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
4313 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4314 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4315 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4316 check_bitmap_surface(bitmap2, TRUE, 0);
4317 ID2D1Bitmap_Release(bitmap2);
4318 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IUnknown, bitmap1, NULL, &bitmap2);
4319 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
4320 ID2D1RenderTarget_Release(rt2);
4322 /* DXGI surface render targets with the same device but different factories. */
4323 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
4324 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4325 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4326 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
4327 ID2D1RenderTarget_Release(rt2);
4329 /* DXGI surface render targets with different devices but the same factory. */
4330 IDXGISurface_Release(surface2);
4331 IDXGISwapChain_Release(swapchain2);
4332 device2 = create_device();
4333 ok(!!device2, "Failed to create device.\n");
4334 swapchain2 = create_swapchain(device2, window2, TRUE);
4335 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
4336 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4338 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
4339 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4340 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4341 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
4342 ID2D1RenderTarget_Release(rt2);
4344 /* DXGI surface render targets with different devices and different factories. */
4345 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
4346 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4347 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4348 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
4349 ID2D1RenderTarget_Release(rt2);
4351 /* DXGI surface render target and WIC bitmap render target, same factory. */
4352 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
4353 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4354 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4355 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
4356 ID2D1RenderTarget_Release(rt2);
4358 /* WIC bitmap render targets on different D2D factories. */
4359 ID2D1Bitmap_Release(bitmap1);
4360 ID2D1RenderTarget_Release(rt1);
4361 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap1, &desc, &rt1);
4362 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4363 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
4364 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4366 hr = ID2D1RenderTarget_QueryInterface(rt1, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
4367 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
4368 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
4369 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4370 ok(rt3 == rt1, "Unexpected render target\n");
4371 ID2D1RenderTarget_Release(rt3);
4372 ID2D1GdiInteropRenderTarget_Release(interop);
4374 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory2, wic_bitmap2, &desc, &rt2);
4375 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4376 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4377 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
4378 ID2D1RenderTarget_Release(rt2);
4380 /* WIC bitmap render targets on the same D2D factory. */
4381 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
4382 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4383 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
4384 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4385 check_bitmap_surface(bitmap2, FALSE, 0);
4386 ID2D1Bitmap_Release(bitmap2);
4387 ID2D1RenderTarget_Release(rt2);
4389 /* Shared DXGI surface. */
4390 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4391 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4392 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4393 desc.dpiX = 0.0f;
4394 desc.dpiY = 0.0f;
4395 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4396 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4398 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
4399 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4401 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4402 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4403 bitmap_desc.dpiX = 0.0f;
4404 bitmap_desc.dpiY = 0.0f;
4406 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface, surface2, &bitmap_desc, &bitmap2);
4407 ok(SUCCEEDED(hr) || broken(hr == E_INVALIDARG) /* vista */, "Failed to create bitmap, hr %#x.\n", hr);
4409 if (SUCCEEDED(hr))
4411 static const struct bitmap_format_test
4413 D2D1_PIXEL_FORMAT original;
4414 D2D1_PIXEL_FORMAT result;
4415 HRESULT hr;
4417 bitmap_format_tests[] =
4419 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
4420 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED } },
4422 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE },
4423 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
4425 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
4427 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
4429 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE },
4430 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
4432 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
4433 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
4435 unsigned int i;
4437 size = ID2D1Bitmap_GetPixelSize(bitmap2);
4438 hr = IDXGISurface_GetDesc(surface2, &surface_desc);
4439 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
4440 ok(size.width == surface_desc.Width && size.height == surface_desc.Height, "Got wrong bitmap size.\n");
4442 check_bitmap_surface(bitmap2, TRUE, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW);
4444 ID2D1Bitmap_Release(bitmap2);
4446 /* IDXGISurface1 is supported too. */
4447 if (IDXGISurface_QueryInterface(surface2, &IID_IDXGISurface1, (void **)&surface3) == S_OK)
4449 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface1, surface3, &bitmap_desc, &bitmap2);
4450 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4452 ID2D1Bitmap_Release(bitmap2);
4453 IDXGISurface1_Release(surface3);
4456 for (i = 0; i < ARRAY_SIZE(bitmap_format_tests); ++i)
4458 bitmap_desc.pixelFormat = bitmap_format_tests[i].original;
4460 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface, surface2, &bitmap_desc, &bitmap2);
4461 todo_wine_if(i == 2 || i == 3 || i == 5 || i == 6)
4462 ok(hr == bitmap_format_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
4464 if (SUCCEEDED(bitmap_format_tests[i].hr))
4466 pixel_format = ID2D1Bitmap_GetPixelFormat(bitmap2);
4467 ok(pixel_format.format == bitmap_format_tests[i].result.format, "%u: unexpected pixel format %#x.\n",
4468 i, pixel_format.format);
4469 ok(pixel_format.alphaMode == bitmap_format_tests[i].result.alphaMode, "%u: unexpected alpha mode %d.\n",
4470 i, pixel_format.alphaMode);
4472 ID2D1Bitmap_Release(bitmap2);
4477 ID2D1RenderTarget_Release(rt2);
4479 ID2D1Bitmap_Release(bitmap1);
4480 ID2D1RenderTarget_Release(rt1);
4481 ID2D1Factory_Release(factory2);
4482 ID2D1Factory_Release(factory1);
4483 IWICBitmap_Release(wic_bitmap2);
4484 IWICBitmap_Release(wic_bitmap1);
4485 IDXGISurface_Release(surface2);
4486 IDXGISurface_Release(surface1);
4487 IDXGISwapChain_Release(swapchain2);
4488 IDXGISwapChain_Release(swapchain1);
4489 ID3D10Device1_Release(device2);
4490 ID3D10Device1_Release(device1);
4491 DestroyWindow(window2);
4492 DestroyWindow(window1);
4493 CoUninitialize();
4496 static void test_bitmap_updates(void)
4498 D2D1_BITMAP_PROPERTIES bitmap_desc;
4499 IDXGISwapChain *swapchain;
4500 ID2D1RenderTarget *rt;
4501 ID3D10Device1 *device;
4502 IDXGISurface *surface;
4503 D2D1_RECT_U dst_rect;
4504 ID2D1Bitmap *bitmap;
4505 D2D1_COLOR_F color;
4506 D2D1_RECT_F rect;
4507 D2D1_SIZE_U size;
4508 HWND window;
4509 HRESULT hr;
4510 BOOL match;
4512 static const DWORD bitmap_data[] =
4514 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
4515 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
4516 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
4517 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
4520 if (!(device = create_device()))
4522 skip("Failed to create device, skipping tests.\n");
4523 return;
4525 window = create_window();
4526 swapchain = create_swapchain(device, window, TRUE);
4527 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
4528 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4529 rt = create_render_target(surface);
4530 ok(!!rt, "Failed to create render target.\n");
4532 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4534 ID2D1RenderTarget_BeginDraw(rt);
4535 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
4536 ID2D1RenderTarget_Clear(rt, &color);
4538 set_size_u(&size, 4, 4);
4539 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4540 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4541 bitmap_desc.dpiX = 96.0f;
4542 bitmap_desc.dpiY = 96.0f;
4543 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
4544 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4546 set_rect(&rect, 0.0f, 0.0f, 320.0f, 240.0f);
4547 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
4548 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
4550 ID2D1Bitmap_Release(bitmap);
4552 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
4553 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
4554 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4556 set_rect(&rect, 0.0f, 240.0f, 320.0f, 480.0f);
4557 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
4558 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
4560 set_rect_u(&dst_rect, 1, 1, 3, 3);
4561 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, 4 * sizeof(*bitmap_data));
4562 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
4563 set_rect_u(&dst_rect, 0, 3, 3, 4);
4564 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[6], 4 * sizeof(*bitmap_data));
4565 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
4566 set_rect_u(&dst_rect, 0, 0, 4, 1);
4567 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[10], 4 * sizeof(*bitmap_data));
4568 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
4569 set_rect_u(&dst_rect, 0, 1, 1, 3);
4570 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[2], sizeof(*bitmap_data));
4571 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
4572 set_rect_u(&dst_rect, 4, 4, 3, 1);
4573 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, sizeof(*bitmap_data));
4574 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
4575 set_rect(&rect, 320.0f, 240.0f, 640.0f, 480.0f);
4576 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
4577 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
4579 hr = ID2D1Bitmap_CopyFromMemory(bitmap, NULL, bitmap_data, 4 * sizeof(*bitmap_data));
4580 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
4581 set_rect(&rect, 320.0f, 0.0f, 640.0f, 240.0f);
4582 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
4583 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
4585 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4586 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4588 match = compare_surface(surface, "cb8136c91fbbdc76bb83b8c09edc1907b0a5d0a6");
4589 ok(match, "Surface does not match.\n");
4591 ID2D1Bitmap_Release(bitmap);
4592 ID2D1RenderTarget_Release(rt);
4593 IDXGISurface_Release(surface);
4594 IDXGISwapChain_Release(swapchain);
4595 ID3D10Device1_Release(device);
4596 DestroyWindow(window);
4599 static void test_opacity_brush(void)
4601 ID2D1BitmapBrush *bitmap_brush, *opacity_brush;
4602 D2D1_BITMAP_PROPERTIES bitmap_desc;
4603 ID2D1RectangleGeometry *geometry;
4604 ID2D1SolidColorBrush *color_brush;
4605 IDXGISwapChain *swapchain;
4606 D2D1_MATRIX_3X2_F matrix;
4607 ID2D1RenderTarget *rt;
4608 ID3D10Device1 *device;
4609 IDXGISurface *surface;
4610 ID2D1Factory *factory;
4611 ID2D1Bitmap *bitmap;
4612 D2D1_COLOR_F color;
4613 D2D1_RECT_F rect;
4614 D2D1_SIZE_U size;
4615 ULONG refcount;
4616 HWND window;
4617 HRESULT hr;
4618 BOOL match;
4620 static const DWORD bitmap_data[] =
4622 0xffff0000, 0x40ffff00, 0x4000ff00, 0xff00ffff,
4623 0x7f0000ff, 0x00ff00ff, 0x00000000, 0x7f7f7f7f,
4624 0x7fffffff, 0x00ffffff, 0x00ffffff, 0x7f000000,
4625 0xffffffff, 0x40000000, 0x40000000, 0xff000000,
4628 if (!(device = create_device()))
4630 skip("Failed to create device, skipping tests.\n");
4631 return;
4633 window = create_window();
4634 swapchain = create_swapchain(device, window, TRUE);
4635 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
4636 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4637 rt = create_render_target(surface);
4638 ok(!!rt, "Failed to create render target.\n");
4639 ID2D1RenderTarget_GetFactory(rt, &factory);
4641 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
4642 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4644 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
4645 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
4646 ok(SUCCEEDED(hr), "Failed to create color brush, hr %#x.\n", hr);
4648 set_size_u(&size, 4, 4);
4649 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4650 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4651 bitmap_desc.dpiX = 96.0f;
4652 bitmap_desc.dpiY = 96.0f;
4653 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
4654 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4655 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &opacity_brush);
4656 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
4657 ID2D1BitmapBrush_SetInterpolationMode(opacity_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
4658 refcount = ID2D1Bitmap_Release(bitmap);
4659 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4661 set_size_u(&size, 1, 1);
4662 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4663 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
4664 bitmap_desc.dpiX = 96.0f;
4665 bitmap_desc.dpiY = 96.0f;
4666 hr = ID2D1RenderTarget_CreateBitmap(rt, size, &bitmap_data[2], sizeof(*bitmap_data), &bitmap_desc, &bitmap);
4667 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
4668 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
4669 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
4670 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
4671 refcount = ID2D1Bitmap_Release(bitmap);
4672 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4674 ID2D1RenderTarget_BeginDraw(rt);
4676 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
4677 ID2D1RenderTarget_Clear(rt, &color);
4679 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
4680 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
4682 set_matrix_identity(&matrix);
4683 translate_matrix(&matrix, 120.0f, 120.0f);
4684 scale_matrix(&matrix, 20.0f, 60.0f);
4685 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
4686 set_rect(&rect, 120.0f, 120.0f, 200.0f, 360.0f);
4687 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)opacity_brush);
4689 set_rect(&rect, 200.0f, 120.0f, 280.0f, 360.0f);
4690 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
4692 set_matrix_identity(&matrix);
4693 translate_matrix(&matrix, 40.0f, 360.0f);
4694 scale_matrix(&matrix, 20.0f, 60.0f);
4695 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
4696 set_rect(&rect, 40.0f, 360.0f, 120.0f, 600.0f);
4697 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4698 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
4699 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
4700 ID2D1RectangleGeometry_Release(geometry);
4702 set_matrix_identity(&matrix);
4703 translate_matrix(&matrix, 120.0f, 360.0f);
4704 scale_matrix(&matrix, 20.0f, 60.0f);
4705 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
4706 set_rect(&rect, 120.0f, 360.0f, 200.0f, 600.0f);
4707 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4708 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
4709 (ID2D1Brush *)color_brush, (ID2D1Brush *)opacity_brush);
4710 ID2D1RectangleGeometry_Release(geometry);
4712 set_matrix_identity(&matrix);
4713 translate_matrix(&matrix, 200.0f, 360.0f);
4714 scale_matrix(&matrix, 20.0f, 60.0f);
4715 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
4716 set_rect(&rect, 200.0f, 360.0f, 280.0f, 600.0f);
4717 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4718 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
4719 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
4721 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4722 ok(hr == D2DERR_INCOMPATIBLE_BRUSH_TYPES, "Got unexpected hr %#x.\n", hr);
4723 match = compare_surface(surface, "7141c6c7b3decb91196428efb1856bcbf9872935");
4724 ok(match, "Surface does not match.\n");
4725 ID2D1RenderTarget_BeginDraw(rt);
4727 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
4728 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
4729 ID2D1RectangleGeometry_Release(geometry);
4731 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.5f);
4732 set_matrix_identity(&matrix);
4733 translate_matrix(&matrix, 40.0f, 600.0f);
4734 scale_matrix(&matrix, 20.0f, 60.0f);
4735 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
4736 set_rect(&rect, 40.0f, 600.0f, 120.0f, 840.0f);
4737 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4738 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
4739 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
4740 ID2D1RectangleGeometry_Release(geometry);
4742 ID2D1BitmapBrush_SetOpacity(opacity_brush, 0.8f);
4743 set_matrix_identity(&matrix);
4744 translate_matrix(&matrix, 120.0f, 600.0f);
4745 scale_matrix(&matrix, 20.0f, 60.0f);
4746 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
4747 set_rect(&rect, 120.0f, 600.0f, 200.0f, 840.0f);
4748 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4749 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
4750 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)bitmap_brush);
4751 ID2D1RectangleGeometry_Release(geometry);
4753 set_matrix_identity(&matrix);
4754 translate_matrix(&matrix, 200.0f, 600.0f);
4755 scale_matrix(&matrix, 20.0f, 60.0f);
4756 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
4757 set_rect(&rect, 200.0f, 600.0f, 280.0f, 840.0f);
4758 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4759 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
4760 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
4761 ID2D1RectangleGeometry_Release(geometry);
4763 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4764 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4765 match = compare_surface(surface, "c3a5802d1750efa3e9122c1a92f6064df3872732");
4766 ok(match, "Surface does not match.\n");
4768 ID2D1BitmapBrush_Release(bitmap_brush);
4769 ID2D1BitmapBrush_Release(opacity_brush);
4770 ID2D1SolidColorBrush_Release(color_brush);
4771 ID2D1RenderTarget_Release(rt);
4772 refcount = ID2D1Factory_Release(factory);
4773 ok(!refcount, "Factory has %u references left.\n", refcount);
4774 IDXGISurface_Release(surface);
4775 IDXGISwapChain_Release(swapchain);
4776 ID3D10Device1_Release(device);
4777 DestroyWindow(window);
4780 static void test_create_target(void)
4782 IDXGISwapChain *swapchain;
4783 ID2D1Factory *factory;
4784 ID2D1RenderTarget *rt;
4785 ID3D10Device1 *device;
4786 IDXGISurface *surface;
4787 HWND window;
4788 HRESULT hr;
4789 static const struct
4791 float dpi_x, dpi_y;
4792 float rt_dpi_x, rt_dpi_y;
4793 HRESULT hr;
4795 create_dpi_tests[] =
4797 { 0.0f, 0.0f, 96.0f, 96.0f, S_OK },
4798 { 192.0f, 0.0f, 96.0f, 96.0f, E_INVALIDARG },
4799 { 0.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
4800 { 192.0f, -10.0f, 96.0f, 96.0f, E_INVALIDARG },
4801 { -10.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
4802 { 48.0f, 96.0f, 48.0f, 96.0f, S_OK },
4804 unsigned int i;
4806 if (!(device = create_device()))
4808 skip("Failed to create device, skipping tests.\n");
4809 return;
4811 window = create_window();
4812 swapchain = create_swapchain(device, window, TRUE);
4813 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
4814 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4816 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4817 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4819 for (i = 0; i < ARRAY_SIZE(create_dpi_tests); ++i)
4821 ID2D1GdiInteropRenderTarget *interop;
4822 D2D1_RENDER_TARGET_PROPERTIES desc;
4823 ID2D1RenderTarget *rt2;
4824 float dpi_x, dpi_y;
4825 IUnknown *unk;
4827 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4828 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
4829 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4830 desc.dpiX = create_dpi_tests[i].dpi_x;
4831 desc.dpiY = create_dpi_tests[i].dpi_y;
4832 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4833 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4835 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
4836 ok(hr == create_dpi_tests[i].hr, "Wrong return code, hr %#x, expected %#x, test %u.\n", hr,
4837 create_dpi_tests[i].hr, i);
4839 if (FAILED(hr))
4840 continue;
4842 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_IUnknown, (void **)&unk);
4843 ok(SUCCEEDED(hr), "Failed to get IUnknown, hr %#x.\n", hr);
4844 ok(unk == (IUnknown *)rt, "Expected same interface pointer.\n");
4845 IUnknown_Release(unk);
4847 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
4848 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
4849 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt2);
4850 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4851 ok(rt2 == rt, "Unexpected render target\n");
4852 ID2D1RenderTarget_Release(rt2);
4853 ID2D1GdiInteropRenderTarget_Release(interop);
4855 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
4856 ok(dpi_x == create_dpi_tests[i].rt_dpi_x, "Wrong dpi_x %.8e, expected %.8e, test %u\n",
4857 dpi_x, create_dpi_tests[i].rt_dpi_x, i);
4858 ok(dpi_y == create_dpi_tests[i].rt_dpi_y, "Wrong dpi_y %.8e, expected %.8e, test %u\n",
4859 dpi_y, create_dpi_tests[i].rt_dpi_y, i);
4861 ID2D1RenderTarget_Release(rt);
4864 ID2D1Factory_Release(factory);
4865 IDXGISurface_Release(surface);
4866 IDXGISwapChain_Release(swapchain);
4867 ID3D10Device1_Release(device);
4868 DestroyWindow(window);
4871 static void test_draw_text_layout(void)
4873 static const struct
4875 D2D1_TEXT_ANTIALIAS_MODE aa_mode;
4876 DWRITE_RENDERING_MODE rendering_mode;
4877 HRESULT hr;
4879 antialias_mode_tests[] =
4881 { D2D1_TEXT_ANTIALIAS_MODE_DEFAULT, DWRITE_RENDERING_MODE_ALIASED },
4882 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_ALIASED },
4883 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_DEFAULT },
4884 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_OUTLINE },
4885 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_DEFAULT },
4886 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_OUTLINE },
4887 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL },
4888 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC },
4889 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL },
4890 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC },
4891 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_DEFAULT },
4892 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL },
4893 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC },
4894 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL },
4895 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC },
4896 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_OUTLINE, E_INVALIDARG },
4897 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_ALIASED, E_INVALIDARG },
4898 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_ALIASED, E_INVALIDARG },
4899 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL, E_INVALIDARG },
4900 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, E_INVALIDARG },
4901 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL, E_INVALIDARG },
4902 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC, E_INVALIDARG },
4904 D2D1_RENDER_TARGET_PROPERTIES desc;
4905 IDXGISwapChain *swapchain;
4906 ID2D1Factory *factory, *factory2;
4907 ID2D1RenderTarget *rt, *rt2;
4908 ID3D10Device1 *device;
4909 IDXGISurface *surface;
4910 HWND window;
4911 HRESULT hr;
4912 IDWriteFactory *dwrite_factory;
4913 IDWriteTextFormat *text_format;
4914 IDWriteTextLayout *text_layout;
4915 D2D1_POINT_2F origin;
4916 DWRITE_TEXT_RANGE range;
4917 D2D1_COLOR_F color;
4918 ID2D1SolidColorBrush *brush, *brush2;
4919 ID2D1RectangleGeometry *geometry;
4920 D2D1_RECT_F rect;
4921 unsigned int i;
4923 if (!(device = create_device()))
4925 skip("Failed to create device, skipping tests.\n");
4926 return;
4928 window = create_window();
4929 swapchain = create_swapchain(device, window, TRUE);
4930 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
4931 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4933 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4934 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4936 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
4937 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4938 ok(factory != factory2, "got same factory\n");
4940 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4941 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
4942 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4943 desc.dpiX = 0.0f;
4944 desc.dpiY = 0.0f;
4945 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4946 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4948 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
4949 ok(SUCCEEDED(hr), "Failed to create a target, hr %#x.\n", hr);
4951 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface, &desc, &rt2);
4952 ok(SUCCEEDED(hr), "Failed to create a target, hr %#x.\n", hr);
4954 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
4955 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4957 hr = IDWriteFactory_CreateTextFormat(dwrite_factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL,
4958 DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"", &text_format);
4959 ok(SUCCEEDED(hr), "Failed to create text format, hr %#x.\n", hr);
4961 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, L"text", 4, text_format, 100.0f, 100.0f, &text_layout);
4962 ok(SUCCEEDED(hr), "Failed to create text layout, hr %#x.\n", hr);
4964 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
4965 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
4966 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4968 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt2, &color, NULL, &brush2);
4969 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4971 /* effect brush is created from different factory */
4972 range.startPosition = 0;
4973 range.length = 4;
4974 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)brush2, range);
4975 ok(SUCCEEDED(hr), "Failed to set drawing effect, hr %#x.\n", hr);
4977 ID2D1RenderTarget_BeginDraw(rt);
4979 origin.x = origin.y = 0.0f;
4980 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
4982 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4983 todo_wine
4984 ok(hr == D2DERR_WRONG_FACTORY, "Unexpected hr %#x.\n", hr);
4986 /* Effect is d2d resource, but not a brush. */
4987 set_rect(&rect, 0.0f, 0.0f, 10.0f, 10.0f);
4988 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4989 ok(SUCCEEDED(hr), "Failed to geometry, hr %#x.\n", hr);
4991 range.startPosition = 0;
4992 range.length = 4;
4993 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)geometry, range);
4994 ok(SUCCEEDED(hr), "Failed to set drawing effect, hr %#x.\n", hr);
4995 ID2D1RectangleGeometry_Release(geometry);
4997 ID2D1RenderTarget_BeginDraw(rt);
4999 origin.x = origin.y = 0.0f;
5000 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
5002 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5003 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
5005 for (i = 0; i < ARRAY_SIZE(antialias_mode_tests); ++i)
5007 IDWriteRenderingParams *rendering_params;
5009 ID2D1RenderTarget_SetTextAntialiasMode(rt, antialias_mode_tests[i].aa_mode);
5011 hr = IDWriteFactory_CreateCustomRenderingParams(dwrite_factory, 2.0f, 1.0f, 0.0f, DWRITE_PIXEL_GEOMETRY_FLAT,
5012 antialias_mode_tests[i].rendering_mode, &rendering_params);
5013 ok(SUCCEEDED(hr), "Failed to create custom rendering params, hr %#x.\n", hr);
5015 ID2D1RenderTarget_SetTextRenderingParams(rt, rendering_params);
5017 ID2D1RenderTarget_BeginDraw(rt);
5019 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush *)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
5021 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5022 ok(hr == antialias_mode_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
5024 IDWriteRenderingParams_Release(rendering_params);
5027 IDWriteTextFormat_Release(text_format);
5028 IDWriteTextLayout_Release(text_layout);
5029 IDWriteFactory_Release(dwrite_factory);
5030 ID2D1RenderTarget_Release(rt);
5031 ID2D1RenderTarget_Release(rt2);
5033 ID2D1Factory_Release(factory);
5034 ID2D1Factory_Release(factory2);
5035 IDXGISurface_Release(surface);
5036 IDXGISwapChain_Release(swapchain);
5037 ID3D10Device1_Release(device);
5038 DestroyWindow(window);
5041 static void create_target_dibsection(HDC hdc, UINT32 width, UINT32 height)
5043 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
5044 BITMAPINFO *bmi = (BITMAPINFO*)bmibuf;
5045 HBITMAP hbm;
5047 memset(bmi, 0, sizeof(bmibuf));
5048 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
5049 bmi->bmiHeader.biHeight = -height;
5050 bmi->bmiHeader.biWidth = width;
5051 bmi->bmiHeader.biBitCount = 32;
5052 bmi->bmiHeader.biPlanes = 1;
5053 bmi->bmiHeader.biCompression = BI_RGB;
5055 hbm = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
5056 ok(hbm != NULL, "Failed to create a dib section.\n");
5058 DeleteObject(SelectObject(hdc, hbm));
5061 static void test_dc_target(void)
5063 static const D2D1_PIXEL_FORMAT invalid_formats[] =
5065 { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
5066 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN },
5067 { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
5069 D2D1_TEXT_ANTIALIAS_MODE text_aa_mode;
5070 ID2D1GdiInteropRenderTarget *interop;
5071 D2D1_RENDER_TARGET_PROPERTIES desc;
5072 D2D1_MATRIX_3X2_F matrix, matrix2;
5073 ID2D1DCRenderTarget *rt, *rt2;
5074 D2D1_ANTIALIAS_MODE aa_mode;
5075 ID2D1SolidColorBrush *brush;
5076 ID2D1RenderTarget *rt3;
5077 ID2D1Factory *factory;
5078 ID3D10Device1 *device;
5079 FLOAT dpi_x, dpi_y;
5080 D2D1_COLOR_F color;
5081 D2D1_SIZE_U sizeu;
5082 D2D1_SIZE_F size;
5083 D2D1_TAG t1, t2;
5084 unsigned int i;
5085 HDC hdc, hdc2;
5086 D2D_RECT_F r;
5087 COLORREF clr;
5088 HRESULT hr;
5089 RECT rect;
5091 if (!(device = create_device()))
5093 skip("Failed to create device, skipping tests.\n");
5094 return;
5096 ID3D10Device1_Release(device);
5098 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5099 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
5101 for (i = 0; i < ARRAY_SIZE(invalid_formats); ++i)
5103 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5104 desc.pixelFormat = invalid_formats[i];
5105 desc.dpiX = 96.0f;
5106 desc.dpiY = 96.0f;
5107 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5108 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5110 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
5111 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x.\n", hr);
5114 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5115 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
5116 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5117 desc.dpiX = 96.0f;
5118 desc.dpiY = 96.0f;
5119 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5120 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5121 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
5122 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
5124 hr = ID2D1DCRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5125 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
5126 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
5127 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
5128 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
5129 ID2D1RenderTarget_Release(rt3);
5130 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1DCRenderTarget, (void **)&rt2);
5131 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
5132 ok(rt2 == rt, "Unexpected render target\n");
5133 ID2D1DCRenderTarget_Release(rt2);
5134 ID2D1GdiInteropRenderTarget_Release(interop);
5136 size = ID2D1DCRenderTarget_GetSize(rt);
5137 ok(size.width == 0.0f, "got width %.08e.\n", size.width);
5138 ok(size.height == 0.0f, "got height %.08e.\n", size.height);
5140 sizeu = ID2D1DCRenderTarget_GetPixelSize(rt);
5141 ok(sizeu.width == 0, "got width %u.\n", sizeu.width);
5142 ok(sizeu.height == 0, "got height %u.\n", sizeu.height);
5144 /* object creation methods work without BindDC() */
5145 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
5146 hr = ID2D1DCRenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
5147 ok(SUCCEEDED(hr), "Failed to create a brush, hr %#x.\n", hr);
5148 ID2D1SolidColorBrush_Release(brush);
5150 ID2D1DCRenderTarget_BeginDraw(rt);
5151 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
5152 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
5154 ID2D1DCRenderTarget_Release(rt);
5156 /* BindDC() */
5157 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
5158 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
5160 aa_mode = ID2D1DCRenderTarget_GetAntialiasMode(rt);
5161 ok(aa_mode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, "Got wrong default aa mode %d.\n", aa_mode);
5162 text_aa_mode = ID2D1DCRenderTarget_GetTextAntialiasMode(rt);
5163 ok(text_aa_mode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT, "Got wrong default text aa mode %d.\n", text_aa_mode);
5165 ID2D1DCRenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
5166 ok(dpi_x == 96.0f && dpi_y == 96.0f, "Got dpi_x %f, dpi_y %f.\n", dpi_x, dpi_y);
5168 hdc = CreateCompatibleDC(NULL);
5169 ok(hdc != NULL, "Failed to create an HDC.\n");
5171 create_target_dibsection(hdc, 16, 16);
5173 SetRect(&rect, 0, 0, 32, 32);
5174 hr = ID2D1DCRenderTarget_BindDC(rt, NULL, &rect);
5175 ok(hr == E_INVALIDARG, "BindDC() returned %#x.\n", hr);
5177 /* Target properties are retained during BindDC() */
5178 ID2D1DCRenderTarget_SetTags(rt, 1, 2);
5179 ID2D1DCRenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
5180 ID2D1DCRenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
5182 set_matrix_identity(&matrix);
5183 translate_matrix(&matrix, 200.0f, 600.0f);
5184 ID2D1DCRenderTarget_SetTransform(rt, &matrix);
5186 hr = ID2D1DCRenderTarget_BindDC(rt, hdc, &rect);
5187 ok(hr == S_OK, "BindDC() returned %#x.\n", hr);
5189 ID2D1DCRenderTarget_GetTags(rt, &t1, &t2);
5190 ok(t1 == 1 && t2 == 2, "Got wrong tags.\n");
5192 aa_mode = ID2D1DCRenderTarget_GetAntialiasMode(rt);
5193 ok(aa_mode == D2D1_ANTIALIAS_MODE_ALIASED, "Got wrong aa mode %d.\n", aa_mode);
5195 text_aa_mode = ID2D1DCRenderTarget_GetTextAntialiasMode(rt);
5196 ok(text_aa_mode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, "Got wrong text aa mode %d.\n", text_aa_mode);
5198 ID2D1DCRenderTarget_GetTransform(rt, &matrix2);
5199 ok(!memcmp(&matrix, &matrix2, sizeof(matrix)), "Got wrong target transform.\n");
5201 set_matrix_identity(&matrix);
5202 ID2D1DCRenderTarget_SetTransform(rt, &matrix);
5204 /* target size comes from specified dimensions, not from selected bitmap size */
5205 size = ID2D1DCRenderTarget_GetSize(rt);
5206 ok(size.width == 32.0f, "got width %.08e.\n", size.width);
5207 ok(size.height == 32.0f, "got height %.08e.\n", size.height);
5209 /* clear one HDC to red, switch to another one, partially fill it and test contents */
5210 ID2D1DCRenderTarget_BeginDraw(rt);
5212 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
5213 ID2D1DCRenderTarget_Clear(rt, &color);
5215 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
5216 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
5218 clr = GetPixel(hdc, 0, 0);
5219 ok(clr == RGB(255, 0, 0), "Unexpected color 0x%08x.\n", clr);
5221 hdc2 = CreateCompatibleDC(NULL);
5222 ok(hdc2 != NULL, "Failed to create an HDC.\n");
5224 create_target_dibsection(hdc2, 16, 16);
5226 hr = ID2D1DCRenderTarget_BindDC(rt, hdc2, &rect);
5227 ok(hr == S_OK, "BindDC() returned %#x.\n", hr);
5229 clr = GetPixel(hdc2, 0, 0);
5230 ok(clr == 0, "Unexpected color 0x%08x.\n", clr);
5232 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
5233 hr = ID2D1DCRenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
5234 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
5236 ID2D1DCRenderTarget_BeginDraw(rt);
5238 r.left = r.top = 0.0f;
5239 r.bottom = 16.0f;
5240 r.right = 8.0f;
5241 ID2D1DCRenderTarget_FillRectangle(rt, &r, (ID2D1Brush*)brush);
5243 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
5244 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
5246 ID2D1SolidColorBrush_Release(brush);
5248 clr = GetPixel(hdc2, 0, 0);
5249 ok(clr == RGB(0, 255, 0), "Unexpected color 0x%08x.\n", clr);
5251 clr = GetPixel(hdc2, 10, 0);
5252 ok(clr == 0, "Unexpected color 0x%08x.\n", clr);
5254 /* Invalid DC. */
5255 hr = ID2D1DCRenderTarget_BindDC(rt, (HDC)0xdeadbeef, &rect);
5256 todo_wine
5257 ok(hr == E_INVALIDARG, "BindDC() returned %#x.\n", hr);
5259 ID2D1DCRenderTarget_BeginDraw(rt);
5261 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
5262 ID2D1DCRenderTarget_Clear(rt, &color);
5264 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
5265 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
5267 clr = GetPixel(hdc2, 0, 0);
5268 todo_wine
5269 ok(clr == RGB(255, 0, 0), "Unexpected color 0x%08x.\n", clr);
5271 hr = ID2D1DCRenderTarget_BindDC(rt, NULL, &rect);
5272 ok(hr == E_INVALIDARG, "BindDC() returned %#x.\n", hr);
5274 ID2D1DCRenderTarget_BeginDraw(rt);
5276 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
5277 ID2D1DCRenderTarget_Clear(rt, &color);
5279 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
5280 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
5282 clr = GetPixel(hdc2, 0, 0);
5283 todo_wine
5284 ok(clr == RGB(0, 0, 255), "Unexpected color 0x%08x.\n", clr);
5286 DeleteDC(hdc);
5287 DeleteDC(hdc2);
5288 ID2D1DCRenderTarget_Release(rt);
5289 ID2D1Factory_Release(factory);
5292 static void test_hwnd_target(void)
5294 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
5295 ID2D1GdiInteropRenderTarget *interop;
5296 D2D1_RENDER_TARGET_PROPERTIES desc;
5297 ID2D1HwndRenderTarget *rt, *rt2;
5298 ID2D1RenderTarget *rt3;
5299 ID2D1Factory *factory;
5300 ID3D10Device1 *device;
5301 D2D1_SIZE_U size;
5302 HRESULT hr;
5304 if (!(device = create_device()))
5306 skip("Failed to create device, skipping tests.\n");
5307 return;
5309 ID3D10Device1_Release(device);
5311 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5312 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
5314 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5315 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
5316 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5317 desc.dpiX = 0.0f;
5318 desc.dpiY = 0.0f;
5319 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5320 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5322 hwnd_rt_desc.hwnd = NULL;
5323 hwnd_rt_desc.pixelSize.width = 64;
5324 hwnd_rt_desc.pixelSize.height = 64;
5325 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
5327 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
5328 ok(FAILED(hr), "Target creation should fail, hr %#x.\n", hr);
5330 hwnd_rt_desc.hwnd = (HWND)0xdeadbeef;
5331 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
5332 ok(FAILED(hr), "Target creation should fail, hr %#x.\n", hr);
5334 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
5335 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
5336 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
5337 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5339 hr = ID2D1HwndRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5340 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
5341 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
5342 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
5343 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
5344 ID2D1RenderTarget_Release(rt3);
5345 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1HwndRenderTarget, (void **)&rt2);
5346 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
5347 ok(rt2 == rt, "Unexpected render target\n");
5348 ID2D1HwndRenderTarget_Release(rt2);
5349 ID2D1GdiInteropRenderTarget_Release(interop);
5351 size.width = 128;
5352 size.height = 64;
5353 hr = ID2D1HwndRenderTarget_Resize(rt, &size);
5354 ok(SUCCEEDED(hr), "Failed to resize render target, hr %#x.\n", hr);
5356 ID2D1HwndRenderTarget_Release(rt);
5358 DestroyWindow(hwnd_rt_desc.hwnd);
5359 ID2D1Factory_Release(factory);
5362 #define test_compatible_target_size(r) test_compatible_target_size_(__LINE__, r)
5363 static void test_compatible_target_size_(unsigned int line, ID2D1RenderTarget *rt)
5365 static const D2D1_SIZE_F size_1_0 = { 1.0f, 0.0f };
5366 static const D2D1_SIZE_F size_1_1 = { 1.0f, 1.0f };
5367 static const D2D1_SIZE_U px_size_1_1 = { 1, 1 };
5368 static const D2D1_SIZE_U zero_px_size;
5369 static const D2D1_SIZE_F zero_size;
5370 static const struct size_test
5372 const D2D1_SIZE_U *pixel_size;
5373 const D2D1_SIZE_F *size;
5375 size_tests[] =
5377 { &zero_px_size, NULL },
5378 { &zero_px_size, &zero_size },
5379 { NULL, &zero_size },
5380 { NULL, &size_1_0 },
5381 { &px_size_1_1, &size_1_1 },
5383 float dpi_x, dpi_y, rt_dpi_x, rt_dpi_y;
5384 D2D1_SIZE_U pixel_size, expected_size;
5385 ID2D1BitmapRenderTarget *bitmap_rt;
5386 ID2D1DeviceContext *context;
5387 unsigned int i;
5388 HRESULT hr;
5390 ID2D1RenderTarget_GetDpi(rt, &rt_dpi_x, &rt_dpi_y);
5392 for (i = 0; i < ARRAY_SIZE(size_tests); ++i)
5394 hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, size_tests[i].size, size_tests[i].pixel_size,
5395 NULL, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &bitmap_rt);
5396 ok_(__FILE__, line)(SUCCEEDED(hr), "%u: Failed to create render target, hr %#x.\n", i, hr);
5398 if (size_tests[i].pixel_size)
5400 expected_size = *size_tests[i].pixel_size;
5402 else if (size_tests[i].size)
5404 expected_size.width = ceilf((size_tests[i].size->width * rt_dpi_x) / 96.0f);
5405 expected_size.height = ceilf((size_tests[i].size->height * rt_dpi_y) / 96.0f);
5407 else
5409 expected_size = ID2D1RenderTarget_GetPixelSize(rt);
5412 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(bitmap_rt);
5413 ok_(__FILE__, line)(!memcmp(&pixel_size, &expected_size, sizeof(pixel_size)),
5414 "%u: unexpected target size %ux%u.\n", i, pixel_size.width, pixel_size.height);
5416 ID2D1BitmapRenderTarget_GetDpi(bitmap_rt, &dpi_x, &dpi_y);
5417 if (size_tests[i].pixel_size && size_tests[i].size && size_tests[i].size->width != 0.0f
5418 && size_tests[i].size->height != 0.0f)
5420 ok_(__FILE__, line)(dpi_x == pixel_size.width * 96.0f / size_tests[i].size->width
5421 && dpi_y == pixel_size.height * 96.0f / size_tests[i].size->height,
5422 "%u: unexpected target dpi %.8ex%.8e.\n", i, dpi_x, dpi_y);
5424 else
5425 ok_(__FILE__, line)(dpi_x == rt_dpi_x && dpi_y == rt_dpi_y,
5426 "%u: unexpected target dpi %.8ex%.8e.\n", i, dpi_x, dpi_y);
5427 ID2D1BitmapRenderTarget_Release(bitmap_rt);
5430 pixel_size.height = pixel_size.width = 0;
5431 hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, NULL, &pixel_size, NULL,
5432 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &bitmap_rt);
5433 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5435 if (SUCCEEDED(ID2D1BitmapRenderTarget_QueryInterface(bitmap_rt, &IID_ID2D1DeviceContext, (void **)&context)))
5437 ID2D1Bitmap *bitmap;
5439 pixel_size = ID2D1DeviceContext_GetPixelSize(context);
5440 ok_(__FILE__, line)(!pixel_size.width && !pixel_size.height, "Unexpected target size %ux%u.\n",
5441 pixel_size.width, pixel_size.height);
5443 ID2D1DeviceContext_GetTarget(context, (ID2D1Image **)&bitmap);
5444 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
5445 ok_(__FILE__, line)(!pixel_size.width && !pixel_size.height, "Unexpected target size %ux%u.\n",
5446 pixel_size.width, pixel_size.height);
5447 ID2D1Bitmap_Release(bitmap);
5449 ID2D1DeviceContext_Release(context);
5452 ID2D1BitmapRenderTarget_Release(bitmap_rt);
5455 static void test_bitmap_target(void)
5457 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
5458 ID2D1GdiInteropRenderTarget *interop;
5459 D2D1_SIZE_U pixel_size, pixel_size2;
5460 D2D1_RENDER_TARGET_PROPERTIES desc;
5461 ID2D1BitmapRenderTarget *rt, *rt2;
5462 ID2D1HwndRenderTarget *hwnd_rt;
5463 ID2D1Bitmap *bitmap, *bitmap2;
5464 ID2D1DCRenderTarget *dc_rt;
5465 D2D1_SIZE_F size, size2;
5466 ID2D1RenderTarget *rt3;
5467 ID2D1Factory *factory;
5468 ID3D10Device1 *device;
5469 float dpi[2], dpi2[2];
5470 D2D1_COLOR_F color;
5471 ULONG refcount;
5472 HRESULT hr;
5474 if (!(device = create_device()))
5476 skip("Failed to create device, skipping tests.\n");
5477 return;
5479 ID3D10Device1_Release(device);
5481 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5482 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
5484 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5485 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
5486 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5487 desc.dpiX = 96.0f;
5488 desc.dpiY = 192.0f;
5489 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5490 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5492 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
5493 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
5494 hwnd_rt_desc.pixelSize.width = 64;
5495 hwnd_rt_desc.pixelSize.height = 64;
5496 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
5498 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &hwnd_rt);
5499 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5501 test_compatible_target_size((ID2D1RenderTarget *)hwnd_rt);
5503 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, NULL, NULL,
5504 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
5505 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5507 hr = ID2D1BitmapRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5508 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
5509 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
5510 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
5511 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
5512 ID2D1RenderTarget_Release(rt3);
5513 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1BitmapRenderTarget, (void **)&rt2);
5514 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
5515 ok(rt2 == rt, "Unexpected render target\n");
5516 ID2D1BitmapRenderTarget_Release(rt2);
5517 ID2D1GdiInteropRenderTarget_Release(interop);
5519 /* See if parent target is referenced. */
5520 ID2D1HwndRenderTarget_AddRef(hwnd_rt);
5521 refcount = ID2D1HwndRenderTarget_Release(hwnd_rt);
5522 ok(refcount == 1, "Target should not have been referenced, got %u.\n", refcount);
5524 /* Size was not specified, should match parent. */
5525 pixel_size = ID2D1HwndRenderTarget_GetPixelSize(hwnd_rt);
5526 pixel_size2 = ID2D1BitmapRenderTarget_GetPixelSize(rt);
5527 ok(!memcmp(&pixel_size, &pixel_size2, sizeof(pixel_size)), "Got target pixel size mismatch.\n");
5529 size = ID2D1HwndRenderTarget_GetSize(hwnd_rt);
5530 size2 = ID2D1BitmapRenderTarget_GetSize(rt);
5531 ok(!memcmp(&size, &size2, sizeof(size)), "Got target DIP size mismatch.\n");
5533 ID2D1HwndRenderTarget_GetDpi(hwnd_rt, dpi, dpi + 1);
5534 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
5535 ok(!memcmp(dpi, dpi2, sizeof(dpi)), "Got dpi mismatch.\n");
5537 ID2D1BitmapRenderTarget_Release(rt);
5539 /* Pixel size specified. */
5540 set_size_u(&pixel_size, 32, 32);
5541 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, &pixel_size, NULL,
5542 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
5543 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5545 pixel_size2 = ID2D1BitmapRenderTarget_GetPixelSize(rt);
5546 ok(!memcmp(&pixel_size, &pixel_size2, sizeof(pixel_size)), "Got target pixel size mismatch.\n");
5548 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
5549 ok(!memcmp(dpi, dpi2, sizeof(dpi)), "Got dpi mismatch.\n");
5551 ID2D1BitmapRenderTarget_Release(rt);
5553 /* Both pixel size and DIP size are specified. */
5554 set_size_u(&pixel_size, 128, 128);
5555 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, &size, &pixel_size, NULL,
5556 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
5557 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5559 /* Doubled pixel size dimensions with the same DIP size give doubled dpi. */
5560 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
5561 ok(dpi[0] == dpi2[0] / 2.0f && dpi[1] == dpi2[1] / 2.0f, "Got dpi mismatch.\n");
5563 ID2D1BitmapRenderTarget_Release(rt);
5565 /* DIP size is specified, fractional. */
5566 set_size_f(&size, 70.1f, 70.4f);
5567 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, &size, NULL, NULL,
5568 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
5569 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5571 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
5573 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt);
5574 ok(pixel_size.width == ceilf(size.width * dpi[0] / 96.0f)
5575 && pixel_size.height == ceilf(size.height * dpi[1] / 96.0f), "Wrong pixel size %ux%u\n",
5576 pixel_size.width, pixel_size.height);
5578 dpi[0] *= (pixel_size.width / size.width) * (96.0f / dpi[0]);
5579 dpi[1] *= (pixel_size.height / size.height) * (96.0f / dpi[1]);
5581 ok(compare_float(dpi[0], dpi2[0], 1) && compare_float(dpi[1], dpi2[1], 1), "Got dpi mismatch.\n");
5583 ID2D1HwndRenderTarget_Release(hwnd_rt);
5585 /* Check if GetBitmap() returns same instance. */
5586 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap);
5587 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
5588 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap2);
5589 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
5590 ok(bitmap == bitmap2, "Got different bitmap instances.\n");
5592 /* Draw something, see if bitmap instance is retained. */
5593 ID2D1BitmapRenderTarget_BeginDraw(rt);
5594 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
5595 ID2D1BitmapRenderTarget_Clear(rt, &color);
5596 hr = ID2D1BitmapRenderTarget_EndDraw(rt, NULL, NULL);
5597 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
5599 ID2D1Bitmap_Release(bitmap2);
5600 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap2);
5601 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
5602 ok(bitmap == bitmap2, "Got different bitmap instances.\n");
5604 ID2D1Bitmap_Release(bitmap);
5605 ID2D1Bitmap_Release(bitmap2);
5607 refcount = ID2D1BitmapRenderTarget_Release(rt);
5608 ok(!refcount, "Target should be released, got %u.\n", refcount);
5610 DestroyWindow(hwnd_rt_desc.hwnd);
5612 /* Compatible target created from a DC target without associated HDC */
5613 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5614 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
5615 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5616 desc.dpiX = 192.0f;
5617 desc.dpiY = 96.0f;
5618 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5619 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5620 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &dc_rt);
5621 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
5623 test_compatible_target_size((ID2D1RenderTarget *)dc_rt);
5625 hr = ID2D1DCRenderTarget_CreateCompatibleRenderTarget(dc_rt, NULL, NULL, NULL,
5626 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
5627 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5629 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt);
5630 ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
5632 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap);
5633 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
5634 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
5635 ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
5636 ID2D1Bitmap_Release(bitmap);
5638 ID2D1BitmapRenderTarget_Release(rt);
5639 ID2D1DCRenderTarget_Release(dc_rt);
5641 ID2D1Factory_Release(factory);
5644 static void test_desktop_dpi(void)
5646 ID2D1Factory *factory;
5647 float dpi_x, dpi_y;
5648 HRESULT hr;
5650 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5651 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
5653 dpi_x = dpi_y = 0.0f;
5654 ID2D1Factory_GetDesktopDpi(factory, &dpi_x, &dpi_y);
5655 ok(dpi_x > 0.0f && dpi_y > 0.0f, "Got wrong dpi %f x %f.\n", dpi_x, dpi_y);
5657 ID2D1Factory_Release(factory);
5660 static void test_stroke_style(void)
5662 static const struct
5664 D2D1_DASH_STYLE dash_style;
5665 UINT32 dash_count;
5666 float dashes[6];
5668 dash_style_tests[] =
5670 {D2D1_DASH_STYLE_SOLID, 0},
5671 {D2D1_DASH_STYLE_DASH, 2, {2.0f, 2.0f}},
5672 {D2D1_DASH_STYLE_DOT, 2, {0.0f, 2.0f}},
5673 {D2D1_DASH_STYLE_DASH_DOT, 4, {2.0f, 2.0f, 0.0f, 2.0f}},
5674 {D2D1_DASH_STYLE_DASH_DOT_DOT, 6, {2.0f, 2.0f, 0.0f, 2.0f, 0.0f, 2.0f}},
5676 D2D1_STROKE_STYLE_PROPERTIES desc;
5677 ID2D1StrokeStyle *style;
5678 ID2D1Factory *factory;
5679 UINT32 count;
5680 HRESULT hr;
5681 D2D1_CAP_STYLE cap_style;
5682 D2D1_LINE_JOIN line_join;
5683 float miter_limit, dash_offset;
5684 D2D1_DASH_STYLE dash_style;
5685 unsigned int i;
5686 float dashes[2];
5688 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5689 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
5691 desc.startCap = D2D1_CAP_STYLE_SQUARE;
5692 desc.endCap = D2D1_CAP_STYLE_ROUND;
5693 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
5694 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
5695 desc.miterLimit = 1.5f;
5696 desc.dashStyle = D2D1_DASH_STYLE_DOT;
5697 desc.dashOffset = -1.0f;
5699 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
5700 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
5702 cap_style = ID2D1StrokeStyle_GetStartCap(style);
5703 ok(cap_style == D2D1_CAP_STYLE_SQUARE, "Unexpected cap style %d.\n", cap_style);
5704 cap_style = ID2D1StrokeStyle_GetEndCap(style);
5705 ok(cap_style == D2D1_CAP_STYLE_ROUND, "Unexpected cap style %d.\n", cap_style);
5706 cap_style = ID2D1StrokeStyle_GetDashCap(style);
5707 ok(cap_style == D2D1_CAP_STYLE_TRIANGLE, "Unexpected cap style %d.\n", cap_style);
5708 line_join = ID2D1StrokeStyle_GetLineJoin(style);
5709 ok(line_join == D2D1_LINE_JOIN_BEVEL, "Unexpected line joind %d.\n", line_join);
5710 miter_limit = ID2D1StrokeStyle_GetMiterLimit(style);
5711 ok(miter_limit == 1.5f, "Unexpected miter limit %f.\n", miter_limit);
5712 dash_style = ID2D1StrokeStyle_GetDashStyle(style);
5713 ok(dash_style == D2D1_DASH_STYLE_DOT, "Unexpected dash style %d.\n", dash_style);
5714 dash_offset = ID2D1StrokeStyle_GetDashOffset(style);
5715 ok(dash_offset == -1.0f, "Unexpected dash offset %f.\n", dash_offset);
5717 /* Custom dash pattern, no dashes data specified. */
5718 desc.startCap = D2D1_CAP_STYLE_SQUARE;
5719 desc.endCap = D2D1_CAP_STYLE_ROUND;
5720 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
5721 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
5722 desc.miterLimit = 1.5f;
5723 desc.dashStyle = D2D1_DASH_STYLE_CUSTOM;
5724 desc.dashOffset = 0.0f;
5726 ID2D1StrokeStyle_Release(style);
5728 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
5729 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
5731 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 0, &style);
5732 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
5734 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
5735 ok(hr == S_OK, "Unexpected return value, %#x.\n", hr);
5736 ID2D1StrokeStyle_Release(style);
5738 /* Builtin style, dashes are specified. */
5739 desc.dashStyle = D2D1_DASH_STYLE_DOT;
5740 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
5741 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
5743 /* Invalid style. */
5744 desc.dashStyle = 100;
5745 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
5746 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
5748 /* Test returned dash pattern for builtin styles. */
5749 desc.startCap = D2D1_CAP_STYLE_SQUARE;
5750 desc.endCap = D2D1_CAP_STYLE_ROUND;
5751 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
5752 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
5753 desc.miterLimit = 1.5f;
5754 desc.dashOffset = 0.0f;
5756 for (i = 0; i < ARRAY_SIZE(dash_style_tests); ++i)
5758 float dashes[10];
5759 UINT dash_count;
5761 desc.dashStyle = dash_style_tests[i].dash_style;
5763 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
5764 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
5766 dash_count = ID2D1StrokeStyle_GetDashesCount(style);
5767 ok(dash_count == dash_style_tests[i].dash_count, "%u: unexpected dash count %u, expected %u.\n",
5768 i, dash_count, dash_style_tests[i].dash_count);
5769 ok(dash_count < ARRAY_SIZE(dashes), "%u: unexpectedly large dash count %u.\n", i, dash_count);
5770 if (dash_count == dash_style_tests[i].dash_count)
5772 unsigned int j;
5774 ID2D1StrokeStyle_GetDashes(style, dashes, dash_count);
5775 ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
5776 "%u: unexpected dash array.\n", i);
5778 /* Ask for more dashes than style actually has. */
5779 memset(dashes, 0xcc, sizeof(dashes));
5780 ID2D1StrokeStyle_GetDashes(style, dashes, ARRAY_SIZE(dashes));
5781 ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
5782 "%u: unexpected dash array.\n", i);
5784 for (j = dash_count; j < ARRAY_SIZE(dashes); ++j)
5785 ok(dashes[j] == 0.0f, "%u: unexpected dash value at %u.\n", i, j);
5788 ID2D1StrokeStyle_Release(style);
5791 /* NULL dashes array, non-zero length. */
5792 memset(&desc, 0, sizeof(desc));
5793 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 1, &style);
5794 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
5796 count = ID2D1StrokeStyle_GetDashesCount(style);
5797 ok(count == 0, "Unexpected dashes count %u.\n", count);
5799 ID2D1StrokeStyle_Release(style);
5801 ID2D1Factory_Release(factory);
5804 static void test_gradient(void)
5806 ID2D1GradientStopCollection *gradient;
5807 D2D1_GRADIENT_STOP stops[3], stops2[3];
5808 IDXGISwapChain *swapchain;
5809 ID2D1RenderTarget *rt;
5810 ID3D10Device1 *device;
5811 IDXGISurface *surface;
5812 D2D1_COLOR_F color;
5813 unsigned int i;
5814 UINT32 count;
5815 HWND window;
5816 HRESULT hr;
5818 if (!(device = create_device()))
5820 skip("Failed to create device, skipping tests.\n");
5821 return;
5823 window = create_window();
5824 swapchain = create_swapchain(device, window, TRUE);
5825 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
5826 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
5827 rt = create_render_target(surface);
5828 ok(!!rt, "Failed to create render target.\n");
5830 stops2[0].position = 0.5f;
5831 set_color(&stops2[0].color, 1.0f, 1.0f, 0.0f, 1.0f);
5832 stops2[1] = stops2[0];
5833 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops2, 2, D2D1_GAMMA_2_2,
5834 D2D1_EXTEND_MODE_CLAMP, &gradient);
5835 ok(SUCCEEDED(hr), "Failed to create stop collection, hr %#x.\n", hr);
5837 count = ID2D1GradientStopCollection_GetGradientStopCount(gradient);
5838 ok(count == 2, "Unexpected stop count %u.\n", count);
5840 /* Request more stops than collection has. */
5841 stops[0].position = 123.4f;
5842 set_color(&stops[0].color, 1.0f, 0.5f, 0.4f, 1.0f);
5843 color = stops[0].color;
5844 stops[2] = stops[1] = stops[0];
5845 ID2D1GradientStopCollection_GetGradientStops(gradient, stops, ARRAY_SIZE(stops));
5846 ok(!memcmp(stops, stops2, sizeof(*stops) * count), "Unexpected gradient stops array.\n");
5847 for (i = count; i < ARRAY_SIZE(stops); ++i)
5849 ok(stops[i].position == 123.4f, "%u: unexpected stop position %f.\n", i, stops[i].position);
5850 ok(!memcmp(&stops[i].color, &color, sizeof(color)), "%u: unexpected stop color.\n", i);
5853 ID2D1GradientStopCollection_Release(gradient);
5854 ID2D1RenderTarget_Release(rt);
5856 IDXGISurface_Release(surface);
5857 IDXGISwapChain_Release(swapchain);
5858 ID3D10Device1_Release(device);
5859 DestroyWindow(window);
5862 static void test_draw_geometry(void)
5864 ID2D1TransformedGeometry *transformed_geometry[4];
5865 ID2D1RectangleGeometry *rect_geometry[2];
5866 D2D1_POINT_2F point = {0.0f, 0.0f};
5867 D2D1_ROUNDED_RECT rounded_rect;
5868 ID2D1SolidColorBrush *brush;
5869 ID2D1PathGeometry *geometry;
5870 IDXGISwapChain *swapchain;
5871 D2D1_MATRIX_3X2_F matrix;
5872 ID2D1GeometrySink *sink;
5873 ID2D1RenderTarget *rt;
5874 ID3D10Device1 *device;
5875 IDXGISurface *surface;
5876 ID2D1Factory *factory;
5877 D2D1_POINT_2F p0, p1;
5878 D2D1_ELLIPSE ellipse;
5879 D2D1_COLOR_F color;
5880 D2D1_RECT_F rect;
5881 ULONG refcount;
5882 HWND window;
5883 HRESULT hr;
5884 BOOL match;
5886 if (!(device = create_device()))
5888 skip("Failed to create device, skipping tests.\n");
5889 return;
5891 window = create_window();
5892 swapchain = create_swapchain(device, window, TRUE);
5893 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
5894 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
5895 rt = create_render_target(surface);
5896 ok(!!rt, "Failed to create render target.\n");
5897 ID2D1RenderTarget_GetFactory(rt, &factory);
5899 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
5900 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
5901 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
5902 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
5903 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
5905 ID2D1RenderTarget_BeginDraw(rt);
5906 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
5907 ID2D1RenderTarget_Clear(rt, &color);
5909 set_point(&p0, 40.0f, 160.0f);
5910 ID2D1RenderTarget_DrawLine(rt, p0, p0, (ID2D1Brush *)brush, 10.0f, NULL);
5911 set_point(&p0, 100.0f, 160.0f);
5912 set_point(&p1, 140.0f, 160.0f);
5913 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
5914 set_point(&p0, 200.0f, 80.0f);
5915 set_point(&p1, 200.0f, 240.0f);
5916 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
5917 set_point(&p0, 260.0f, 240.0f);
5918 set_point(&p1, 300.0f, 80.0f);
5919 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
5921 set_rect(&rect, 40.0f, 480.0f, 40.0f, 480.0f);
5922 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
5923 set_rect(&rect, 100.0f, 480.0f, 140.0f, 480.0f);
5924 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
5925 set_rect(&rect, 200.0f, 400.0f, 200.0f, 560.0f);
5926 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
5927 set_rect(&rect, 260.0f, 560.0f, 300.0f, 400.0f);
5928 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
5930 set_ellipse(&ellipse, 40.0f, 800.0f, 0.0f, 0.0f);
5931 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
5932 set_ellipse(&ellipse, 120.0f, 800.0f, 20.0f, 0.0f);
5933 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
5934 set_ellipse(&ellipse, 200.0f, 800.0f, 0.0f, 80.0f);
5935 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
5936 set_ellipse(&ellipse, 280.0f, 800.0f, 20.0f, 80.0f);
5937 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
5939 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5940 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5942 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "");
5943 ok(match, "Figure does not match.\n");
5944 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "yGBQUFBQUFBQUFDoYQAA");
5945 ok(match, "Figure does not match.\n");
5946 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0,
5947 "xjIUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5948 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5949 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5950 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5951 "jAEUjAEUjAEUjAEUxjIA");
5952 ok(match, "Figure does not match.\n");
5953 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 2,
5954 "zjECnQETjAEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
5955 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
5956 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
5957 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
5958 "igEVigEVigEVigEVjAETnQECzjEA");
5959 ok(match, "Figure does not match.\n");
5961 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "5mAUjAEUjAEUjAEUjAEUhmIA");
5962 ok(match, "Figure does not match.\n");
5963 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0, "vmBkPGQ8ZDxkPGTeYQAA");
5964 ok(match, "Figure does not match.\n");
5965 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0,
5966 "5i4UjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5967 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5968 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5969 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5970 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUhjAA");
5971 ok(match, "Figure does not match.\n");
5972 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 0,
5973 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5974 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5975 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5976 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5977 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5978 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
5979 ok(match, "Figure does not match.\n");
5981 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
5982 todo_wine ok(match, "Figure does not match.\n");
5983 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
5984 todo_wine ok(match, "Figure does not match.\n");
5985 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0,
5986 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5987 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5988 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5989 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5990 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
5991 todo_wine ok(match, "Figure does not match.\n");
5992 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 10,
5993 "hDAYgwEieyh1LnAybBcIF2gWDhZkFhIWYRUWFV4VGhVbFRwVWRUeFVcVIBVVFCQUUxQmFFEUKBRP"
5994 "FSgVTRUqFUwULBRLFC4USRQwFEgUMBRHFDIURhQyFEUUNBREFDQUQxQ2FEIUNhRBFDgUQBQ4FEAU"
5995 "OBQ/FDoUPhQ6FD4UOhQ+FDoUPhQ6FD0UPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5996 "FDwUPBQ8FDwUPBQ8FD0UOhQ+FDoUPhQ6FD4UOhQ+FDoUPxQ4FEAUOBRAFDgUQRQ2FEIUNhRDFDQU"
5997 "RBQ0FEUUMhRGFDIURxQwFEgUMBRJFC4USxQsFEwVKhVNFSgVTxQoFFEUJhRTFCQUVRUgFVcVHhVZ"
5998 "FRwVWxUaFV4VFhVhFhIWZBYOFmgXCBdsMnAudSh7IoMBGIQw");
5999 todo_wine ok(match, "Figure does not match.\n");
6001 ID2D1RenderTarget_BeginDraw(rt);
6002 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
6003 ID2D1RenderTarget_Clear(rt, &color);
6005 set_rounded_rect(&rounded_rect, 40.0f, 160.0f, 40.0f, 160.0f, 10.0f, 10.0f);
6006 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6007 set_rounded_rect(&rounded_rect, 100.0f, 160.0f, 140.0f, 160.0f, 10.0f, 10.0f);
6008 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6009 set_rounded_rect(&rounded_rect, 200.0f, 80.0f, 200.0f, 240.0f, 10.0f, 10.0f);
6010 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6011 set_rounded_rect(&rounded_rect, 260.0f, 240.0f, 300.0f, 80.0f, 10.0f, 10.0f);
6012 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6014 set_rounded_rect(&rounded_rect, 40.0f, 480.0f, 40.0f, 480.0f, 10.0f, 20.0f);
6015 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6016 set_rounded_rect(&rounded_rect, 100.0f, 480.0f, 140.0f, 480.0f, 10.0f, 20.0f);
6017 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6018 set_rounded_rect(&rounded_rect, 200.0f, 400.0f, 200.0f, 560.0f, 10.0f, 20.0f);
6019 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6020 set_rounded_rect(&rounded_rect, 260.0f, 560.0f, 300.0f, 400.0f, 10.0f, 20.0f);
6021 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6023 set_rounded_rect(&rounded_rect, 40.0f, 800.0f, 40.0f, 800.0f, 10.0f, 5.0f);
6024 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6025 set_rounded_rect(&rounded_rect, 100.0f, 800.0f, 140.0f, 800.0f, 10.0f, 5.0f);
6026 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6027 set_rounded_rect(&rounded_rect, 200.0f, 720.0f, 200.0f, 880.0f, 10.0f, 5.0f);
6028 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6029 set_rounded_rect(&rounded_rect, 260.0f, 880.0f, 300.0f, 720.0f, 10.0f, 5.0f);
6030 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6032 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6033 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
6035 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6036 todo_wine ok(match, "Figure does not match.\n");
6037 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6038 todo_wine ok(match, "Figure does not match.\n");
6039 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0,
6040 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6041 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6042 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6043 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6044 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6045 todo_wine ok(match, "Figure does not match.\n");
6046 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 0,
6047 "3C4oaUZVUExYRlxCHCgcPxU4FT0UPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6048 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6049 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6050 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6051 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6052 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FD0VOBU/YEJcRlhMUFVG7S8A");
6053 todo_wine ok(match, "Figure does not match.\n");
6055 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6056 todo_wine ok(match, "Figure does not match.\n");
6057 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6058 todo_wine ok(match, "Figure does not match.\n");
6059 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0,
6060 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6061 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6062 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6063 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6064 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6065 todo_wine ok(match, "Figure does not match.\n");
6066 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 8,
6067 "3C4obT5dSFRQTlRKGCgYRhYwFkMVNBVBFTYVPxU5FD4UOhQ9FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6068 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6069 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6070 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6071 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6072 "PBQ8FDwUPRQ6FD4UOhQ/FTYVQRU0FUMWMBZGWEpVTVBTSltA8C8A");
6073 todo_wine ok(match, "Figure does not match.\n");
6075 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6076 todo_wine ok(match, "Figure does not match.\n");
6077 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6078 todo_wine ok(match, "Figure does not match.\n");
6079 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0,
6080 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6081 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6082 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6083 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6084 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6085 todo_wine ok(match, "Figure does not match.\n");
6086 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 0,
6087 "3C4oZU5NWERgP2I9HigePBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6088 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6089 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6090 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6091 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6092 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZD1iP2BEWE1O6S8A");
6093 todo_wine ok(match, "Figure does not match.\n");
6095 ID2D1RenderTarget_BeginDraw(rt);
6096 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
6097 ID2D1RenderTarget_Clear(rt, &color);
6099 set_rounded_rect(&rounded_rect, 40.0f, 160.0f, 40.0f, 160.0f, 1000.0f, 1000.0f);
6100 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6101 set_rounded_rect(&rounded_rect, 100.0f, 160.0f, 140.0f, 160.0f, 1000.0f, 1000.0f);
6102 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6103 set_rounded_rect(&rounded_rect, 200.0f, 80.0f, 200.0f, 240.0f, 1000.0f, 1000.0f);
6104 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6105 set_rounded_rect(&rounded_rect, 260.0f, 240.0f, 300.0f, 80.0f, 1000.0f, 1000.0f);
6106 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6108 set_rounded_rect(&rounded_rect, 40.0f, 480.0f, 40.0f, 480.0f, 10.0f, 1000.0f);
6109 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6110 set_rounded_rect(&rounded_rect, 100.0f, 480.0f, 140.0f, 480.0f, 10.0f, 1000.0f);
6111 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6112 set_rounded_rect(&rounded_rect, 200.0f, 400.0f, 200.0f, 560.0f, 10.0f, 1000.0f);
6113 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6114 set_rounded_rect(&rounded_rect, 260.0f, 560.0f, 300.0f, 400.0f, 10.0f, 1000.0f);
6115 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6117 set_rounded_rect(&rounded_rect, 40.0f, 800.0f, 40.0f, 800.0f, 1000.0f, 10.0f);
6118 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6119 set_rounded_rect(&rounded_rect, 100.0f, 800.0f, 140.0f, 800.0f, 1000.0f, 10.0f);
6120 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6121 set_rounded_rect(&rounded_rect, 200.0f, 720.0f, 200.0f, 880.0f, 1000.0f, 10.0f);
6122 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6123 set_rounded_rect(&rounded_rect, 260.0f, 880.0f, 300.0f, 720.0f, 1000.0f, 10.0f);
6124 ID2D1RenderTarget_DrawRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush, 10.0f, NULL);
6126 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6127 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
6129 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6130 todo_wine ok(match, "Figure does not match.\n");
6131 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6132 todo_wine ok(match, "Figure does not match.\n");
6133 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0,
6134 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6135 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6136 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6137 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6138 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6139 todo_wine ok(match, "Figure does not match.\n");
6140 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 16,
6141 "hDAYgwEieyh1LnAybBcIF2gWDhZkFhIWYRUWFV4WGRVbFRwVWRUeFVcVIBVVFSMUUxQmFFEVJxRP"
6142 "FSgVTRUqFUwULBRLFC4USRUvFEgUMBRHFDIURhQyFEUUNBREFDQUQxQ2FEIUNhRBFDgUQBQ4FEAU"
6143 "OBQ/FTkUPhQ6FD4UOhQ+FDoUPhQ6FD0UPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6144 "FDwUPBQ8FDwUPBQ8FD0UOhQ+FDoUPhQ6FD4UOhQ+FDoUPxQ4FEAUOBRAFDgUQRQ2FEIUNhRDFDQU"
6145 "RBQ0FEUUMhRGFDIURxQwFEgUMBRJFC4USxQsFEwVKhVNFSgVTxQoFFEUJhRTFCQUVRUgFVcVHhVZ"
6146 "FRwVWxUaFV4VFhVhFhIWZBYOFmgWChZsMnAudCp6IoMBGIQw");
6147 todo_wine ok(match, "Figure does not match.\n");
6149 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6150 todo_wine ok(match, "Figure does not match.\n");
6151 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6152 todo_wine ok(match, "Figure does not match.\n");
6153 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0,
6154 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6155 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6156 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6157 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6158 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6159 todo_wine ok(match, "Figure does not match.\n");
6160 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 16,
6161 "3C4obzpjQF5EWkhXFSAVVRQkFFMUJhRRFCgUTxQqFE0VKhVMFCwUSxQuFEoULhVIFDAUSBQwFUYU"
6162 "MhRGFDIURRQ0FEQUNBRDFTQVQhQ2FEIUNhRCFDYUQRQ4FEAUOBRAFDgUQBQ4FD8UOhQ+FDoUPhQ6"
6163 "FD4UOhQ+FDoUPhQ6FD0VOxQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6164 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBU7FD0UOhQ+FDoUPhQ6FD4UOhQ+FDoUPhQ6FD8UOBRA"
6165 "FDgUQBQ4FEAUOBRBFDYUQhQ2FEIUNhRCFTQVQxQ0FEQUNBRFFDIURhQyFEYVMBVHFDAUSBUuFUkU"
6166 "LhRLFCwUTBUrFE0UKhRPFCgUURQmFFMUJBRVSldIWUZdQWI78i8A");
6167 todo_wine ok(match, "Figure does not match.\n");
6169 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
6170 todo_wine ok(match, "Figure does not match.\n");
6171 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
6172 todo_wine ok(match, "Figure does not match.\n");
6173 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0,
6174 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6175 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6176 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6177 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
6178 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
6179 todo_wine ok(match, "Figure does not match.\n");
6180 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 8,
6181 "9i80ZERWUExYRV5AHCocPRY4FjwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6182 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6183 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6184 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6185 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6186 "PBQ8FDwUPBQ8FDwUPBQ8FToVPRssG0BeRFpLUFVGYzT2LwAA");
6187 todo_wine ok(match, "Figure does not match.\n");
6189 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
6190 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
6191 hr = ID2D1PathGeometry_Open(geometry, &sink);
6192 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
6194 set_point(&point, 40.0f, 160.0f);
6195 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6196 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6198 set_point(&point, 120.0f, 160.0f);
6199 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6200 line_to(sink, 120.0f, 160.0f);
6201 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6203 set_point(&point, 200.0f, 160.0f);
6204 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6205 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6207 set_point(&point, 280.0f, 160.0f);
6208 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6209 line_to(sink, 280.0f, 160.0f);
6210 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6212 set_point(&point, 20.0f, 480.0f);
6213 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6214 line_to(sink, 60.0f, 480.0f);
6215 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6217 set_point(&point, 120.0f, 400.0f);
6218 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6219 line_to(sink, 120.0f, 560.0f);
6220 line_to(sink, 120.0f, 400.0f);
6221 line_to(sink, 120.0f, 560.0f);
6222 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6224 set_point(&point, 180.0f, 480.0f);
6225 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6226 line_to(sink, 220.0f, 480.0f);
6227 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6229 set_point(&point, 280.0f, 400.0f);
6230 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6231 line_to(sink, 280.0f, 560.0f);
6232 line_to(sink, 280.0f, 400.0f);
6233 line_to(sink, 280.0f, 560.0f);
6234 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6236 set_point(&point, 20.0f, 880.0f);
6237 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6238 line_to(sink, 40.0f, 720.0f);
6239 line_to(sink, 60.0f, 880.0f);
6240 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6242 set_point(&point, 100.0f, 720.0f);
6243 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6244 line_to(sink, 120.0f, 880.0f);
6245 line_to(sink, 140.0f, 720.0f);
6246 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6248 set_point(&point, 180.0f, 880.0f);
6249 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6250 line_to(sink, 200.0f, 720.0f);
6251 line_to(sink, 220.0f, 880.0f);
6252 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6254 set_point(&point, 260.0f, 720.0f);
6255 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
6256 line_to(sink, 280.0f, 880.0f);
6257 line_to(sink, 300.0f, 720.0f);
6258 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6260 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
6261 hr = ID2D1GeometrySink_Close(sink);
6262 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
6263 ID2D1GeometrySink_Release(sink);
6265 ID2D1RenderTarget_BeginDraw(rt);
6266 ID2D1RenderTarget_Clear(rt, &color);
6267 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, 5.0f, NULL);
6268 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6269 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
6270 ID2D1PathGeometry_Release(geometry);
6272 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "");
6273 ok(match, "Figure does not match.\n");
6274 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "");
6275 ok(match, "Figure does not match.\n");
6276 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0, "");
6277 ok(match, "Figure does not match.\n");
6278 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 0, "q2MKlgEKq2MA");
6279 todo_wine ok(match, "Figure does not match.\n");
6281 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "iGNQUFCIYwAA");
6282 ok(match, "Figure does not match.\n");
6283 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0,
6284 "qyIKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
6285 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
6286 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKQQpLCkEKSwqWAQqW"
6287 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
6288 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
6289 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQrLIwAA");
6290 ok(match, "Figure does not match.\n");
6291 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0, "4GLAAuBi");
6292 ok(match, "Figure does not match.\n");
6293 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 0,
6294 "qyIKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
6295 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
6296 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKSwpBCksKQQqWAQqWAQqW"
6297 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
6298 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
6299 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQrLIwAA");
6300 ok(match, "Figure does not match.\n");
6302 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0,
6303 "rycCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
6304 "jAEUiwEKAgqKAQoCCokBCgQKiAEKBAqHAQoGCoYBCgYKhQEKCAqEAQoICoMBCgoKggEKCgqBAQoM"
6305 "CoABCgwKfwoOCn4KDgp9ChAKfAoQCnsKEgp6ChIKeQoUCngKFAp3ChYKdgoWCnUKGAp0ChgKcwoa"
6306 "CnIKGgpxChwKcAocCm8KHgpuCh4KbQogCmwKIAprCiIKagoiCmkKJApoCiQKZwomCmYKJgplCigK"
6307 "ZAooCmMKKgpiCioKYQosCmAKLApfCi4KXgouCl0KMApcCjAKWwoyCloKMgpZCjQKWAo0ClcKNgpW"
6308 "CjYKVQo4ClQKOApTCjoKUgo6ClEKPApQCjwKTwo+Ck4KPgpNCkAKTApACksKQgpKCkIKSQpECkgK"
6309 "RApHCkYKozIA");
6310 ok(match, "Figure does not match.\n");
6311 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0,
6312 "ozIKRgpHCkQKSApECkkKQgpKCkIKSwpACkwKQApNCj4KTgo+Ck8KPApQCjwKUQo6ClIKOgpTCjgK"
6313 "VAo4ClUKNgpWCjYKVwo0ClgKNApZCjIKWgoyClsKMApcCjAKXQouCl4KLgpfCiwKYAosCmEKKgpi"
6314 "CioKYwooCmQKKAplCiYKZgomCmcKJApoCiQKaQoiCmoKIgprCiAKbAogCm0KHgpuCh4KbwocCnAK"
6315 "HApxChoKcgoaCnMKGAp0ChgKdQoWCnYKFgp3ChQKeAoUCnkKEgp6ChIKewoQCnwKEAp9Cg4KfgoO"
6316 "Cn8KDAqAAQoMCoEBCgoKggEKCgqDAQoICoQBCggKhQEKBgqGAQoGCocBCgQKiAEKBAqJAQoCCooB"
6317 "CgIKiwEUjAEUjQESjgESjwEQkAEQkQEOkgEOkwEMlAEMlQEKlgEKlwEImAEImQEGmgEGmwEEnAEE"
6318 "nQECngECrycA");
6319 ok(match, "Figure does not match.\n");
6320 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0,
6321 "rycCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
6322 "jAEUiwEKAgqKAQoCCokBCgQKiAEKBAqHAQoGCoYBCgYKhQEKCAqEAQoICoMBCgoKggEKCgqBAQoM"
6323 "CoABCgwKfwoOCn4KDgp9ChAKfAoQCnsKEgp6ChIKeQoUCngKFAp3ChYKdgoWCnUKGAp0ChgKcwoa"
6324 "CnIKGgpxChwKcAocCm8KHgpuCh4KbQogCmwKIAprCiIKagoiCmkKJApoCiQKZwomCmYKJgplCigK"
6325 "ZAooCmMKKgpiCioKYQosCmAKLApfCi4KXgouCl0KMApcCjAKWwoyCloKMgpZCjQKWAo0ClcKNgpW"
6326 "CjYKVQo4ClQKOApTCjoKUgo6ClEKPApQCjwKTwo+Ck4KPgpNCkAKTApACksKQgpKCkIKSQpECkgK"
6327 "RApHWkZagzEA");
6328 ok(match, "Figure does not match.\n");
6329 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 0,
6330 "gzFaRlpHCkQKSApECkkKQgpKCkIKSwpACkwKQApNCj4KTgo+Ck8KPApQCjwKUQo6ClIKOgpTCjgK"
6331 "VAo4ClUKNgpWCjYKVwo0ClgKNApZCjIKWgoyClsKMApcCjAKXQouCl4KLgpfCiwKYAosCmEKKgpi"
6332 "CioKYwooCmQKKAplCiYKZgomCmcKJApoCiQKaQoiCmoKIgprCiAKbAogCm0KHgpuCh4KbwocCnAK"
6333 "HApxChoKcgoaCnMKGAp0ChgKdQoWCnYKFgp3ChQKeAoUCnkKEgp6ChIKewoQCnwKEAp9Cg4KfgoO"
6334 "Cn8KDAqAAQoMCoEBCgoKggEKCgqDAQoICoQBCggKhQEKBgqGAQoGCocBCgQKiAEKBAqJAQoCCooB"
6335 "CgIKiwEUjAEUjQESjgESjwEQkAEQkQEOkgEOkwEMlAEMlQEKlgEKlwEImAEImQEGmgEGmwEEnAEE"
6336 "nQECngECrycA");
6337 ok(match, "Figure does not match.\n");
6339 set_rect(&rect, 20.0f, 80.0f, 60.0f, 240.0f);
6340 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[0]);
6341 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
6343 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
6344 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[1]);
6345 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
6347 set_matrix_identity(&matrix);
6348 translate_matrix(&matrix, 160.0f, 640.0f);
6349 scale_matrix(&matrix, 40.0f, 160.0f);
6350 rotate_matrix(&matrix, M_PI / -5.0f);
6351 hr = ID2D1Factory_CreateTransformedGeometry(factory,
6352 (ID2D1Geometry *)rect_geometry[1], &matrix, &transformed_geometry[0]);
6353 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
6355 set_matrix_identity(&matrix);
6356 scale_matrix(&matrix, 0.5f, 1.0f);
6357 translate_matrix(&matrix, -80.0f, 0.0f);
6358 hr = ID2D1Factory_CreateTransformedGeometry(factory,
6359 (ID2D1Geometry *)transformed_geometry[0], &matrix, &transformed_geometry[1]);
6360 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
6362 set_matrix_identity(&matrix);
6363 rotate_matrix(&matrix, M_PI / 2.0f);
6364 translate_matrix(&matrix, 80.0f, -320.0f);
6365 scale_matrix(&matrix, 2.0f, 0.25f);
6366 hr = ID2D1Factory_CreateTransformedGeometry(factory,
6367 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
6368 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
6370 ID2D1RenderTarget_BeginDraw(rt);
6371 ID2D1RenderTarget_Clear(rt, &color);
6372 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)rect_geometry[0], (ID2D1Brush *)brush, 10.0f, NULL);
6373 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, 10.0f, NULL);
6374 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, 5.0f, NULL);
6375 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, 15.0f, NULL);
6376 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6377 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
6378 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
6379 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
6380 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
6381 ID2D1RectangleGeometry_Release(rect_geometry[1]);
6382 ID2D1RectangleGeometry_Release(rect_geometry[0]);
6384 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0,
6385 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6386 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6387 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6388 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6389 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6390 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6391 ok(match, "Figure does not match.\n");
6392 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 32,
6393 "8XYGtQIOrAIXpAIfmwIokwIwigI4gwJA+gFJ8gFR6QEzAiXhATMKJdgBMxMl0AEzGyXHATMkJb8B"
6394 "MysmtgEzNCWvATM8JaYBM0UlngEzTSWVATNWJY0BM14lhAEzZyV8M28lczN4JWszgAElYjOIASZa"
6395 "M5ABJVgtmQElWCWhASVYJaEBJVgloQElWCWhASVYJaEBJVgloQElWCWhASVYJaEBJVglmQEtWCWQ"
6396 "ATNaJogBM2IlgAEzayV4M3MlbzN8JWczhAElXjONASVWM5UBJU0zngElRTOmASU8M68BJTQztgEm"
6397 "KzO/ASUkM8cBJRsz0AElEzPYASUKM+EBJQIz6QFR8gFJ+gFAgwI4igIwkwIomwIfpAIXrAIOtQIG"
6398 "8XYA");
6399 ok(match, "Figure does not match.\n");
6400 match = compare_figure(surface, 0, 160, 160, 320, 0xff652e89, 32,
6401 "ujEBngECnQEDnQEEmwEFmgEHmQEHmAEIlwEKlgEKlQELlAENkwENkgEOkQEQjwERjwESjQETjAEU"
6402 "jAEKAQqKAQoCCokBCgMKiQEKBAqHAQoFCoYBCgYKhgEKBwqEAQoICoMBCgkKgwEKCgqBAQoLCoAB"
6403 "Cg0KfgsNCn4KDgp9ChAKewsQCnsKEQp6ChMKeAoUCngKFAp3ChYKdQoXCnUKGApzChkKcgoaCnIK"
6404 "GwpwChwKbwodCm4LHgptCh8KbAogCmsLIQpqCiIKaQokCmcKJQpnCiUKZgonCmQKKApkCigKYwoq"
6405 "CmEKKwphCisKYAotCl4KLgpdCy8KXAowClsKMQpaCzIKWQozClgKNApXCjYKVgo2ClUKNwpUCjkK"
6406 "Uwo5ClIKOwpQCjwKTws8Ck8KPgpNCj8KTAs/CkwKQQpKCkIKSQtCCkkKRApHCkUKRgpHCkUKRwpE"
6407 "CkgKQwpKCkIKSgpBCksKQApNCj4LTQo+Ck4KPQpQCjsLUAo7ClIKOQpTCjgLUwo4ClUKNgpWCjUK"
6408 "Vwo1ClgKMwpZCjQKWAo0ClkKMwpZCjQKWQozClkKMwpZCjQKWQozClkKMwpZCjQKWQozClkKNApY"
6409 "CjQKWQozClkKNApZCjMKWQozClkKNApZCjMKWQozClkKNApZCjMKWQo0ClgKNApZCjMKWQo0ClkK"
6410 "MwpZCjMKWQo0ClkKMwpZCjMKWQo0ClkKMwpZCjQKWAo0ClkKMwpYCjUKVwo1ClYKNgpVCjgKUws4"
6411 "ClMKOQpSCjsKUAs7ClAKPQpOCj4KTQs+Ck0KQApLCkEKSgpCCkoKQwpICkQKRwpFCkcKRgpFCkcK"
6412 "RApJCkILSQpCCkoKQQpMCj8LTAo/Ck0KPgpPCjwLTwo8ClAKOwpSCjkKUwo5ClQKNwpVCjYKVgo2"
6413 "ClcKNApYCjMKWQoyC1oKMQpbCjAKXAovC10KLgpeCi0KYAorCmEKKwphCioKYwooCmQKKApkCicK"
6414 "ZgolCmcKJQpnCiQKaQoiCmoKIQtrCiAKbAofCm0KHgtuCh0KbwocCnAKGwpyChoKcgoZCnMKGAp1"
6415 "ChcKdQoWCncKFAp4ChQKeAoTCnoKEQp7ChALewoQCn0KDgp+Cg0LfgoNCoABCgsKgQEKCgqDAQoJ"
6416 "CoMBCggKhAEKBwqGAQoGCoYBCgUKhwEKBAqJAQoDCokBCgIKigEKAQqMARSMARONARKPARGPARCR"
6417 "AQ6SAQ2TAQ2UAQuVAQqWAQqXAQiYAQeZAQeaAQWbAQSdAQOdAQKeAQG6MQAA");
6418 ok(match, "Figure does not match.\n");
6419 match = compare_figure(surface, 160, 160, 320, 320, 0xff652e89, 64,
6420 "82ICvQIEugIHuAIJtgIKtAINsgIPsAIRrQITrAIVqQIYpwIZpgIbowIeoQIgnwIhnQIkmwImmAIp"
6421 "lgIVARSVAhUDFJICFQUVkAIVBxSPAhUJFIwCFQwUigIVDRWHAhYPFIYCFRIUhAIVFBSBAhUWFf8B"
6422 "FRgU/gEVGhT7ARUcFfkBFR4U9wEWIBT1ARUjFPMBFSQV8AEVJxTvARUpFOwBFisU6gEVLRXoARUv"
6423 "FOYBFjEU5AEVMxXiARU1FOABFTgU3gEVOhTbARY7FdkBFT4U2AEVQBTVARZCFNMBFUQV0QEVRhTP"
6424 "ARVJFM0BFUoVygEWTBTJARVPFMcBFVEUxAEVUxXCARVVFMEBFVcUvgEVWRW8ARVbFbkBFl0UuAEV"
6425 "YBS2ARVhFbMBFWQUsgEVZhSwARVoFK0BFWoVqwEVbBSpARZuFKcBFXAVpQEVchWiARV1FKEBFXcU"
6426 "nwEVeBWcARV7FJsBFX0UmAEWfxSWARWBARWUARWDARSSARWGARSQARWHARWOARWJARWLARWMARSK"
6427 "ARWOARSHARaPARWFARWSARSEARWUARSBARWXARR/FZgBFX0VmgEUexWdARR5FZ4BFXYWoAEVdBWj"
6428 "ARRzFaUBFHAVpwEVbhWpARRtFasBFGoVrgEUaBWvARVmFbEBFGcUsgEUZxSxARVmFbEBFWYUsgEU"
6429 "ZxSyARRnFLEBFWYVsQEUZxSyARRnFLIBFGcUsQEVZhWxARRnFLIBFGcUsQEVZhWxARVmFLIBFGcU"
6430 "sgEUZxSxARVmFbEBFGcUsgEUZxSyARRmFbEBFWYVsQEUZxSyARRnFLEBFWYVsQEUZxSyARRnFLIB"
6431 "FGcUsQEVZhWxARRnFLIBFGcUsgEUZhWxARVmFbEBFGcUsgEUZxSxARVmFa8BFWgUrgEVahSrARVt"
6432 "FKkBFW4VpwEVcBSlARVzFKMBFXQVoAEWdhWeARV5FJ0BFXsUmgEVfRWYARV/FJcBFYEBFJQBFYQB"
6433 "FJIBFYUBFY8BFocBFI4BFYoBFIwBFYsBFYkBFY4BFYcBFZABFIYBFZIBFIMBFZQBFYEBFZYBFH8W"
6434 "mAEUfRWbARR7FZwBFXgVnwEUdxWhARR1FaIBFXIVpQEVcBWnARRuFqkBFGwVqwEVahWtARRoFbAB"
6435 "FGYVsgEUZBWzARVhFbYBFGAVuAEUXRa5ARVbFbwBFVkVvgEUVxXBARRVFcIBFVMVxAEUURXHARRP"
6436 "FckBFEwWygEVShXNARRJFc8BFEYV0QEVRBXTARRCFtUBFEAV2AEUPhXZARU7FtsBFDoV3gEUOBXg"
6437 "ARQ1FeIBFTMV5AEUMRbmARQvFegBFS0V6gEUKxbsARQpFe8BFCcV8AEVJBXzARQjFfUBFCAW9wEU"
6438 "HhX5ARUcFfsBFBoV/gEUGBX/ARUWFYECFBQVhAIUEhWGAhQPFocCFQ0VigIUDBWMAhQJFY8CFAcV"
6439 "kAIVBRWSAhQDFZUCFAEVlgIpmAImmwIknQIhnwIgoQIeowIbpgIZpwIYqQIVrAITrQIRsAIPsgIN"
6440 "tAIKtgIJuAIHugIEvQIC82IA");
6441 ok(match, "Figure does not match.\n");
6443 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
6444 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
6445 hr = ID2D1PathGeometry_Open(geometry, &sink);
6446 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
6448 set_point(&point, 20.0f, 80.0f);
6449 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6450 quadratic_to(sink, 40.0f, 80.0f, 60.0f, 80.0f);
6451 quadratic_to(sink, 60.0f, 160.0f, 60.0f, 240.0f);
6452 quadratic_to(sink, 40.0f, 240.0f, 20.0f, 240.0f);
6453 quadratic_to(sink, 20.0f, 160.0f, 20.0f, 80.0f);
6454 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6456 set_point(&point, 100.0f, 80.0f);
6457 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6458 quadratic_to(sink, 105.0f, 80.0f, 140.0f, 80.0f);
6459 quadratic_to(sink, 140.0f, 100.0f, 140.0f, 240.0f);
6460 quadratic_to(sink, 135.0f, 240.0f, 100.0f, 240.0f);
6461 quadratic_to(sink, 100.0f, 220.0f, 100.0f, 80.0f);
6462 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6464 set_point(&point, 180.0f, 80.0f);
6465 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6466 quadratic_to(sink, 215.0f, 80.0f, 220.0f, 80.0f);
6467 quadratic_to(sink, 220.0f, 220.0f, 220.0f, 240.0f);
6468 quadratic_to(sink, 185.0f, 240.0f, 180.0f, 240.0f);
6469 quadratic_to(sink, 180.0f, 100.0f, 180.0f, 80.0f);
6470 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6472 set_point(&point, 260.0f, 80.0f);
6473 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6474 quadratic_to(sink, 280.0f, 80.0f, 300.0f, 80.0f);
6475 quadratic_to(sink, 300.0f, 160.0f, 300.0f, 240.0f);
6476 quadratic_to(sink, 280.0f, 240.0f, 260.0f, 240.0f);
6477 quadratic_to(sink, 260.0f, 160.0f, 260.0f, 80.0f);
6478 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6480 set_point(&point, 20.0f, 400.0f);
6481 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6482 quadratic_to(sink, 40.0f, 420.0f, 60.0f, 400.0f);
6483 quadratic_to(sink, 55.0f, 480.0f, 60.0f, 560.0f);
6484 quadratic_to(sink, 40.0f, 540.0f, 20.0f, 560.0f);
6485 quadratic_to(sink, 25.0f, 480.0f, 20.0f, 400.0f);
6486 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6488 set_point(&point, 100.0f, 400.0f);
6489 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6490 quadratic_to(sink, 105.0f, 420.0f, 140.0f, 400.0f);
6491 quadratic_to(sink, 135.0f, 420.0f, 140.0f, 560.0f);
6492 quadratic_to(sink, 135.0f, 540.0f, 100.0f, 560.0f);
6493 quadratic_to(sink, 105.0f, 540.0f, 100.0f, 400.0f);
6494 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6496 set_point(&point, 180.0f, 400.0f);
6497 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6498 quadratic_to(sink, 215.0f, 420.0f, 220.0f, 400.0f);
6499 quadratic_to(sink, 215.0f, 540.0f, 220.0f, 560.0f);
6500 quadratic_to(sink, 185.0f, 540.0f, 180.0f, 560.0f);
6501 quadratic_to(sink, 185.0f, 420.0f, 180.0f, 400.0f);
6502 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6504 set_point(&point, 260.0f, 400.0f);
6505 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6506 quadratic_to(sink, 280.0f, 420.0f, 300.0f, 400.0f);
6507 quadratic_to(sink, 295.0f, 480.0f, 300.0f, 560.0f);
6508 quadratic_to(sink, 280.0f, 540.0f, 260.0f, 560.0f);
6509 quadratic_to(sink, 265.0f, 480.0f, 260.0f, 400.0f);
6510 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6512 set_point(&point, 20.0f, 720.0f);
6513 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6514 quadratic_to(sink, 40.0f, 700.0f, 60.0f, 720.0f);
6515 quadratic_to(sink, 65.0f, 800.0f, 60.0f, 880.0f);
6516 quadratic_to(sink, 40.0f, 900.0f, 20.0f, 880.0f);
6517 quadratic_to(sink, 15.0f, 800.0f, 20.0f, 720.0f);
6518 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6520 set_point(&point, 100.0f, 720.0f);
6521 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6522 quadratic_to(sink, 105.0f, 700.0f, 140.0f, 720.0f);
6523 quadratic_to(sink, 145.0f, 740.0f, 140.0f, 880.0f);
6524 quadratic_to(sink, 135.0f, 900.0f, 100.0f, 880.0f);
6525 quadratic_to(sink, 95.0f, 860.0f, 100.0f, 720.0f);
6526 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6528 set_point(&point, 180.0f, 720.0f);
6529 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6530 quadratic_to(sink, 215.0f, 700.0f, 220.0f, 720.0f);
6531 quadratic_to(sink, 225.0f, 860.0f, 220.0f, 880.0f);
6532 quadratic_to(sink, 185.0f, 900.0f, 180.0f, 880.0f);
6533 quadratic_to(sink, 175.0f, 740.0f, 180.0f, 720.0f);
6534 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6536 set_point(&point, 260.0f, 720.0f);
6537 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6538 quadratic_to(sink, 280.0f, 700.0f, 300.0f, 720.0f);
6539 quadratic_to(sink, 305.0f, 800.0f, 300.0f, 880.0f);
6540 quadratic_to(sink, 280.0f, 900.0f, 260.0f, 880.0f);
6541 quadratic_to(sink, 255.0f, 800.0f, 260.0f, 720.0f);
6542 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
6544 hr = ID2D1GeometrySink_Close(sink);
6545 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
6546 ID2D1GeometrySink_Release(sink);
6548 ID2D1RenderTarget_BeginDraw(rt);
6549 ID2D1RenderTarget_Clear(rt, &color);
6550 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, 10.0f, NULL);
6551 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6552 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
6553 ID2D1PathGeometry_Release(geometry);
6555 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0,
6556 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6557 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6558 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6559 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6560 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6561 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6562 ok(match, "Figure does not match.\n");
6563 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0,
6564 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6565 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6566 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6567 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6568 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6569 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6570 ok(match, "Figure does not match.\n");
6571 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0,
6572 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6573 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6574 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6575 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6576 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6577 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6578 ok(match, "Figure does not match.\n");
6579 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 0,
6580 "yC5aRlpGWjxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6581 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6582 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6583 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
6584 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
6585 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
6586 ok(match, "Figure does not match.\n");
6588 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 64,
6589 "3SoDYAM6B1gHOgtQCzoPSA87EkASPBc2FzwcLBw8IiAiPWI+Yj5iPhQBOAEUPhQKJgoUPxQ4FEAU"
6590 "OBRAFDgUQBQ4FEAUOBRBFDYUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRDFDQURBQ0FEQUNBREFDQURBQ0"
6591 "FEQUNBREFDQURBQ0FEQUNBREFDQURRQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIU"
6592 "RhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRG"
6593 "FDIURRQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEMUNhRCFDYUQhQ2FEIU"
6594 "NhRCFDYUQhQ2FEEUOBRAFDgUQBQ4FEAUOBRAFDgUPxQKJgoUPhQBOAEUPmI+Yj5iPSIgIjwcLBw8"
6595 "FzYXPBJAEjsPSA86C1ALOgdYBzoDYAPdKgAA");
6596 ok(match, "Figure does not match.\n");
6597 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 1024,
6598 "uxUBnwECngEDnQEEnAEFmwEGmwEGmgEHmQEImAEJlwEKlgELlQEMlQEMlAENkwEOkgEPkQEQkAER"
6599 "VQQ2Ek0KOBJFEDkTPRY6FDUcOxUrJDwYHi09Yj5iP2BAQwkUQDgUFEAUOBRAFDcUQRQ3FEEUNxRC"
6600 "FDYUQhQ2FEIUNhRCFDUUQxQ1FEMUNRRDFDUUQxQ1FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQU"
6601 "NBREFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQ0"
6602 "FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQ0FEQUNBREFDQU"
6603 "RBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRDFDUUQxQ1FEMUNRRDFDUUQhQ2FEIUNhRC"
6604 "FDYUQhQ3FEEUNxRBFDcUQBQ4FEAUFDhAFAlDQGA/Yj5iPS0eGDwkKxU7HDUUOhY9EzkQRRI4Ck0S"
6605 "NgRVEZABEJEBD5IBDpMBDZQBDJUBDJUBC5YBCpcBCZgBCJkBB5oBBpsBBpsBBZwBBJ0BA54BAp8B"
6606 "AbsV");
6607 ok(match, "Figure does not match.\n");
6608 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 1024,
6609 "pBYBngECnQEDnAEEmwEFmgEGmQEGmQEHmAEIlwEJlgEKlQELlAEMkwEMkwENkgEOkQEPkAEQNgRV"
6610 "ETcKTRI4EEUSOhY9EzscNRQ8JCsVPS0eGD5iPmI/YEAUCUNAFBQ4QBQ4FEEUNxRBFDcUQRQ3FEEU"
6611 "NhRCFDYUQhQ2FEMUNRRDFDUUQxQ1FEMUNRRDFDUUQxQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0"
6612 "FEQUNBREFDQURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxREFDQU"
6613 "RBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxREFDQURBQ0FEQUNBRE"
6614 "FDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQUQxQ1FEMUNRRDFDUUQxQ1FEMUNRRDFDYUQhQ2FEIU"
6615 "NhRBFDcUQRQ3FEEUNxRBFDgUQDgUFEBDCRRAYD9iPmI+GB4tPRUrJDwUNRw7Ez0WOhJFEDgSTQo3"
6616 "EVUENhCQAQ+RAQ6SAQ2TAQyTAQyUAQuVAQqWAQmXAQiYAQeZAQaZAQaaAQWbAQScAQOdAQKeAQGk"
6617 "FgAA");
6618 ok(match, "Figure does not match.\n");
6619 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 64,
6620 "wCsDmQEHlQELkQEPSwJAEkgLNhc8HCwcPCIgIj1iPmI+Yj4UATgBFD4UCiYKFD8UOBRAFDgUQBQ4"
6621 "FEAUOBRAFDgUQRQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDYUQxQ0FEQUNBREFDQURBQ0FEQUNBREFDQU"
6622 "RBQ0FEQUNBREFDQURBQ0FEUUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRG"
6623 "FDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEUU"
6624 "NBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBRDFDYUQhQ2FEIUNhRCFDYUQhQ2"
6625 "FEIUNhRBFDgUQBQ4FEAUOBRAFDgUQBQ4FD8UCiYKFD4UATgBFD5iPmI+Yj0iICI8HCwcPBc2FzwS"
6626 "QBI7D0gPOgtQCzoHWAc6A2AD3SoA");
6627 ok(match, "Figure does not match.\n");
6629 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 64,
6630 "3SkmcThiRFdOTVhEICAgPhwsHDwXNhc8FDwUOxQ+FDoUPhQ6FD4UOhQ+FDoUPhQ5FEAUOBRAFDgU"
6631 "QBQ4FEAUOBRAFDcUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDUURBQ0FEQUNBREFDQURBQ0FEQUNBRE"
6632 "FDQURBQ0FEQUNBREFDQURBQzFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYU"
6633 "MhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQz"
6634 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRCFDYUQhQ2FEIUNhRCFDYU"
6635 "QhQ2FEIUNxRAFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPhQ6FD4UOhQ+FDsUPBQ8FzYXPBws"
6636 "HD4gICBEWE1OV0RiOHEm3SkA");
6637 ok(match, "Figure does not match.\n");
6638 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 1024,
6639 "zykoczhkRVhQTlpEFx4tPRUrJDwUNRw7FDwVOxQ+FDoUPhQ5FEAUOBRAFDgUQBQ4FEAUOBRBFDcU"
6640 "QRQ3FEEUNhRCFDYUQhQ2FEIUNhRDFDUUQxQ1FEMUNRRDFDUUQxQ0FEQUNBREFDQURBQ0FEQUNBRE"
6641 "FDQURBQ0FEQUNBREFDQURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUU"
6642 "MxRFFDMURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURBQ0"
6643 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEMUNRRDFDUUQxQ1FEMUNRRDFDYU"
6644 "QhQ2FEIUNhRCFDYUQRQ3FEEUNxRBFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDsVPBQ7HDUUPCQr"
6645 "FT0tHhdEWk5QWEVkOHMozykA");
6646 ok(match, "Figure does not match.\n");
6647 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 1024,
6648 "6SkobThfRVNQSFpALR4XPSQrFTscNRQ7FTwUOhQ+FDoUPhQ5FEAUOBRAFDgUQBQ4FEAUNxRBFDcU"
6649 "QRQ3FEEUNxRCFDYUQhQ2FEIUNRRDFDUUQxQ1FEMUNRRDFDUUQxQ1FEQUNBREFDQURBQ0FEQUNBRE"
6650 "FDQURBQ0FEQUNBREFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUU"
6651 "MxRFFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDQURBQ0"
6652 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ1FEMUNRRDFDUUQxQ1FEMUNRRDFDUU"
6653 "QhQ2FEIUNhRCFDcUQRQ3FEEUNxRBFDcUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPBU7FDUcOxUr"
6654 "JD0XHi1AWkhQU0VfOG0o6SkA");
6655 ok(match, "Figure does not match.\n");
6656 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 64,
6657 "3SkmcThiRFdOTVhGHiAgRhQsHDwXNhc8FDwUOxQ+FDoUPhQ6FD4UOhQ+FDoUPhQ5FEAUOBRAFDgU"
6658 "QBQ4FEAUOBRAFDcUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDUURBQ0FEQUNBREFDQURBQ0FEQUNBRE"
6659 "FDQURBQ0FEQUNBREFDQURBQzFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYU"
6660 "MhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQz"
6661 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRCFDYUQhQ2FEIUNhRCFDYU"
6662 "QhQ2FEIUNxRAFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPhQ6FD4UOhQ+FDsUPBQ8FzYXPBws"
6663 "HD4gICBEWE1OV0RiOHEm3SkA");
6664 ok(match, "Figure does not match.\n");
6666 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
6667 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
6668 hr = ID2D1PathGeometry_Open(geometry, &sink);
6669 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
6671 set_point(&point, -0.402914f, 0.915514f);
6672 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
6673 quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
6674 quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f);
6675 quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f);
6676 quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f);
6677 quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f);
6678 quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f);
6679 quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f);
6680 quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f);
6681 quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f);
6682 quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f);
6683 quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f);
6684 quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f);
6685 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
6687 hr = ID2D1GeometrySink_Close(sink);
6688 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
6689 ID2D1GeometrySink_Release(sink);
6691 set_matrix_identity(&matrix);
6692 translate_matrix(&matrix, 40.0f, 160.0f);
6693 scale_matrix(&matrix, 20.0f, 80.0f);
6694 hr = ID2D1Factory_CreateTransformedGeometry(factory,
6695 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]);
6696 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
6698 set_matrix_identity(&matrix);
6699 translate_matrix(&matrix, 160.0f, 640.0f);
6700 scale_matrix(&matrix, 40.0f, 160.0f);
6701 rotate_matrix(&matrix, M_PI / -5.0f);
6702 hr = ID2D1Factory_CreateTransformedGeometry(factory,
6703 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]);
6704 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
6705 ID2D1PathGeometry_Release(geometry);
6707 set_matrix_identity(&matrix);
6708 scale_matrix(&matrix, 0.5f, 1.0f);
6709 translate_matrix(&matrix, -80.0f, 0.0f);
6710 hr = ID2D1Factory_CreateTransformedGeometry(factory,
6711 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
6712 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
6714 set_matrix_identity(&matrix);
6715 rotate_matrix(&matrix, M_PI / 2.0f);
6716 translate_matrix(&matrix, 80.0f, -320.0f);
6717 scale_matrix(&matrix, 2.0f, 0.25f);
6718 hr = ID2D1Factory_CreateTransformedGeometry(factory,
6719 (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]);
6720 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
6722 ID2D1RenderTarget_BeginDraw(rt);
6723 ID2D1RenderTarget_Clear(rt, &color);
6724 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, 2.0f, NULL);
6725 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, 10.0f, NULL);
6726 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, 5.0f, NULL);
6727 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[3], (ID2D1Brush *)brush, 15.0f, NULL);
6728 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6729 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
6730 ID2D1TransformedGeometry_Release(transformed_geometry[3]);
6731 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
6732 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
6733 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
6735 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 128,
6736 "yjIJkQEHBwaIAQUSBYMBBBYEggEEFgSCAQQWBIIBBBYEggEEFgSCAQQWBIIBBBYEggEEFgSCAQQW"
6737 "BIIBBBYEggEEFgSDAQQVBIMBBBUEgwEEFQSDAQQVBIMBBBUEgwEEFQSDAQQVBIMBBBUEgwEEFQSD"
6738 "AQQVBIQBBBQEhAEEFASEAQQTBIUBBBMEhQEEEwSFAQQTBIUBBBMEhQEEEwSGAQQSBIYBBBIEhgEE"
6739 "EgSGAQQSBIYBBBIEhgEEEgSGAQQRBIgBBBAEiAEEEASIAQQQBIkBBA4EigEEDgSLAQQMBIwBBAwE"
6740 "jQEECgSOAQQJBJABBAgEkAEFBgSSAQQGBJMBBAQElAEEBASVAQQDBJUBBAIElwEEAQSXAQiZAQeZ"
6741 "AQaaAQaaAQaaAQabAQWbAQWbAQWbAQWaAQeZAQeZAQeZAQiXAQQBBJYBBAMElQEEAwWRAQUGBY0B"
6742 "BQwFhwEFEgSCAQUXBYABBBoFfgUYBIIBBhEFiAEUpTEA");
6743 ok(match, "Figure does not match.\n");
6744 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 512,
6745 "yJIBArkCDa4CGKMCIZoCK5ECM4gCO4ECQ/gBS/EBUesBLAYl5QEsDiPeASwWIdkBLBwh0wEsISHO"
6746 "ASsgKMsBKR4vyAEnHDPIASUaNMsBIxg1mQEFMCIUN54BCygiDzijAREhIgY9qAEYGWGuAR4RXbMB"
6747 "JAhbuQGAAcABesYBc84Ba9YBTvQBP4MCOIoCNI4CM5ACMZICL5QCLZYCK5kCKJsCJ54CI6MCHq8C"
6748 "EraSAQAA");
6749 ok(match, "Figure does not match.\n");
6750 match = compare_figure(surface, 0, 160, 160, 320, 0xff652e89, 512,
6751 "xWkCmwEFmAEJlQELlAENkgEOkQEPjwESjQETjAEVigELAQqJAQsCCogBCwQKhwEKBQqGAQoGCoYB"
6752 "CgcKhAEKCAqEAQoIC4IBCgoKggEKCgqBAQoMCoABCgwKfwoNCn8KDgp9Cg8KfQoPCnwKEQp7ChEK"
6753 "egoSCnoKEwp4ChQKeAoUCncLFQp2ChYKdgoWCnYKFwp2ChYKdgoWCncKFgp2ChYKdgoWCncKFQt2"
6754 "ChYKdwoVCncKFQp4ChUKdwoVCncKFQp4ChUKdwoVCngKFAp4ChUKeAoUCngKFAp4CxMKeQoUCngK"
6755 "FAp5ChMKeQoUCnkKEwp5ChMKegoSC3kKEwp6ChIKegoSCnoLEgp6ChIKegoSCnsKEQp7ChEKfAoQ"
6756 "CnwKEAp9Cg8KfQoPCn4KDgp+Cg4KfwoOCn4KDgp/Cg0KfwoNCoABCgwKgAEKDAqBAQoLCoEBCgsK"
6757 "gQELCgqCAQoKCoIBCwkKgwEKCQqDAQoJCoQBCggKhAEKCQqEAQsHCoUBCwYKhgELBQqHAQsECogB"
6758 "CwMKiQELAgqLAQoBCowBFI0BE44BE44BEo8BEZABEJEBD5IBDpMBDpMBDZMBDZQBDJQBDZQBDJQB"
6759 "DBUCfgwSBH4MEQV/DA4GgAEMDAiAAQ0KCYEBDAgLgQENBQ2BAQ0EDoIBDQEPgwEdgwEdgwEdgwEc"
6760 "hAEKAgQCCoUBCgYKhgEKBgqGAQoFC4YBCgUKhwEKBAqIAQoECogBCgMKiQEKAwqIAQoDCokBCgMK"
6761 "iQEKAgqJAQoCCooBCgIKiQEKAgqKAQoBCosBCgEKigEKAQqLARSMARSLARSMAROMARONARKOARGO"
6762 "ARGPARCQAQ6RAQ2YAQTEZAAA");
6763 ok(match, "Figure does not match.\n");
6764 match = compare_figure(surface, 160, 160, 320, 320, 0xff652e89, 1024,
6765 "ytABA7gCCbICD60CFKkCF6cCGqMCHqACIZ0CJJoCJpgCKZUCFgIUkgIWBBWPAhYHFI4CFQoUjAIV"
6766 "DBSKAhUNFYgCFQ8UhwIVERSFAhUTFIMCFRQVgQIUFxSAAhQZFP4BFBoV/AEUHBT7ARQeFPkBFB8V"
6767 "9wEUIRT2ARQjFPQBFSMV8gEVJRTxARUnFPABFCgV7gEUKhTtARQsFOwBFCwV7AEULBTsARUsFOwB"
6768 "FSsV7AEULBTtARQsFO0BFCsU7QEVKxTtARUqFe0BFSoU7gEUKxTuARQqFe4BFCoU7wEUKhTuARUp"
6769 "FO8BFSkU7wEVKBXvARUoFPABFCkU8AEUKBTxARQoFPEBFCcV8QEUJxTxARUnFPEBFSYU8gEVJhTy"
6770 "ARUlFfIBFSUU8wEUJRXzARQlFPQBFCUU9AEUJBT1ARQkFPUBFCMU9gEUIhT2ARUhFPcBFSAU+AEV"
6771 "HxT5ARUeFPoBFR4U+gEVHRT7ARUcFPwBFRsU/QEVGhT+ARUZFP8BFBkUgAIUGBSBAhQXFIICFBcU"
6772 "ggIUFhSDAhQVFIQCFBQUhQIUExSGAhQSFIcCFBIUhwIUERSIAhUPFIkCFg0UigIXCxSNAhYJFI8C"
6773 "FggUkAIXBRSSAhcDFJQCFwEUlgIrlwIpmgImnAIkngIjnwIhoQIfowIepAIcpgIbpgIaqAIZqAIZ"
6774 "qAIYKwP7ARgnBf0BGCMI/QEZHgz+ARgbD/8BGBcSgAIYEhaAAhoNGIICGggcgwIaBB+DAjyEAjyF"
6775 "AjqGAjmIAjiIAiECFIkCFAIIBBSKAhQNFIsCFAwUjAIUCxSNAhQKFI4CFAkUjwIUBxWQAhQGFZEC"
6776 "FAUVkQIUBRWRAhQFFZECFQMVkwIUAxWTAhQDFZMCFAIVlAIVARWVAiqVAimWAimWAiiYAiaZAiaZ"
6777 "AiWaAiScAiKdAiGeAh+hAhyjAhmuAg3GxgEA");
6778 ok(match, "Figure does not match.\n");
6780 ID2D1SolidColorBrush_Release(brush);
6781 ID2D1RenderTarget_Release(rt);
6782 refcount = ID2D1Factory_Release(factory);
6783 ok(!refcount, "Factory has %u references left.\n", refcount);
6784 IDXGISurface_Release(surface);
6785 IDXGISwapChain_Release(swapchain);
6786 ID3D10Device1_Release(device);
6787 DestroyWindow(window);
6790 static void test_fill_geometry(void)
6792 ID2D1TransformedGeometry *transformed_geometry[4];
6793 ID2D1RectangleGeometry *rect_geometry[2];
6794 D2D1_POINT_2F point = {0.0f, 0.0f};
6795 D2D1_ROUNDED_RECT rounded_rect;
6796 ID2D1SolidColorBrush *brush;
6797 ID2D1PathGeometry *geometry;
6798 IDXGISwapChain *swapchain;
6799 D2D1_MATRIX_3X2_F matrix;
6800 ID2D1GeometrySink *sink;
6801 ID2D1RenderTarget *rt;
6802 ID3D10Device1 *device;
6803 IDXGISurface *surface;
6804 ID2D1Factory *factory;
6805 D2D1_ELLIPSE ellipse;
6806 D2D1_COLOR_F color;
6807 D2D1_RECT_F rect;
6808 ULONG refcount;
6809 HWND window;
6810 HRESULT hr;
6811 BOOL match;
6813 if (!(device = create_device()))
6815 skip("Failed to create device, skipping tests.\n");
6816 return;
6818 window = create_window();
6819 swapchain = create_swapchain(device, window, TRUE);
6820 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
6821 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
6822 rt = create_render_target(surface);
6823 ok(!!rt, "Failed to create render target.\n");
6824 ID2D1RenderTarget_GetFactory(rt, &factory);
6826 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
6827 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
6828 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
6829 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
6830 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
6832 ID2D1RenderTarget_BeginDraw(rt);
6833 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
6834 ID2D1RenderTarget_Clear(rt, &color);
6836 set_rect(&rect, 40.0f, 480.0f, 40.0f, 480.0f);
6837 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
6838 set_rect(&rect, 100.0f, 480.0f, 140.0f, 480.0f);
6839 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
6840 set_rect(&rect, 200.0f, 400.0f, 200.0f, 560.0f);
6841 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
6842 set_rect(&rect, 260.0f, 560.0f, 300.0f, 400.0f);
6843 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
6845 set_ellipse(&ellipse, 40.0f, 800.0f, 0.0f, 0.0f);
6846 ID2D1RenderTarget_FillEllipse(rt, &ellipse, (ID2D1Brush *)brush);
6847 set_ellipse(&ellipse, 120.0f, 800.0f, 20.0f, 0.0f);
6848 ID2D1RenderTarget_FillEllipse(rt, &ellipse, (ID2D1Brush *)brush);
6849 set_ellipse(&ellipse, 200.0f, 800.0f, 0.0f, 80.0f);
6850 ID2D1RenderTarget_FillEllipse(rt, &ellipse, (ID2D1Brush *)brush);
6851 set_ellipse(&ellipse, 280.0f, 800.0f, 20.0f, 80.0f);
6852 ID2D1RenderTarget_FillEllipse(rt, &ellipse, (ID2D1Brush *)brush);
6854 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6855 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
6857 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "gMgB");
6858 ok(match, "Figure does not match.\n");
6859 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0, "gMgB");
6860 ok(match, "Figure does not match.\n");
6861 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0, "gMgB");
6862 ok(match, "Figure does not match.\n");
6863 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 0,
6864 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
6865 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
6866 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
6867 ok(match, "Figure does not match.\n");
6869 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0, "gMgB");
6870 ok(match, "Figure does not match.\n");
6871 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0, "gMgB");
6872 ok(match, "Figure does not match.\n");
6873 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0, "gMgB");
6874 ok(match, "Figure does not match.\n");
6875 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 8,
6876 "yjIMjwEWhwEcggEgfiR6KHYscy5xMG40azZpOGc6ZTxjPmI+YUBfQl1EXERbRlpGWUhYSFdKVkpV"
6877 "TFRMVExTTlJOUk5STlJOUVBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUU5STlJOUk5STlNMVExUTFVK"
6878 "VkpXSFhIWUZaRltEXERdQl9AYT5iPmM8ZTpnOGk2azRuMHEucyx2KHokfiCCARyHARaPAQzKMgAA");
6879 ok(match, "Figure does not match.\n");
6881 ID2D1RenderTarget_BeginDraw(rt);
6882 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
6883 ID2D1RenderTarget_Clear(rt, &color);
6885 set_rounded_rect(&rounded_rect, 40.0f, 160.0f, 40.0f, 160.0f, 10.0f, 10.0f);
6886 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6887 set_rounded_rect(&rounded_rect, 100.0f, 160.0f, 140.0f, 160.0f, 10.0f, 10.0f);
6888 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6889 set_rounded_rect(&rounded_rect, 200.0f, 80.0f, 200.0f, 240.0f, 10.0f, 10.0f);
6890 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6891 set_rounded_rect(&rounded_rect, 260.0f, 240.0f, 300.0f, 80.0f, 10.0f, 10.0f);
6892 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6894 set_rounded_rect(&rounded_rect, 40.0f, 480.0f, 40.0f, 480.0f, 10.0f, 20.0f);
6895 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6896 set_rounded_rect(&rounded_rect, 100.0f, 480.0f, 140.0f, 480.0f, 10.0f, 20.0f);
6897 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6898 set_rounded_rect(&rounded_rect, 200.0f, 400.0f, 200.0f, 560.0f, 10.0f, 20.0f);
6899 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6900 set_rounded_rect(&rounded_rect, 260.0f, 560.0f, 300.0f, 400.0f, 10.0f, 20.0f);
6901 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6903 set_rounded_rect(&rounded_rect, 40.0f, 800.0f, 40.0f, 800.0f, 10.0f, 5.0f);
6904 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6905 set_rounded_rect(&rounded_rect, 100.0f, 800.0f, 140.0f, 800.0f, 10.0f, 5.0f);
6906 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6907 set_rounded_rect(&rounded_rect, 200.0f, 720.0f, 200.0f, 880.0f, 10.0f, 5.0f);
6908 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6909 set_rounded_rect(&rounded_rect, 260.0f, 880.0f, 300.0f, 720.0f, 10.0f, 5.0f);
6910 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6912 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6913 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
6915 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "gMgB");
6916 ok(match, "Figure does not match.\n");
6917 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "gMgB");
6918 ok(match, "Figure does not match.\n");
6919 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0, "gMgB");
6920 ok(match, "Figure does not match.\n");
6921 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 0,
6922 "szI6YURZSlROUVBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
6923 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
6924 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUU5USllEYTqzMgAA");
6925 ok(match, "Figure does not match.\n");
6927 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "gMgB");
6928 ok(match, "Figure does not match.\n");
6929 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0, "gMgB");
6930 ok(match, "Figure does not match.\n");
6931 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0, "gMgB");
6932 ok(match, "Figure does not match.\n");
6933 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 2,
6934 "tjI0aDxhQlxGWEpVTFNOUk5RUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
6935 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
6936 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFFOUk5TTFVKWEZcQmA+ZzS2MgAA");
6937 ok(match, "Figure does not match.\n");
6939 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0, "gMgB");
6940 ok(match, "Figure does not match.\n");
6941 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0, "gMgB");
6942 ok(match, "Figure does not match.\n");
6943 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0, "gMgB");
6944 ok(match, "Figure does not match.\n");
6945 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 0,
6946 "sDJAWkxSUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
6947 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
6948 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFJMWkCwMgAA");
6949 ok(match, "Figure does not match.\n");
6951 ID2D1RenderTarget_BeginDraw(rt);
6952 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
6953 ID2D1RenderTarget_Clear(rt, &color);
6955 set_rounded_rect(&rounded_rect, 40.0f, 160.0f, 40.0f, 160.0f, 1000.0f, 1000.0f);
6956 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6957 set_rounded_rect(&rounded_rect, 100.0f, 160.0f, 140.0f, 160.0f, 1000.0f, 1000.0f);
6958 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6959 set_rounded_rect(&rounded_rect, 200.0f, 80.0f, 200.0f, 240.0f, 1000.0f, 1000.0f);
6960 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6961 set_rounded_rect(&rounded_rect, 260.0f, 240.0f, 300.0f, 80.0f, 1000.0f, 1000.0f);
6962 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6964 set_rounded_rect(&rounded_rect, 40.0f, 480.0f, 40.0f, 480.0f, 10.0f, 1000.0f);
6965 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6966 set_rounded_rect(&rounded_rect, 100.0f, 480.0f, 140.0f, 480.0f, 10.0f, 1000.0f);
6967 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6968 set_rounded_rect(&rounded_rect, 200.0f, 400.0f, 200.0f, 560.0f, 10.0f, 1000.0f);
6969 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6970 set_rounded_rect(&rounded_rect, 260.0f, 560.0f, 300.0f, 400.0f, 10.0f, 1000.0f);
6971 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6973 set_rounded_rect(&rounded_rect, 40.0f, 800.0f, 40.0f, 800.0f, 1000.0f, 10.0f);
6974 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6975 set_rounded_rect(&rounded_rect, 100.0f, 800.0f, 140.0f, 800.0f, 1000.0f, 10.0f);
6976 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6977 set_rounded_rect(&rounded_rect, 200.0f, 720.0f, 200.0f, 880.0f, 1000.0f, 10.0f);
6978 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6979 set_rounded_rect(&rounded_rect, 260.0f, 880.0f, 300.0f, 720.0f, 1000.0f, 10.0f);
6980 ID2D1RenderTarget_FillRoundedRectangle(rt, &rounded_rect, (ID2D1Brush *)brush);
6982 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
6983 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
6985 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "gMgB");
6986 ok(match, "Figure does not match.\n");
6987 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "gMgB");
6988 ok(match, "Figure does not match.\n");
6989 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0, "gMgB");
6990 ok(match, "Figure does not match.\n");
6991 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 10,
6992 "yjIMjwEWhwEcggEgfiR6KHYscy5xMG40azZpOGc6ZTxjPmI+YUBfQl1EXERbRlpGWUhYSFdKVkpV"
6993 "TFRMVExTTlJOUk5STlJOUVBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUU5STlJOUk5STlNMVExUTFVK"
6994 "VkpXSFhIWUZaRltEXERdQl9AYT5iPmM8ZTpnOGk2azRuMHEucyx2KHokfiCCARyHARaPAQzKMgAA");
6995 ok(match, "Figure does not match.\n");
6997 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "gMgB");
6998 ok(match, "Figure does not match.\n");
6999 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0, "gMgB");
7000 ok(match, "Figure does not match.\n");
7001 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0, "gMgB");
7002 ok(match, "Figure does not match.\n");
7003 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 10,
7004 "uTIucDJsNmk4ZzplPGM+YUBgQF9CXkJdRFxEW0ZaRllIWEhXSlZKVkpWSlVMVExUTFRMU05STlJO"
7005 "Uk5STlJOUk9QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFFPUU5STlJOUk5STlJOU0xU"
7006 "TFRMVExVSlZKVkpWSldIWEhZRlpGW0RcRF1CXkJfQGBAYT5jPGU6ZzhpNmwycC65MgAA");
7007 ok(match, "Figure does not match.\n");
7009 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0, "gMgB");
7010 ok(match, "Figure does not match.\n");
7011 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0, "gMgB");
7012 ok(match, "Figure does not match.\n");
7013 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0, "gMgB");
7014 ok(match, "Figure does not match.\n");
7015 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 10,
7016 "vzIiczhhRldMUlBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7017 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7018 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUkxXRmA6cSS+MgAA");
7019 ok(match, "Figure does not match.\n");
7021 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7022 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
7023 hr = ID2D1PathGeometry_Open(geometry, &sink);
7024 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
7026 set_point(&point, 40.0f, 160.0f);
7027 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7028 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7030 set_point(&point, 120.0f, 160.0f);
7031 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7032 line_to(sink, 120.0f, 160.0f);
7033 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7035 set_point(&point, 200.0f, 160.0f);
7036 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7037 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7039 set_point(&point, 280.0f, 160.0f);
7040 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7041 line_to(sink, 280.0f, 160.0f);
7042 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7044 set_point(&point, 20.0f, 480.0f);
7045 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7046 line_to(sink, 60.0f, 480.0f);
7047 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7049 set_point(&point, 120.0f, 400.0f);
7050 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7051 line_to(sink, 120.0f, 560.0f);
7052 line_to(sink, 120.0f, 400.0f);
7053 line_to(sink, 120.0f, 560.0f);
7054 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7056 set_point(&point, 180.0f, 480.0f);
7057 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7058 line_to(sink, 220.0f, 480.0f);
7059 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7061 set_point(&point, 280.0f, 400.0f);
7062 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7063 line_to(sink, 280.0f, 560.0f);
7064 line_to(sink, 280.0f, 400.0f);
7065 line_to(sink, 280.0f, 560.0f);
7066 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7068 set_point(&point, 20.0f, 880.0f);
7069 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7070 line_to(sink, 40.0f, 720.0f);
7071 line_to(sink, 60.0f, 880.0f);
7072 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7074 set_point(&point, 100.0f, 720.0f);
7075 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7076 line_to(sink, 120.0f, 880.0f);
7077 line_to(sink, 140.0f, 720.0f);
7078 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7080 set_point(&point, 180.0f, 880.0f);
7081 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7082 line_to(sink, 200.0f, 720.0f);
7083 line_to(sink, 220.0f, 880.0f);
7084 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7086 set_point(&point, 260.0f, 720.0f);
7087 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7088 line_to(sink, 280.0f, 880.0f);
7089 line_to(sink, 300.0f, 720.0f);
7090 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7092 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
7093 hr = ID2D1GeometrySink_Close(sink);
7094 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
7095 ID2D1GeometrySink_Release(sink);
7097 ID2D1RenderTarget_BeginDraw(rt);
7098 ID2D1RenderTarget_Clear(rt, &color);
7099 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
7100 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7101 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
7102 ID2D1PathGeometry_Release(geometry);
7104 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "gMgB");
7105 ok(match, "Figure does not match.\n");
7106 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "gMgB");
7107 ok(match, "Figure does not match.\n");
7108 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0, "gMgB");
7109 ok(match, "Figure does not match.\n");
7110 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 0, "gMgB");
7111 ok(match, "Figure does not match.\n");
7113 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "gMgB");
7114 ok(match, "Figure does not match.\n");
7115 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0, "gMgB");
7116 ok(match, "Figure does not match.\n");
7117 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0, "gMgB");
7118 ok(match, "Figure does not match.\n");
7119 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 0, "gMgB");
7120 ok(match, "Figure does not match.\n");
7122 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0,
7123 "7zMCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
7124 "jAEUiwEWigEWiQEYiAEYhwEahgEahQEchAEcgwEeggEegQEggAEgfyJ+In0kfCR7JnomeSh4KHcq"
7125 "dip1LHQscy5yLnEwcDBvMm4ybTRsNGs2ajZpOGg4ZzpmOmU8ZDxjPmI+YUBgQF9CXkJdRFxEW0Za"
7126 "RllIWEhXSlZKVUxUTFNOUk5RUKgy");
7127 ok(match, "Figure does not match.\n");
7128 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0,
7129 "qDJQUU5STlNMVExVSlZKV0hYSFlGWkZbRFxEXUJeQl9AYEBhPmI+YzxkPGU6ZjpnOGg4aTZqNms0"
7130 "bDRtMm4ybzBwMHEuci5zLHQsdSp2KncoeCh5JnomeyR8JH0ifiJ/IIABIIEBHoIBHoMBHIQBHIUB"
7131 "GoYBGocBGIgBGIkBFooBFosBFIwBFI0BEo4BEo8BEJABEJEBDpIBDpMBDJQBDJUBCpYBCpcBCJgB"
7132 "CJkBBpoBBpsBBJwBBJ0BAp4BAu8z");
7133 ok(match, "Figure does not match.\n");
7134 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0,
7135 "7zMCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
7136 "jAEUiwEWigEWiQEYiAEYhwEahgEahQEchAEcgwEeggEegQEggAEgfyJ+In0kfCR7JnomeSh4KHcq"
7137 "dip1LHQscy5yLnEwcDBvMm4ybTRsNGs2ajZpOGg4ZzpmOmU8ZDxjPmI+YUBgQF9CXkJdRFxEW0Za"
7138 "RllIWEhXSlZKVUxUTFNOUk5RUKgy");
7139 ok(match, "Figure does not match.\n");
7140 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 0,
7141 "qDJQUU5STlNMVExVSlZKV0hYSFlGWkZbRFxEXUJeQl9AYEBhPmI+YzxkPGU6ZjpnOGg4aTZqNms0"
7142 "bDRtMm4ybzBwMHEuci5zLHQsdSp2KncoeCh5JnomeyR8JH0ifiJ/IIABIIEBHoIBHoMBHIQBHIUB"
7143 "GoYBGocBGIgBGIkBFooBFosBFIwBFI0BEo4BEo8BEJABEJEBDpIBDpMBDJQBDJUBCpYBCpcBCJgB"
7144 "CJkBBpoBBpsBBJwBBJ0BAp4BAu8z");
7145 ok(match, "Figure does not match.\n");
7147 set_rect(&rect, 20.0f, 80.0f, 60.0f, 240.0f);
7148 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[0]);
7149 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7151 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
7152 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[1]);
7153 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7155 set_matrix_identity(&matrix);
7156 translate_matrix(&matrix, 160.0f, 640.0f);
7157 scale_matrix(&matrix, 40.0f, 160.0f);
7158 rotate_matrix(&matrix, M_PI / -5.0f);
7159 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7160 (ID2D1Geometry *)rect_geometry[1], &matrix, &transformed_geometry[0]);
7161 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7163 set_matrix_identity(&matrix);
7164 scale_matrix(&matrix, 0.5f, 1.0f);
7165 translate_matrix(&matrix, -80.0f, 0.0f);
7166 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7167 (ID2D1Geometry *)transformed_geometry[0], &matrix, &transformed_geometry[1]);
7168 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7170 set_matrix_identity(&matrix);
7171 rotate_matrix(&matrix, M_PI / 2.0f);
7172 translate_matrix(&matrix, 80.0f, -320.0f);
7173 scale_matrix(&matrix, 2.0f, 0.25f);
7174 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7175 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
7176 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7178 ID2D1RenderTarget_BeginDraw(rt);
7179 ID2D1RenderTarget_Clear(rt, &color);
7180 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)rect_geometry[0], (ID2D1Brush *)brush, NULL);
7181 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, NULL);
7182 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, NULL);
7183 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, NULL);
7184 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7185 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
7186 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
7187 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
7188 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
7189 ID2D1RectangleGeometry_Release(rect_geometry[1]);
7190 ID2D1RectangleGeometry_Release(rect_geometry[0]);
7192 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0,
7193 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7194 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7195 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7196 ok(match, "Figure does not match.\n");
7197 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 32,
7198 "sIMBA7cCDK8CFKYCHZ4CJJYCLY4CNYUCPv0BRvQBT+wBV+MBYNsBaNIBccoBecEBgQG6AYkBsQGS"
7199 "AakBmgGgAaMBmAGrAY8BtAGHAbwBfsUBfcYBfcYBfcUBfsUBfcYBfcYBfcYBfcYBfcUBfr0BhgG0"
7200 "AY8BrAGXAaMBoAGbAagBkgGwAYsBuAGCAcEBeskBcdIBadoBYOMBWOsBT/QBR/wBPoUCNowCLpUC"
7201 "Jp0CHaYCFa4CDLcCBK+DAQAA");
7202 ok(match, "Figure does not match.\n");
7203 match = compare_figure(surface, 0, 160, 160, 320, 0xff652e89, 32,
7204 "+D0BngEDnQEDnAEEmwEGmgEGmQEHmAEJlwEJlgELlAEMkwENkwEOkQEPkAEQkAERjgESjQETjQEU"
7205 "iwEVigEXiQEXiAEYhwEahgEahQEbhAEdggEeggEegQEgfyF/In0jfCR8JXomeSd5KHcpdip2K3Qs"
7206 "cy5xL3EvcDFuMm4ybTRrNWs1ajdoOGg5ZjplO2U8Yz1iPmFAYEBfQV5DXUNcRVpGWkZZSFdJV0lW"
7207 "S1RMVExTTlFPUFFPUU5STVRMVEtVSldJV0hYR1pGWkVcQ11CXkJfQGA/YT9iPWM+Yj5jPWM+Yz1j"
7208 "PWM+Yz1jPmI+Yz1jPmI+Yz1jPmM9Yz1jPmM9Yz5iPmM9Yz5iPmM9Yz5jPWM9Yz5jPWM+Yj5jPWM+"
7209 "Yj5jPWI/YT9gQF9CXkJdRFtFW0VaR1hIV0lXSlVLVExUTVJOUVBQUE9RTlNNU0xUS1ZKVklXSFlG"
7210 "WkZaRVxDXUNeQV9AYEBhPmI9Yz1kO2U6ZjpnOGg3ajVrNWs0bTJuMm4xcC9xL3Eucyx0LHUqdil3"
7211 "KXgneSZ6JXwkfCN9In8hfyCBAR6CAR6CAR2EARuFARuFARqHARiIAReJAReKARWLARSNARONARKO"
7212 "ARGQARCQAQ+RAQ6TAQ2TAQyUAQuWAQqWAQmYAQeZAQaaAQabAQScAQOdAQOeAQH4PQAA");
7213 ok(match, "Figure does not match.\n");
7214 match = compare_figure(surface, 160, 160, 320, 320, 0xff652e89, 32,
7215 "sXkBvgIDvAIEugIHuAIJtgILswINsgIPrwISrQITrAIVqQIYpwIapQIbowIeoQIgngIjnAIkmwIm"
7216 "mAIplgIqlQIskgIvkAIxjQIzjAI1igI3hwI5hgI7hAI9gQJA/wFB/QFE+wFG+QFI9gFK9QFM8wFO"
7217 "8AFQ7wFS7AFV6gFX6AFY5gFb5AFd4gFf3wFh3gFj2wFm2QFn2AFp1QFs0wFu0QFvzwFyzQF0ygF3"
7218 "yAF4xwF6xAF9wgF+wAGBAb4BgwG8AYUBuQGHAbgBiQG2AYsBswGOAbEBjwGvAZIBrQGUAasBlQGp"
7219 "AZgBpwGaAaUBnAGiAZ4BoQGgAZ4BowGcAaUBmgGmAZgBqQGWAasBlAGsAZIBrwGQAbEBjQG0AYsB"
7220 "tQGKAbcBhwG6AYUBvAGDAb0BgQHAAX/CAXzEAXvGAXvGAXvGAXvFAXvGAXvGAXvGAXvFAXvGAXvG"
7221 "AXvFAXvGAXvGAXvGAXvFAXvGAXvGAXvFAXzFAXvGAXvGAXvFAXvGAXvGAXvGAXvFAXvGAXvGAXvF"
7222 "AXzFAXvGAXvGAXvFAXvGAXvGAXvGAXvEAXzCAX/AAYEBvgGCAbwBhQG6AYcBtwGKAbUBiwG0AY0B"
7223 "sQGQAa8BkgGtAZMBqwGWAakBmAGmAZoBpQGcAaMBngGgAaEBngGiAZ0BpAGaAacBmAGpAZUBqwGU"
7224 "Aa0BkgGvAY8BsQGOAbMBjAG1AYkBuAGHAbkBhQG8AYMBvgGBAcABfsIBfcQBe8YBeMgBd8oBdM0B"
7225 "cs8BcNABbtMBbNUBatcBZ9kBZtsBY94BYd8BYOEBXeQBW+YBWOgBV+oBVewBUu8BUPABT/IBTPUB"
7226 "SvYBSPkBRvsBRP0BQf8BQIECPoMCO4YCOYcCN4oCNYwCM40CMZACL5ICLZQCKpYCKZgCJpsCJJ0C"
7227 "Ip4CIKECHqMCHKQCGqcCGKkCFawCE60CEq8CD7ICDbMCDLUCCbgCB7oCBLwCA74CAbF5");
7228 ok(match, "Figure does not match.\n");
7230 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7231 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
7232 hr = ID2D1PathGeometry_Open(geometry, &sink);
7233 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
7235 set_point(&point, 20.0f, 80.0f);
7236 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7237 quadratic_to(sink, 40.0f, 80.0f, 60.0f, 80.0f);
7238 quadratic_to(sink, 60.0f, 160.0f, 60.0f, 240.0f);
7239 quadratic_to(sink, 40.0f, 240.0f, 20.0f, 240.0f);
7240 quadratic_to(sink, 20.0f, 160.0f, 20.0f, 80.0f);
7241 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7243 set_point(&point, 100.0f, 80.0f);
7244 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7245 quadratic_to(sink, 105.0f, 80.0f, 140.0f, 80.0f);
7246 quadratic_to(sink, 140.0f, 100.0f, 140.0f, 240.0f);
7247 quadratic_to(sink, 135.0f, 240.0f, 100.0f, 240.0f);
7248 quadratic_to(sink, 100.0f, 220.0f, 100.0f, 80.0f);
7249 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7251 set_point(&point, 180.0f, 80.0f);
7252 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7253 quadratic_to(sink, 215.0f, 80.0f, 220.0f, 80.0f);
7254 quadratic_to(sink, 220.0f, 220.0f, 220.0f, 240.0f);
7255 quadratic_to(sink, 185.0f, 240.0f, 180.0f, 240.0f);
7256 quadratic_to(sink, 180.0f, 100.0f, 180.0f, 80.0f);
7257 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7259 set_point(&point, 260.0f, 80.0f);
7260 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7261 quadratic_to(sink, 280.0f, 80.0f, 300.0f, 80.0f);
7262 quadratic_to(sink, 300.0f, 160.0f, 300.0f, 240.0f);
7263 quadratic_to(sink, 280.0f, 240.0f, 260.0f, 240.0f);
7264 quadratic_to(sink, 260.0f, 160.0f, 260.0f, 80.0f);
7265 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7267 set_point(&point, 20.0f, 400.0f);
7268 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7269 quadratic_to(sink, 40.0f, 420.0f, 60.0f, 400.0f);
7270 quadratic_to(sink, 55.0f, 480.0f, 60.0f, 560.0f);
7271 quadratic_to(sink, 40.0f, 540.0f, 20.0f, 560.0f);
7272 quadratic_to(sink, 25.0f, 480.0f, 20.0f, 400.0f);
7273 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7275 set_point(&point, 100.0f, 400.0f);
7276 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7277 quadratic_to(sink, 105.0f, 420.0f, 140.0f, 400.0f);
7278 quadratic_to(sink, 135.0f, 420.0f, 140.0f, 560.0f);
7279 quadratic_to(sink, 135.0f, 540.0f, 100.0f, 560.0f);
7280 quadratic_to(sink, 105.0f, 540.0f, 100.0f, 400.0f);
7281 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7283 set_point(&point, 180.0f, 400.0f);
7284 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7285 quadratic_to(sink, 215.0f, 420.0f, 220.0f, 400.0f);
7286 quadratic_to(sink, 215.0f, 540.0f, 220.0f, 560.0f);
7287 quadratic_to(sink, 185.0f, 540.0f, 180.0f, 560.0f);
7288 quadratic_to(sink, 185.0f, 420.0f, 180.0f, 400.0f);
7289 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7291 set_point(&point, 260.0f, 400.0f);
7292 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7293 quadratic_to(sink, 280.0f, 420.0f, 300.0f, 400.0f);
7294 quadratic_to(sink, 295.0f, 480.0f, 300.0f, 560.0f);
7295 quadratic_to(sink, 280.0f, 540.0f, 260.0f, 560.0f);
7296 quadratic_to(sink, 265.0f, 480.0f, 260.0f, 400.0f);
7297 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7299 set_point(&point, 20.0f, 720.0f);
7300 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7301 quadratic_to(sink, 40.0f, 700.0f, 60.0f, 720.0f);
7302 quadratic_to(sink, 65.0f, 800.0f, 60.0f, 880.0f);
7303 quadratic_to(sink, 40.0f, 900.0f, 20.0f, 880.0f);
7304 quadratic_to(sink, 15.0f, 800.0f, 20.0f, 720.0f);
7305 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7307 set_point(&point, 100.0f, 720.0f);
7308 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7309 quadratic_to(sink, 105.0f, 700.0f, 140.0f, 720.0f);
7310 quadratic_to(sink, 145.0f, 740.0f, 140.0f, 880.0f);
7311 quadratic_to(sink, 135.0f, 900.0f, 100.0f, 880.0f);
7312 quadratic_to(sink, 95.0f, 860.0f, 100.0f, 720.0f);
7313 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7315 set_point(&point, 180.0f, 720.0f);
7316 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7317 quadratic_to(sink, 215.0f, 700.0f, 220.0f, 720.0f);
7318 quadratic_to(sink, 225.0f, 860.0f, 220.0f, 880.0f);
7319 quadratic_to(sink, 185.0f, 900.0f, 180.0f, 880.0f);
7320 quadratic_to(sink, 175.0f, 740.0f, 180.0f, 720.0f);
7321 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7323 set_point(&point, 260.0f, 720.0f);
7324 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7325 quadratic_to(sink, 280.0f, 700.0f, 300.0f, 720.0f);
7326 quadratic_to(sink, 305.0f, 800.0f, 300.0f, 880.0f);
7327 quadratic_to(sink, 280.0f, 900.0f, 260.0f, 880.0f);
7328 quadratic_to(sink, 255.0f, 800.0f, 260.0f, 720.0f);
7329 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
7331 hr = ID2D1GeometrySink_Close(sink);
7332 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
7333 ID2D1GeometrySink_Release(sink);
7335 ID2D1RenderTarget_BeginDraw(rt);
7336 ID2D1RenderTarget_Clear(rt, &color);
7337 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
7338 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7339 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
7340 ID2D1PathGeometry_Release(geometry);
7342 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0,
7343 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7344 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7345 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7346 ok(match, "Figure does not match.\n");
7347 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0,
7348 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7349 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7350 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7351 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0,
7352 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7353 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7354 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7355 ok(match, "Figure does not match.\n");
7356 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 0,
7357 "qDJQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7358 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ"
7359 "UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFCoMgAA");
7360 ok(match, "Figure does not match.\n");
7362 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 16,
7363 "qDICTAJQB0IHUQs4C1IRLBFSGxgbUk5STlNMVExUTFRMVExVSlZKVkpWSlZKVkpXSFhIWEhYSFhI"
7364 "WEhYSFhIWEhYSFlGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZa"
7365 "RllIWEhYSFhIWEhYSFhIWEhYSFhIV0pWSlZKVkpWSlZKVUxUTFRMVExUTFNOUk5SGxgbUhEsEVIL"
7366 "OAtRB0IHUAJMAqgy");
7367 ok(match, "Figure does not match.\n");
7368 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 16,
7369 "qDIBSwRQAkMKUQQ5EVIIKxtTDRkmVExUTFRMVEtVS1VLVkpWSlZKVklXSVdJV0lXSVhIWEhYSFhI"
7370 "WEhYSFhIWEhYSFhIWUdZR1lHWUdZR1lHWUdZR1lHWUdZSFhIWUdZR1lHWUdZR1lHWUdZR1lHWUdZ"
7371 "SFhIWEhYSFhIWEhYSFhIWEhYSFhJV0lXSVdJV0lWSlZKVkpWS1VLVUtUTFRMVExUJhkNUxsrCFIR"
7372 "OQRRCkMCUARLAagy");
7373 ok(match, "Figure does not match.\n");
7374 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 16,
7375 "qDIESwFRCkMCUhE5BFIbKwhTJhkNVExUTFRMVUtVS1VLVUpWSlZKV0lXSVdJV0lXSVdIWEhYSFhI"
7376 "WEhYSFhIWEhYSFhIWEdZR1lHWUdZR1lHWUdZR1lHWUdYSFhIWEdZR1lHWUdZR1lHWUdZR1lHWUdY"
7377 "SFhIWEhYSFhIWEhYSFhIWEhYSFdJV0lXSVdJV0lXSlZKVkpVS1VLVUtVTFRMVExUDRkmUwgrG1IE"
7378 "ORFSAkMKUQFLBKgy");
7379 ok(match, "Figure does not match.\n");
7380 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 16,
7381 "qDICTAJQB0IHUQs4C1IRLBFSGxgbUk5STlNMVExUTFRMVExVSlZKVkpWSlZKVkpXSFhIWEhYSFhI"
7382 "WEhYSFhIWEhYSFlGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZa"
7383 "RllIWEhYSFhIWEhYSFhIWEhYSFhIV0pWSlZKVkpWSlZKVUxUTFRMVExUTFNOUk5SGxgbUhEsEVIL"
7384 "OAtRB0IHUAJMAqgy");
7385 ok(match, "Figure does not match.\n");
7387 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 16,
7388 "pCwYfixuOGNCWUxSUFBQT1JOUk5STlJOUk1UTFRMVExUTFRLVkpWSlZKVkpWSlZJWEhYSFhIWEhY"
7389 "SFhIWEhYSFhIWEdaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpG"
7390 "WkdYSFhIWEhYSFhIWEhYSFhIWEhYSVZKVkpWSlZKVkpWS1RMVExUTFRMVE1STlJOUk5STlJPUFBQ"
7391 "UkxZQmM4bix+GKQs");
7392 ok(match, "Figure does not match.\n");
7393 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 16,
7394 "liwZgQErcTllQ1xLVFBQUU9STlJNVExUTFRMVExVS1VLVUpWSlZKVkpXSVdJV0lXSVdIWEhYSFhI"
7395 "WEhYSFhIWEhYSFhIWEdZR1lHWUdZR1lHWUdZR1lHWUdZR1hIWEdZR1lHWUdZR1lHWUdZR1lHWUdZ"
7396 "R1hIWEhYSFhIWEhYSFhIWEhYSFhIV0lXSVdJV0lXSlZKVkpWSlVLVUtVTFRMVExUTFRNUk5ST1FQ"
7397 "UFRLXENlOXErgQEZliwA");
7398 ok(match, "Figure does not match.\n");
7399 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 16,
7400 "sSwZeytrOV9DVktRUE9RTlJOUk1UTFRMVExUS1VLVUtVS1ZKVkpWSVdJV0lXSVdJV0lYSFhIWEhY"
7401 "SFhIWEhYSFhIWEhYSFlHWUdZR1lHWUdZR1lHWUdZR1lIWEhYSFlHWUdZR1lHWUdZR1lHWUdZR1lI"
7402 "WEhYSFhIWEhYSFhIWEhYSFhIWElXSVdJV0lXSVdJVkpWSlZLVUtVS1VLVExUTFRMVE1STlJOUU9Q"
7403 "UUtWQ185ayt7GbEs");
7404 ok(match, "Figure does not match.\n");
7405 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 16,
7406 "pCwYfixuOGNCWUxSUFBQT1JOUk5STlJOUk1UTFRMVExUTFRLVkpWSlZKVkpWSlZJWEhYSFhIWEhY"
7407 "SFhIWEhYSFhIWEdaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpGWkZaRlpG"
7408 "WkdYSFhIWEhYSFhIWEhYSFhIWEhYSVZKVkpWSlZKVkpWS1RMVExUTFRMVE1STlJOUk5STlJPUFBQ"
7409 "UkxZQmM4bix+GKQs");
7410 ok(match, "Figure does not match.\n");
7412 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7413 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
7414 hr = ID2D1PathGeometry_Open(geometry, &sink);
7415 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
7417 set_point(&point, -0.402914f, 0.915514f);
7418 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7419 quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
7420 quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f);
7421 quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f);
7422 quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f);
7423 quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f);
7424 quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f);
7425 quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f);
7426 quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f);
7427 quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f);
7428 quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f);
7429 quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f);
7430 quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f);
7431 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7433 hr = ID2D1GeometrySink_Close(sink);
7434 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
7435 ID2D1GeometrySink_Release(sink);
7437 set_matrix_identity(&matrix);
7438 translate_matrix(&matrix, 40.0f, 160.0f);
7439 scale_matrix(&matrix, 20.0f, 80.0f);
7440 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7441 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]);
7442 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7444 set_matrix_identity(&matrix);
7445 translate_matrix(&matrix, 160.0f, 640.0f);
7446 scale_matrix(&matrix, 40.0f, 160.0f);
7447 rotate_matrix(&matrix, M_PI / -5.0f);
7448 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7449 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]);
7450 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7451 ID2D1PathGeometry_Release(geometry);
7453 set_matrix_identity(&matrix);
7454 scale_matrix(&matrix, 0.5f, 1.0f);
7455 translate_matrix(&matrix, -80.0f, 0.0f);
7456 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7457 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
7458 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7460 set_matrix_identity(&matrix);
7461 rotate_matrix(&matrix, M_PI / 2.0f);
7462 translate_matrix(&matrix, 80.0f, -320.0f);
7463 scale_matrix(&matrix, 2.0f, 0.25f);
7464 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7465 (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]);
7466 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7468 ID2D1RenderTarget_BeginDraw(rt);
7469 ID2D1RenderTarget_Clear(rt, &color);
7470 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, NULL);
7471 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, NULL);
7472 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, NULL);
7473 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[3], (ID2D1Brush *)brush, NULL);
7474 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7475 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
7476 ID2D1TransformedGeometry_Release(transformed_geometry[3]);
7477 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
7478 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
7479 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
7481 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 32,
7482 "6DMNjgEWiAEahgEahgEahgEahgEahgEahgEahgEahgEahgEahgEahwEZhwEZhwEZhwEZhwEZhwEZ"
7483 "hwEZhwEZhwEZiAEYiAEYiAEYiAEYiAEXiQEXiQEXiQEXigEWigEWigEWigEWigEWigEWigEWiwEU"
7484 "jAEUjAEUjAEUjQESjgESjwEQkAEQkQEOkgENlAEMlQEKlgEKlwEImAEImQEHmQEGmwEFmwEEnQED"
7485 "nQECngECngECnwEBnwEBnwEBnwEBnwEBnwECnQEDnQEDnQEEmwEFmgEHmQEHlwELkQERjAEXhgEd"
7486 "hAEfgwEchgEXjwEMqTEA");
7487 ok(match, "Figure does not match.\n");
7488 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 32,
7489 "h58BBrYCDq0CF6QCIJwCKJMCMIwCNoUCPf8BQ/kBSPQBTu4BTe8BTPEBSfUBRvgBQf0BPYECOYUC"
7490 "NIoCMI4CK+UBAS0W/AEHIwiPAgsaBZcCEAwIngIepAIaqAIWrAITsAIRsgIPtQIMtwILugIHwAIB"
7491 "ypwB");
7492 ok(match, "Figure does not match.\n");
7493 match = compare_figure(surface, 0, 160, 160, 320, 0xff652e89, 32,
7494 "wW4DnAEEmwEFmgEHmAEIlwEKlQELlAEMkwEOkQEPkAEQkAERjgESjgETjAEUjAEUiwEWigEWiQEX"
7495 "iQEYhwEZhwEZhgEbhQEbhAEchAEdggEeggEeggEfgAEggAEggAEhgAEggAEggQEggAEggAEggQEg"
7496 "gAEggQEfgQEfggEfgQEfgQEfggEfgQEfggEeggEfggEeggEegwEdgwEeggEegwEdgwEegwEdgwEd"
7497 "hAEchAEdhAEchAEchAEdhAEchAEchQEbhQEbhgEahgEahwEZhwEZiAEYiAEYiQEYiAEYiQEXiQEX"
7498 "igEWigEWiwEViwEViwEVjAEUjAEUjQETjQETjgESjgETjgESjwERkAEQkQEPkwENlAEMlQELlgEK"
7499 "lwEKlwEJmAEImQEHmgEGmwEFnAEEnQEEnQEDnQEDngECngEDngECngECnwECngECnwECngECngED"
7500 "ngECEgGLAQMQAosBAw4EjAEDCwaMAQQJBo0BBQYIjQEHAgqNARKOARKPARCQARCQARCQAQ+RAQ6S"
7501 "AQ6SAQ2TAQ2SAQ2TAQ2TAQyTAQyUAQyUAQuUAQuVAQuUAQuVAQqWAQmWAQqWAQmXAQiXAQiYAQeY"
7502 "AQeZAQWbAQSDZwAA");
7503 ok(match, "Figure does not match.\n");
7504 match = compare_figure(surface, 160, 160, 320, 320, 0xff652e89, 32,
7505 "g90BBLkCCLYCC7ICDrACEa0CFKoCF6cCGqQCHKMCHqECIJ8CIpwCJJsCJpkCKJcCKZYCK5QCLZIC"
7506 "L5ACMI8CMo0CNIsCNYoCN4gCOYcCOYYCO4QCPYICPoECQIACQYACQIECQIACQIECQIECQIECP4IC"
7507 "P4ICP4ECP4ICP4ICPoMCPoMCPoMCPYQCPYMCPYQCPYQCPYQCPIUCPIUCPIUCO4YCO4YCOoYCO4YC"
7508 "OocCOocCOocCOYgCOYgCOIkCOIkCN4oCNosCNYwCNI0CM44CMo4CM44CMo8CMZACMJECL5ICLpMC"
7509 "LZQCLJUCK5YCK5YCKpcCKZgCKJkCJ5oCJpsCJpsCJZwCJJ4CIqACIKICH6MCHaUCG6cCGakCF6wC"
7510 "Fa0CE68CEbECD7MCDrQCDLYCCrgCCbkCB7sCBrsCBbwCBbwCBL0CBL0CBL0CBL0CA70CBL0CBL0C"
7511 "BLwCBSUBlgIFIQSXAgYbCJcCBxcKmQIIEQ6ZAgoMEJoCDQUTnAIknAIjnQIingIhnwIgoAIfoQIe"
7512 "ogIdowIcpAIbpQIapQIZpgIZpgIZpwIYpwIXqAIXqAIXqQIVqgIVqgIUqwITrQISrQIRrgIQsAIO"
7513 "sQIMswILtQIIhs4B");
7514 ok(match, "Figure does not match.\n");
7516 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7517 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
7518 hr = ID2D1PathGeometry_Open(geometry, &sink);
7519 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
7521 set_point(&point, -0.402914f, 0.915514f);
7522 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
7523 quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
7524 quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f);
7525 quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f);
7526 quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f);
7527 quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f);
7528 quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f);
7529 quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f);
7530 quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f);
7531 quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f);
7532 quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f);
7533 quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f);
7534 quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f);
7535 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7537 hr = ID2D1GeometrySink_Close(sink);
7538 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
7539 ID2D1GeometrySink_Release(sink);
7541 set_matrix_identity(&matrix);
7542 translate_matrix(&matrix, 40.0f, 160.0f);
7543 scale_matrix(&matrix, 20.0f, 80.0f);
7544 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7545 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]);
7546 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7548 set_matrix_identity(&matrix);
7549 translate_matrix(&matrix, 160.0f, 640.0f);
7550 scale_matrix(&matrix, 40.0f, 160.0f);
7551 rotate_matrix(&matrix, M_PI / -5.0f);
7552 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7553 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]);
7554 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7555 ID2D1PathGeometry_Release(geometry);
7557 set_matrix_identity(&matrix);
7558 scale_matrix(&matrix, 0.5f, 1.0f);
7559 translate_matrix(&matrix, -80.0f, 0.0f);
7560 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7561 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
7562 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7564 set_matrix_identity(&matrix);
7565 rotate_matrix(&matrix, M_PI / 2.0f);
7566 translate_matrix(&matrix, 80.0f, -320.0f);
7567 scale_matrix(&matrix, 2.0f, 0.25f);
7568 hr = ID2D1Factory_CreateTransformedGeometry(factory,
7569 (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]);
7570 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
7572 ID2D1RenderTarget_BeginDraw(rt);
7573 ID2D1RenderTarget_Clear(rt, &color);
7574 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, NULL);
7575 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, NULL);
7576 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, NULL);
7577 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry[3], (ID2D1Brush *)brush, NULL);
7578 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7579 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
7580 ID2D1TransformedGeometry_Release(transformed_geometry[3]);
7581 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
7582 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
7583 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
7585 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "gMgB");
7586 ok(match, "Figure does not match.\n");
7587 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 0, "gJAD");
7588 ok(match, "Figure does not match.\n");
7589 match = compare_figure(surface, 0, 160, 160, 320, 0xff652e89, 0, "gJAD");
7590 ok(match, "Figure does not match.\n");
7591 match = compare_figure(surface, 160, 160, 320, 320, 0xff652e89, 0, "gKAG");
7592 ok(match, "Figure does not match.\n");
7594 ID2D1SolidColorBrush_Release(brush);
7595 ID2D1RenderTarget_Release(rt);
7596 refcount = ID2D1Factory_Release(factory);
7597 ok(!refcount, "Factory has %u references left.\n", refcount);
7598 IDXGISurface_Release(surface);
7599 IDXGISwapChain_Release(swapchain);
7600 ID3D10Device1_Release(device);
7601 DestroyWindow(window);
7604 static void test_gdi_interop(void)
7606 ID2D1GdiInteropRenderTarget *interop;
7607 D2D1_RENDER_TARGET_PROPERTIES desc;
7608 IWICImagingFactory *wic_factory;
7609 IWICBitmapLock *wic_lock;
7610 IWICBitmap *wic_bitmap;
7611 ID2D1RenderTarget *rt;
7612 ID2D1Factory *factory;
7613 ID3D10Device1 *device;
7614 D2D1_COLOR_F color;
7615 HRESULT hr;
7616 BOOL match;
7617 RECT rect;
7618 HDC dc;
7620 if (!(device = create_device()))
7622 skip("Failed to create device, skipping tests.\n");
7623 return;
7626 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
7627 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
7629 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
7630 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
7631 &IID_IWICImagingFactory, (void **)&wic_factory);
7632 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
7633 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
7634 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
7635 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
7636 IWICImagingFactory_Release(wic_factory);
7638 /* WIC target, default usage */
7639 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
7640 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
7641 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
7642 desc.dpiX = 0.0f;
7643 desc.dpiY = 0.0f;
7644 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
7645 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
7647 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory, wic_bitmap, &desc, &rt);
7648 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
7650 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
7651 ok(SUCCEEDED(hr), "Failed to get gdi interop interface, hr %#x.\n", hr);
7653 ID2D1RenderTarget_BeginDraw(rt);
7654 dc = (void *)0xdeadbeef;
7655 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
7656 ok(FAILED(hr), "GetDC() was expected to fail, hr %#x.\n", hr);
7657 todo_wine
7658 ok(dc == NULL, "Expected NULL dc, got %p.\n", dc);
7659 ID2D1GdiInteropRenderTarget_Release(interop);
7660 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7662 ID2D1RenderTarget_Release(rt);
7664 /* WIC target, gdi compatible */
7665 desc.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
7667 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory, wic_bitmap, &desc, &rt);
7668 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
7670 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
7671 ok(SUCCEEDED(hr), "Failed to get gdi interop interface, hr %#x.\n", hr);
7673 ID2D1RenderTarget_BeginDraw(rt);
7674 dc = NULL;
7675 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
7676 ok(SUCCEEDED(hr), "GetDC() was expected to succeed, hr %#x.\n", hr);
7677 ok(dc != NULL, "Expected NULL dc, got %p.\n", dc);
7678 ID2D1GdiInteropRenderTarget_ReleaseDC(interop, NULL);
7679 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7680 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
7682 ID2D1RenderTarget_BeginDraw(rt);
7683 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
7684 ID2D1RenderTarget_Clear(rt, &color);
7685 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7686 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
7688 match = compare_wic_bitmap(wic_bitmap, "54034063dbc1c1bb61cb60ec57e4498678dc2b13");
7689 ok(match, "Bitmap does not match.\n");
7691 /* Do solid fill using GDI */
7692 ID2D1RenderTarget_BeginDraw(rt);
7694 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
7695 ok(SUCCEEDED(hr), "GetDC() was expected to succeed, hr %#x.\n", hr);
7697 SetRect(&rect, 0, 0, 16, 16);
7698 FillRect(dc, &rect, GetStockObject(BLACK_BRUSH));
7699 ID2D1GdiInteropRenderTarget_ReleaseDC(interop, NULL);
7701 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7702 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
7704 match = compare_wic_bitmap(wic_bitmap, "60cacbf3d72e1e7834203da608037b1bf83b40e8");
7705 ok(match, "Bitmap does not match.\n");
7707 /* Bitmap is locked at BeginDraw(). */
7708 hr = IWICBitmap_Lock(wic_bitmap, NULL, WICBitmapLockRead, &wic_lock);
7709 ok(SUCCEEDED(hr), "Expected bitmap to be unlocked, hr %#x.\n", hr);
7710 IWICBitmapLock_Release(wic_lock);
7712 ID2D1RenderTarget_BeginDraw(rt);
7713 hr = IWICBitmap_Lock(wic_bitmap, NULL, WICBitmapLockRead, &wic_lock);
7714 todo_wine
7715 ok(hr == WINCODEC_ERR_ALREADYLOCKED, "Expected bitmap to be locked, hr %#x.\n", hr);
7716 if (SUCCEEDED(hr))
7717 IWICBitmapLock_Release(wic_lock);
7718 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7719 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
7721 /* Lock before BeginDraw(). */
7722 hr = IWICBitmap_Lock(wic_bitmap, NULL, WICBitmapLockRead, &wic_lock);
7723 ok(SUCCEEDED(hr), "Expected bitmap to be unlocked, hr %#x.\n", hr);
7724 ID2D1RenderTarget_BeginDraw(rt);
7725 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7726 todo_wine
7727 ok(hr == WINCODEC_ERR_ALREADYLOCKED, "Unexpected hr %#x.\n", hr);
7728 IWICBitmapLock_Release(wic_lock);
7730 ID2D1GdiInteropRenderTarget_Release(interop);
7731 ID2D1RenderTarget_Release(rt);
7733 IWICBitmap_Release(wic_bitmap);
7734 ID2D1Factory_Release(factory);
7737 static void test_layer(void)
7739 ID2D1Factory *factory, *layer_factory;
7740 IDXGISwapChain *swapchain;
7741 ID2D1RenderTarget *rt;
7742 ID3D10Device1 *device;
7743 IDXGISurface *surface;
7744 ID2D1Layer *layer;
7745 D2D1_SIZE_F size;
7746 ULONG refcount;
7747 HWND window;
7748 HRESULT hr;
7750 if (!(device = create_device()))
7752 skip("Failed to create device, skipping tests.\n");
7753 return;
7755 window = create_window();
7756 swapchain = create_swapchain(device, window, TRUE);
7757 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
7758 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
7759 rt = create_render_target(surface);
7760 ok(!!rt, "Failed to create render target.\n");
7761 ID2D1RenderTarget_GetFactory(rt, &factory);
7763 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
7764 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
7766 hr = ID2D1RenderTarget_CreateLayer(rt, NULL, &layer);
7767 ok(SUCCEEDED(hr), "Failed to create layer, hr %#x.\n", hr);
7768 ID2D1Layer_GetFactory(layer, &layer_factory);
7769 ok(layer_factory == factory, "Got unexpected layer factory %p, expected %p.\n", layer_factory, factory);
7770 ID2D1Factory_Release(layer_factory);
7771 size = ID2D1Layer_GetSize(layer);
7772 ok(size.width == 0.0f, "Got unexpected width %.8e.\n", size.width);
7773 ok(size.height == 0.0f, "Got unexpected height %.8e.\n", size.height);
7774 ID2D1Layer_Release(layer);
7776 set_size_f(&size, 800.0f, 600.0f);
7777 hr = ID2D1RenderTarget_CreateLayer(rt, &size, &layer);
7778 ok(SUCCEEDED(hr), "Failed to create layer, hr %#x.\n", hr);
7779 size = ID2D1Layer_GetSize(layer);
7780 ok(size.width == 800.0f, "Got unexpected width %.8e.\n", size.width);
7781 ok(size.height == 600.0f, "Got unexpected height %.8e.\n", size.height);
7782 ID2D1Layer_Release(layer);
7784 ID2D1RenderTarget_Release(rt);
7785 refcount = ID2D1Factory_Release(factory);
7786 ok(!refcount, "Factory has %u references left.\n", refcount);
7787 IDXGISurface_Release(surface);
7788 IDXGISwapChain_Release(swapchain);
7789 ID3D10Device1_Release(device);
7790 DestroyWindow(window);
7793 static void test_bezier_intersect(void)
7795 D2D1_POINT_2F point = {0.0f, 0.0f};
7796 ID2D1SolidColorBrush *brush;
7797 ID2D1PathGeometry *geometry;
7798 IDXGISwapChain *swapchain;
7799 ID2D1GeometrySink *sink;
7800 ID2D1RenderTarget *rt;
7801 ID3D10Device1 *device;
7802 IDXGISurface *surface;
7803 ID2D1Factory *factory;
7804 D2D1_COLOR_F color;
7805 ULONG refcount;
7806 HWND window;
7807 HRESULT hr;
7808 BOOL match;
7810 if (!(device = create_device()))
7812 skip("Failed to create device, skipping tests.\n");
7813 return;
7815 window = create_window();
7816 swapchain = create_swapchain(device, window, TRUE);
7817 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
7818 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
7819 rt = create_render_target(surface);
7820 ok(!!rt, "Failed to create render target.\n");
7821 ID2D1RenderTarget_GetFactory(rt, &factory);
7823 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
7824 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
7825 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
7826 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
7827 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
7829 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7830 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
7831 hr = ID2D1PathGeometry_Open(geometry, &sink);
7832 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
7834 set_point(&point, 160.0f, 720.0f);
7835 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7836 cubic_to(sink, 119.0f, 720.0f, 83.0f, 600.0f, 80.0f, 474.0f);
7837 cubic_to(sink, 78.0f, 349.0f, 108.0f, 245.0f, 135.0f, 240.0f);
7838 cubic_to(sink, 163.0f, 235.0f, 180.0f, 318.0f, 176.0f, 370.0f);
7839 cubic_to(sink, 171.0f, 422.0f, 149.0f, 422.0f, 144.0f, 370.0f);
7840 cubic_to(sink, 140.0f, 318.0f, 157.0f, 235.0f, 185.0f, 240.0f);
7841 cubic_to(sink, 212.0f, 245.0f, 242.0f, 349.0f, 240.0f, 474.0f);
7842 cubic_to(sink, 238.0f, 600.0f, 201.0f, 720.0f, 160.0f, 720.0f);
7843 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7845 set_point(&point, 160.0f, 240.0f);
7846 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7847 line_to(sink, 240.0f, 240.0f);
7848 line_to(sink, 240.0f, 720.0f);
7849 line_to(sink, 160.0f, 720.0f);
7850 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7852 hr = ID2D1GeometrySink_Close(sink);
7853 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
7854 ID2D1GeometrySink_Release(sink);
7856 ID2D1RenderTarget_BeginDraw(rt);
7857 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
7858 ID2D1RenderTarget_Clear(rt, &color);
7859 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
7860 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7861 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
7862 ID2D1PathGeometry_Release(geometry);
7864 match = compare_figure(surface, 160, 120, 320, 240, 0xff652e89, 2048,
7865 "aRQjIxRpYiIcHCJiXSwXFyxdWTQTEzRZVTsQEDtVUkIMDEJST0cKCkdPTUsICEtNSlEFBVFKSFUD"
7866 "A1VIRlkBAVlGRFsBAVtEQlwCAlxCQFwEBFxAPl0FBV0+PF0HB108Ol4ICF46OV0KCl05N14LC143"
7867 "Nl4MDF42NF8NDV80M14PD14zMV8QEF8xMF8REV8wL18SEl8vLWATE2AtLGAUFGAsK2EUFGErKWIV"
7868 "FWIpKGIWFmIoJ2IXF2InJmIYGGImJWMYGGMlJGMZGWMkI2MaGmMjImQaGmQiIWQbG2QhIGQcHGQg"
7869 "H2UcHGUfHmUdHWUeHWYdHWYdHGcdHWccG2ceHmcbGmgeHmgaGWgfH2gZGWgfH2gZGGkfH2kYF2kg"
7870 "IGkXFmogIGoWFmogIGoWFWsgIGsVFGshIWsUE2whIWwTE2whIWwTEm0hIW0SEW4hIW4REW4hIW4R"
7871 "EG8hIW8QD3AhIXAPD3AhIXAPDnEhIXEODnEhIXEODXIhIXINDHQgIHQMDHQgIHQMC3UgIHULC3Yf"
7872 "H3YLCncfH3cKCngeHngKCXkeHnkJCXodHXoJCXscHHsJCHwcHHwICH0bG30IB38aGn8HB4ABGRmA"
7873 "AQcHgQEYGIEBBwaEARYWhAEGBoUBFRWFAQYFiAETE4gBBQWKARERigEFBYwBDw+MAQUEkAEMDJAB"
7874 "BASTAQkJkwEEBJwBnAEEA50BnQEDA50BnQEDA50BnQEDA50BnQEDAp4BngECAp4BngECAp4BngEC"
7875 "Ap4BngECAp4BngECAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwGhAaAB"
7876 "oAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGg"
7877 "AaABoAGgAaABoAGgAaABoAGhAZ8BoQGfAZ8BAQGfAZ8BAQGfAZ8BAQGfAZ8BAQGfAZ8BAQKeAZ8B"
7878 "AQKeAZ4BAgKeAZ4BAgKeAZ4BAgOdAZ4BAgOdAZ4BAgOdAZ0BAwScAZ0BAwScAZ0BAwScAZ0BAwSc"
7879 "AZwBBAWbAZwBBAWbAZwBBAWbAZsBBQaaAZsBBQaaAZoBBgeZAZoBBgeZAZoBBgeZAZkBBwiYAZkB"
7880 "BwiYAZgBCAmXAZgBCAmXAZgBCAmXAZcBCQqWAZcBCQqWAZYBCguVAZYBCguVAZUBCwyUAZUBCw2T"
7881 "AZQBDA2TAZQBDA6SAZMBDQ6SAZMBDQ+RAZIBDg+RAZIBDhCQAZEBDxCQAZABEBGPAZABEBKOAY8B"
7882 "ERONAY4BEhONAY4BEhSMAY0BExWLAYwBFBWLAYwBFBaKAYsBFReJAYoBFheJAYoBFhiIAYkBFxmH"
7883 "AYgBGBqGAYcBGRuFAYYBGhuFAYUBGxyEAYUBGx2DAYQBHB6CAYMBHR+BAYIBHiCAAYEBHyF/gAEg"
7884 "In5/ISJ+fiIjfX0jJHx8JCV7eyUmenomJ3l5Jyh4eCgpd3cpK3V2Kix0dSstc3QsLnJzLS9xci4w"
7885 "cHAwMm5vMTNtbjI0bG0zNWtrNTdpajY4aGk3OmZnOTtlZjo8ZGQ8PmJjPT9hYj5BX2BAQl5eQkRc"
7886 "XUNGWltFR1lZR0lXWEhLVVZKTVNUTE9RUk5RT1BQUk5OUlRMTFRWSkpWWUdIWFtFRVteQkNdYEBA"
7887 "YGI+PmJlOztlaDg4aGs1NWtuMjJuci4vcXUrK3V6JiZ6fiIifoMBHR2DAYsBFRWLAZUBCwuVAQAA");
7888 ok(match, "Figure does not match.\n");
7890 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
7891 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
7892 hr = ID2D1PathGeometry_Open(geometry, &sink);
7893 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
7895 set_point(&point, 240.0f, 720.0f);
7896 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
7897 cubic_to(sink, 152.0f, 720.0f, 80.0f, 613.0f, 80.0f, 480.0f);
7898 cubic_to(sink, 80.0f, 347.0f, 152.0f, 240.0f, 240.0f, 240.0f);
7899 cubic_to(sink, 152.0f, 339.0f, 134.0f, 528.0f, 200.0f, 660.0f);
7900 cubic_to(sink, 212.0f, 683.0f, 225.0f, 703.0f, 240.0f, 720.0f);
7901 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
7903 hr = ID2D1GeometrySink_Close(sink);
7904 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
7905 ID2D1GeometrySink_Release(sink);
7907 ID2D1RenderTarget_BeginDraw(rt);
7908 ID2D1RenderTarget_Clear(rt, &color);
7909 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
7910 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
7911 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
7912 ID2D1PathGeometry_Release(geometry);
7914 match = compare_figure(surface, 160, 120, 320, 240, 0xff652e89, 2048,
7915 "pQIZkgIrhAI5/QE/9gFH7wFO6wFS5wFW4gFb3gFf2wFi2AFl1gFn1AFp0gFszwFuzQFxywFyyQF1"
7916 "xwF2xgF4xAF5xAF6wgF8wAF+vwF+vwF/vQGBAbwBggG7AYMBugGEAbkBhQG4AYYBtwGHAbcBiAG1"
7917 "AYkBtAGKAbQBigGzAYsBswGMAbEBjQGxAY0BsQGOAa8BjwGvAZABrgGQAa4BkQGtAZEBrQGSAawB"
7918 "kgGsAZMBqwGTAasBlAGrAZQBqgGVAakBlQGqAZUBqQGWAagBlwGoAZYBqAGXAagBlwGnAZgBpwGY"
7919 "AaYBmQGmAZkBpgGZAaUBmgGlAZoBpQGaAaUBmgGkAZsBpAGbAaQBmwGkAZsBpAGcAaMBnAGjAZwB"
7920 "owGcAaMBnAGjAZ0BogGdAaIBnQGiAZ4BoQGeAaEBngGiAZ4BoQGeAaEBnwGgAZ8BoQGeAaEBnwGh"
7921 "AZ4BoQGfAaABnwGhAZ8BoAGgAaABnwGgAaABoAGfAaABoAGgAaABnwGgAaABoAGgAaABnwGgAaAB"
7922 "oAGgAaABnwGhAZ8BoQGfAaABoAGgAaABoAGfAaEBnwGhAZ8BoQGfAaEBnwGhAZ8BoQGfAaABoAGg"
7923 "AaABoAGgAaEBnwGhAZ8BoQGfAaEBnwGhAaABoAGgAaABoAGgAaABoAGgAaEBoAGgAaABoAGgAaAB"
7924 "oQGgAaABoAGgAaABoQGfAaEBoAGhAZ8BoQGfAaIBnwGhAZ8BogGfAaEBnwGiAZ8BogGeAaIBnwGi"
7925 "AZ4BogGfAaIBngGjAZ4BowGdAaMBngGjAZ4BowGdAaQBnQGkAZ0BpAGcAaUBnAGlAZwBpQGcAaUB"
7926 "mwGmAZsBpgGbAaYBmwGmAZsBpgGbAacBmgGnAZkBqAGZAagBmQGpAZgBqQGZAagBmQGpAZgBqQGY"
7927 "AaoBlwGqAZcBqwGWAasBlgGsAZUBrQGVAawBlQGtAZQBrgGUAa0BlAGuAZMBrwGTAa8BkgGwAZEB"
7928 "sQGRAbEBkAGyAZABsgGPAbMBjwG0AY4BtAGNAbUBjQG2AYwBtgGLAbgBigG4AYoBuQGJAboBhwG7"
7929 "AYcBvAGGAb0BhQG+AYQBvwGDAcABggHBAYIBwgGAAcMBf8QBfsYBfMgBe8gBesoBeMwBd80BddAB"
7930 "c9EBcdQBb9YBbNkBatsBaN0BZeEBYuQBX+gBW+0BVvEBUvUBTvwBR4QCQIoCOZgCK6oCGQIA");
7931 ok(match, "Figure does not match.\n");
7933 ID2D1SolidColorBrush_Release(brush);
7934 ID2D1RenderTarget_Release(rt);
7935 refcount = ID2D1Factory_Release(factory);
7936 ok(!refcount, "Factory has %u references left.\n", refcount);
7937 IDXGISurface_Release(surface);
7938 IDXGISwapChain_Release(swapchain);
7939 ID3D10Device1_Release(device);
7940 DestroyWindow(window);
7943 static void test_create_device(void)
7945 D2D1_CREATION_PROPERTIES properties = {0};
7946 ID3D10Device1 *d3d_device;
7947 IDXGIDevice *dxgi_device;
7948 ID2D1Factory1 *factory;
7949 ID2D1Factory *factory2;
7950 ID2D1Device *device;
7951 ULONG refcount;
7952 HRESULT hr;
7954 if (!(d3d_device = create_device()))
7956 skip("Failed to create device, skipping tests.\n");
7957 return;
7960 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
7962 win_skip("ID2D1Factory1 is not supported.\n");
7963 ID3D10Device1_Release(d3d_device);
7964 return;
7967 hr = ID3D10Device1_QueryInterface(d3d_device, &IID_IDXGIDevice, (void **)&dxgi_device);
7968 ok(SUCCEEDED(hr), "Failed to get IDXGIDevice interface, hr %#x.\n", hr);
7970 hr = ID2D1Factory1_CreateDevice(factory, dxgi_device, &device);
7971 ok(SUCCEEDED(hr), "Failed to get ID2D1Device, hr %#x.\n", hr);
7973 ID2D1Device_GetFactory(device, &factory2);
7974 ok(factory2 == (ID2D1Factory *)factory, "Got unexpected factory %p, expected %p.\n", factory2, factory);
7975 ID2D1Factory_Release(factory2);
7976 ID2D1Device_Release(device);
7978 if (pD2D1CreateDevice)
7980 hr = pD2D1CreateDevice(dxgi_device, NULL, &device);
7981 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
7982 ID2D1Device_Release(device);
7984 hr = pD2D1CreateDevice(dxgi_device, &properties, &device);
7985 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
7986 ID2D1Device_Release(device);
7988 else
7989 win_skip("D2D1CreateDevice() is unavailable.\n");
7991 IDXGIDevice_Release(dxgi_device);
7992 ID3D10Device1_Release(d3d_device);
7994 refcount = ID2D1Factory1_Release(factory);
7995 ok(!refcount, "Factory has %u references left.\n", refcount);
7998 #define check_rt_bitmap_surface(r, s, o) check_rt_bitmap_surface_(__LINE__, r, s, o)
7999 static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, BOOL has_surface, DWORD options)
8001 ID2D1BitmapRenderTarget *compatible_rt;
8002 D2D1_BITMAP_PROPERTIES bitmap_desc;
8003 IWICImagingFactory *wic_factory;
8004 ID2D1Bitmap *bitmap, *bitmap2;
8005 ID2D1DeviceContext *context;
8006 ID2D1DCRenderTarget *dc_rt;
8007 IWICBitmap *wic_bitmap;
8008 ID2D1Image *target;
8009 D2D1_SIZE_U size;
8010 HRESULT hr;
8012 static const DWORD bitmap_data[] =
8014 0x7f7f0000,
8017 /* Raw data bitmap. */
8018 set_size_u(&size, 1, 1);
8019 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
8020 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
8021 bitmap_desc.dpiX = 96.0f;
8022 bitmap_desc.dpiY = 96.0f;
8023 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, sizeof(*bitmap_data), &bitmap_desc, &bitmap);
8024 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
8026 check_bitmap_surface_(line, bitmap, has_surface, options);
8028 ID2D1Bitmap_Release(bitmap);
8030 /* Zero sized bitmaps. */
8031 set_size_u(&size, 0, 0);
8032 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
8033 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
8034 check_bitmap_surface_(line, bitmap, has_surface, options);
8035 ID2D1Bitmap_Release(bitmap);
8037 set_size_u(&size, 2, 0);
8038 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
8039 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
8040 check_bitmap_surface_(line, bitmap, has_surface, options);
8041 ID2D1Bitmap_Release(bitmap);
8043 set_size_u(&size, 0, 2);
8044 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
8045 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
8046 check_bitmap_surface_(line, bitmap, has_surface, options);
8047 ID2D1Bitmap_Release(bitmap);
8049 /* WIC bitmap. */
8050 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
8052 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
8053 &IID_IWICImagingFactory, (void **)&wic_factory);
8054 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
8056 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
8057 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
8058 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create WIC bitmap, hr %#x.\n", hr);
8059 IWICImagingFactory_Release(wic_factory);
8061 hr = ID2D1RenderTarget_CreateBitmapFromWicBitmap(rt, (IWICBitmapSource *)wic_bitmap, NULL, &bitmap);
8062 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create bitmap from WIC source, hr %#x.\n", hr);
8064 check_bitmap_surface_(line, bitmap, has_surface, options);
8066 ID2D1Bitmap_Release(bitmap);
8068 CoUninitialize();
8070 /* Compatible target follows its parent. */
8071 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&context);
8072 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get device context, hr %#x.\n", hr);
8074 dc_rt = NULL;
8075 ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DCRenderTarget, (void **)&dc_rt);
8077 bitmap = NULL;
8078 target = NULL;
8079 ID2D1DeviceContext_GetTarget(context, &target);
8080 if (target && FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
8082 ID2D1Image_Release(target);
8083 target = NULL;
8085 if (bitmap)
8087 D2D1_PIXEL_FORMAT rt_format, bitmap_format;
8089 rt_format = ID2D1RenderTarget_GetPixelFormat(rt);
8090 bitmap_format = ID2D1Bitmap_GetPixelFormat(bitmap);
8091 ok_(__FILE__, line)(!memcmp(&rt_format, &bitmap_format, sizeof(rt_format)), "Unexpected bitmap format.\n");
8093 ID2D1Bitmap_Release(bitmap);
8096 /* Pixel format is not defined until target is set, for DC target it's specified on creation. */
8097 if (target || dc_rt)
8099 ID2D1Device *device, *device2;
8100 ID2D1DeviceContext *context2;
8102 ID2D1DeviceContext_GetDevice(context, &device);
8104 hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, NULL, NULL, NULL,
8105 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &compatible_rt);
8106 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create compatible render target, hr %#x.\n", hr);
8108 hr = ID2D1BitmapRenderTarget_QueryInterface(compatible_rt, &IID_ID2D1DeviceContext, (void **)&context2);
8109 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get device context, hr %#x.\n", hr);
8111 ID2D1DeviceContext_GetDevice(context2, &device2);
8112 ok_(__FILE__, line)(device == device2, "Unexpected device.\n");
8114 ID2D1Device_Release(device);
8115 ID2D1Device_Release(device2);
8117 hr = ID2D1BitmapRenderTarget_CreateBitmap(compatible_rt, size,
8118 bitmap_data, sizeof(*bitmap_data), &bitmap_desc, &bitmap);
8119 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
8120 check_bitmap_surface_(line, bitmap, has_surface, options);
8121 ID2D1Bitmap_Release(bitmap);
8123 hr = ID2D1BitmapRenderTarget_GetBitmap(compatible_rt, &bitmap);
8124 ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get compatible target bitmap, hr %#x.\n", hr);
8126 bitmap2 = NULL;
8127 ID2D1DeviceContext_GetTarget(context2, (ID2D1Image **)&bitmap2);
8128 ok_(__FILE__, line)(bitmap2 == bitmap, "Unexpected bitmap.\n");
8130 check_bitmap_surface_(line, bitmap, has_surface, D2D1_BITMAP_OPTIONS_TARGET);
8131 ID2D1Bitmap_Release(bitmap2);
8132 ID2D1Bitmap_Release(bitmap);
8134 ID2D1BitmapRenderTarget_Release(compatible_rt);
8135 ID2D1DeviceContext_Release(context2);
8137 else
8139 hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, NULL, NULL, NULL,
8140 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &compatible_rt);
8141 ok_(__FILE__, line)(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT, "Unexpected hr %#x.\n", hr);
8144 ID2D1DeviceContext_Release(context);
8145 if (target)
8146 ID2D1Image_Release(target);
8147 if (dc_rt)
8148 ID2D1DCRenderTarget_Release(dc_rt);
8151 static IDXGISurface *create_surface(IDXGIDevice *dxgi_device, DXGI_FORMAT format)
8153 D3D10_TEXTURE2D_DESC texture_desc;
8154 ID3D10Texture2D *texture;
8155 ID3D10Device *d3d_device;
8156 IDXGISurface *surface;
8157 HRESULT hr;
8159 texture_desc.Width = 1;
8160 texture_desc.Height = 1;
8161 texture_desc.MipLevels = 1;
8162 texture_desc.ArraySize = 1;
8163 texture_desc.Format = format;
8164 texture_desc.SampleDesc.Count = 1;
8165 texture_desc.SampleDesc.Quality = 0;
8166 texture_desc.Usage = D3D10_USAGE_DEFAULT;
8167 texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
8168 texture_desc.CPUAccessFlags = 0;
8169 texture_desc.MiscFlags = 0;
8171 hr = IDXGIDevice_QueryInterface(dxgi_device, &IID_ID3D10Device, (void **)&d3d_device);
8172 ok(SUCCEEDED(hr), "Failed to get device interface, hr %#x.\n", hr);
8174 hr = ID3D10Device_CreateTexture2D(d3d_device, &texture_desc, NULL, &texture);
8175 ok(SUCCEEDED(hr), "Failed to create a texture, hr %#x.\n", hr);
8177 hr = ID3D10Texture2D_QueryInterface(texture, &IID_IDXGISurface, (void **)&surface);
8178 ok(SUCCEEDED(hr), "Failed to get surface interface, hr %#x.\n", hr);
8180 ID3D10Device_Release(d3d_device);
8181 ID3D10Texture2D_Release(texture);
8183 return surface;
8186 static void test_bitmap_surface(void)
8188 static const struct bitmap_format_test
8190 D2D1_PIXEL_FORMAT original;
8191 D2D1_PIXEL_FORMAT result;
8192 HRESULT hr;
8194 bitmap_format_tests[] =
8196 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
8197 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED } },
8199 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
8201 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE },
8202 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
8204 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
8206 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
8208 { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE },
8209 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
8211 { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
8213 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
8214 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
8215 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
8216 ID2D1DeviceContext *device_context;
8217 IDXGISurface *surface, *surface2;
8218 D2D1_PIXEL_FORMAT pixel_format;
8219 ID3D10Device1 *d3d_device;
8220 IDXGISwapChain *swapchain;
8221 IDXGIDevice *dxgi_device;
8222 ID2D1Factory1 *factory;
8223 ID2D1RenderTarget *rt;
8224 ID2D1Bitmap1 *bitmap;
8225 ID2D1Device *device;
8226 ID2D1Image *target;
8227 D2D1_SIZE_U size;
8228 D2D1_TAG t1, t2;
8229 unsigned int i;
8230 HWND window;
8231 HRESULT hr;
8233 IWICBitmap *wic_bitmap;
8234 IWICImagingFactory *wic_factory;
8236 if (!(d3d_device = create_device()))
8238 skip("Failed to create device, skipping tests.\n");
8239 return;
8242 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
8244 win_skip("ID2D1Factory1 is not supported.\n");
8245 ID3D10Device1_Release(d3d_device);
8246 return;
8249 /* DXGI target */
8250 window = create_window();
8251 swapchain = create_swapchain(d3d_device, window, TRUE);
8252 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
8253 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
8254 rt = create_render_target(surface);
8255 ok(!!rt, "Failed to create render target.\n");
8257 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8258 ok(SUCCEEDED(hr), "Failed to get device context, hr %#x.\n", hr);
8260 bitmap = NULL;
8261 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8262 ok(!!bitmap, "Unexpected target.\n");
8263 check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW);
8264 ID2D1Bitmap1_Release(bitmap);
8266 check_rt_bitmap_surface(rt, TRUE, D2D1_BITMAP_OPTIONS_NONE);
8268 ID2D1DeviceContext_Release(device_context);
8270 ID2D1RenderTarget_Release(rt);
8272 /* Bitmap created from DXGI surface. */
8273 hr = ID3D10Device1_QueryInterface(d3d_device, &IID_IDXGIDevice, (void **)&dxgi_device);
8274 ok(SUCCEEDED(hr), "Failed to get IDXGIDevice interface, hr %#x.\n", hr);
8276 hr = ID2D1Factory1_CreateDevice(factory, dxgi_device, &device);
8277 ok(SUCCEEDED(hr), "Failed to get ID2D1Device, hr %#x.\n", hr);
8279 hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &device_context);
8280 ok(SUCCEEDED(hr), "Failed to create device context, hr %#x.\n", hr);
8282 for (i = 0; i < ARRAY_SIZE(bitmap_format_tests); ++i)
8284 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
8285 bitmap_desc.pixelFormat = bitmap_format_tests[i].original;
8286 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
8288 hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, surface, &bitmap_desc, &bitmap);
8289 todo_wine_if(bitmap_format_tests[i].hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT)
8290 ok(hr == bitmap_format_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
8292 if (SUCCEEDED(bitmap_format_tests[i].hr))
8294 pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap);
8296 ok(pixel_format.format == bitmap_format_tests[i].result.format, "%u: unexpected pixel format %#x.\n",
8297 i, pixel_format.format);
8298 ok(pixel_format.alphaMode == bitmap_format_tests[i].result.alphaMode, "%u: unexpected alpha mode %d.\n",
8299 i, pixel_format.alphaMode);
8301 ID2D1Bitmap1_Release(bitmap);
8305 /* A8 surface */
8306 hr = IDXGISurface_GetDevice(surface, &IID_IDXGIDevice, (void **)&dxgi_device);
8307 ok(SUCCEEDED(hr), "Failed to get the device, hr %#x.\n", hr);
8309 surface2 = create_surface(dxgi_device, DXGI_FORMAT_A8_UNORM);
8311 hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, surface2, NULL, &bitmap);
8312 ok(SUCCEEDED(hr) || broken(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT) /* Win7 */,
8313 "Failed to create a bitmap, hr %#x.\n", hr);
8315 if (SUCCEEDED(hr))
8317 pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap);
8318 ok(pixel_format.alphaMode == D2D1_ALPHA_MODE_PREMULTIPLIED,
8319 "Unexpected alpha mode %#x.\n", pixel_format.alphaMode);
8321 ID2D1Bitmap1_Release(bitmap);
8324 IDXGIDevice_Release(dxgi_device);
8325 IDXGISurface_Release(surface2);
8327 hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, surface, NULL, &bitmap);
8328 ok(SUCCEEDED(hr), "Failed to create a bitmap, hr %#x.\n", hr);
8330 pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap);
8331 ok(pixel_format.alphaMode == D2D1_ALPHA_MODE_PREMULTIPLIED,
8332 "Unexpected alpha mode %#x.\n", pixel_format.alphaMode);
8334 check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW);
8335 check_rt_bitmap_surface((ID2D1RenderTarget *)device_context, TRUE, D2D1_BITMAP_OPTIONS_NONE);
8337 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
8338 ID2D1DeviceContext_GetTarget(device_context, &target);
8339 ok(target == (ID2D1Image *)bitmap, "Unexpected target.\n");
8341 check_rt_bitmap_surface((ID2D1RenderTarget *)device_context, TRUE, D2D1_BITMAP_OPTIONS_NONE);
8343 ID2D1Bitmap1_Release(bitmap);
8345 /* Without D2D1_BITMAP_OPTIONS_TARGET. */
8346 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
8347 bitmap_desc.pixelFormat = ID2D1DeviceContext_GetPixelFormat(device_context);
8348 size.width = size.height = 4;
8349 hr = ID2D1DeviceContext_CreateBitmap(device_context, size, NULL, 0, &bitmap_desc, &bitmap);
8350 ok(SUCCEEDED(hr), "Failed to create a bitmap, hr %#x.\n", hr);
8351 check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_NONE);
8352 ID2D1DeviceContext_SetTags(device_context, 1, 2);
8354 ID2D1DeviceContext_BeginDraw(device_context);
8355 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
8356 hr = ID2D1DeviceContext_EndDraw(device_context, &t1, &t2);
8357 ok(hr == D2DERR_INVALID_TARGET, "Unexpected hr %#x.\n", hr);
8358 ok(t1 == 1 && t2 == 2, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
8360 ID2D1Bitmap1_Release(bitmap);
8362 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8363 ok(!!bitmap, "Expected target bitmap.\n");
8364 ID2D1Bitmap1_Release(bitmap);
8366 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET;
8367 hr = ID2D1DeviceContext_CreateBitmap(device_context, size, NULL, 0, &bitmap_desc, &bitmap);
8368 ok(SUCCEEDED(hr), "Failed to create a bitmap, hr %#x.\n", hr);
8369 check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET);
8370 ID2D1DeviceContext_SetTarget(device_context, NULL);
8371 ID2D1DeviceContext_SetTags(device_context, 3, 4);
8373 ID2D1DeviceContext_BeginDraw(device_context);
8374 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
8375 hr = ID2D1DeviceContext_EndDraw(device_context, &t1, &t2);
8376 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
8377 ok(!t1 && !t2, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
8379 ID2D1Bitmap1_Release(bitmap);
8381 ID2D1DeviceContext_Release(device_context);
8383 ID2D1Device_Release(device);
8384 IDXGIDevice_Release(dxgi_device);
8385 IDXGISurface_Release(surface);
8387 /* DC target */
8388 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
8389 rt_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
8390 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
8391 rt_desc.dpiX = 96.0f;
8392 rt_desc.dpiY = 96.0f;
8393 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
8394 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
8395 hr = ID2D1Factory1_CreateDCRenderTarget(factory, &rt_desc, (ID2D1DCRenderTarget **)&rt);
8396 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
8398 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8399 ok(SUCCEEDED(hr), "Failed to get device context, hr %#x.\n", hr);
8401 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8402 ok(!bitmap, "Unexpected target.\n");
8404 ID2D1DeviceContext_Release(device_context);
8405 ID2D1RenderTarget_Release(rt);
8407 /* HWND target */
8408 hwnd_rt_desc.hwnd = NULL;
8409 hwnd_rt_desc.pixelSize.width = 64;
8410 hwnd_rt_desc.pixelSize.height = 64;
8411 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
8412 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
8413 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
8415 hr = ID2D1Factory1_CreateHwndRenderTarget(factory, &rt_desc, &hwnd_rt_desc, (ID2D1HwndRenderTarget **)&rt);
8416 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8418 check_rt_bitmap_surface(rt, FALSE, D2D1_BITMAP_OPTIONS_NONE);
8419 ID2D1RenderTarget_Release(rt);
8420 DestroyWindow(hwnd_rt_desc.hwnd);
8422 /* WIC target */
8423 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
8425 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
8426 &IID_IWICImagingFactory, (void **)&wic_factory);
8427 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
8428 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
8429 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
8430 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
8431 IWICImagingFactory_Release(wic_factory);
8433 hr = ID2D1Factory1_CreateWicBitmapRenderTarget(factory, wic_bitmap, &rt_desc, &rt);
8434 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8436 check_rt_bitmap_surface(rt, FALSE, D2D1_BITMAP_OPTIONS_NONE);
8437 ID2D1RenderTarget_Release(rt);
8439 CoUninitialize();
8441 ID2D1Factory1_Release(factory);
8442 ID3D10Device1_Release(d3d_device);
8445 static void test_device_context(void)
8447 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
8448 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
8449 ID2D1DeviceContext *device_context;
8450 IDXGISurface *surface, *surface2;
8451 ID2D1Device *device, *device2;
8452 D2D1_BITMAP_OPTIONS options;
8453 ID2D1DCRenderTarget *dc_rt;
8454 ID3D10Device1 *d3d_device;
8455 IDXGISwapChain *swapchain;
8456 IDXGIDevice *dxgi_device;
8457 D2D1_UNIT_MODE unit_mode;
8458 ID2D1Factory1 *factory;
8459 ID2D1RenderTarget *rt;
8460 ID2D1Bitmap1 *bitmap;
8461 ID2D1Image *target;
8462 HWND window;
8463 HRESULT hr;
8464 RECT rect;
8465 HDC hdc;
8467 IWICBitmap *wic_bitmap;
8468 IWICImagingFactory *wic_factory;
8470 if (!(d3d_device = create_device()))
8472 skip("Failed to create device, skipping tests.\n");
8473 return;
8476 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
8478 win_skip("ID2D1Factory1 is not supported.\n");
8479 ID3D10Device1_Release(d3d_device);
8480 return;
8483 hr = ID3D10Device1_QueryInterface(d3d_device, &IID_IDXGIDevice, (void **)&dxgi_device);
8484 ok(SUCCEEDED(hr), "Failed to get IDXGIDevice interface, hr %#x.\n", hr);
8486 hr = ID2D1Factory1_CreateDevice(factory, dxgi_device, &device);
8487 ok(SUCCEEDED(hr), "Failed to get ID2D1Device, hr %#x.\n", hr);
8488 IDXGIDevice_Release(dxgi_device);
8490 hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &device_context);
8491 ok(SUCCEEDED(hr), "Failed to create device context, hr %#x.\n", hr);
8493 ID2D1DeviceContext_GetDevice(device_context, &device2);
8494 ok(device2 == device, "Unexpected device instance.\n");
8495 ID2D1Device_Release(device2);
8497 target = (void *)0xdeadbeef;
8498 ID2D1DeviceContext_GetTarget(device_context, &target);
8499 ok(target == NULL, "Unexpected target instance %p.\n", target);
8501 unit_mode = ID2D1DeviceContext_GetUnitMode(device_context);
8502 ok(unit_mode == D2D1_UNIT_MODE_DIPS, "Unexpected unit mode %d.\n", unit_mode);
8504 ID2D1DeviceContext_Release(device_context);
8506 /* DXGI target */
8507 window = create_window();
8508 swapchain = create_swapchain(d3d_device, window, TRUE);
8509 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
8510 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
8511 rt = create_render_target(surface);
8512 ok(!!rt, "Failed to create render target.\n");
8514 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8515 ok(SUCCEEDED(hr), "Failed to get device context interface, hr %#x.\n", hr);
8516 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8517 options = ID2D1Bitmap1_GetOptions(bitmap);
8518 ok(options == (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW),
8519 "Unexpected bitmap options %#x.\n", options);
8520 hr = ID2D1Bitmap1_GetSurface(bitmap, &surface2);
8521 ok(SUCCEEDED(hr), "Failed to get bitmap surface, hr %#x.\n", hr);
8522 ok(surface2 == surface, "Unexpected surface instance.\n");
8523 IDXGISurface_Release(surface2);
8525 ID2D1DeviceContext_BeginDraw(device_context);
8526 hr = ID2D1Bitmap1_GetSurface(bitmap, &surface2);
8527 ok(SUCCEEDED(hr), "Failed to get bitmap surface, hr %#x.\n", hr);
8528 ok(surface2 == surface, "Unexpected surface instance.\n");
8529 IDXGISurface_Release(surface2);
8530 ID2D1DeviceContext_EndDraw(device_context, NULL, NULL);
8531 ID2D1Bitmap1_Release(bitmap);
8533 ID2D1DeviceContext_SetTarget(device_context, NULL);
8534 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8535 ok(bitmap == NULL, "Unexpected target instance.\n");
8537 ID2D1DeviceContext_Release(device_context);
8538 ID2D1RenderTarget_Release(rt);
8539 IDXGISurface_Release(surface);
8540 DestroyWindow(window);
8542 /* WIC target */
8543 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
8545 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
8546 &IID_IWICImagingFactory, (void **)&wic_factory);
8547 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
8548 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
8549 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
8550 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
8551 IWICImagingFactory_Release(wic_factory);
8553 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
8554 rt_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
8555 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
8556 rt_desc.dpiX = 96.0f;
8557 rt_desc.dpiY = 96.0f;
8558 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
8559 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
8560 hr = ID2D1Factory1_CreateWicBitmapRenderTarget(factory, wic_bitmap, &rt_desc, &rt);
8561 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8563 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8564 ok(SUCCEEDED(hr), "Failed to get device context interface, hr %#x.\n", hr);
8565 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8566 options = ID2D1Bitmap1_GetOptions(bitmap);
8567 ok(options == (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW),
8568 "Unexpected bitmap options %#x.\n", options);
8569 hr = ID2D1Bitmap1_GetSurface(bitmap, &surface);
8570 todo_wine
8571 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
8572 ID2D1Bitmap1_Release(bitmap);
8574 ID2D1DeviceContext_SetTarget(device_context, NULL);
8575 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8576 ok(bitmap == NULL, "Unexpected target instance.\n");
8578 ID2D1DeviceContext_Release(device_context);
8579 ID2D1RenderTarget_Release(rt);
8581 CoUninitialize();
8583 /* HWND target */
8584 hwnd_rt_desc.hwnd = NULL;
8585 hwnd_rt_desc.pixelSize.width = 64;
8586 hwnd_rt_desc.pixelSize.height = 64;
8587 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
8588 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
8589 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
8591 hr = ID2D1Factory1_CreateHwndRenderTarget(factory, &rt_desc, &hwnd_rt_desc, (ID2D1HwndRenderTarget **)&rt);
8592 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8594 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8595 ok(SUCCEEDED(hr), "Failed to get device context interface, hr %#x.\n", hr);
8596 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8597 options = ID2D1Bitmap1_GetOptions(bitmap);
8598 ok(options == (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW),
8599 "Unexpected bitmap options %#x.\n", options);
8600 hr = ID2D1Bitmap1_GetSurface(bitmap, &surface);
8601 ok(hr == D2DERR_INVALID_CALL, "Unexpected hr %#x.\n", hr);
8602 ID2D1Bitmap1_Release(bitmap);
8604 ID2D1DeviceContext_SetTarget(device_context, NULL);
8605 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8606 ok(bitmap == NULL, "Unexpected target instance.\n");
8608 ID2D1DeviceContext_Release(device_context);
8609 ID2D1RenderTarget_Release(rt);
8610 DestroyWindow(hwnd_rt_desc.hwnd);
8612 /* DC target */
8613 hr = ID2D1Factory1_CreateDCRenderTarget(factory, &rt_desc, &dc_rt);
8614 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
8616 hr = ID2D1DCRenderTarget_QueryInterface(dc_rt, &IID_ID2D1DeviceContext, (void **)&device_context);
8617 ok(SUCCEEDED(hr), "Failed to get device context interface, hr %#x.\n", hr);
8618 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8619 ok(bitmap == NULL, "Unexpected bitmap instance.\n");
8621 hdc = CreateCompatibleDC(NULL);
8622 ok(hdc != NULL, "Failed to create an HDC.\n");
8624 create_target_dibsection(hdc, 16, 16);
8626 SetRect(&rect, 0, 0, 16, 16);
8627 hr = ID2D1DCRenderTarget_BindDC(dc_rt, hdc, &rect);
8628 ok(SUCCEEDED(hr), "BindDC() failed, hr %#x.\n", hr);
8630 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8631 options = ID2D1Bitmap1_GetOptions(bitmap);
8632 ok(options == (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE),
8633 "Unexpected bitmap options %#x.\n", options);
8634 hr = ID2D1Bitmap1_GetSurface(bitmap, &surface);
8635 ok(hr == D2DERR_INVALID_CALL, "Unexpected hr %#x.\n", hr);
8636 ID2D1Bitmap1_Release(bitmap);
8638 ID2D1DeviceContext_SetTarget(device_context, NULL);
8639 ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
8640 ok(bitmap == NULL, "Unexpected target instance.\n");
8642 ID2D1DeviceContext_Release(device_context);
8643 ID2D1DCRenderTarget_Release(dc_rt);
8644 DeleteDC(hdc);
8646 ID2D1Device_Release(device);
8647 ID2D1Factory1_Release(factory);
8648 ID3D10Device1_Release(d3d_device);
8651 static void test_invert_matrix(void)
8653 static const struct
8655 D2D1_MATRIX_3X2_F matrix;
8656 D2D1_MATRIX_3X2_F inverse;
8657 BOOL invertible;
8659 invert_tests[] =
8661 { {{{ 0 }}}, {{{ 0 }}}, FALSE },
8664 1.0f, 2.0f,
8665 1.0f, 2.0f,
8666 4.0f, 8.0f
8667 }}},
8669 1.0f, 2.0f,
8670 1.0f, 2.0f,
8671 4.0f, 8.0f
8672 }}},
8673 FALSE
8677 2.0f, 0.0f,
8678 0.0f, 2.0f,
8679 4.0f, 8.0f
8680 }}},
8682 0.5f, -0.0f,
8683 -0.0f, 0.5f,
8684 -2.0f, -4.0f
8685 }}},
8686 TRUE
8690 2.0f, 1.0f,
8691 2.0f, 2.0f,
8692 4.0f, 8.0f
8693 }}},
8695 1.0f, -0.5f,
8696 -1.0f, 1.0f,
8697 4.0f, -6.0f
8698 }}},
8699 TRUE
8703 2.0f, 1.0f,
8704 3.0f, 1.0f,
8705 4.0f, 8.0f
8706 }}},
8708 -1.0f, 1.0f,
8709 3.0f, -2.0f,
8710 -20.0f, 12.0f
8711 }}},
8712 TRUE
8715 unsigned int i;
8717 for (i = 0; i < ARRAY_SIZE(invert_tests); ++i)
8719 D2D1_MATRIX_3X2_F m;
8720 BOOL ret;
8722 m = invert_tests[i].matrix;
8723 ret = D2D1InvertMatrix(&m);
8724 ok(ret == invert_tests[i].invertible, "%u: unexpected return value %d.\n", i, ret);
8725 ok(!memcmp(&m, &invert_tests[i].inverse, sizeof(m)),
8726 "%u: unexpected matrix value {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n", i,
8727 m._11, m._12, m._21, m._22, m._31, m._32);
8729 ret = D2D1IsMatrixInvertible(&invert_tests[i].matrix);
8730 ok(ret == invert_tests[i].invertible, "%u: unexpected return value %d.\n", i, ret);
8734 static void test_skew_matrix(void)
8736 static const struct
8738 float angle_x;
8739 float angle_y;
8740 D2D1_POINT_2F center;
8741 D2D1_MATRIX_3X2_F matrix;
8743 skew_tests[] =
8745 { 0.0f, 0.0f, { 0.0f, 0.0f }, {{{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }}} },
8746 { 45.0f, 0.0f, { 0.0f, 0.0f }, {{{ 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f }}} },
8747 { 0.0f, 0.0f, { 10.0f, -3.0f }, {{{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }}} },
8748 { -45.0f, 45.0f, { 0.1f, 0.5f }, {{{ 1.0f, 1.0f, -1.0f, 1.0f, 0.5f, -0.1f }}} },
8749 { -45.0f, 45.0f, { 1.0f, 2.0f }, {{{ 1.0f, 1.0f, -1.0f, 1.0f, 2.0f, -1.0f }}} },
8750 { 45.0f, -45.0f, { 1.0f, 2.0f }, {{{ 1.0f, -1.0f, 1.0f, 1.0f, -2.0f, 1.0f }}} },
8751 { 30.0f, -60.0f, { 12.0f, -5.0f }, {{{ 1.0f, -1.7320509f, 0.577350259f, 1.0f, 2.88675117f, 20.7846107f }}} },
8753 unsigned int i;
8755 for (i = 0; i < ARRAY_SIZE(skew_tests); ++i)
8757 const D2D1_MATRIX_3X2_F *expected = &skew_tests[i].matrix;
8758 D2D1_MATRIX_3X2_F m;
8759 BOOL ret;
8761 D2D1MakeSkewMatrix(skew_tests[i].angle_x, skew_tests[i].angle_y, skew_tests[i].center, &m);
8762 ret = compare_float(m._11, expected->_11, 3) && compare_float(m._12, expected->_12, 3)
8763 && compare_float(m._21, expected->_21, 3) && compare_float(m._22, expected->_22, 3)
8764 && compare_float(m._31, expected->_31, 3) && compare_float(m._32, expected->_32, 3);
8766 ok(ret, "%u: unexpected matrix value {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}, expected "
8767 "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n", i, m._11, m._12, m._21, m._22, m._31, m._32,
8768 expected->_11, expected->_12, expected->_21, expected->_22, expected->_31, expected->_32);
8772 static ID2D1DeviceContext *create_device_context(ID2D1Factory1 *factory, ID3D10Device1 *d3d_device)
8774 ID2D1DeviceContext *device_context;
8775 IDXGIDevice *dxgi_device;
8776 ID2D1Device *device;
8777 HRESULT hr;
8779 hr = ID3D10Device1_QueryInterface(d3d_device, &IID_IDXGIDevice, (void **)&dxgi_device);
8780 ok(SUCCEEDED(hr), "Failed to get IDXGIDevice interface, hr %#x.\n", hr);
8782 hr = ID2D1Factory1_CreateDevice(factory, dxgi_device, &device);
8783 ok(SUCCEEDED(hr), "Failed to get ID2D1Device, hr %#x.\n", hr);
8784 IDXGIDevice_Release(dxgi_device);
8786 hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &device_context);
8787 ok(SUCCEEDED(hr), "Failed to create device context, hr %#x.\n", hr);
8788 ID2D1Device_Release(device);
8790 return device_context;
8793 static void test_command_list(void)
8795 static const DWORD bitmap_data[] =
8797 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
8799 static const D2D1_GRADIENT_STOP stops[] =
8801 {0.0f, {1.0f, 0.0f, 0.0f, 1.0f}},
8802 {0.5f, {0.0f, 1.0f, 0.0f, 1.0f}},
8803 {1.0f, {0.0f, 0.0f, 1.0f, 1.0f}},
8805 D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES radial_gradient_properties;
8806 D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES linear_gradient_properties;
8807 ID2D1DeviceContext *device_context, *device_context2;
8808 D2D1_STROKE_STYLE_PROPERTIES stroke_desc;
8809 ID2D1GradientStopCollection *gradient;
8810 D2D1_BITMAP_PROPERTIES bitmap_desc;
8811 ID2D1StrokeStyle *stroke_style;
8812 ID2D1CommandList *command_list;
8813 ID3D10Device1 *d3d_device;
8814 ID2D1Geometry *geometry;
8815 ID2D1Factory1 *factory;
8816 ID2D1RenderTarget *rt;
8817 D2D1_POINT_2F p0, p1;
8818 ID2D1Bitmap *bitmap;
8819 ID2D1Image *target;
8820 D2D1_COLOR_F color;
8821 ID2D1Brush *brush;
8822 D2D1_RECT_F rect;
8823 D2D_SIZE_U size;
8824 ULONG refcount;
8825 HRESULT hr;
8827 if (!(d3d_device = create_device()))
8829 skip("Failed to create device, skipping tests.\n");
8830 return;
8833 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
8835 win_skip("ID2D1Factory1 is not supported.\n");
8836 ID3D10Device1_Release(d3d_device);
8837 return;
8840 device_context = create_device_context(factory, d3d_device);
8841 ok(device_context != NULL, "Failed to create device context.\n");
8843 hr = ID2D1DeviceContext_CreateCommandList(device_context, &command_list);
8844 todo_wine
8845 ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr);
8847 if (FAILED(hr))
8849 ID2D1DeviceContext_Release(device_context);
8850 ID2D1Factory1_Release(factory);
8851 return;
8854 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)command_list);
8855 ID2D1DeviceContext_BeginDraw(device_context);
8857 hr = ID2D1DeviceContext_QueryInterface(device_context, &IID_ID2D1RenderTarget, (void **)&rt);
8858 ok(SUCCEEDED(hr), "Failed to get rt interface, hr %#x.\n", hr);
8860 /* Test how resources are referenced by the list. */
8862 /* Bitmap. */
8863 set_size_u(&size, 4, 1);
8864 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
8865 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
8866 bitmap_desc.dpiX = 96.0f;
8867 bitmap_desc.dpiY = 96.0f;
8868 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
8869 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
8871 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
8873 refcount = ID2D1Bitmap_Release(bitmap);
8874 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8876 /* Solid color brush. */
8877 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
8878 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, (ID2D1SolidColorBrush **)&brush);
8879 ok(SUCCEEDED(hr), "Failed to create a brush, hr %#x.\n", hr);
8881 set_rect(&rect, 0.0f, 0.0f, 16.0f, 16.0f);
8882 ID2D1RenderTarget_FillRectangle(rt, &rect, brush);
8884 refcount = ID2D1Brush_Release(brush);
8885 ok(refcount == 0, "Got unexpected refcount %u.\n", refcount);
8887 /* Bitmap brush. */
8888 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
8889 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
8891 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, (ID2D1BitmapBrush **)&brush);
8892 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
8894 set_rect(&rect, 0.0f, 0.0f, 16.0f, 16.0f);
8895 ID2D1RenderTarget_FillRectangle(rt, &rect, brush);
8897 refcount = ID2D1Brush_Release(brush);
8898 ok(refcount == 0, "Got unexpected refcount %u.\n", refcount);
8900 refcount = ID2D1Bitmap_Release(bitmap);
8901 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8903 /* Linear gradient brush. */
8904 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops, ARRAY_SIZE(stops),
8905 D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &gradient);
8906 ok(SUCCEEDED(hr), "Failed to create stop collection, hr %#x.\n", hr);
8908 set_point(&linear_gradient_properties.startPoint, 320.0f, 0.0f);
8909 set_point(&linear_gradient_properties.endPoint, 0.0f, 960.0f);
8910 hr = ID2D1RenderTarget_CreateLinearGradientBrush(rt, &linear_gradient_properties, NULL, gradient,
8911 (ID2D1LinearGradientBrush **)&brush);
8912 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
8914 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
8915 hr = ID2D1Factory1_CreateRectangleGeometry(factory, &rect, (ID2D1RectangleGeometry **)&geometry);
8916 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
8918 ID2D1RenderTarget_FillGeometry(rt, geometry, brush, NULL);
8920 refcount = ID2D1Brush_Release(brush);
8921 ok(refcount == 0, "Got unexpected refcount %u.\n", refcount);
8923 refcount = ID2D1Geometry_Release(geometry);
8924 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8926 refcount = ID2D1GradientStopCollection_Release(gradient);
8927 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8929 /* Radial gradient brush. */
8930 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops, ARRAY_SIZE(stops),
8931 D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &gradient);
8932 ok(SUCCEEDED(hr), "Failed to create stop collection, hr %#x.\n", hr);
8934 set_point(&radial_gradient_properties.center, 160.0f, 480.0f);
8935 set_point(&radial_gradient_properties.gradientOriginOffset, 40.0f, -120.0f);
8936 radial_gradient_properties.radiusX = 160.0f;
8937 radial_gradient_properties.radiusY = 480.0f;
8938 hr = ID2D1RenderTarget_CreateRadialGradientBrush(rt, &radial_gradient_properties, NULL, gradient,
8939 (ID2D1RadialGradientBrush **)&brush);
8940 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
8942 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
8943 hr = ID2D1Factory1_CreateRectangleGeometry(factory, &rect, (ID2D1RectangleGeometry **)&geometry);
8944 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
8946 ID2D1RenderTarget_FillGeometry(rt, geometry, brush, NULL);
8948 refcount = ID2D1Brush_Release(brush);
8949 ok(refcount == 0, "Got unexpected refcount %u.\n", refcount);
8951 refcount = ID2D1Geometry_Release(geometry);
8952 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8954 refcount = ID2D1GradientStopCollection_Release(gradient);
8955 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8957 /* Geometry. */
8958 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
8959 hr = ID2D1Factory1_CreateRectangleGeometry(factory, &rect, (ID2D1RectangleGeometry **)&geometry);
8960 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
8962 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
8963 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, (ID2D1SolidColorBrush **)&brush);
8964 ok(SUCCEEDED(hr), "Failed to create a brush, hr %#x.\n", hr);
8966 ID2D1RenderTarget_FillGeometry(rt, geometry, brush, NULL);
8968 refcount = ID2D1Brush_Release(brush);
8969 ok(refcount == 0, "Got unexpected refcount %u.\n", refcount);
8971 refcount = ID2D1Geometry_Release(geometry);
8972 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8974 /* Stroke style. */
8975 stroke_desc.startCap = D2D1_CAP_STYLE_SQUARE;
8976 stroke_desc.endCap = D2D1_CAP_STYLE_ROUND;
8977 stroke_desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
8978 stroke_desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
8979 stroke_desc.miterLimit = 1.5f;
8980 stroke_desc.dashStyle = D2D1_DASH_STYLE_DOT;
8981 stroke_desc.dashOffset = -1.0f;
8983 hr = ID2D1Factory_CreateStrokeStyle((ID2D1Factory *)factory, &stroke_desc, NULL, 0, &stroke_style);
8984 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
8986 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
8987 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, (ID2D1SolidColorBrush **)&brush);
8988 ok(SUCCEEDED(hr), "Failed to create a brush, hr %#x.\n", hr);
8990 set_point(&p0, 100.0f, 160.0f);
8991 set_point(&p1, 140.0f, 160.0f);
8992 ID2D1RenderTarget_DrawLine(rt, p0, p1, brush, 1.0f, stroke_style);
8994 refcount = ID2D1Brush_Release(brush);
8995 ok(refcount == 0, "Got unexpected refcount %u.\n", refcount);
8997 refcount = ID2D1StrokeStyle_Release(stroke_style);
8998 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
9000 /* Close on attached list. */
9001 ID2D1DeviceContext_GetTarget(device_context, &target);
9002 ok(target == (ID2D1Image *)command_list, "Unexpected context target.\n");
9003 ID2D1Image_Release(target);
9005 hr = ID2D1CommandList_Close(command_list);
9006 ok(SUCCEEDED(hr), "Failed to close a list, hr %#x.\n", hr);
9008 ID2D1DeviceContext_GetTarget(device_context, &target);
9009 ok(target == NULL, "Unexpected context target.\n");
9011 hr = ID2D1CommandList_Close(command_list);
9012 ok(hr == D2DERR_WRONG_STATE, "Unexpected hr %#x.\n", hr);
9014 ID2D1CommandList_Release(command_list);
9016 /* Close empty list. */
9017 hr = ID2D1DeviceContext_CreateCommandList(device_context, &command_list);
9018 ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr);
9020 hr = ID2D1CommandList_Close(command_list);
9021 ok(SUCCEEDED(hr), "Failed to close a list, hr %#x.\n", hr);
9023 ID2D1CommandList_Release(command_list);
9025 /* List created with different context. */
9026 device_context2 = create_device_context(factory, d3d_device);
9027 ok(device_context2 != NULL, "Failed to create device context.\n");
9029 hr = ID2D1DeviceContext_CreateCommandList(device_context, &command_list);
9030 ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr);
9032 ID2D1DeviceContext_SetTarget(device_context2, (ID2D1Image *)command_list);
9033 ID2D1DeviceContext_GetTarget(device_context2, &target);
9034 ok(target == NULL, "Unexpected target.\n");
9036 ID2D1CommandList_Release(command_list);
9037 ID2D1DeviceContext_Release(device_context2);
9039 ID2D1RenderTarget_Release(rt);
9040 ID2D1DeviceContext_Release(device_context);
9041 refcount = ID2D1Factory1_Release(factory);
9042 ok(!refcount, "Factory has %u references left.\n", refcount);
9045 static void test_max_bitmap_size(void)
9047 D2D1_RENDER_TARGET_PROPERTIES desc;
9048 D2D1_BITMAP_PROPERTIES bitmap_desc;
9049 IDXGISwapChain *swapchain;
9050 ID2D1Factory *factory;
9051 IDXGISurface *surface;
9052 ID2D1RenderTarget *rt;
9053 ID3D10Device1 *device;
9054 ID2D1Bitmap *bitmap;
9055 UINT32 bitmap_size;
9056 unsigned int i, j;
9057 HWND window;
9058 HRESULT hr;
9060 static const struct
9062 const char *name;
9063 DWORD type;
9065 device_types[] =
9067 { "HW", D3D10_DRIVER_TYPE_HARDWARE },
9068 { "WARP", D3D10_DRIVER_TYPE_WARP },
9069 { "REF", D3D10_DRIVER_TYPE_REFERENCE },
9071 static const struct
9073 const char *name;
9074 DWORD type;
9076 target_types[] =
9078 { "DEFAULT", D2D1_RENDER_TARGET_TYPE_DEFAULT },
9079 { "HW", D2D1_RENDER_TARGET_TYPE_HARDWARE },
9082 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
9083 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
9085 for (i = 0; i < ARRAY_SIZE(device_types); ++i)
9087 if (FAILED(hr = D3D10CreateDevice1(NULL, device_types[i].type, NULL, D3D10_CREATE_DEVICE_BGRA_SUPPORT,
9088 D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
9090 skip("Failed to create %s d3d device, hr %#x.\n", device_types[i].name, hr);
9091 continue;
9094 window = create_window();
9095 swapchain = create_swapchain(device, window, TRUE);
9096 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
9097 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
9099 for (j = 0; j < ARRAY_SIZE(target_types); ++j)
9101 D3D10_TEXTURE2D_DESC texture_desc;
9102 ID3D10Texture2D *texture;
9103 D2D1_SIZE_U size;
9105 desc.type = target_types[j].type;
9106 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
9107 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
9108 desc.dpiX = 0.0f;
9109 desc.dpiY = 0.0f;
9110 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
9111 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
9113 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
9114 ok(SUCCEEDED(hr), "%s/%s: failed to create render target, hr %#x.\n", device_types[i].name,
9115 target_types[j].name, hr);
9117 bitmap_size = ID2D1RenderTarget_GetMaximumBitmapSize(rt);
9118 ok(bitmap_size >= D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION, "%s/%s: unexpected bitmap size %u.\n",
9119 device_types[i].name, target_types[j].name, bitmap_size);
9121 bitmap_desc.dpiX = 96.0f;
9122 bitmap_desc.dpiY = 96.0f;
9123 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
9124 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
9126 size.width = bitmap_size;
9127 size.height = 1;
9128 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
9129 ok(SUCCEEDED(hr), "Failed to create a bitmap, hr %#x.\n", hr);
9130 ID2D1Bitmap_Release(bitmap);
9132 ID2D1RenderTarget_Release(rt);
9134 texture_desc.Width = bitmap_size;
9135 texture_desc.Height = 1;
9136 texture_desc.MipLevels = 1;
9137 texture_desc.ArraySize = 1;
9138 texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
9139 texture_desc.SampleDesc.Count = 1;
9140 texture_desc.SampleDesc.Quality = 0;
9141 texture_desc.Usage = D3D10_USAGE_DEFAULT;
9142 texture_desc.BindFlags = 0;
9143 texture_desc.CPUAccessFlags = 0;
9144 texture_desc.MiscFlags = 0;
9146 hr = ID3D10Device1_CreateTexture2D(device, &texture_desc, NULL, &texture);
9147 ok(SUCCEEDED(hr) || broken(hr == E_INVALIDARG && device_types[i].type == D3D10_DRIVER_TYPE_WARP) /* Vista */,
9148 "%s/%s: failed to create texture, hr %#x.\n", device_types[i].name, target_types[j].name, hr);
9149 if (SUCCEEDED(hr))
9150 ID3D10Texture2D_Release(texture);
9153 IDXGISurface_Release(surface);
9154 IDXGISwapChain_Release(swapchain);
9155 DestroyWindow(window);
9157 ID3D10Device1_Release(device);
9160 ID2D1Factory_Release(factory);
9163 static void test_dpi(void)
9165 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
9166 ID2D1DeviceContext *device_context;
9167 IWICImagingFactory *wic_factory;
9168 IDXGISwapChain *swapchain;
9169 ID3D10Device1 *d3d_device;
9170 ID2D1Factory1 *factory;
9171 IDXGISurface *surface;
9172 ID2D1Bitmap1 *bitmap;
9173 float dpi_x, dpi_y;
9174 HWND window;
9175 HRESULT hr;
9177 static const struct
9179 float dpi_x, dpi_y;
9180 HRESULT hr;
9182 create_dpi_tests[] =
9184 { 0.0f, 0.0f, S_OK},
9185 {192.0f, 0.0f, E_INVALIDARG},
9186 { 0.0f, 192.0f, E_INVALIDARG},
9187 {192.0f, -10.0f, E_INVALIDARG},
9188 {-10.0f, 192.0f, E_INVALIDARG},
9189 {-10.0f, -10.0f, E_INVALIDARG},
9190 { 48.0f, 96.0f, S_OK},
9191 { 96.0f, 48.0f, S_OK},
9193 static const float init_dpi_x = 60.0f, init_dpi_y = 288.0f;
9194 static const float dc_dpi_x = 120.0f, dc_dpi_y = 144.0f;
9195 unsigned int i;
9197 if (!(d3d_device = create_device()))
9199 skip("Failed to create device, skipping tests.\n");
9200 return;
9203 if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
9205 win_skip("ID2D1Factory1 is not supported.\n");
9206 ID3D10Device1_Release(d3d_device);
9207 return;
9210 window = create_window();
9211 swapchain = create_swapchain(d3d_device, window, TRUE);
9212 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
9213 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
9215 device_context = create_device_context(factory, d3d_device);
9216 ok(!!device_context, "Failed to create device context.\n");
9218 ID2D1DeviceContext_GetDpi(device_context, &dpi_x, &dpi_y);
9219 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
9220 ok(dpi_y == 96.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
9222 /* DXGI surface */
9223 for (i = 0; i < ARRAY_SIZE(create_dpi_tests); ++i)
9225 ID2D1DeviceContext_SetDpi(device_context, init_dpi_x, init_dpi_y);
9227 bitmap_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
9228 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
9229 bitmap_desc.dpiX = create_dpi_tests[i].dpi_x;
9230 bitmap_desc.dpiY = create_dpi_tests[i].dpi_y;
9231 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
9232 bitmap_desc.colorContext = NULL;
9233 hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, surface, &bitmap_desc, &bitmap);
9234 /* Native accepts negative DPI values for DXGI surface bitmap. */
9235 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9237 ID2D1DeviceContext_SetDpi(device_context, dc_dpi_x, dc_dpi_y);
9239 ID2D1Bitmap1_GetDpi(bitmap, &dpi_x, &dpi_y);
9240 todo_wine_if(bitmap_desc.dpiX == 0.0f)
9241 ok(dpi_x == bitmap_desc.dpiX, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n",
9242 i, dpi_x, bitmap_desc.dpiX);
9243 todo_wine_if(bitmap_desc.dpiY == 0.0f)
9244 ok(dpi_y == bitmap_desc.dpiY, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n",
9245 i, dpi_y, bitmap_desc.dpiY);
9247 ID2D1DeviceContext_BeginDraw(device_context);
9248 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
9249 hr = ID2D1DeviceContext_EndDraw(device_context, NULL, NULL);
9250 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9252 /* Device context DPI values aren't updated by SetTarget. */
9253 ID2D1DeviceContext_GetDpi(device_context, &dpi_x, &dpi_y);
9254 ok(dpi_x == dc_dpi_x, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n", i, dpi_x, dc_dpi_x);
9255 ok(dpi_y == dc_dpi_y, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n", i, dpi_y, dc_dpi_y);
9257 ID2D1Bitmap1_Release(bitmap);
9260 /* WIC bitmap */
9261 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
9262 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
9263 &IID_IWICImagingFactory, (void **)&wic_factory);
9264 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
9265 for (i = 0; i < ARRAY_SIZE(create_dpi_tests); ++i)
9267 IWICBitmapSource *wic_bitmap_src;
9268 IWICBitmap *wic_bitmap;
9270 ID2D1DeviceContext_SetDpi(device_context, init_dpi_x, init_dpi_y);
9272 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
9273 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
9274 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9275 hr = IWICBitmap_QueryInterface(wic_bitmap, &IID_IWICBitmapSource, (void **)&wic_bitmap_src);
9276 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9277 IWICBitmap_Release(wic_bitmap);
9279 bitmap_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
9280 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
9281 bitmap_desc.dpiX = create_dpi_tests[i].dpi_x;
9282 bitmap_desc.dpiY = create_dpi_tests[i].dpi_y;
9283 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
9284 bitmap_desc.colorContext = NULL;
9285 hr = ID2D1DeviceContext_CreateBitmapFromWicBitmap(device_context, wic_bitmap_src, &bitmap_desc, &bitmap);
9286 ok(hr == create_dpi_tests[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
9287 i, hr, create_dpi_tests[i].hr);
9288 IWICBitmapSource_Release(wic_bitmap_src);
9290 if (FAILED(hr))
9291 continue;
9293 ID2D1DeviceContext_SetDpi(device_context, dc_dpi_x, dc_dpi_y);
9295 ID2D1Bitmap1_GetDpi(bitmap, &dpi_x, &dpi_y);
9296 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
9298 /* Bitmap DPI values are inherited at creation time. */
9299 ok(dpi_x == init_dpi_x, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n", i, dpi_x, init_dpi_x);
9300 ok(dpi_y == init_dpi_y, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n", i, dpi_y, init_dpi_y);
9302 else
9304 ok(dpi_x == bitmap_desc.dpiX, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n",
9305 i, dpi_x, bitmap_desc.dpiX);
9306 ok(dpi_y == bitmap_desc.dpiY, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n",
9307 i, dpi_y, bitmap_desc.dpiY);
9310 ID2D1DeviceContext_BeginDraw(device_context);
9311 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
9312 hr = ID2D1DeviceContext_EndDraw(device_context, NULL, NULL);
9313 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9315 /* Device context DPI values aren't updated by SetTarget. */
9316 ID2D1DeviceContext_GetDpi(device_context, &dpi_x, &dpi_y);
9317 ok(dpi_x == dc_dpi_x, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n", i, dpi_x, dc_dpi_x);
9318 ok(dpi_y == dc_dpi_y, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n", i, dpi_y, dc_dpi_y);
9320 ID2D1Bitmap1_Release(bitmap);
9322 IWICImagingFactory_Release(wic_factory);
9323 CoUninitialize();
9325 /* D2D bitmap */
9326 for (i = 0; i < ARRAY_SIZE(create_dpi_tests); ++i)
9328 const D2D1_SIZE_U size = {16, 16};
9330 ID2D1DeviceContext_SetDpi(device_context, init_dpi_x, init_dpi_y);
9332 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
9333 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
9334 bitmap_desc.dpiX = create_dpi_tests[i].dpi_x;
9335 bitmap_desc.dpiY = create_dpi_tests[i].dpi_y;
9336 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
9337 bitmap_desc.colorContext = NULL;
9338 hr = ID2D1DeviceContext_CreateBitmap(device_context, size, NULL, 0, &bitmap_desc, &bitmap);
9339 ok(hr == create_dpi_tests[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
9340 i, hr, create_dpi_tests[i].hr);
9342 if (FAILED(hr))
9343 continue;
9345 ID2D1DeviceContext_SetDpi(device_context, dc_dpi_x, dc_dpi_y);
9347 ID2D1Bitmap1_GetDpi(bitmap, &dpi_x, &dpi_y);
9348 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
9350 /* Bitmap DPI values are inherited at creation time. */
9351 ok(dpi_x == init_dpi_x, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n", i, dpi_x, init_dpi_x);
9352 ok(dpi_y == init_dpi_y, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n", i, dpi_y, init_dpi_y);
9354 else
9356 ok(dpi_x == bitmap_desc.dpiX, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n",
9357 i, dpi_x, bitmap_desc.dpiX);
9358 ok(dpi_y == bitmap_desc.dpiY, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n",
9359 i, dpi_y, bitmap_desc.dpiY);
9362 ID2D1DeviceContext_BeginDraw(device_context);
9363 ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap);
9364 hr = ID2D1DeviceContext_EndDraw(device_context, NULL, NULL);
9365 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9367 /* Device context DPI values aren't updated by SetTarget. */
9368 ID2D1DeviceContext_GetDpi(device_context, &dpi_x, &dpi_y);
9369 ok(dpi_x == dc_dpi_x, "Test %u: Got unexpected dpi_x %.8e, expected %.8e.\n", i, dpi_x, dc_dpi_x);
9370 ok(dpi_y == dc_dpi_y, "Test %u: Got unexpected dpi_y %.8e, expected %.8e.\n", i, dpi_y, dc_dpi_y);
9372 ID2D1Bitmap1_Release(bitmap);
9375 ID2D1DeviceContext_SetTarget(device_context, NULL);
9376 ID2D1DeviceContext_GetDpi(device_context, &dpi_x, &dpi_y);
9377 ok(dpi_x == dc_dpi_x, "Got unexpected dpi_x %.8e, expected %.8e.\n", dpi_x, dc_dpi_x);
9378 ok(dpi_y == dc_dpi_y, "Got unexpected dpi_y %.8e, expected %.8e.\n", dpi_y, dc_dpi_y);
9380 ID2D1DeviceContext_Release(device_context);
9381 IDXGISurface_Release(surface);
9382 IDXGISwapChain_Release(swapchain);
9383 ID2D1Factory1_Release(factory);
9384 ID3D10Device1_Release(d3d_device);
9385 DestroyWindow(window);
9388 static void test_wic_bitmap_format(void)
9390 IWICImagingFactory *wic_factory;
9391 IDXGISwapChain *swapchain;
9392 D2D1_PIXEL_FORMAT format;
9393 IWICBitmap *wic_bitmap;
9394 ID2D1RenderTarget *rt;
9395 ID3D10Device1 *device;
9396 IDXGISurface *surface;
9397 ID2D1Bitmap *bitmap;
9398 unsigned int i;
9399 HWND window;
9400 HRESULT hr;
9402 static const struct
9404 const WICPixelFormatGUID *wic;
9405 D2D1_PIXEL_FORMAT d2d;
9407 tests[] =
9409 {&GUID_WICPixelFormat32bppPBGRA, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED}},
9410 {&GUID_WICPixelFormat32bppPRGBA, {DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED}},
9411 {&GUID_WICPixelFormat32bppBGR, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE}},
9414 if (!(device = create_device()))
9416 skip("Failed to create device, skipping tests.\n");
9417 return;
9419 window = create_window();
9420 swapchain = create_swapchain(device, window, TRUE);
9421 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
9422 ok(hr == S_OK, "Failed to get buffer, hr %#x.\n", hr);
9423 rt = create_render_target(surface);
9424 ok(!!rt, "Failed to create render target.\n");
9425 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
9427 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
9428 &IID_IWICImagingFactory, (void **)&wic_factory);
9429 ok(hr == S_OK, "Failed to create WIC imaging factory, hr %#x.\n", hr);
9431 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9433 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
9434 tests[i].wic, WICBitmapCacheOnDemand, &wic_bitmap);
9435 ok(hr == S_OK, "%s: Failed to create WIC bitmap, hr %#x.\n", debugstr_guid(tests[i].wic), hr);
9437 hr = ID2D1RenderTarget_CreateBitmapFromWicBitmap(rt, (IWICBitmapSource *)wic_bitmap, NULL, &bitmap);
9438 ok(hr == S_OK, "%s: Failed to create bitmap from WIC source, hr %#x.\n", debugstr_guid(tests[i].wic), hr);
9440 format = ID2D1Bitmap_GetPixelFormat(bitmap);
9441 ok(format.format == tests[i].d2d.format, "%s: Got unexpected DXGI format %#x.\n",
9442 debugstr_guid(tests[i].wic), format.format);
9443 ok(format.alphaMode == tests[i].d2d.alphaMode, "%s: Got unexpected alpha mode %#x.\n",
9444 debugstr_guid(tests[i].wic), format.alphaMode);
9446 ID2D1Bitmap_Release(bitmap);
9447 IWICBitmap_Release(wic_bitmap);
9450 IWICImagingFactory_Release(wic_factory);
9451 CoUninitialize();
9452 ID2D1RenderTarget_Release(rt);
9453 IDXGISurface_Release(surface);
9454 IDXGISwapChain_Release(swapchain);
9455 ID3D10Device1_Release(device);
9456 DestroyWindow(window);
9459 static void test_math(void)
9461 float s, c, t, l;
9462 unsigned int i;
9464 static const struct
9466 float x;
9467 float s;
9468 float c;
9470 sc_data[] =
9472 {0.0f, 0.0f, 1.0f},
9473 {1.0f, 8.41470957e-001f, 5.40302277e-001f},
9474 {2.0f, 9.09297407e-001f, -4.16146845e-001f},
9475 {M_PI / 2.0f, 1.0f, -4.37113883e-008f},
9476 {M_PI, -8.74227766e-008f, -1.0f},
9479 static const struct
9481 float x;
9482 float t;
9484 t_data[] =
9486 {0.0f, 0.0f},
9487 {1.0f, 1.55740774f},
9488 {2.0f, -2.18503976f},
9489 {M_PI / 2.0f, -2.28773320e+007f},
9490 {M_PI, 8.74227766e-008f},
9493 static const struct
9495 float x;
9496 float y;
9497 float z;
9498 float l;
9500 l_data[] =
9502 {0.0f, 0.0f, 0.0f, 0.0f},
9503 {1.0f, 0.0f, 0.0f, 1.0f},
9504 {0.0f, 1.0f, 0.0f, 1.0f},
9505 {0.0f, 0.0f, 1.0f, 1.0f},
9506 {1.0f, 1.0f, 1.0f, 1.73205078f},
9507 {1.0f, 2.0f, 2.0f, 3.0f},
9508 {1.0f, 2.0f, 3.0f, 3.74165750f},
9511 for (i = 0; i < ARRAY_SIZE(sc_data); ++i)
9513 D2D1SinCos(sc_data[i].x, &s, &c);
9514 ok(compare_float(s, sc_data[i].s, 0),
9515 "Test %u: Got unexpected sin %.8e, expected %.8e.\n", i, s, sc_data[i].s);
9516 ok(compare_float(c, sc_data[i].c, 0),
9517 "Test %u: Got unexpected cos %.8e, expected %.8e.\n", i, c, sc_data[i].c);
9520 for (i = 0; i < ARRAY_SIZE(t_data); ++i)
9522 t = D2D1Tan(t_data[i].x);
9523 ok(compare_float(t, t_data[i].t, 1),
9524 "Test %u: Got unexpected tan %.8e, expected %.8e.\n", i, t, t_data[i].t);
9527 for (i = 0; i < ARRAY_SIZE(l_data); ++i)
9529 l = D2D1Vec3Length(l_data[i].x, l_data[i].y, l_data[i].z);
9530 ok(compare_float(l, l_data[i].l, 0),
9531 "Test %u: Got unexpected length %.8e, expected %.8e.\n", i, l, l_data[i].l);
9535 START_TEST(d2d1)
9537 unsigned int argc, i;
9538 char **argv;
9540 pD2D1CreateDevice = (void *)GetProcAddress(GetModuleHandleA("d2d1.dll"), "D2D1CreateDevice");
9542 use_mt = !getenv("WINETEST_NO_MT_D3D");
9544 argc = winetest_get_mainargs(&argv);
9545 for (i = 2; i < argc; ++i)
9547 if (!strcmp(argv[i], "--single"))
9548 use_mt = FALSE;
9551 queue_test(test_clip);
9552 queue_test(test_state_block);
9553 queue_test(test_color_brush);
9554 queue_test(test_bitmap_brush);
9555 queue_test(test_linear_brush);
9556 queue_test(test_radial_brush);
9557 queue_test(test_path_geometry);
9558 queue_test(test_rectangle_geometry);
9559 queue_test(test_rounded_rectangle_geometry);
9560 queue_test(test_bitmap_formats);
9561 queue_test(test_alpha_mode);
9562 queue_test(test_shared_bitmap);
9563 queue_test(test_bitmap_updates);
9564 queue_test(test_opacity_brush);
9565 queue_test(test_create_target);
9566 queue_test(test_draw_text_layout);
9567 queue_test(test_dc_target);
9568 queue_test(test_hwnd_target);
9569 queue_test(test_bitmap_target);
9570 queue_test(test_desktop_dpi);
9571 queue_test(test_stroke_style);
9572 queue_test(test_gradient);
9573 queue_test(test_draw_geometry);
9574 queue_test(test_fill_geometry);
9575 queue_test(test_gdi_interop);
9576 queue_test(test_layer);
9577 queue_test(test_bezier_intersect);
9578 queue_test(test_create_device);
9579 queue_test(test_bitmap_surface);
9580 queue_test(test_device_context);
9581 queue_test(test_invert_matrix);
9582 queue_test(test_skew_matrix);
9583 queue_test(test_command_list);
9584 queue_test(test_max_bitmap_size);
9585 queue_test(test_dpi);
9586 queue_test(test_wic_bitmap_format);
9587 queue_test(test_math);
9589 run_queued_tests();