d2d1/tests: Add a test for bezier intersections.
[wine.git] / dlls / d2d1 / tests / d2d1.c
blobbb1b0569dcfbb59b08b2039a61112109c3a6d7c4
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 "d2d1.h"
23 #include "wincrypt.h"
24 #include "wine/test.h"
25 #include "initguid.h"
26 #include "dwrite.h"
27 #include "wincodec.h"
29 struct figure
31 unsigned int *spans;
32 unsigned int spans_size;
33 unsigned int span_count;
36 struct geometry_sink
38 ID2D1SimplifiedGeometrySink ID2D1SimplifiedGeometrySink_iface;
40 struct geometry_figure
42 D2D1_FIGURE_BEGIN begin;
43 D2D1_FIGURE_END end;
44 D2D1_POINT_2F start_point;
45 struct geometry_segment
47 enum
49 SEGMENT_BEZIER,
50 SEGMENT_LINE,
51 } type;
52 union
54 D2D1_BEZIER_SEGMENT bezier;
55 D2D1_POINT_2F line;
56 } u;
57 DWORD flags;
58 } *segments;
59 unsigned int segments_size;
60 unsigned int segment_count;
61 } *figures;
62 unsigned int figures_size;
63 unsigned int figure_count;
65 D2D1_FILL_MODE fill_mode;
66 DWORD segment_flags;
67 BOOL closed;
70 struct expected_geometry_figure
72 D2D1_FIGURE_BEGIN begin;
73 D2D1_FIGURE_END end;
74 D2D1_POINT_2F start_point;
75 unsigned int segment_count;
76 const struct geometry_segment *segments;
79 static void set_point(D2D1_POINT_2F *point, float x, float y)
81 point->x = x;
82 point->y = y;
85 static void set_quadratic(D2D1_QUADRATIC_BEZIER_SEGMENT *quadratic, float x1, float y1, float x2, float y2)
87 quadratic->point1.x = x1;
88 quadratic->point1.y = y1;
89 quadratic->point2.x = x2;
90 quadratic->point2.y = y2;
93 static void set_rect(D2D1_RECT_F *rect, float left, float top, float right, float bottom)
95 rect->left = left;
96 rect->top = top;
97 rect->right = right;
98 rect->bottom = bottom;
101 static void set_rounded_rect(D2D1_ROUNDED_RECT *rect, float left, float top, float right, float bottom,
102 float radius_x, float radius_y)
104 set_rect(&rect->rect, left, top, right, bottom);
105 rect->radiusX = radius_x;
106 rect->radiusY = radius_y;
109 static void set_rect_u(D2D1_RECT_U *rect, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
111 rect->left = left;
112 rect->top = top;
113 rect->right = right;
114 rect->bottom = bottom;
117 static void set_ellipse(D2D1_ELLIPSE *ellipse, float x, float y, float rx, float ry)
119 set_point(&ellipse->point, x, y);
120 ellipse->radiusX = rx;
121 ellipse->radiusY = ry;
124 static void set_color(D2D1_COLOR_F *color, float r, float g, float b, float a)
126 color->r = r;
127 color->g = g;
128 color->b = b;
129 color->a = a;
132 static void set_size_u(D2D1_SIZE_U *size, unsigned int w, unsigned int h)
134 size->width = w;
135 size->height = h;
138 static void set_size_f(D2D1_SIZE_F *size, float w, float h)
140 size->width = w;
141 size->height = h;
144 static void set_matrix_identity(D2D1_MATRIX_3X2_F *matrix)
146 matrix->_11 = 1.0f;
147 matrix->_12 = 0.0f;
148 matrix->_21 = 0.0f;
149 matrix->_22 = 1.0f;
150 matrix->_31 = 0.0f;
151 matrix->_32 = 0.0f;
154 static void rotate_matrix(D2D1_MATRIX_3X2_F *matrix, float theta)
156 float sin_theta, cos_theta, tmp_11, tmp_12;
158 sin_theta = sinf(theta);
159 cos_theta = cosf(theta);
160 tmp_11 = matrix->_11;
161 tmp_12 = matrix->_12;
163 matrix->_11 = cos_theta * tmp_11 + sin_theta * matrix->_21;
164 matrix->_12 = cos_theta * tmp_12 + sin_theta * matrix->_22;
165 matrix->_21 = -sin_theta * tmp_11 + cos_theta * matrix->_21;
166 matrix->_22 = -sin_theta * tmp_12 + cos_theta * matrix->_22;
169 static void scale_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
171 matrix->_11 *= x;
172 matrix->_12 *= x;
173 matrix->_21 *= y;
174 matrix->_22 *= y;
177 static void translate_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
179 matrix->_31 += x * matrix->_11 + y * matrix->_21;
180 matrix->_32 += x * matrix->_12 + y * matrix->_22;
183 static void line_to(ID2D1GeometrySink *sink, float x, float y)
185 D2D1_POINT_2F point;
187 set_point(&point, x, y);
188 ID2D1GeometrySink_AddLine(sink, point);
191 static void quadratic_to(ID2D1GeometrySink *sink, float x1, float y1, float x2, float y2)
193 D2D1_QUADRATIC_BEZIER_SEGMENT quadratic;
195 set_quadratic(&quadratic, x1, y1, x2, y2);
196 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
199 static void cubic_to(ID2D1GeometrySink *sink, float x1, float y1, float x2, float y2, float x3, float y3)
201 D2D1_BEZIER_SEGMENT b;
203 b.point1.x = x1;
204 b.point1.y = y1;
205 b.point2.x = x2;
206 b.point2.y = y2;
207 b.point3.x = x3;
208 b.point3.y = y3;
209 ID2D1GeometrySink_AddBezier(sink, &b);
212 static BOOL compare_float(float f, float g, unsigned int ulps)
214 int x = *(int *)&f;
215 int y = *(int *)&g;
217 if (x < 0)
218 x = INT_MIN - x;
219 if (y < 0)
220 y = INT_MIN - y;
222 if (abs(x - y) > ulps)
223 return FALSE;
225 return TRUE;
228 static BOOL compare_point(const D2D1_POINT_2F *point, float x, float y, unsigned int ulps)
230 return compare_float(point->x, x, ulps)
231 && compare_float(point->y, y, ulps);
234 static BOOL compare_rect(const D2D1_RECT_F *rect, float left, float top, float right, float bottom, unsigned int ulps)
236 return compare_float(rect->left, left, ulps)
237 && compare_float(rect->top, top, ulps)
238 && compare_float(rect->right, right, ulps)
239 && compare_float(rect->bottom, bottom, ulps);
242 static BOOL compare_bezier_segment(const D2D1_BEZIER_SEGMENT *b, float x1, float y1,
243 float x2, float y2, float x3, float y3, unsigned int ulps)
245 return compare_point(&b->point1, x1, y1, ulps)
246 && compare_point(&b->point2, x2, y2, ulps)
247 && compare_point(&b->point3, x3, y3, ulps);
250 static BOOL compare_sha1(void *data, unsigned int pitch, unsigned int bpp,
251 unsigned int w, unsigned int h, const char *ref_sha1)
253 static const char hex_chars[] = "0123456789abcdef";
254 HCRYPTPROV provider;
255 BYTE hash_data[20];
256 HCRYPTHASH hash;
257 unsigned int i;
258 char sha1[41];
259 BOOL ret;
261 ret = CryptAcquireContextW(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
262 ok(ret, "Failed to acquire crypt context.\n");
263 ret = CryptCreateHash(provider, CALG_SHA1, 0, 0, &hash);
264 ok(ret, "Failed to create hash.\n");
266 for (i = 0; i < h; ++i)
268 if (!(ret = CryptHashData(hash, (BYTE *)data + pitch * i, w * bpp, 0)))
269 break;
271 ok(ret, "Failed to hash data.\n");
273 i = sizeof(hash_data);
274 ret = CryptGetHashParam(hash, HP_HASHVAL, hash_data, &i, 0);
275 ok(ret, "Failed to get hash value.\n");
276 ok(i == sizeof(hash_data), "Got unexpected hash size %u.\n", i);
278 ret = CryptDestroyHash(hash);
279 ok(ret, "Failed to destroy hash.\n");
280 ret = CryptReleaseContext(provider, 0);
281 ok(ret, "Failed to release crypt context.\n");
283 for (i = 0; i < 20; ++i)
285 sha1[i * 2] = hex_chars[hash_data[i] >> 4];
286 sha1[i * 2 + 1] = hex_chars[hash_data[i] & 0xf];
288 sha1[40] = 0;
290 return !strcmp(ref_sha1, (char *)sha1);
293 static BOOL compare_surface(IDXGISurface *surface, const char *ref_sha1)
295 D3D10_MAPPED_TEXTURE2D mapped_texture;
296 D3D10_TEXTURE2D_DESC texture_desc;
297 DXGI_SURFACE_DESC surface_desc;
298 ID3D10Resource *src_resource;
299 ID3D10Texture2D *texture;
300 ID3D10Device *device;
301 HRESULT hr;
302 BOOL ret;
304 hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
305 ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
306 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
307 ok(SUCCEEDED(hr), "Failed to query resource interface, hr %#x.\n", hr);
309 hr = IDXGISurface_GetDesc(surface, &surface_desc);
310 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
311 texture_desc.Width = surface_desc.Width;
312 texture_desc.Height = surface_desc.Height;
313 texture_desc.MipLevels = 1;
314 texture_desc.ArraySize = 1;
315 texture_desc.Format = surface_desc.Format;
316 texture_desc.SampleDesc = surface_desc.SampleDesc;
317 texture_desc.Usage = D3D10_USAGE_STAGING;
318 texture_desc.BindFlags = 0;
319 texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
320 texture_desc.MiscFlags = 0;
321 hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &texture);
322 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
324 ID3D10Device_CopyResource(device, (ID3D10Resource *)texture, src_resource);
325 hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_READ, 0, &mapped_texture);
326 ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr);
327 ret = compare_sha1(mapped_texture.pData, mapped_texture.RowPitch, 4,
328 texture_desc.Width, texture_desc.Height, ref_sha1);
329 ID3D10Texture2D_Unmap(texture, 0);
331 ID3D10Texture2D_Release(texture);
332 ID3D10Resource_Release(src_resource);
333 ID3D10Device_Release(device);
335 return ret;
338 static BOOL compare_wic_bitmap(IWICBitmap *bitmap, const char *ref_sha1)
340 UINT stride, width, height, buffer_size;
341 IWICBitmapLock *lock;
342 BYTE *data;
343 HRESULT hr;
344 BOOL ret;
346 hr = IWICBitmap_Lock(bitmap, NULL, WICBitmapLockRead, &lock);
347 ok(SUCCEEDED(hr), "Failed to lock bitmap, hr %#x.\n", hr);
349 hr = IWICBitmapLock_GetDataPointer(lock, &buffer_size, &data);
350 ok(SUCCEEDED(hr), "Failed to get bitmap data, hr %#x.\n", hr);
352 hr = IWICBitmapLock_GetStride(lock, &stride);
353 ok(SUCCEEDED(hr), "Failed to get bitmap stride, hr %#x.\n", hr);
355 hr = IWICBitmapLock_GetSize(lock, &width, &height);
356 ok(SUCCEEDED(hr), "Failed to get bitmap size, hr %#x.\n", hr);
358 ret = compare_sha1(data, stride, 4, width, height, ref_sha1);
360 IWICBitmapLock_Release(lock);
362 return ret;
365 static void serialize_figure(struct figure *figure)
367 static const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
368 unsigned int i, j, k, span;
369 char output[76];
370 char t[3];
371 char *p;
373 for (i = 0, j = 0, k = 0, p = output; i < figure->span_count; ++i)
375 span = figure->spans[i];
376 while (span)
378 t[j] = span & 0x7f;
379 if (span > 0x7f)
380 t[j] |= 0x80;
381 span >>= 7;
382 if (++j == 3)
384 p[0] = lookup[(t[0] & 0xfc) >> 2];
385 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
386 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
387 p[3] = lookup[t[2] & 0x3f];
388 p += 4;
389 if (++k == 19)
391 trace("%.76s\n", output);
392 p = output;
393 k = 0;
395 j = 0;
399 if (j)
401 for (i = j; i < 3; ++i)
402 t[i] = 0;
403 p[0] = lookup[(t[0] & 0xfc) >> 2];
404 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
405 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
406 p[3] = lookup[t[2] & 0x3f];
407 ++k;
409 if (k)
410 trace("%.*s\n", k * 4, output);
413 static void figure_add_span(struct figure *figure, unsigned int span)
415 if (figure->span_count == figure->spans_size)
417 figure->spans_size *= 2;
418 figure->spans = HeapReAlloc(GetProcessHeap(), 0, figure->spans,
419 figure->spans_size * sizeof(*figure->spans));
422 figure->spans[figure->span_count++] = span;
425 static void deserialize_span(struct figure *figure, unsigned int *current, unsigned int *shift, unsigned int c)
427 *current |= (c & 0x7f) << *shift;
428 if (c & 0x80)
430 *shift += 7;
431 return;
434 if (*current)
435 figure_add_span(figure, *current);
436 *current = 0;
437 *shift = 0;
440 static void deserialize_figure(struct figure *figure, const BYTE *s)
442 static const BYTE lookup[] =
444 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
445 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
446 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
447 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
448 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
449 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
450 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
451 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
453 unsigned int current = 0, shift = 0;
454 const BYTE *ptr;
455 BYTE x, y;
457 figure->span_count = 0;
458 figure->spans_size = 64;
459 figure->spans = HeapAlloc(GetProcessHeap(), 0, figure->spans_size * sizeof(*figure->spans));
461 for (ptr = s; *ptr; ptr += 4)
463 x = lookup[ptr[0]];
464 y = lookup[ptr[1]];
465 deserialize_span(figure, &current, &shift, ((x & 0x3f) << 2) | ((y & 0x3f) >> 4));
466 x = lookup[ptr[2]];
467 deserialize_span(figure, &current, &shift, ((y & 0x0f) << 4) | ((x & 0x3f) >> 2));
468 y = lookup[ptr[3]];
469 deserialize_span(figure, &current, &shift, ((x & 0x03) << 6) | (y & 0x3f));
473 static void read_figure(struct figure *figure, BYTE *data, unsigned int pitch,
474 unsigned int x, unsigned int y, unsigned int w, unsigned int h, DWORD prev)
476 unsigned int i, j, span;
478 figure->span_count = 0;
479 for (i = 0, span = 0; i < h; ++i)
481 const DWORD *row = (DWORD *)&data[(y + i) * pitch + x * 4];
482 for (j = 0; j < w; ++j, ++span)
484 if ((i || j) && prev != row[j])
486 figure_add_span(figure, span);
487 prev = row[j];
488 span = 0;
492 if (span)
493 figure_add_span(figure, span);
496 static BOOL compare_figure(IDXGISurface *surface, unsigned int x, unsigned int y,
497 unsigned int w, unsigned int h, DWORD prev, unsigned int max_diff, const char *ref)
499 D3D10_MAPPED_TEXTURE2D mapped_texture;
500 D3D10_TEXTURE2D_DESC texture_desc;
501 struct figure ref_figure, figure;
502 DXGI_SURFACE_DESC surface_desc;
503 unsigned int i, j, span, diff;
504 ID3D10Resource *src_resource;
505 ID3D10Texture2D *texture;
506 ID3D10Device *device;
507 HRESULT hr;
509 hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
510 ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
511 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
512 ok(SUCCEEDED(hr), "Failed to query resource interface, hr %#x.\n", hr);
514 hr = IDXGISurface_GetDesc(surface, &surface_desc);
515 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
516 texture_desc.Width = surface_desc.Width;
517 texture_desc.Height = surface_desc.Height;
518 texture_desc.MipLevels = 1;
519 texture_desc.ArraySize = 1;
520 texture_desc.Format = surface_desc.Format;
521 texture_desc.SampleDesc = surface_desc.SampleDesc;
522 texture_desc.Usage = D3D10_USAGE_STAGING;
523 texture_desc.BindFlags = 0;
524 texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
525 texture_desc.MiscFlags = 0;
526 hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &texture);
527 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
529 ID3D10Device_CopyResource(device, (ID3D10Resource *)texture, src_resource);
530 hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_READ, 0, &mapped_texture);
531 ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr);
533 figure.span_count = 0;
534 figure.spans_size = 64;
535 figure.spans = HeapAlloc(GetProcessHeap(), 0, figure.spans_size * sizeof(*figure.spans));
537 read_figure(&figure, mapped_texture.pData, mapped_texture.RowPitch, x, y, w, h, prev);
539 deserialize_figure(&ref_figure, (BYTE *)ref);
540 span = w * h;
541 for (i = 0; i < ref_figure.span_count; ++i)
543 span -= ref_figure.spans[i];
545 if (span)
546 figure_add_span(&ref_figure, span);
548 for (i = 0, j = 0, diff = 0; i < figure.span_count && j < ref_figure.span_count;)
550 if (figure.spans[i] == ref_figure.spans[j])
552 if ((i ^ j) & 1)
553 diff += ref_figure.spans[j];
554 ++i;
555 ++j;
557 else if (figure.spans[i] > ref_figure.spans[j])
559 if ((i ^ j) & 1)
560 diff += ref_figure.spans[j];
561 figure.spans[i] -= ref_figure.spans[j];
562 ++j;
564 else
566 if ((i ^ j) & 1)
567 diff += figure.spans[i];
568 ref_figure.spans[j] -= figure.spans[i];
569 ++i;
572 if (diff > max_diff)
574 trace("diff %u > max_diff %u.\n", diff, max_diff);
575 read_figure(&figure, mapped_texture.pData, mapped_texture.RowPitch, x, y, w, h, prev);
576 serialize_figure(&figure);
579 HeapFree(GetProcessHeap(), 0, ref_figure.spans);
580 HeapFree(GetProcessHeap(), 0, figure.spans);
581 ID3D10Texture2D_Unmap(texture, 0);
583 ID3D10Texture2D_Release(texture);
584 ID3D10Resource_Release(src_resource);
585 ID3D10Device_Release(device);
587 return diff <= max_diff;
590 static ID3D10Device1 *create_device(void)
592 ID3D10Device1 *device;
594 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL,
595 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
596 return device;
597 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_WARP, NULL,
598 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
599 return device;
600 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL,
601 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
602 return device;
604 return NULL;
607 static HWND create_window(void)
609 RECT r = {0, 0, 640, 480};
611 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
613 return CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
614 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
617 static IDXGISwapChain *create_swapchain(ID3D10Device1 *device, HWND window, BOOL windowed)
619 IDXGISwapChain *swapchain;
620 DXGI_SWAP_CHAIN_DESC desc;
621 IDXGIDevice *dxgi_device;
622 IDXGIAdapter *adapter;
623 IDXGIFactory *factory;
624 HRESULT hr;
626 hr = ID3D10Device1_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
627 ok(SUCCEEDED(hr), "Failed to get DXGI device, hr %#x.\n", hr);
628 hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter);
629 ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr);
630 IDXGIDevice_Release(dxgi_device);
631 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
632 ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr);
633 IDXGIAdapter_Release(adapter);
635 desc.BufferDesc.Width = 640;
636 desc.BufferDesc.Height = 480;
637 desc.BufferDesc.RefreshRate.Numerator = 60;
638 desc.BufferDesc.RefreshRate.Denominator = 1;
639 desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
640 desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
641 desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
642 desc.SampleDesc.Count = 1;
643 desc.SampleDesc.Quality = 0;
644 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
645 desc.BufferCount = 1;
646 desc.OutputWindow = window;
647 desc.Windowed = windowed;
648 desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
649 desc.Flags = 0;
651 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &desc, &swapchain);
652 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
653 IDXGIFactory_Release(factory);
655 return swapchain;
658 static ID2D1RenderTarget *create_render_target_desc(IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
660 ID2D1RenderTarget *render_target;
661 ID2D1Factory *factory;
662 HRESULT hr;
664 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
665 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
666 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, desc, &render_target);
667 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
668 ID2D1Factory_Release(factory);
670 return render_target;
673 static ID2D1RenderTarget *create_render_target(IDXGISurface *surface)
675 D2D1_RENDER_TARGET_PROPERTIES desc;
677 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
678 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
679 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
680 desc.dpiX = 0.0f;
681 desc.dpiY = 0.0f;
682 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
683 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
685 return create_render_target_desc(surface, &desc);
688 static inline struct geometry_sink *impl_from_ID2D1SimplifiedGeometrySink(ID2D1SimplifiedGeometrySink *iface)
690 return CONTAINING_RECORD(iface, struct geometry_sink, ID2D1SimplifiedGeometrySink_iface);
693 static HRESULT STDMETHODCALLTYPE geometry_sink_QueryInterface(ID2D1SimplifiedGeometrySink *iface,
694 REFIID iid, void **out)
696 if (IsEqualGUID(iid, &IID_ID2D1SimplifiedGeometrySink)
697 || IsEqualGUID(iid, &IID_IUnknown))
699 *out = iface;
700 return S_OK;
703 *out = NULL;
704 return E_NOINTERFACE;
707 static ULONG STDMETHODCALLTYPE geometry_sink_AddRef(ID2D1SimplifiedGeometrySink *iface)
709 return 0;
712 static ULONG STDMETHODCALLTYPE geometry_sink_Release(ID2D1SimplifiedGeometrySink *iface)
714 return 0;
717 static void STDMETHODCALLTYPE geometry_sink_SetFillMode(ID2D1SimplifiedGeometrySink *iface, D2D1_FILL_MODE mode)
719 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
721 sink->fill_mode = mode;
724 static void STDMETHODCALLTYPE geometry_sink_SetSegmentFlags(ID2D1SimplifiedGeometrySink *iface,
725 D2D1_PATH_SEGMENT flags)
727 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
729 sink->segment_flags = flags;
732 static void STDMETHODCALLTYPE geometry_sink_BeginFigure(ID2D1SimplifiedGeometrySink *iface,
733 D2D1_POINT_2F start_point, D2D1_FIGURE_BEGIN figure_begin)
735 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
736 struct geometry_figure *figure;
738 if (sink->figure_count == sink->figures_size)
740 sink->figures_size *= 2;
741 sink->figures = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sink->figures,
742 sink->figures_size * sizeof(*sink->figures));
744 figure = &sink->figures[sink->figure_count++];
746 figure->begin = figure_begin;
747 figure->start_point = start_point;
748 figure->segments_size = 4;
749 figure->segments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
750 figure->segments_size * sizeof(*figure->segments));
753 static struct geometry_segment *geometry_figure_add_segment(struct geometry_figure *figure)
755 if (figure->segment_count == figure->segments_size)
757 figure->segments_size *= 2;
758 figure->segments = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, figure->segments,
759 figure->segments_size * sizeof(*figure->segments));
761 return &figure->segments[figure->segment_count++];
764 static void STDMETHODCALLTYPE geometry_sink_AddLines(ID2D1SimplifiedGeometrySink *iface,
765 const D2D1_POINT_2F *points, UINT32 count)
767 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
768 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
769 struct geometry_segment *segment;
770 unsigned int i;
772 for (i = 0; i < count; ++i)
774 segment = geometry_figure_add_segment(figure);
775 segment->type = SEGMENT_LINE;
776 segment->u.line = points[i];
777 segment->flags = sink->segment_flags;
781 static void STDMETHODCALLTYPE geometry_sink_AddBeziers(ID2D1SimplifiedGeometrySink *iface,
782 const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
784 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
785 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
786 struct geometry_segment *segment;
787 unsigned int i;
789 for (i = 0; i < count; ++i)
791 segment = geometry_figure_add_segment(figure);
792 segment->type = SEGMENT_BEZIER;
793 segment->u.bezier = beziers[i];
794 segment->flags = sink->segment_flags;
798 static void STDMETHODCALLTYPE geometry_sink_EndFigure(ID2D1SimplifiedGeometrySink *iface,
799 D2D1_FIGURE_END figure_end)
801 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
802 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
804 figure->end = figure_end;
807 static HRESULT STDMETHODCALLTYPE geometry_sink_Close(ID2D1SimplifiedGeometrySink *iface)
809 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
811 sink->closed = TRUE;
813 return S_OK;
816 static const struct ID2D1SimplifiedGeometrySinkVtbl geometry_sink_vtbl =
818 geometry_sink_QueryInterface,
819 geometry_sink_AddRef,
820 geometry_sink_Release,
821 geometry_sink_SetFillMode,
822 geometry_sink_SetSegmentFlags,
823 geometry_sink_BeginFigure,
824 geometry_sink_AddLines,
825 geometry_sink_AddBeziers,
826 geometry_sink_EndFigure,
827 geometry_sink_Close,
830 static void geometry_sink_init(struct geometry_sink *sink)
832 memset(sink, 0, sizeof(*sink));
833 sink->ID2D1SimplifiedGeometrySink_iface.lpVtbl = &geometry_sink_vtbl;
834 sink->figures_size = 4;
835 sink->figures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
836 sink->figures_size * sizeof(*sink->figures));
839 static void geometry_sink_cleanup(struct geometry_sink *sink)
841 unsigned int i;
843 for (i = 0; i < sink->figure_count; ++i)
845 HeapFree(GetProcessHeap(), 0, sink->figures[i].segments);
847 HeapFree(GetProcessHeap(), 0, sink->figures);
850 #define geometry_sink_check(a, b, c, d, e) geometry_sink_check_(__LINE__, a, b, c, d, e)
851 static void geometry_sink_check_(unsigned int line, const struct geometry_sink *sink, D2D1_FILL_MODE fill_mode,
852 unsigned int figure_count, const struct expected_geometry_figure *expected_figures, unsigned int ulps)
854 const struct geometry_segment *segment, *expected_segment;
855 const struct expected_geometry_figure *expected_figure;
856 const struct geometry_figure *figure;
857 unsigned int i, j;
858 BOOL match;
860 ok_(__FILE__, line)(sink->fill_mode == fill_mode,
861 "Got unexpected fill mode %#x.\n", sink->fill_mode);
862 ok_(__FILE__, line)(sink->figure_count == figure_count,
863 "Got unexpected figure count %u, expected %u.\n", sink->figure_count, figure_count);
864 ok_(__FILE__, line)(!sink->closed, "Sink is closed.\n");
866 for (i = 0; i < figure_count; ++i)
868 expected_figure = &expected_figures[i];
869 figure = &sink->figures[i];
871 ok_(__FILE__, line)(figure->begin == expected_figure->begin,
872 "Got unexpected figure %u begin %#x, expected %#x.\n",
873 i, figure->begin, expected_figure->begin);
874 ok_(__FILE__, line)(figure->end == expected_figure->end,
875 "Got unexpected figure %u end %#x, expected %#x.\n",
876 i, figure->end, expected_figure->end);
877 match = compare_point(&figure->start_point,
878 expected_figure->start_point.x, expected_figure->start_point.y, ulps);
879 ok_(__FILE__, line)(match, "Got unexpected figure %u start point {%.8e, %.8e}, expected {%.8e, %.8e}.\n",
880 i, figure->start_point.x, figure->start_point.y,
881 expected_figure->start_point.x, expected_figure->start_point.y);
882 ok_(__FILE__, line)(figure->segment_count == expected_figure->segment_count,
883 "Got unexpected figure %u segment count %u, expected %u.\n",
884 i, figure->segment_count, expected_figure->segment_count);
886 for (j = 0; j < figure->segment_count; ++j)
888 expected_segment = &expected_figure->segments[j];
889 segment = &figure->segments[j];
890 ok_(__FILE__, line)(segment->type == expected_segment->type,
891 "Got unexpected figure %u, segment %u type %#x, expected %#x.\n",
892 i, j, segment->type, expected_segment->type);
893 ok_(__FILE__, line)(segment->flags == expected_segment->flags,
894 "Got unexpected figure %u, segment %u flags %#x, expected %#x.\n",
895 i, j, segment->flags, expected_segment->flags);
896 switch (segment->type)
898 case SEGMENT_LINE:
899 match = compare_point(&segment->u.line,
900 expected_segment->u.line.x, expected_segment->u.line.y, ulps);
901 ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u {%.8e, %.8e}, "
902 "expected {%.8e, %.8e}.\n",
903 i, j, segment->u.line.x, segment->u.line.y,
904 expected_segment->u.line.x, expected_segment->u.line.y);
905 break;
907 case SEGMENT_BEZIER:
908 match = compare_bezier_segment(&segment->u.bezier,
909 expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
910 expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
911 expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y,
912 ulps);
913 ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u "
914 "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}, "
915 "expected {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
916 i, j, segment->u.bezier.point1.x, segment->u.bezier.point1.y,
917 segment->u.bezier.point2.x, segment->u.bezier.point2.y,
918 segment->u.bezier.point3.x, segment->u.bezier.point3.y,
919 expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
920 expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
921 expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y);
922 break;
928 static void test_clip(void)
930 IDXGISwapChain *swapchain;
931 D2D1_MATRIX_3X2_F matrix;
932 D2D1_SIZE_U pixel_size;
933 ID2D1RenderTarget *rt;
934 ID3D10Device1 *device;
935 IDXGISurface *surface;
936 D2D1_POINT_2F point;
937 D2D1_COLOR_F color;
938 float dpi_x, dpi_y;
939 D2D1_RECT_F rect;
940 D2D1_SIZE_F size;
941 HWND window;
942 HRESULT hr;
943 BOOL match;
944 static const D2D1_MATRIX_3X2_F identity =
946 1.0f, 0.0f,
947 0.0f, 1.0f,
948 0.0f, 0.0f,
951 if (!(device = create_device()))
953 skip("Failed to create device, skipping tests.\n");
954 return;
956 window = create_window();
957 swapchain = create_swapchain(device, window, TRUE);
958 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
959 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
960 rt = create_render_target(surface);
961 ok(!!rt, "Failed to create render target.\n");
963 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
964 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
965 ok(dpi_y == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
966 size = ID2D1RenderTarget_GetSize(rt);
967 ok(size.width == 640.0f, "Got unexpected width %.8e.\n", size.width);
968 ok(size.height == 480.0f, "Got unexpected height %.8e.\n", size.height);
969 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
970 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
971 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
973 ID2D1RenderTarget_GetTransform(rt, &matrix);
974 ok(!memcmp(&matrix, &identity, sizeof(matrix)),
975 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
976 matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32);
978 ID2D1RenderTarget_BeginDraw(rt);
980 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
981 ID2D1RenderTarget_Clear(rt, &color);
983 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
984 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
985 ok(dpi_x == 48.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
986 ok(dpi_y == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
987 size = ID2D1RenderTarget_GetSize(rt);
988 ok(size.width == 1280.0f, "Got unexpected width %.8e.\n", size.width);
989 ok(size.height == 240.0f, "Got unexpected height %.8e.\n", size.height);
990 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
991 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
992 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
994 /* The effective clip rect is the intersection of all currently pushed
995 * clip rects. Clip rects are in DIPs. */
996 set_rect(&rect, 0.0f, 0.0f, 1280.0f, 80.0f);
997 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
998 set_rect(&rect, 0.0f, 0.0f, 426.0f, 240.0f);
999 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1001 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
1002 ID2D1RenderTarget_Clear(rt, &color);
1003 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1004 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1006 ID2D1RenderTarget_SetDpi(rt, 0.0f, 0.0f);
1007 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1008 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1009 ok(dpi_y == 96.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1011 ID2D1RenderTarget_SetDpi(rt, 192.0f, 192.0f);
1012 ID2D1RenderTarget_SetDpi(rt, 0.0f, 96.0f);
1013 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1014 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1015 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1017 ID2D1RenderTarget_SetDpi(rt, -10.0f, 96.0f);
1018 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1019 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1020 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1022 ID2D1RenderTarget_SetDpi(rt, 96.0f, -10.0f);
1023 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1024 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1025 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1027 ID2D1RenderTarget_SetDpi(rt, 96.0f, 0.0f);
1028 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1029 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1030 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1032 ID2D1RenderTarget_SetDpi(rt, 96.0f, 96.0f);
1034 /* Transformations apply to clip rects, the effective clip rect is the
1035 * (axis-aligned) bounding box of the transformed clip rect. */
1036 set_point(&point, 320.0f, 240.0f);
1037 D2D1MakeRotateMatrix(30.0f, point, &matrix);
1038 ID2D1RenderTarget_SetTransform(rt, &matrix);
1039 set_rect(&rect, 215.0f, 208.0f, 425.0f, 272.0f);
1040 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1041 set_color(&color, 1.0f, 1.0f, 1.0f, 1.0f);
1042 ID2D1RenderTarget_Clear(rt, &color);
1043 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1045 /* Transformations are applied when pushing the clip rect, transformations
1046 * set afterwards have no effect on the current clip rect. This includes
1047 * SetDpi(). */
1048 ID2D1RenderTarget_SetTransform(rt, &identity);
1049 set_rect(&rect, 427.0f, 320.0f, 640.0f, 480.0f);
1050 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1051 ID2D1RenderTarget_SetTransform(rt, &matrix);
1052 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
1053 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
1054 ID2D1RenderTarget_Clear(rt, &color);
1055 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1057 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1058 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1059 match = compare_surface(surface, "035a44d4198d6e422e9de6185b5b2c2bac5e33c9");
1060 ok(match, "Surface does not match.\n");
1062 ID2D1RenderTarget_Release(rt);
1063 IDXGISurface_Release(surface);
1064 IDXGISwapChain_Release(swapchain);
1065 ID3D10Device1_Release(device);
1066 DestroyWindow(window);
1069 static void test_state_block(void)
1071 IDWriteRenderingParams *text_rendering_params1, *text_rendering_params2;
1072 D2D1_DRAWING_STATE_DESCRIPTION drawing_state;
1073 ID2D1DrawingStateBlock *state_block;
1074 IDWriteFactory *dwrite_factory;
1075 IDXGISwapChain *swapchain;
1076 ID2D1RenderTarget *rt;
1077 ID3D10Device1 *device;
1078 IDXGISurface *surface;
1079 ID2D1Factory *factory;
1080 ULONG refcount;
1081 HWND window;
1082 HRESULT hr;
1083 static const D2D1_MATRIX_3X2_F identity =
1085 1.0f, 0.0f,
1086 0.0f, 1.0f,
1087 0.0f, 0.0f,
1089 static const D2D1_MATRIX_3X2_F transform1 =
1091 1.0f, 2.0f,
1092 3.0f, 4.0f,
1093 5.0f, 6.0f,
1095 static const D2D1_MATRIX_3X2_F transform2 =
1097 7.0f, 8.0f,
1098 9.0f, 10.0f,
1099 11.0f, 12.0f,
1102 if (!(device = create_device()))
1104 skip("Failed to create device, skipping tests.\n");
1105 return;
1107 window = create_window();
1108 swapchain = create_swapchain(device, window, TRUE);
1109 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1110 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1111 rt = create_render_target(surface);
1112 ok(!!rt, "Failed to create render target.\n");
1113 ID2D1RenderTarget_GetFactory(rt, &factory);
1114 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
1115 ok(SUCCEEDED(hr), "Failed to create dwrite factory, hr %#x.\n", hr);
1116 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &text_rendering_params1);
1117 ok(SUCCEEDED(hr), "Failed to create dwrite rendering params, hr %#x.\n", hr);
1118 IDWriteFactory_Release(dwrite_factory);
1120 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1121 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1122 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1123 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1124 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
1125 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1126 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1127 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %s:%s.\n",
1128 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1129 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1130 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
1131 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1132 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1133 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1134 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1135 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1137 hr = ID2D1Factory_CreateDrawingStateBlock(factory, NULL, NULL, &state_block);
1138 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
1139 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1140 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1141 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1142 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
1143 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1144 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %s:%s.\n",
1145 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1146 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
1147 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1148 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1149 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1150 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1151 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1152 ID2D1DrawingStateBlock_Release(state_block);
1154 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
1155 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
1156 drawing_state.tag1 = 0xdead;
1157 drawing_state.tag2 = 0xbeef;
1158 drawing_state.transform = transform1;
1159 hr = ID2D1Factory_CreateDrawingStateBlock(factory, &drawing_state, text_rendering_params1, &state_block);
1160 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
1162 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1163 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1164 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1165 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
1166 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1167 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %s:%s.\n",
1168 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1169 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1170 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1171 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1172 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1173 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1174 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1175 text_rendering_params2, text_rendering_params1);
1176 IDWriteRenderingParams_Release(text_rendering_params2);
1178 ID2D1RenderTarget_RestoreDrawingState(rt, state_block);
1180 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1181 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1182 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1183 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1184 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
1185 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1186 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1187 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %s:%s.\n",
1188 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1189 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1190 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1191 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1192 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1193 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1194 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1195 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1196 text_rendering_params2, text_rendering_params1);
1197 IDWriteRenderingParams_Release(text_rendering_params2);
1199 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
1200 ID2D1RenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
1201 ID2D1RenderTarget_SetTags(rt, 1, 2);
1202 ID2D1RenderTarget_SetTransform(rt, &transform2);
1203 ID2D1RenderTarget_SetTextRenderingParams(rt, NULL);
1205 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1206 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1207 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1208 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1209 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
1210 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1211 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1212 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %s:%s.\n",
1213 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1214 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1215 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
1216 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1217 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1218 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1219 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1220 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1222 ID2D1RenderTarget_SaveDrawingState(rt, state_block);
1224 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1225 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1226 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1227 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
1228 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1229 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %s:%s.\n",
1230 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1231 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
1232 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1233 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1234 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1235 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1236 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1238 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
1239 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1240 drawing_state.tag1 = 3;
1241 drawing_state.tag2 = 4;
1242 drawing_state.transform = transform1;
1243 ID2D1DrawingStateBlock_SetDescription(state_block, &drawing_state);
1244 ID2D1DrawingStateBlock_SetTextRenderingParams(state_block, text_rendering_params1);
1246 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1247 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1248 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1249 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE,
1250 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1251 ok(drawing_state.tag1 == 3 && drawing_state.tag2 == 4, "Got unexpected tags %s:%s.\n",
1252 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1253 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1254 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1255 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1256 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1257 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1258 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1259 text_rendering_params2, text_rendering_params1);
1260 IDWriteRenderingParams_Release(text_rendering_params2);
1262 ID2D1DrawingStateBlock_Release(state_block);
1264 refcount = IDWriteRenderingParams_Release(text_rendering_params1);
1265 ok(!refcount, "Rendering params %u references left.\n", refcount);
1266 ID2D1Factory_Release(factory);
1267 ID2D1RenderTarget_Release(rt);
1268 IDXGISurface_Release(surface);
1269 IDXGISwapChain_Release(swapchain);
1270 ID3D10Device1_Release(device);
1271 DestroyWindow(window);
1274 static void test_color_brush(void)
1276 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1277 D2D1_BRUSH_PROPERTIES brush_desc;
1278 D2D1_COLOR_F color, tmp_color;
1279 ID2D1SolidColorBrush *brush;
1280 IDXGISwapChain *swapchain;
1281 ID2D1RenderTarget *rt;
1282 ID3D10Device1 *device;
1283 IDXGISurface *surface;
1284 D2D1_RECT_F rect;
1285 float opacity;
1286 HWND window;
1287 HRESULT hr;
1288 BOOL match;
1290 if (!(device = create_device()))
1292 skip("Failed to create device, skipping tests.\n");
1293 return;
1295 window = create_window();
1296 swapchain = create_swapchain(device, window, TRUE);
1297 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1298 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1299 rt = create_render_target(surface);
1300 ok(!!rt, "Failed to create render target.\n");
1302 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1303 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1305 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
1306 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
1307 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1308 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
1309 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
1310 set_matrix_identity(&matrix);
1311 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
1312 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1313 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1314 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1315 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1316 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
1317 ok(!memcmp(&tmp_color, &color, sizeof(color)),
1318 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
1319 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
1320 ID2D1SolidColorBrush_Release(brush);
1322 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
1323 brush_desc.opacity = 0.3f;
1324 set_matrix_identity(&matrix);
1325 scale_matrix(&matrix, 2.0f, 2.0f);
1326 brush_desc.transform = matrix;
1327 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, &brush_desc, &brush);
1328 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1329 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
1330 ok(opacity == 0.3f, "Got unexpected opacity %.8e.\n", opacity);
1331 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
1332 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1333 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1334 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1335 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1336 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
1337 ok(!memcmp(&tmp_color, &color, sizeof(color)),
1338 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
1339 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
1341 ID2D1RenderTarget_BeginDraw(rt);
1343 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1344 ID2D1RenderTarget_Clear(rt, &color);
1346 ID2D1SolidColorBrush_SetOpacity(brush, 1.0f);
1347 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
1348 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
1350 set_matrix_identity(&matrix);
1351 scale_matrix(&matrix, 0.5f, 2.0f);
1352 translate_matrix(&matrix, 320.0f, 240.0f);
1353 rotate_matrix(&matrix, M_PI / 4.0f);
1354 ID2D1RenderTarget_SetTransform(rt, &matrix);
1355 set_color(&color, 1.0f, 0.0f, 0.0f, 0.625f);
1356 ID2D1SolidColorBrush_SetColor(brush, &color);
1357 ID2D1SolidColorBrush_SetOpacity(brush, 0.75f);
1358 set_rect(&rect, -80.0f, -60.0f, 80.0f, 60.0f);
1359 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
1361 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1362 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1363 match = compare_surface(surface, "6d1218fca5e21fb7e287b3a439d60dbc251f5ceb");
1364 ok(match, "Surface does not match.\n");
1366 ID2D1SolidColorBrush_Release(brush);
1367 ID2D1RenderTarget_Release(rt);
1368 IDXGISurface_Release(surface);
1369 IDXGISwapChain_Release(swapchain);
1370 ID3D10Device1_Release(device);
1371 DestroyWindow(window);
1374 static void test_bitmap_brush(void)
1376 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode;
1377 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1378 D2D1_BITMAP_PROPERTIES bitmap_desc;
1379 ID2D1Bitmap *bitmap, *tmp_bitmap;
1380 D2D1_RECT_F src_rect, dst_rect;
1381 D2D1_EXTEND_MODE extend_mode;
1382 IDXGISwapChain *swapchain;
1383 ID2D1BitmapBrush *brush;
1384 ID2D1RenderTarget *rt;
1385 ID3D10Device1 *device;
1386 IDXGISurface *surface;
1387 D2D1_COLOR_F color;
1388 D2D1_SIZE_U size;
1389 unsigned int i;
1390 ULONG refcount;
1391 float opacity;
1392 HWND window;
1393 HRESULT hr;
1394 BOOL match;
1396 static const struct
1398 D2D1_EXTEND_MODE extend_mode_x;
1399 D2D1_EXTEND_MODE extend_mode_y;
1400 float translate_x;
1401 float translate_y;
1402 D2D1_RECT_F rect;
1404 extend_mode_tests[] =
1406 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_MIRROR, -7.0f, 1.0f, {-4.0f, 0.0f, -8.0f, 4.0f}},
1407 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_MIRROR, -3.0f, 1.0f, {-4.0f, 4.0f, 0.0f, 0.0f}},
1408 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_MIRROR, 1.0f, 1.0f, { 4.0f, 0.0f, 0.0f, 4.0f}},
1409 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_WRAP, -7.0f, 5.0f, {-8.0f, 8.0f, -4.0f, 4.0f}},
1410 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP, -3.0f, 5.0f, { 0.0f, 4.0f, -4.0f, 8.0f}},
1411 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_WRAP, 1.0f, 5.0f, { 0.0f, 8.0f, 4.0f, 4.0f}},
1412 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_CLAMP, -7.0f, 9.0f, {-4.0f, 8.0f, -8.0f, 12.0f}},
1413 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, -3.0f, 9.0f, {-4.0f, 12.0f, 0.0f, 8.0f}},
1414 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_CLAMP, 1.0f, 9.0f, { 4.0f, 8.0f, 0.0f, 12.0f}},
1416 static const DWORD bitmap_data[] =
1418 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
1419 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
1420 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
1421 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
1424 if (!(device = create_device()))
1426 skip("Failed to create device, skipping tests.\n");
1427 return;
1429 window = create_window();
1430 swapchain = create_swapchain(device, window, TRUE);
1431 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1432 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1433 rt = create_render_target(surface);
1434 ok(!!rt, "Failed to create render target.\n");
1436 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1437 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1439 set_size_u(&size, 4, 4);
1440 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1441 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1442 bitmap_desc.dpiX = 96.0f;
1443 bitmap_desc.dpiY = 96.0f;
1444 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1445 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1447 /* Creating a brush with a NULL bitmap crashes on Vista, but works fine on
1448 * Windows 7+. */
1449 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1450 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1451 ID2D1BitmapBrush_GetBitmap(brush, &tmp_bitmap);
1452 ok(tmp_bitmap == bitmap, "Got unexpected bitmap %p, expected %p.\n", tmp_bitmap, bitmap);
1453 ID2D1Bitmap_Release(tmp_bitmap);
1454 opacity = ID2D1BitmapBrush_GetOpacity(brush);
1455 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
1456 set_matrix_identity(&matrix);
1457 ID2D1BitmapBrush_GetTransform(brush, &tmp_matrix);
1458 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1459 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1460 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1461 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1462 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1463 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1464 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1465 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1466 interpolation_mode = ID2D1BitmapBrush_GetInterpolationMode(brush);
1467 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
1468 "Got unexpected interpolation mode %#x.\n", interpolation_mode);
1469 ID2D1BitmapBrush_Release(brush);
1471 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1472 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1473 set_matrix_identity(&matrix);
1474 translate_matrix(&matrix, 40.0f, 120.0f);
1475 scale_matrix(&matrix, 20.0f, 60.0f);
1476 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1477 ID2D1BitmapBrush_SetInterpolationMode(brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1479 ID2D1RenderTarget_BeginDraw(rt);
1481 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1482 ID2D1RenderTarget_Clear(rt, &color);
1484 set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
1485 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1487 set_matrix_identity(&matrix);
1488 scale_matrix(&matrix, 0.5f, 2.0f);
1489 translate_matrix(&matrix, 320.0f, 240.0f);
1490 rotate_matrix(&matrix, M_PI / 4.0f);
1491 ID2D1RenderTarget_SetTransform(rt, &matrix);
1492 set_matrix_identity(&matrix);
1493 translate_matrix(&matrix, -80.0f, -60.0f);
1494 scale_matrix(&matrix, 64.0f, 32.0f);
1495 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1496 ID2D1BitmapBrush_SetOpacity(brush, 0.75f);
1497 set_rect(&dst_rect, -80.0f, -60.0f, 80.0f, 60.0f);
1498 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1500 set_matrix_identity(&matrix);
1501 translate_matrix(&matrix, 200.0f, 120.0f);
1502 scale_matrix(&matrix, 20.0f, 60.0f);
1503 ID2D1RenderTarget_SetTransform(rt, &matrix);
1504 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f,
1505 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1506 set_rect(&dst_rect, -4.0f, 12.0f, -8.0f, 8.0f);
1507 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 0.75f,
1508 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1509 set_rect(&dst_rect, 0.0f, 8.0f, 4.0f, 12.0f);
1510 set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
1511 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1512 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1514 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1515 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1516 match = compare_surface(surface, "9437f4447d98feaad41a1c4202ee90aadc718ee6");
1517 ok(match, "Surface does not match.\n");
1519 ID2D1RenderTarget_BeginDraw(rt);
1521 ID2D1RenderTarget_Clear(rt, &color);
1523 ID2D1BitmapBrush_SetOpacity(brush, 1.0f);
1524 for (i = 0; i < sizeof(extend_mode_tests) / sizeof(*extend_mode_tests); ++i)
1526 ID2D1BitmapBrush_SetExtendModeX(brush, extend_mode_tests[i].extend_mode_x);
1527 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1528 ok(extend_mode == extend_mode_tests[i].extend_mode_x,
1529 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1530 i, extend_mode, extend_mode_tests[i].extend_mode_x);
1531 ID2D1BitmapBrush_SetExtendModeY(brush, extend_mode_tests[i].extend_mode_y);
1532 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1533 ok(extend_mode == extend_mode_tests[i].extend_mode_y,
1534 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1535 i, extend_mode, extend_mode_tests[i].extend_mode_y);
1536 set_matrix_identity(&matrix);
1537 translate_matrix(&matrix, extend_mode_tests[i].translate_x, extend_mode_tests[i].translate_y);
1538 scale_matrix(&matrix, 0.5f, 0.5f);
1539 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1540 ID2D1RenderTarget_FillRectangle(rt, &extend_mode_tests[i].rect, (ID2D1Brush *)brush);
1543 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1544 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1545 match = compare_surface(surface, "b4b775afecdae2d26642001f4faff73663bb8b31");
1546 ok(match, "Surface does not match.\n");
1548 ID2D1BitmapBrush_Release(brush);
1549 refcount = ID2D1Bitmap_Release(bitmap);
1550 ok(!refcount, "Bitmap has %u references left.\n", refcount);
1551 ID2D1RenderTarget_Release(rt);
1552 IDXGISurface_Release(surface);
1553 IDXGISwapChain_Release(swapchain);
1554 ID3D10Device1_Release(device);
1555 DestroyWindow(window);
1558 static void fill_geometry_sink(ID2D1GeometrySink *sink)
1560 D2D1_POINT_2F point;
1562 set_point(&point, 15.0f, 20.0f);
1563 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1564 line_to(sink, 55.0f, 20.0f);
1565 line_to(sink, 55.0f, 220.0f);
1566 line_to(sink, 25.0f, 220.0f);
1567 line_to(sink, 25.0f, 100.0f);
1568 line_to(sink, 75.0f, 100.0f);
1569 line_to(sink, 75.0f, 300.0f);
1570 line_to(sink, 5.0f, 300.0f);
1571 line_to(sink, 5.0f, 60.0f);
1572 line_to(sink, 45.0f, 60.0f);
1573 line_to(sink, 45.0f, 180.0f);
1574 line_to(sink, 35.0f, 180.0f);
1575 line_to(sink, 35.0f, 140.0f);
1576 line_to(sink, 65.0f, 140.0f);
1577 line_to(sink, 65.0f, 260.0f);
1578 line_to(sink, 15.0f, 260.0f);
1579 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1581 set_point(&point, 155.0f, 300.0f);
1582 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1583 line_to(sink, 155.0f, 160.0f);
1584 line_to(sink, 85.0f, 160.0f);
1585 line_to(sink, 85.0f, 300.0f);
1586 line_to(sink, 120.0f, 300.0f);
1587 line_to(sink, 120.0f, 20.0f);
1588 line_to(sink, 155.0f, 20.0f);
1589 line_to(sink, 155.0f, 160.0f);
1590 line_to(sink, 85.0f, 160.0f);
1591 line_to(sink, 85.0f, 20.0f);
1592 line_to(sink, 120.0f, 20.0f);
1593 line_to(sink, 120.0f, 300.0f);
1594 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1596 set_point(&point, 165.0f, 20.0f);
1597 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1598 line_to(sink, 165.0f, 300.0f);
1599 line_to(sink, 235.0f, 300.0f);
1600 line_to(sink, 235.0f, 20.0f);
1601 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1602 set_point(&point, 225.0f, 60.0f);
1603 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1604 line_to(sink, 225.0f, 260.0f);
1605 line_to(sink, 175.0f, 260.0f);
1606 line_to(sink, 175.0f, 60.0f);
1607 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1608 set_point(&point, 215.0f, 220.0f);
1609 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1610 line_to(sink, 185.0f, 220.0f);
1611 line_to(sink, 185.0f, 100.0f);
1612 line_to(sink, 215.0f, 100.0f);
1613 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1614 set_point(&point, 195.0f, 180.0f);
1615 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1616 line_to(sink, 205.0f, 180.0f);
1617 line_to(sink, 205.0f, 140.0f);
1618 line_to(sink, 195.0f, 140.0f);
1619 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1622 static void fill_geometry_sink_bezier(ID2D1GeometrySink *sink)
1624 D2D1_POINT_2F point;
1626 set_point(&point, 5.0f, 160.0f);
1627 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1628 quadratic_to(sink, 40.0f, 160.0f, 40.0f, 20.0f);
1629 quadratic_to(sink, 40.0f, 160.0f, 75.0f, 160.0f);
1630 quadratic_to(sink, 40.0f, 160.0f, 40.0f, 300.0f);
1631 quadratic_to(sink, 40.0f, 160.0f, 5.0f, 160.0f);
1632 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1634 set_point(&point, 20.0f, 160.0f);
1635 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1636 quadratic_to(sink, 20.0f, 80.0f, 40.0f, 80.0f);
1637 quadratic_to(sink, 60.0f, 80.0f, 60.0f, 160.0f);
1638 quadratic_to(sink, 60.0f, 240.0f, 40.0f, 240.0f);
1639 quadratic_to(sink, 20.0f, 240.0f, 20.0f, 160.0f);
1640 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1642 set_point(&point, 5.0f, 612.0f);
1643 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1644 quadratic_to(sink, 40.0f, 612.0f, 40.0f, 752.0f);
1645 quadratic_to(sink, 40.0f, 612.0f, 75.0f, 612.0f);
1646 quadratic_to(sink, 40.0f, 612.0f, 40.0f, 472.0f);
1647 quadratic_to(sink, 40.0f, 612.0f, 5.0f, 612.0f);
1648 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1650 set_point(&point, 20.0f, 612.0f);
1651 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1652 quadratic_to(sink, 20.0f, 692.0f, 40.0f, 692.0f);
1653 quadratic_to(sink, 60.0f, 692.0f, 60.0f, 612.0f);
1654 quadratic_to(sink, 60.0f, 532.0f, 40.0f, 532.0f);
1655 quadratic_to(sink, 20.0f, 532.0f, 20.0f, 612.0f);
1656 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1659 static void test_path_geometry(void)
1661 ID2D1TransformedGeometry *transformed_geometry;
1662 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1663 ID2D1GeometrySink *sink, *tmp_sink;
1664 struct geometry_sink simplify_sink;
1665 D2D1_POINT_2F point = {0.0f, 0.0f};
1666 ID2D1SolidColorBrush *brush;
1667 ID2D1PathGeometry *geometry;
1668 ID2D1Geometry *tmp_geometry;
1669 IDXGISwapChain *swapchain;
1670 ID2D1RenderTarget *rt;
1671 ID3D10Device1 *device;
1672 IDXGISurface *surface;
1673 ID2D1Factory *factory;
1674 BOOL match, contains;
1675 D2D1_COLOR_F color;
1676 ULONG refcount;
1677 UINT32 count;
1678 HWND window;
1679 HRESULT hr;
1681 static const struct geometry_segment expected_segments[] =
1683 /* Figure 0. */
1684 {SEGMENT_LINE, {{{ 55.0f, 20.0f}}}},
1685 {SEGMENT_LINE, {{{ 55.0f, 220.0f}}}},
1686 {SEGMENT_LINE, {{{ 25.0f, 220.0f}}}},
1687 {SEGMENT_LINE, {{{ 25.0f, 100.0f}}}},
1688 {SEGMENT_LINE, {{{ 75.0f, 100.0f}}}},
1689 {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}},
1690 {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}},
1691 {SEGMENT_LINE, {{{ 5.0f, 60.0f}}}},
1692 {SEGMENT_LINE, {{{ 45.0f, 60.0f}}}},
1693 {SEGMENT_LINE, {{{ 45.0f, 180.0f}}}},
1694 {SEGMENT_LINE, {{{ 35.0f, 180.0f}}}},
1695 {SEGMENT_LINE, {{{ 35.0f, 140.0f}}}},
1696 {SEGMENT_LINE, {{{ 65.0f, 140.0f}}}},
1697 {SEGMENT_LINE, {{{ 65.0f, 260.0f}}}},
1698 {SEGMENT_LINE, {{{ 15.0f, 260.0f}}}},
1699 /* Figure 1. */
1700 {SEGMENT_LINE, {{{155.0f, 160.0f}}}},
1701 {SEGMENT_LINE, {{{ 85.0f, 160.0f}}}},
1702 {SEGMENT_LINE, {{{ 85.0f, 300.0f}}}},
1703 {SEGMENT_LINE, {{{120.0f, 300.0f}}}},
1704 {SEGMENT_LINE, {{{120.0f, 20.0f}}}},
1705 {SEGMENT_LINE, {{{155.0f, 20.0f}}}},
1706 {SEGMENT_LINE, {{{155.0f, 160.0f}}}},
1707 {SEGMENT_LINE, {{{ 85.0f, 160.0f}}}},
1708 {SEGMENT_LINE, {{{ 85.0f, 20.0f}}}},
1709 {SEGMENT_LINE, {{{120.0f, 20.0f}}}},
1710 {SEGMENT_LINE, {{{120.0f, 300.0f}}}},
1711 /* Figure 2. */
1712 {SEGMENT_LINE, {{{165.0f, 300.0f}}}},
1713 {SEGMENT_LINE, {{{235.0f, 300.0f}}}},
1714 {SEGMENT_LINE, {{{235.0f, 20.0f}}}},
1715 /* Figure 3. */
1716 {SEGMENT_LINE, {{{225.0f, 260.0f}}}},
1717 {SEGMENT_LINE, {{{175.0f, 260.0f}}}},
1718 {SEGMENT_LINE, {{{175.0f, 60.0f}}}},
1719 /* Figure 4. */
1720 {SEGMENT_LINE, {{{185.0f, 220.0f}}}},
1721 {SEGMENT_LINE, {{{185.0f, 100.0f}}}},
1722 {SEGMENT_LINE, {{{215.0f, 100.0f}}}},
1723 /* Figure 5. */
1724 {SEGMENT_LINE, {{{205.0f, 180.0f}}}},
1725 {SEGMENT_LINE, {{{205.0f, 140.0f}}}},
1726 {SEGMENT_LINE, {{{195.0f, 140.0f}}}},
1727 /* Figure 6. */
1728 {SEGMENT_LINE, {{{135.0f, 620.0f}}}},
1729 {SEGMENT_LINE, {{{135.0f, 420.0f}}}},
1730 {SEGMENT_LINE, {{{105.0f, 420.0f}}}},
1731 {SEGMENT_LINE, {{{105.0f, 540.0f}}}},
1732 {SEGMENT_LINE, {{{155.0f, 540.0f}}}},
1733 {SEGMENT_LINE, {{{155.0f, 340.0f}}}},
1734 {SEGMENT_LINE, {{{ 85.0f, 340.0f}}}},
1735 {SEGMENT_LINE, {{{ 85.0f, 580.0f}}}},
1736 {SEGMENT_LINE, {{{125.0f, 580.0f}}}},
1737 {SEGMENT_LINE, {{{125.0f, 460.0f}}}},
1738 {SEGMENT_LINE, {{{115.0f, 460.0f}}}},
1739 {SEGMENT_LINE, {{{115.0f, 500.0f}}}},
1740 {SEGMENT_LINE, {{{145.0f, 500.0f}}}},
1741 {SEGMENT_LINE, {{{145.0f, 380.0f}}}},
1742 {SEGMENT_LINE, {{{ 95.0f, 380.0f}}}},
1743 /* Figure 7. */
1744 {SEGMENT_LINE, {{{235.0f, 480.0f}}}},
1745 {SEGMENT_LINE, {{{165.0f, 480.0f}}}},
1746 {SEGMENT_LINE, {{{165.0f, 340.0f}}}},
1747 {SEGMENT_LINE, {{{200.0f, 340.0f}}}},
1748 {SEGMENT_LINE, {{{200.0f, 620.0f}}}},
1749 {SEGMENT_LINE, {{{235.0f, 620.0f}}}},
1750 {SEGMENT_LINE, {{{235.0f, 480.0f}}}},
1751 {SEGMENT_LINE, {{{165.0f, 480.0f}}}},
1752 {SEGMENT_LINE, {{{165.0f, 620.0f}}}},
1753 {SEGMENT_LINE, {{{200.0f, 620.0f}}}},
1754 {SEGMENT_LINE, {{{200.0f, 340.0f}}}},
1755 /* Figure 8. */
1756 {SEGMENT_LINE, {{{245.0f, 340.0f}}}},
1757 {SEGMENT_LINE, {{{315.0f, 340.0f}}}},
1758 {SEGMENT_LINE, {{{315.0f, 620.0f}}}},
1759 /* Figure 9. */
1760 {SEGMENT_LINE, {{{305.0f, 380.0f}}}},
1761 {SEGMENT_LINE, {{{255.0f, 380.0f}}}},
1762 {SEGMENT_LINE, {{{255.0f, 580.0f}}}},
1763 /* Figure 10. */
1764 {SEGMENT_LINE, {{{265.0f, 420.0f}}}},
1765 {SEGMENT_LINE, {{{265.0f, 540.0f}}}},
1766 {SEGMENT_LINE, {{{295.0f, 540.0f}}}},
1767 /* Figure 11. */
1768 {SEGMENT_LINE, {{{285.0f, 460.0f}}}},
1769 {SEGMENT_LINE, {{{285.0f, 500.0f}}}},
1770 {SEGMENT_LINE, {{{275.0f, 500.0f}}}},
1771 /* Figure 12. */
1772 {SEGMENT_BEZIER, {{{2.83333340e+01f, 1.60000000e+02f},
1773 {4.00000000e+01f, 1.13333336e+02f},
1774 {4.00000000e+01f, 2.00000000e+01f}}}},
1775 {SEGMENT_BEZIER, {{{4.00000000e+01f, 1.13333336e+02f},
1776 {5.16666641e+01f, 1.60000000e+02f},
1777 {7.50000000e+01f, 1.60000000e+02f}}}},
1778 {SEGMENT_BEZIER, {{{5.16666641e+01f, 1.60000000e+02f},
1779 {4.00000000e+01f, 2.06666656e+02f},
1780 {4.00000000e+01f, 3.00000000e+02f}}}},
1781 {SEGMENT_BEZIER, {{{4.00000000e+01f, 2.06666656e+02f},
1782 {2.83333340e+01f, 1.60000000e+02f},
1783 {5.00000000e+00f, 1.60000000e+02f}}}},
1784 /* Figure 13. */
1785 {SEGMENT_BEZIER, {{{2.00000000e+01f, 1.06666664e+02f},
1786 {2.66666660e+01f, 8.00000000e+01f},
1787 {4.00000000e+01f, 8.00000000e+01f}}}},
1788 {SEGMENT_BEZIER, {{{5.33333321e+01f, 8.00000000e+01f},
1789 {6.00000000e+01f, 1.06666664e+02f},
1790 {6.00000000e+01f, 1.60000000e+02f}}}},
1791 {SEGMENT_BEZIER, {{{6.00000000e+01f, 2.13333328e+02f},
1792 {5.33333321e+01f, 2.40000000e+02f},
1793 {4.00000000e+01f, 2.40000000e+02f}}}},
1794 {SEGMENT_BEZIER, {{{2.66666660e+01f, 2.40000000e+02f},
1795 {2.00000000e+01f, 2.13333328e+02f},
1796 {2.00000000e+01f, 1.60000000e+02f}}}},
1797 /* Figure 14. */
1798 {SEGMENT_BEZIER, {{{2.83333340e+01f, 6.12000000e+02f},
1799 {4.00000000e+01f, 6.58666687e+02f},
1800 {4.00000000e+01f, 7.52000000e+02f}}}},
1801 {SEGMENT_BEZIER, {{{4.00000000e+01f, 6.58666687e+02f},
1802 {5.16666641e+01f, 6.12000000e+02f},
1803 {7.50000000e+01f, 6.12000000e+02f}}}},
1804 {SEGMENT_BEZIER, {{{5.16666641e+01f, 6.12000000e+02f},
1805 {4.00000000e+01f, 5.65333313e+02f},
1806 {4.00000000e+01f, 4.72000000e+02f}}}},
1807 {SEGMENT_BEZIER, {{{4.00000000e+01f, 5.65333313e+02f},
1808 {2.83333340e+01f, 6.12000000e+02f},
1809 {5.00000000e+00f, 6.12000000e+02f}}}},
1810 /* Figure 15. */
1811 {SEGMENT_BEZIER, {{{2.00000000e+01f, 6.65333313e+02f},
1812 {2.66666660e+01f, 6.92000000e+02f},
1813 {4.00000000e+01f, 6.92000000e+02f}}}},
1814 {SEGMENT_BEZIER, {{{5.33333321e+01f, 6.92000000e+02f},
1815 {6.00000000e+01f, 6.65333313e+02f},
1816 {6.00000000e+01f, 6.12000000e+02f}}}},
1817 {SEGMENT_BEZIER, {{{6.00000000e+01f, 5.58666687e+02f},
1818 {5.33333321e+01f, 5.32000000e+02f},
1819 {4.00000000e+01f, 5.32000000e+02f}}}},
1820 {SEGMENT_BEZIER, {{{2.66666660e+01f, 5.32000000e+02f},
1821 {2.00000000e+01f, 5.58666687e+02f},
1822 {2.00000000e+01f, 6.12000000e+02f}}}},
1823 /* Figure 16. */
1824 {SEGMENT_BEZIER, {{{1.91750427e+02f, 1.27275856e+02f},
1825 {2.08249573e+02f, 1.27275856e+02f},
1826 {2.24748734e+02f, 6.12792168e+01f}}}},
1827 {SEGMENT_BEZIER, {{{2.08249573e+02f, 1.27275856e+02f},
1828 {2.08249573e+02f, 1.93272476e+02f},
1829 {2.24748734e+02f, 2.59269104e+02f}}}},
1830 {SEGMENT_BEZIER, {{{2.08249573e+02f, 1.93272476e+02f},
1831 {1.91750427e+02f, 1.93272476e+02f},
1832 {1.75251266e+02f, 2.59269104e+02f}}}},
1833 {SEGMENT_BEZIER, {{{1.91750427e+02f, 1.93272476e+02f},
1834 {1.91750427e+02f, 1.27275856e+02f},
1835 {1.75251266e+02f, 6.12792168e+01f}}}},
1836 /* Figure 17. */
1837 {SEGMENT_BEZIER, {{{1.95285950e+02f, 6.59932632e+01f},
1838 {2.04714050e+02f, 6.59932632e+01f},
1839 {2.14142136e+02f, 1.03705627e+02f}}}},
1840 {SEGMENT_BEZIER, {{{2.23570221e+02f, 1.41417984e+02f},
1841 {2.23570221e+02f, 1.79130356e+02f},
1842 {2.14142136e+02f, 2.16842712e+02f}}}},
1843 {SEGMENT_BEZIER, {{{2.04714050e+02f, 2.54555069e+02f},
1844 {1.95285950e+02f, 2.54555069e+02f},
1845 {1.85857864e+02f, 2.16842712e+02f}}}},
1846 {SEGMENT_BEZIER, {{{1.76429779e+02f, 1.79130356e+02f},
1847 {1.76429779e+02f, 1.41417984e+02f},
1848 {1.85857864e+02f, 1.03705627e+02f}}}},
1849 /* Figure 18. */
1850 {SEGMENT_BEZIER, {{{1.11847351e+02f, 4.46888092e+02f},
1851 {1.11847351e+02f, 5.12884705e+02f},
1852 {9.53481979e+01f, 5.78881348e+02f}}}},
1853 {SEGMENT_BEZIER, {{{1.11847351e+02f, 5.12884705e+02f},
1854 {1.28346512e+02f, 5.12884705e+02f},
1855 {1.44845673e+02f, 5.78881348e+02f}}}},
1856 {SEGMENT_BEZIER, {{{1.28346512e+02f, 5.12884705e+02f},
1857 {1.28346512e+02f, 4.46888092e+02f},
1858 {1.44845673e+02f, 3.80891479e+02f}}}},
1859 {SEGMENT_BEZIER, {{{1.28346512e+02f, 4.46888092e+02f},
1860 {1.11847351e+02f, 4.46888092e+02f},
1861 {9.53481979e+01f, 3.80891479e+02f}}}},
1862 /* Figure 19. */
1863 {SEGMENT_BEZIER, {{{9.65267105e+01f, 4.61030243e+02f},
1864 {9.65267105e+01f, 4.98742584e+02f},
1865 {1.05954803e+02f, 5.36454956e+02f}}}},
1866 {SEGMENT_BEZIER, {{{1.15382889e+02f, 5.74167297e+02f},
1867 {1.24810982e+02f, 5.74167297e+02f},
1868 {1.34239075e+02f, 5.36454956e+02f}}}},
1869 {SEGMENT_BEZIER, {{{1.43667160e+02f, 4.98742584e+02f},
1870 {1.43667160e+02f, 4.61030243e+02f},
1871 {1.34239075e+02f, 4.23317871e+02f}}}},
1872 {SEGMENT_BEZIER, {{{1.24810982e+02f, 3.85605499e+02f},
1873 {1.15382889e+02f, 3.85605499e+02f},
1874 {1.05954803e+02f, 4.23317871e+02f}}}},
1875 /* Figure 20. */
1876 {SEGMENT_LINE, {{{ 40.0f, 20.0f}}}},
1877 {SEGMENT_LINE, {{{ 75.0f, 160.0f}}}},
1878 {SEGMENT_LINE, {{{ 40.0f, 300.0f}}}},
1879 {SEGMENT_LINE, {{{ 5.0f, 160.0f}}}},
1880 /* Figure 21. */
1881 {SEGMENT_LINE, {{{ 40.0f, 80.0f}}}},
1882 {SEGMENT_LINE, {{{ 60.0f, 160.0f}}}},
1883 {SEGMENT_LINE, {{{ 40.0f, 240.0f}}}},
1884 {SEGMENT_LINE, {{{ 20.0f, 160.0f}}}},
1885 /* Figure 22. */
1886 {SEGMENT_LINE, {{{ 40.0f, 752.0f}}}},
1887 {SEGMENT_LINE, {{{ 75.0f, 612.0f}}}},
1888 {SEGMENT_LINE, {{{ 40.0f, 472.0f}}}},
1889 {SEGMENT_LINE, {{{ 5.0f, 612.0f}}}},
1890 /* Figure 23. */
1891 {SEGMENT_LINE, {{{ 40.0f, 692.0f}}}},
1892 {SEGMENT_LINE, {{{ 60.0f, 612.0f}}}},
1893 {SEGMENT_LINE, {{{ 40.0f, 532.0f}}}},
1894 {SEGMENT_LINE, {{{ 20.0f, 612.0f}}}},
1895 /* Figure 24. */
1896 {SEGMENT_LINE, {{{2.03125019e+01f, 1.51250000e+02f}}}},
1897 {SEGMENT_LINE, {{{3.12500019e+01f, 1.25000008e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1898 {SEGMENT_LINE, {{{3.78125000e+01f, 8.12500076e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1899 {SEGMENT_LINE, {{{4.00000000e+01f, 2.00000000e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1900 {SEGMENT_LINE, {{{4.21875000e+01f, 8.12500076e+01f}}}},
1901 {SEGMENT_LINE, {{{4.87500000e+01f, 1.25000008e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1902 {SEGMENT_LINE, {{{5.96875000e+01f, 1.51250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1903 {SEGMENT_LINE, {{{7.50000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1904 {SEGMENT_LINE, {{{5.96875000e+01f, 1.68750000e+02f}}}},
1905 {SEGMENT_LINE, {{{4.87500000e+01f, 1.95000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1906 {SEGMENT_LINE, {{{4.21875000e+01f, 2.38750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1907 {SEGMENT_LINE, {{{4.00000000e+01f, 3.00000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1908 {SEGMENT_LINE, {{{3.78125000e+01f, 2.38750000e+02f}}}},
1909 {SEGMENT_LINE, {{{3.12500019e+01f, 1.95000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1910 {SEGMENT_LINE, {{{2.03125019e+01f, 1.68750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1911 {SEGMENT_LINE, {{{5.00000000e+00f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1912 /* Figure 25. */
1913 {SEGMENT_LINE, {{{2.50000000e+01f, 1.00000000e+02f}}}},
1914 {SEGMENT_LINE, {{{4.00000000e+01f, 8.00000000e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1915 {SEGMENT_LINE, {{{5.50000000e+01f, 1.00000000e+02f}}}},
1916 {SEGMENT_LINE, {{{6.00000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1917 {SEGMENT_LINE, {{{5.50000000e+01f, 2.20000000e+02f}}}},
1918 {SEGMENT_LINE, {{{4.00000000e+01f, 2.40000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1919 {SEGMENT_LINE, {{{2.50000000e+01f, 2.20000000e+02f}}}},
1920 {SEGMENT_LINE, {{{2.00000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1921 /* Figure 26. */
1922 {SEGMENT_LINE, {{{2.03125019e+01f, 6.20750000e+02f}}}},
1923 {SEGMENT_LINE, {{{3.12500019e+01f, 6.47000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1924 {SEGMENT_LINE, {{{3.78125000e+01f, 6.90750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1925 {SEGMENT_LINE, {{{4.00000000e+01f, 7.52000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1926 {SEGMENT_LINE, {{{4.21875000e+01f, 6.90750000e+02f}}}},
1927 {SEGMENT_LINE, {{{4.87500000e+01f, 6.47000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1928 {SEGMENT_LINE, {{{5.96875000e+01f, 6.20750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1929 {SEGMENT_LINE, {{{7.50000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1930 {SEGMENT_LINE, {{{5.96875000e+01f, 6.03250000e+02f}}}},
1931 {SEGMENT_LINE, {{{4.87500000e+01f, 5.77000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1932 {SEGMENT_LINE, {{{4.21875000e+01f, 5.33250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1933 {SEGMENT_LINE, {{{4.00000000e+01f, 4.72000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1934 {SEGMENT_LINE, {{{3.78125000e+01f, 5.33250000e+02f}}}},
1935 {SEGMENT_LINE, {{{3.12500019e+01f, 5.77000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1936 {SEGMENT_LINE, {{{2.03125019e+01f, 6.03250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1937 {SEGMENT_LINE, {{{5.00000000e+00f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1938 /* Figure 27. */
1939 {SEGMENT_LINE, {{{2.50000000e+01f, 6.72000000e+02f}}}},
1940 {SEGMENT_LINE, {{{4.00000000e+01f, 6.92000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1941 {SEGMENT_LINE, {{{5.50000000e+01f, 6.72000000e+02f}}}},
1942 {SEGMENT_LINE, {{{6.00000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1943 {SEGMENT_LINE, {{{5.50000000e+01f, 5.52000000e+02f}}}},
1944 {SEGMENT_LINE, {{{4.00000000e+01f, 5.32000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1945 {SEGMENT_LINE, {{{2.50000000e+01f, 5.52000000e+02f}}}},
1946 {SEGMENT_LINE, {{{2.00000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
1947 /* Figure 28. */
1948 {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}},
1949 {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}},
1951 static const struct expected_geometry_figure expected_figures[] =
1953 /* 0 */
1954 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 15.0f, 20.0f}, 15, &expected_segments[0]},
1955 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {155.0f, 300.0f}, 11, &expected_segments[15]},
1956 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {165.0f, 20.0f}, 3, &expected_segments[26]},
1957 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {225.0f, 60.0f}, 3, &expected_segments[29]},
1958 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {215.0f, 220.0f}, 3, &expected_segments[32]},
1959 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {195.0f, 180.0f}, 3, &expected_segments[35]},
1960 /* 6 */
1961 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 95.0f, 620.0f}, 15, &expected_segments[38]},
1962 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {235.0f, 340.0f}, 11, &expected_segments[53]},
1963 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {245.0f, 620.0f}, 3, &expected_segments[64]},
1964 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {305.0f, 580.0f}, 3, &expected_segments[67]},
1965 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {295.0f, 420.0f}, 3, &expected_segments[70]},
1966 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {275.0f, 460.0f}, 3, &expected_segments[73]},
1967 /* 12 */
1968 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 4, &expected_segments[76]},
1969 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 4, &expected_segments[80]},
1970 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 4, &expected_segments[84]},
1971 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 4, &expected_segments[88]},
1972 /* 16 */
1973 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
1974 {1.75251266e+02f, 6.12792168e+01f}, 4, &expected_segments[92]},
1975 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
1976 {1.85857864e+02f, 1.03705627e+02f}, 4, &expected_segments[96]},
1977 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
1978 {9.53481979e+01f, 3.80891479e+02f}, 4, &expected_segments[100]},
1979 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
1980 {1.05954803e+02f, 4.23317871e+02f}, 4, &expected_segments[104]},
1981 /* 20 */
1982 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 4, &expected_segments[108]},
1983 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 4, &expected_segments[112]},
1984 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 4, &expected_segments[116]},
1985 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 4, &expected_segments[120]},
1986 /* 24 */
1987 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 16, &expected_segments[124]},
1988 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 8, &expected_segments[140]},
1989 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 16, &expected_segments[148]},
1990 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 8, &expected_segments[164]},
1991 /* 28 */
1992 {D2D1_FIGURE_BEGIN_HOLLOW, D2D1_FIGURE_END_OPEN, { 40.0f, 20.0f}, 2, &expected_segments[172]},
1995 if (!(device = create_device()))
1997 skip("Failed to create device, skipping tests.\n");
1998 return;
2000 window = create_window();
2001 swapchain = create_swapchain(device, window, TRUE);
2002 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2003 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2004 rt = create_render_target(surface);
2005 ok(!!rt, "Failed to create render target.\n");
2006 ID2D1RenderTarget_GetFactory(rt, &factory);
2008 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
2009 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2010 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
2011 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
2012 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2014 /* Close() when closed. */
2015 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2016 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2017 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2018 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2019 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2020 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2021 hr = ID2D1PathGeometry_Open(geometry, &sink);
2022 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2023 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2024 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2025 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2026 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2027 hr = ID2D1GeometrySink_Close(sink);
2028 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2029 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2030 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2031 ok(!count, "Got unexpected figure count %u.\n", count);
2032 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2033 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2034 ok(!count, "Got unexpected segment count %u.\n", count);
2035 hr = ID2D1GeometrySink_Close(sink);
2036 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2037 ID2D1GeometrySink_Release(sink);
2038 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2039 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2040 ok(!count, "Got unexpected figure count %u.\n", count);
2041 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2042 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2043 ok(!count, "Got unexpected segment count %u.\n", count);
2044 ID2D1PathGeometry_Release(geometry);
2046 /* Open() when closed. */
2047 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2048 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2049 hr = ID2D1PathGeometry_Open(geometry, &sink);
2050 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2051 hr = ID2D1GeometrySink_Close(sink);
2052 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2053 ID2D1GeometrySink_Release(sink);
2054 hr = ID2D1PathGeometry_Open(geometry, &sink);
2055 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2056 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2057 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2058 ok(!count, "Got unexpected figure count %u.\n", count);
2059 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2060 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2061 ok(!count, "Got unexpected segment count %u.\n", count);
2062 ID2D1PathGeometry_Release(geometry);
2064 /* Open() when open. */
2065 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2066 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2067 hr = ID2D1PathGeometry_Open(geometry, &sink);
2068 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2069 hr = ID2D1PathGeometry_Open(geometry, &tmp_sink);
2070 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2071 hr = ID2D1GeometrySink_Close(sink);
2072 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2073 ID2D1GeometrySink_Release(sink);
2074 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2075 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2076 ok(!count, "Got unexpected figure count %u.\n", count);
2077 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2078 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2079 ok(!count, "Got unexpected segment count %u.\n", count);
2080 ID2D1PathGeometry_Release(geometry);
2082 /* BeginFigure() without EndFigure(). */
2083 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2084 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2085 hr = ID2D1PathGeometry_Open(geometry, &sink);
2086 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2087 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2088 hr = ID2D1GeometrySink_Close(sink);
2089 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2090 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2091 hr = ID2D1GeometrySink_Close(sink);
2092 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2093 ID2D1GeometrySink_Release(sink);
2094 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2095 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2096 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2097 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2098 ID2D1PathGeometry_Release(geometry);
2100 /* EndFigure() without BeginFigure(). */
2101 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2102 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2103 hr = ID2D1PathGeometry_Open(geometry, &sink);
2104 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2105 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2106 hr = ID2D1GeometrySink_Close(sink);
2107 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2108 ID2D1GeometrySink_Release(sink);
2109 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2110 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2111 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2112 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2113 ID2D1PathGeometry_Release(geometry);
2115 /* BeginFigure()/EndFigure() mismatch. */
2116 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2117 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2118 hr = ID2D1PathGeometry_Open(geometry, &sink);
2119 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2120 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2121 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2122 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2123 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2124 hr = ID2D1GeometrySink_Close(sink);
2125 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2126 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2127 hr = ID2D1GeometrySink_Close(sink);
2128 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2129 ID2D1GeometrySink_Release(sink);
2130 ID2D1PathGeometry_Release(geometry);
2132 /* AddLine() outside BeginFigure()/EndFigure(). */
2133 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2134 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2135 hr = ID2D1PathGeometry_Open(geometry, &sink);
2136 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2137 ID2D1GeometrySink_AddLine(sink, point);
2138 hr = ID2D1GeometrySink_Close(sink);
2139 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2140 ID2D1GeometrySink_AddLine(sink, point);
2141 ID2D1GeometrySink_Release(sink);
2142 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2143 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2144 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2145 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2146 ID2D1PathGeometry_Release(geometry);
2148 /* Empty figure. */
2149 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2150 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2151 hr = ID2D1PathGeometry_Open(geometry, &sink);
2152 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2153 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2154 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2155 hr = ID2D1GeometrySink_Close(sink);
2156 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2157 ID2D1GeometrySink_Release(sink);
2158 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2159 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2160 ok(count == 1, "Got unexpected figure count %u.\n", count);
2161 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2162 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2163 ok(count == 1, "Got unexpected segment count %u.\n", count);
2164 ID2D1PathGeometry_Release(geometry);
2166 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2167 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2168 hr = ID2D1PathGeometry_Open(geometry, &sink);
2169 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2170 /* The fillmode that's used is the last one set before the sink is closed. */
2171 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
2172 fill_geometry_sink(sink);
2173 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
2174 hr = ID2D1GeometrySink_Close(sink);
2175 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2176 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2177 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2178 ok(count == 6, "Got unexpected figure count %u.\n", count);
2179 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2180 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2181 /* Intersections don't create extra segments. */
2182 ok(count == 44, "Got unexpected segment count %u.\n", count);
2183 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
2184 ID2D1GeometrySink_Release(sink);
2186 geometry_sink_init(&simplify_sink);
2187 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2188 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2189 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2190 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[0], 0);
2191 geometry_sink_cleanup(&simplify_sink);
2192 geometry_sink_init(&simplify_sink);
2193 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2194 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2195 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2196 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[0], 0);
2197 geometry_sink_cleanup(&simplify_sink);
2199 set_matrix_identity(&matrix);
2200 translate_matrix(&matrix, 80.0f, 640.0f);
2201 scale_matrix(&matrix, 1.0f, -1.0f);
2202 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
2203 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
2205 geometry_sink_init(&simplify_sink);
2206 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2207 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2208 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2209 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[6], 0);
2210 geometry_sink_cleanup(&simplify_sink);
2212 ID2D1TransformedGeometry_GetSourceGeometry(transformed_geometry, &tmp_geometry);
2213 ok(tmp_geometry == (ID2D1Geometry *)geometry,
2214 "Got unexpected source geometry %p, expected %p.\n", tmp_geometry, geometry);
2215 ID2D1TransformedGeometry_GetTransform(transformed_geometry, &tmp_matrix);
2216 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
2217 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2218 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
2219 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
2220 geometry_sink_init(&simplify_sink);
2221 hr = ID2D1Geometry_Simplify(tmp_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2222 &tmp_matrix, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2223 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2224 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[6], 0);
2225 geometry_sink_cleanup(&simplify_sink);
2226 ID2D1Geometry_Release(tmp_geometry);
2228 ID2D1RenderTarget_BeginDraw(rt);
2229 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
2230 ID2D1RenderTarget_Clear(rt, &color);
2231 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
2232 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2233 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2234 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2235 match = compare_surface(surface, "3aace1b22aae111cb577614fed16e4eb1650dba5");
2236 ok(match, "Surface does not match.\n");
2238 /* Edge test. */
2239 set_point(&point, 94.0f, 620.0f);
2240 contains = TRUE;
2241 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, NULL, 0.0f, &contains);
2242 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
2243 ok(!contains, "Got unexpected contains %#x.\n", contains);
2245 set_point(&point, 95.0f, 620.0f);
2246 contains = FALSE;
2247 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, NULL, 0.0f, &contains);
2248 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
2249 ok(contains == TRUE, "Got unexpected contains %#x.\n", contains);
2251 /* With transformation matrix. */
2252 set_matrix_identity(&matrix);
2253 translate_matrix(&matrix, -10.0f, 0.0f);
2254 set_point(&point, 85.0f, 620.0f);
2255 contains = FALSE;
2256 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, &matrix, 0.0f, &contains);
2257 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
2258 ok(contains == TRUE, "Got unexpected contains %#x.\n", contains);
2260 ID2D1TransformedGeometry_Release(transformed_geometry);
2261 ID2D1PathGeometry_Release(geometry);
2263 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2264 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2265 hr = ID2D1PathGeometry_Open(geometry, &sink);
2266 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2267 fill_geometry_sink(sink);
2268 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
2269 hr = ID2D1GeometrySink_Close(sink);
2270 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2271 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2272 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2273 ok(count == 6, "Got unexpected figure count %u.\n", count);
2274 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2275 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2276 ok(count == 44, "Got unexpected segment count %u.\n", count);
2277 ID2D1GeometrySink_Release(sink);
2279 geometry_sink_init(&simplify_sink);
2280 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2281 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2282 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2283 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 6, &expected_figures[0], 0);
2284 geometry_sink_cleanup(&simplify_sink);
2286 set_matrix_identity(&matrix);
2287 translate_matrix(&matrix, 320.0f, 320.0f);
2288 scale_matrix(&matrix, -1.0f, 1.0f);
2289 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
2290 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
2292 ID2D1RenderTarget_BeginDraw(rt);
2293 ID2D1RenderTarget_Clear(rt, &color);
2294 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
2295 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2296 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2297 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2298 match = compare_surface(surface, "bfb40a1f007694fa07dbd3b854f3f5d9c3e1d76b");
2299 ok(match, "Surface does not match.\n");
2300 ID2D1TransformedGeometry_Release(transformed_geometry);
2301 ID2D1PathGeometry_Release(geometry);
2303 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2304 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2305 hr = ID2D1PathGeometry_Open(geometry, &sink);
2306 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2307 fill_geometry_sink_bezier(sink);
2308 hr = ID2D1GeometrySink_Close(sink);
2309 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2310 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2311 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2312 ok(count == 4, "Got unexpected figure count %u.\n", count);
2313 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2314 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2315 ok(count == 20, "Got unexpected segment count %u.\n", count);
2316 ID2D1GeometrySink_Release(sink);
2318 geometry_sink_init(&simplify_sink);
2319 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2320 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2321 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2322 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[12], 1);
2323 geometry_sink_cleanup(&simplify_sink);
2324 geometry_sink_init(&simplify_sink);
2325 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2326 NULL, 100.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2327 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2328 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[20], 1);
2329 geometry_sink_cleanup(&simplify_sink);
2330 geometry_sink_init(&simplify_sink);
2331 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2332 NULL, 10.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2333 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2334 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[24], 1);
2335 geometry_sink_cleanup(&simplify_sink);
2337 set_matrix_identity(&matrix);
2338 scale_matrix(&matrix, 0.5f, 2.0f);
2339 translate_matrix(&matrix, 400.0f, -33.0f);
2340 rotate_matrix(&matrix, M_PI / 4.0f);
2341 scale_matrix(&matrix, 2.0f, 0.5f);
2342 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
2343 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
2345 geometry_sink_init(&simplify_sink);
2346 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2347 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2348 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2349 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[16], 4);
2350 geometry_sink_cleanup(&simplify_sink);
2352 ID2D1RenderTarget_BeginDraw(rt);
2353 ID2D1RenderTarget_Clear(rt, &color);
2354 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
2355 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2356 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2357 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2358 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
2359 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
2360 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
2361 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
2362 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
2363 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
2364 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
2365 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
2366 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
2367 todo_wine ok(match, "Figure does not match.\n");
2368 match = compare_figure(surface, 0, 226, 160, 160, 0xff652e89, 64,
2369 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
2370 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
2371 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
2372 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
2373 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
2374 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
2375 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
2376 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
2377 todo_wine ok(match, "Figure does not match.\n");
2378 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
2379 "gVQBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQEjDCMB7AECHhQeAu0BAxoYGgPvAQMWHhYD8QEDFCAU"
2380 "A/MBBBAkEAT0AQUOJw0F9QEGCioKBvcBBggsCAb4AQgFLgUI+QEJATIBCfsBCAIwAgj8AQcFLAUH"
2381 "/QEFCCgIBf4BBAwiDAT/AQIQHBAClwISlwIBPgGAAgI8Av8BAzwD/QEEPAT7AQY6BvkBBzoH+AEI"
2382 "OAj3AQk4CfYBCTgK9AELNgvzAQw2DPIBDDYM8QEONA7wAQ40DvABDjQO7wEPNA/uAQ80D+4BEDIQ"
2383 "7QERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewB"
2384 "ETIR7AERMhHsAREyEe0BEDIQ7gEQMw/uAQ80D+4BDzQP7wEONA7wAQ40DvEBDDYM8gEMNgzzAQs2"
2385 "C/QBCzcK9QEJOAn3AQg4CfcBBzoH+QEGOgb7AQU6BfwBBDwE/QEDPAP/AQE+AZkCDpkCAhIYEgKA"
2386 "AgMNIA0D/wEFCSYJBf4BBgYqBgf8AQgDLgMI+wFG+gEIAzADCPkBBwYuBgf3AQYKKgoG9gEFDCgM"
2387 "BfUBBBAlDwTzAQQSIhIE8QEDFh4WA/ABAhkaGQLvAQIcFhwC7QECIBAgAusBASgEKAHpAQFWAecB"
2388 "AVgB5QEBWgHAAgHhUgAA");
2389 todo_wine ok(match, "Figure does not match.\n");
2390 match = compare_figure(surface, 160, 160, 320, 160, 0xff652e89, 64,
2391 "/VUB5QEBWAHnAQFWAekBAVQB6wECIQ8hAe0BAh0VHQLuAQIZGhkD7wEDFh4WA/EBBBMhEwPzAQQQ"
2392 "JQ8F9AEFDCgNBfUBBgoqCgb3AQcHLQcG+QEIBC8ECPkBPAEJ+wEIAy8CCP0BBgYrBQf9AQUJJgkF"
2393 "/wEDDSANBP8BAhEaEQKYAhAXAYACAT4BgAICPQL+AQM8BPwBBTsE+wEGOgb6AQc5B/gBCDgJ9gEJ"
2394 "OAn2AQo3CvQBCzcK8wEMNgzyAQ01DPIBDTUN8AEONA7wAQ40D+4BDzQP7gEQMw/uARAzEO0BEDIR"
2395 "7AERMhHsAREyEewBETIR7AERMhLrAREyEusBETIS6wERMhLrAREyEusBETIS6wERMhHsAREyEewB"
2396 "ETIR7QEQMhHtARAzEO0BEDMP7gEPNA/vAQ40D+8BDjQO8QENNQ3xAQ01DPMBCzYM8wELNwr1AQo3"
2397 "CvUBCTgJ9wEIOAn4AQc5B/kBBjoG+wEFOwT9AQM8BP4BAj0C/wEBPgGYAhAXAYACAhEaEQKAAgMN"
2398 "IA0E/gEFCSYJBf4BBgYrBQf8AQgDLwII+wE8AQn6AQgELwQI+AEHBy0HBvcBBgoqCgb2AQUNJw0F"
2399 "9AEEECQQBfIBBBMhEwPxAQMWHhYD8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB"
2400 "wAIBwlYA");
2401 todo_wine ok(match, "Figure does not match.\n");
2402 ID2D1TransformedGeometry_Release(transformed_geometry);
2403 ID2D1PathGeometry_Release(geometry);
2405 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2406 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2407 hr = ID2D1PathGeometry_Open(geometry, &sink);
2408 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2409 fill_geometry_sink_bezier(sink);
2410 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
2411 hr = ID2D1GeometrySink_Close(sink);
2412 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2413 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2414 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2415 ok(count == 4, "Got unexpected figure count %u.\n", count);
2416 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2417 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2418 ok(count == 20, "Got unexpected segment count %u.\n", count);
2419 ID2D1GeometrySink_Release(sink);
2421 geometry_sink_init(&simplify_sink);
2422 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2423 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2424 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2425 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[12], 1);
2426 geometry_sink_cleanup(&simplify_sink);
2427 geometry_sink_init(&simplify_sink);
2428 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2429 NULL, 100.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2430 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2431 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[20], 1);
2432 geometry_sink_cleanup(&simplify_sink);
2433 geometry_sink_init(&simplify_sink);
2434 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2435 NULL, 10.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2436 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2437 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[24], 1);
2438 geometry_sink_cleanup(&simplify_sink);
2440 set_matrix_identity(&matrix);
2441 scale_matrix(&matrix, 0.5f, 2.0f);
2442 translate_matrix(&matrix, 127.0f, 80.0f);
2443 rotate_matrix(&matrix, M_PI / -4.0f);
2444 scale_matrix(&matrix, 2.0f, 0.5f);
2445 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
2446 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
2448 ID2D1RenderTarget_BeginDraw(rt);
2449 ID2D1RenderTarget_Clear(rt, &color);
2450 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
2451 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2452 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2453 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2454 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
2455 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
2456 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
2457 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
2458 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
2459 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
2460 ok(match, "Figure does not match.\n");
2461 match = compare_figure(surface, 0, 226, 160, 160, 0xff652e89, 64,
2462 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
2463 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
2464 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
2465 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
2466 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
2467 ok(match, "Figure does not match.\n");
2468 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
2469 "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQIhDiIB7QECHRUdAu4BAhkaGQPvAQMWHhYD8QEEEyET"
2470 "A/MBBBAkEAT1AQUMKA0F9QEGCioKBvcBBwctBwb5AQgELwQI+QEJATIBCfsBRP0BQ/0BQv8BQf8B"
2471 "QIECP4ACQIACQf4BQ/wBRPsBRvoBR/gBSPcBSvYBS/QBTPMBTvIBTvIBT/ABUPABUe4BUu4BUu4B"
2472 "U+0BU+wBVOwBVOwBVOwBVOwBVesBVesBVesBVesBVOwBVOwBVOwBVO0BU+0BU+0BUu4BUu8BUe8B"
2473 "UPEBT/EBTvIBTvMBTPUBS/UBSvcBSfcBSPkBRvsBRP0BQ/4BQf8BQIECP4ACQIACQf4BQv4BQ/wB"
2474 "RPsBCQEyAQn6AQgELwQI+AEHBy0GB/cBBgoqCgb2AQUMKA0F9AEEECUPBPMBBBIiEwPxAQMWHhYD"
2475 "8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB5QEBWgHAAgEA");
2476 ok(match, "Figure does not match.\n");
2477 match = compare_figure(surface, 160, 160, 320, 160, 0xff652e89, 64,
2478 "gVQBXAHjAQFaAeUBAVgB5wEBVgHpAQEpAikB6wECIBAgAu0BAhwWHALvAQIZGhkC8AEDFh4WA/EB"
2479 "BBIiEgTzAQQPJRAE9QEFDCgMBfYBBgoqCgb3AQcGLgYH+QEIAzADCPoBRvsBRPwBRP0BQv8BQIAC"
2480 "QIECPoECQP8BQv0BRPwBRPsBRvkBSPgBSPcBSvUBTPQBTPMBTvIBTvEBUPABUO8BUu4BUu4BUu4B"
2481 "Uu0BVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVO0BUu4BUu4BUu8BUPAB"
2482 "UPABUPEBTvIBTvMBTPQBS/YBSvcBSPgBSPkBRvsBRP0BQv8BQIACQIECPoECQP8BQv4BQv0BRPwB"
2483 "RPsBCQEyAQn5AQgFLgUI+AEGCCwIBvcBBgoqCgb1AQUNJw4F9AEEECQQBPMBAxQgFAPxAQMWHhYD"
2484 "7wEDGhgaA+0BAh4UHgLsAQEjDCMB6wEBVAHpAQFWAecBAVgB5QEBWgGiVQAA");
2485 ok(match, "Figure does not match.\n");
2486 ID2D1TransformedGeometry_Release(transformed_geometry);
2487 ID2D1PathGeometry_Release(geometry);
2489 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2490 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2491 hr = ID2D1PathGeometry_Open(geometry, &sink);
2492 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2494 set_point(&point, 40.0f, 20.0f);
2495 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2496 line_to(sink, 75.0f, 300.0f);
2497 line_to(sink, 5.0f, 300.0f);
2498 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2500 set_point(&point, 40.0f, 290.0f);
2501 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2502 line_to(sink, 55.0f, 160.0f);
2503 line_to(sink, 25.0f, 160.0f);
2504 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2506 hr = ID2D1GeometrySink_Close(sink);
2507 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2508 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2509 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2510 ok(count == 2, "Got unexpected figure count %u.\n", count);
2511 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2512 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2513 ok(count == 6, "Got unexpected segment count %u.\n", count);
2514 ID2D1GeometrySink_Release(sink);
2516 ID2D1RenderTarget_BeginDraw(rt);
2517 ID2D1RenderTarget_Clear(rt, &color);
2518 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
2519 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2520 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2521 match = compare_surface(surface, "a875e68e0cb9c055927b1b50b879f90b24e38470");
2522 ok(match, "Surface does not match.\n");
2523 ID2D1PathGeometry_Release(geometry);
2525 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2526 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2527 hr = ID2D1PathGeometry_Open(geometry, &sink);
2528 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2529 set_point(&point, 40.0f, 20.0f);
2530 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
2531 line_to(sink, 75.0f, 300.0f);
2532 line_to(sink, 5.0f, 300.0f);
2533 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
2534 hr = ID2D1GeometrySink_Close(sink);
2535 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2536 ID2D1GeometrySink_Release(sink);
2537 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2538 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2539 ok(count == 2, "Got unexpected segment count %u.\n", count);
2541 geometry_sink_init(&simplify_sink);
2542 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2543 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2544 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2545 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[28], 1);
2546 geometry_sink_cleanup(&simplify_sink);
2548 ID2D1PathGeometry_Release(geometry);
2550 ID2D1SolidColorBrush_Release(brush);
2551 ID2D1RenderTarget_Release(rt);
2552 refcount = ID2D1Factory_Release(factory);
2553 ok(!refcount, "Factory has %u references left.\n", refcount);
2554 IDXGISurface_Release(surface);
2555 IDXGISwapChain_Release(swapchain);
2556 ID3D10Device1_Release(device);
2557 DestroyWindow(window);
2560 static void test_rectangle_geometry(void)
2562 ID2D1TransformedGeometry *transformed_geometry;
2563 ID2D1RectangleGeometry *geometry;
2564 struct geometry_sink sink;
2565 D2D1_MATRIX_3X2_F matrix;
2566 D2D1_RECT_F rect, rect2;
2567 ID2D1Factory *factory;
2568 D2D1_POINT_2F point;
2569 BOOL contains;
2570 HRESULT hr;
2571 BOOL match;
2573 static const struct geometry_segment expected_segments[] =
2575 /* Figure 0. */
2576 {SEGMENT_LINE, {{{10.0f, 0.0f}}}},
2577 {SEGMENT_LINE, {{{10.0f, 20.0f}}}},
2578 {SEGMENT_LINE, {{{ 0.0f, 20.0f}}}},
2579 /* Figure 1. */
2580 {SEGMENT_LINE, {{{4.42705116e+01f, 1.82442951e+01f}}}},
2581 {SEGMENT_LINE, {{{7.95376282e+01f, 5.06049728e+01f}}}},
2582 {SEGMENT_LINE, {{{5.52671127e+01f, 6.23606796e+01f}}}},
2583 /* Figure 2. */
2584 {SEGMENT_LINE, {{{25.0f, 15.0f}}}},
2585 {SEGMENT_LINE, {{{25.0f, 55.0f}}}},
2586 {SEGMENT_LINE, {{{25.0f, 55.0f}}}},
2587 /* Figure 3. */
2588 {SEGMENT_LINE, {{{35.0f, 45.0f}}}},
2589 {SEGMENT_LINE, {{{35.0f, 45.0f}}}},
2590 {SEGMENT_LINE, {{{30.0f, 45.0f}}}},
2591 /* Figure 4. */
2592 {SEGMENT_LINE, {{{ 1.07179585e+01f, 2.23205078e+02f}}}},
2593 {SEGMENT_LINE, {{{-5.85640755e+01f, 2.73205078e+02f}}}},
2594 {SEGMENT_LINE, {{{-7.85640717e+01f, 2.29903809e+02f}}}},
2595 /* Figure 5. */
2596 {SEGMENT_LINE, {{{40.0f, 20.0f}}}},
2597 {SEGMENT_LINE, {{{40.0f, 40.0f}}}},
2598 {SEGMENT_LINE, {{{30.0f, 40.0f}}}},
2599 /* Figure 6. */
2600 {SEGMENT_LINE, {{{ 2.14359169e+01f, 0.0f}}}},
2601 {SEGMENT_LINE, {{{-1.17128151e+02f, 0.0f}}}},
2602 {SEGMENT_LINE, {{{-1.57128143e+02f, 0.0f}}}},
2603 /* Figure 7. */
2604 {SEGMENT_LINE, {{{0.0f, 1.11602539e+02f}}}},
2605 {SEGMENT_LINE, {{{0.0f, 1.36602539e+02f}}}},
2606 {SEGMENT_LINE, {{{0.0f, 1.14951904e+02f}}}},
2608 static const struct expected_geometry_figure expected_figures[] =
2610 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 0.0f, 0.0f}, 3, &expected_segments[0]},
2611 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {20.0f, 30.0f}, 3, &expected_segments[3]},
2612 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {25.0f, 15.0f}, 3, &expected_segments[6]},
2613 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {30.0f, 45.0f}, 3, &expected_segments[9]},
2614 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {-9.28203964e+00f, 1.79903809e+02f},
2615 3, &expected_segments[12]},
2616 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {30.0f, 20.0f}, 3, &expected_segments[15]},
2617 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {-1.85640793e+01f, 0.0f}, 3, &expected_segments[18]},
2618 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {0.0f, 8.99519043e+01f}, 3, &expected_segments[21]},
2621 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
2622 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2624 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
2625 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2626 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2627 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
2628 match = compare_rect(&rect2, 0.0f, 0.0f, 0.0f, 0.0f, 0);
2629 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2630 rect2.left, rect2.top, rect2.right, rect2.bottom);
2631 ID2D1RectangleGeometry_Release(geometry);
2633 set_rect(&rect, 50.0f, 0.0f, 40.0f, 100.0f);
2634 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2635 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2636 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
2637 match = compare_rect(&rect2, 50.0f, 0.0f, 40.0f, 100.0f, 0);
2638 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2639 rect2.left, rect2.top, rect2.right, rect2.bottom);
2640 ID2D1RectangleGeometry_Release(geometry);
2642 set_rect(&rect, 0.0f, 100.0f, 40.0f, 50.0f);
2643 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2644 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2645 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
2646 match = compare_rect(&rect2, 0.0f, 100.0f, 40.0f, 50.0f, 0);
2647 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2648 rect2.left, rect2.top, rect2.right, rect2.bottom);
2649 ID2D1RectangleGeometry_Release(geometry);
2651 set_rect(&rect, 50.0f, 100.0f, 40.0f, 50.0f);
2652 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2653 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2654 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
2655 match = compare_rect(&rect2, 50.0f, 100.0f, 40.0f, 50.0f, 0);
2656 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2657 rect2.left, rect2.top, rect2.right, rect2.bottom);
2658 ID2D1RectangleGeometry_Release(geometry);
2660 set_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f);
2661 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2662 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2664 /* Edge. */
2665 contains = FALSE;
2666 set_point(&point, 0.0f, 0.0f);
2667 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2668 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2669 ok(!!contains, "Got wrong hit test result %d.\n", contains);
2671 /* Within tolerance limit around corner. */
2672 contains = TRUE;
2673 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE, 0.0f);
2674 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2675 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2676 ok(!contains, "Got wrong hit test result %d.\n", contains);
2678 contains = FALSE;
2679 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE + 0.01f, 0.0f);
2680 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2681 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2682 ok(!!contains, "Got wrong hit test result %d.\n", contains);
2684 contains = TRUE;
2685 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE - 0.01f, 0.0f);
2686 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2687 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2688 ok(!contains, "Got wrong hit test result %d.\n", contains);
2690 contains = TRUE;
2691 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE, -D2D1_DEFAULT_FLATTENING_TOLERANCE);
2692 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2693 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2694 ok(!contains, "Got wrong hit test result %d.\n", contains);
2696 /* Inside. */
2697 contains = FALSE;
2698 set_point(&point, 5.0f, 5.0f);
2699 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2700 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2701 ok(!!contains, "Got wrong hit test result %d.\n", contains);
2703 /* Test GetBounds() and Simplify(). */
2704 hr = ID2D1RectangleGeometry_GetBounds(geometry, NULL, &rect);
2705 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2706 match = compare_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f, 0);
2707 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2708 rect.left, rect.top, rect.right, rect.bottom);
2709 geometry_sink_init(&sink);
2710 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2711 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2712 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2713 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[0], 0);
2714 geometry_sink_cleanup(&sink);
2715 geometry_sink_init(&sink);
2716 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2717 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2718 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2719 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[0], 0);
2720 geometry_sink_cleanup(&sink);
2722 set_matrix_identity(&matrix);
2723 translate_matrix(&matrix, 20.0f, 30.0f);
2724 scale_matrix(&matrix, 3.0f, 2.0f);
2725 rotate_matrix(&matrix, M_PI / -5.0f);
2726 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
2727 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2728 match = compare_rect(&rect, 2.00000000e+01f, 1.82442951e+01f, 7.95376282e+01f, 6.23606796e+01f, 0);
2729 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2730 rect.left, rect.top, rect.right, rect.bottom);
2731 geometry_sink_init(&sink);
2732 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2733 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2734 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2735 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[1], 1);
2736 geometry_sink_cleanup(&sink);
2738 set_matrix_identity(&matrix);
2739 translate_matrix(&matrix, 25.0f, 15.0f);
2740 scale_matrix(&matrix, 0.0f, 2.0f);
2741 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
2742 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2743 match = compare_rect(&rect, 25.0f, 15.0f, 25.0f, 55.0f, 0);
2744 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2745 rect.left, rect.top, rect.right, rect.bottom);
2746 geometry_sink_init(&sink);
2747 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2748 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2749 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2750 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[2], 0);
2751 geometry_sink_cleanup(&sink);
2753 set_matrix_identity(&matrix);
2754 translate_matrix(&matrix, 30.0f, 45.0f);
2755 scale_matrix(&matrix, 0.5f, 0.0f);
2756 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
2757 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2758 match = compare_rect(&rect, 30.0f, 45.0f, 35.0f, 45.0f, 0);
2759 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2760 rect.left, rect.top, rect.right, rect.bottom);
2761 geometry_sink_init(&sink);
2762 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2763 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2764 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2765 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[3], 0);
2766 geometry_sink_cleanup(&sink);
2768 set_matrix_identity(&matrix);
2769 scale_matrix(&matrix, 4.0f, 5.0f);
2770 rotate_matrix(&matrix, M_PI / 3.0f);
2771 translate_matrix(&matrix, 30.0f, 20.0f);
2772 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
2773 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
2775 ID2D1TransformedGeometry_GetBounds(transformed_geometry, NULL, &rect);
2776 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2777 match = compare_rect(&rect, -7.85640717e+01f, 1.79903809e+02f, 1.07179594e+01f, 2.73205078e+02f, 1);
2778 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2779 rect.left, rect.top, rect.right, rect.bottom);
2780 geometry_sink_init(&sink);
2781 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2782 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2783 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2784 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[4], 1);
2785 geometry_sink_cleanup(&sink);
2786 geometry_sink_init(&sink);
2787 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2788 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2789 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2790 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[4], 1);
2791 geometry_sink_cleanup(&sink);
2793 set_matrix_identity(&matrix);
2794 rotate_matrix(&matrix, M_PI / -3.0f);
2795 scale_matrix(&matrix, 0.25f, 0.2f);
2796 ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
2797 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2798 match = compare_rect(&rect, 30.0f, 20.0f, 40.0f, 40.0f, 2);
2799 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2800 rect.left, rect.top, rect.right, rect.bottom);
2801 geometry_sink_init(&sink);
2802 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2803 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2804 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2805 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[5], 4);
2806 geometry_sink_cleanup(&sink);
2808 set_matrix_identity(&matrix);
2809 scale_matrix(&matrix, 2.0f, 0.0f);
2810 ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
2811 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2812 match = compare_rect(&rect, -1.57128143e+02f, 0.00000000e+00f, 2.14359188e+01f, 0.00000000e+00f, 1);
2813 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2814 rect.left, rect.top, rect.right, rect.bottom);
2815 geometry_sink_init(&sink);
2816 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2817 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2818 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2819 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[6], 1);
2820 geometry_sink_cleanup(&sink);
2822 set_matrix_identity(&matrix);
2823 scale_matrix(&matrix, 0.0f, 0.5f);
2824 ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
2825 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2826 match = compare_rect(&rect, 0.00000000e+00f, 8.99519043e+01f, 0.00000000e+00, 1.36602539e+02f, 1);
2827 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2828 rect.left, rect.top, rect.right, rect.bottom);
2829 geometry_sink_init(&sink);
2830 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2831 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2832 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2833 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[7], 1);
2834 geometry_sink_cleanup(&sink);
2836 ID2D1TransformedGeometry_Release(transformed_geometry);
2837 ID2D1RectangleGeometry_Release(geometry);
2838 ID2D1Factory_Release(factory);
2841 static void test_rounded_rectangle_geometry(void)
2843 ID2D1RoundedRectangleGeometry *geometry;
2844 D2D1_ROUNDED_RECT rect, rect2;
2845 ID2D1Factory *factory;
2846 HRESULT hr;
2848 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
2849 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2851 set_rounded_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
2852 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
2853 todo_wine
2854 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2855 if (FAILED(hr))
2857 ID2D1Factory_Release(factory);
2858 return;
2861 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
2862 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2863 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
2864 ID2D1RoundedRectangleGeometry_Release(geometry);
2866 /* X radius larger than half width. */
2867 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 30.0f, 5.0f);
2868 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
2869 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
2870 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2871 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
2872 ID2D1RoundedRectangleGeometry_Release(geometry);
2874 /* Y radius larger than half height. */
2875 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 5.0f, 30.0f);
2876 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
2877 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
2878 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2879 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
2880 ID2D1RoundedRectangleGeometry_Release(geometry);
2882 /* Both exceed rectangle size. */
2883 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 30.0f, 25.0f);
2884 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
2885 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
2886 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2887 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
2888 ID2D1RoundedRectangleGeometry_Release(geometry);
2890 ID2D1Factory_Release(factory);
2893 static void test_bitmap_formats(void)
2895 D2D1_BITMAP_PROPERTIES bitmap_desc;
2896 IDXGISwapChain *swapchain;
2897 D2D1_SIZE_U size = {4, 4};
2898 ID2D1RenderTarget *rt;
2899 ID3D10Device1 *device;
2900 IDXGISurface *surface;
2901 ID2D1Bitmap *bitmap;
2902 unsigned int i, j;
2903 HWND window;
2904 HRESULT hr;
2906 static const struct
2908 DXGI_FORMAT format;
2909 DWORD mask;
2911 bitmap_formats[] =
2913 {DXGI_FORMAT_R32G32B32A32_FLOAT, 0x8a},
2914 {DXGI_FORMAT_R16G16B16A16_FLOAT, 0x8a},
2915 {DXGI_FORMAT_R16G16B16A16_UNORM, 0x8a},
2916 {DXGI_FORMAT_R8G8B8A8_TYPELESS, 0x00},
2917 {DXGI_FORMAT_R8G8B8A8_UNORM, 0x0a},
2918 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0x8a},
2919 {DXGI_FORMAT_R8G8B8A8_UINT, 0x00},
2920 {DXGI_FORMAT_R8G8B8A8_SNORM, 0x00},
2921 {DXGI_FORMAT_R8G8B8A8_SINT, 0x00},
2922 {DXGI_FORMAT_A8_UNORM, 0x06},
2923 {DXGI_FORMAT_B8G8R8A8_UNORM, 0x0a},
2924 {DXGI_FORMAT_B8G8R8X8_UNORM, 0x88},
2925 {DXGI_FORMAT_B8G8R8A8_TYPELESS, 0x00},
2926 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 0x8a},
2929 if (!(device = create_device()))
2931 skip("Failed to create device, skipping tests.\n");
2932 return;
2934 window = create_window();
2935 swapchain = create_swapchain(device, window, TRUE);
2936 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2937 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2938 rt = create_render_target(surface);
2939 ok(!!rt, "Failed to create render target.\n");
2941 bitmap_desc.dpiX = 96.0f;
2942 bitmap_desc.dpiY = 96.0f;
2943 for (i = 0; i < sizeof(bitmap_formats) / sizeof(*bitmap_formats); ++i)
2945 for (j = 0; j < 4; ++j)
2947 if ((bitmap_formats[i].mask & (0x80 | (1u << j))) == (0x80 | (1u << j)))
2948 continue;
2950 bitmap_desc.pixelFormat.format = bitmap_formats[i].format;
2951 bitmap_desc.pixelFormat.alphaMode = j;
2952 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
2953 if (bitmap_formats[i].mask & (1u << j))
2954 ok(hr == S_OK, "Got unexpected hr %#x, for format %#x/%#x.\n",
2955 hr, bitmap_formats[i].format, j);
2956 else
2957 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x, for format %#x/%#x.\n",
2958 hr, bitmap_formats[i].format, j);
2959 if (SUCCEEDED(hr))
2960 ID2D1Bitmap_Release(bitmap);
2964 ID2D1RenderTarget_Release(rt);
2965 IDXGISurface_Release(surface);
2966 IDXGISwapChain_Release(swapchain);
2967 ID3D10Device1_Release(device);
2968 DestroyWindow(window);
2971 static void test_alpha_mode(void)
2973 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
2974 D2D1_BITMAP_PROPERTIES bitmap_desc;
2975 ID2D1SolidColorBrush *color_brush;
2976 ID2D1BitmapBrush *bitmap_brush;
2977 IDXGISwapChain *swapchain;
2978 ID2D1RenderTarget *rt;
2979 ID3D10Device1 *device;
2980 IDXGISurface *surface;
2981 ID2D1Bitmap *bitmap;
2982 D2D1_COLOR_F color;
2983 D2D1_RECT_F rect;
2984 D2D1_SIZE_U size;
2985 ULONG refcount;
2986 HWND window;
2987 HRESULT hr;
2988 BOOL match;
2990 static const DWORD bitmap_data[] =
2992 0x7f7f0000, 0x7f7f7f00, 0x7f007f00, 0x7f007f7f,
2993 0x7f00007f, 0x7f7f007f, 0x7f000000, 0x7f404040,
2994 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f000000,
2995 0x7f7f7f7f, 0x7f000000, 0x7f000000, 0x7f000000,
2998 if (!(device = create_device()))
3000 skip("Failed to create device, skipping tests.\n");
3001 return;
3003 window = create_window();
3004 swapchain = create_swapchain(device, window, TRUE);
3005 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3006 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3007 rt = create_render_target(surface);
3008 ok(!!rt, "Failed to create render target.\n");
3010 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
3012 set_size_u(&size, 4, 4);
3013 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3014 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
3015 bitmap_desc.dpiX = 96.0f / 40.0f;
3016 bitmap_desc.dpiY = 96.0f / 30.0f;
3017 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3018 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3020 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
3021 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3022 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
3023 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
3024 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
3026 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
3027 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
3028 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3030 ID2D1RenderTarget_BeginDraw(rt);
3031 ID2D1RenderTarget_Clear(rt, NULL);
3032 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3033 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3034 match = compare_surface(surface, "48c41aff3a130a17ee210866b2ab7d36763934d5");
3035 ok(match, "Surface does not match.\n");
3037 ID2D1RenderTarget_BeginDraw(rt);
3038 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
3039 ID2D1RenderTarget_Clear(rt, &color);
3040 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3041 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3042 match = compare_surface(surface, "6487e683730fb5a77c1911388d00b04664c5c4e4");
3043 ok(match, "Surface does not match.\n");
3045 ID2D1RenderTarget_BeginDraw(rt);
3046 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
3047 ID2D1RenderTarget_Clear(rt, &color);
3048 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3049 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3050 match = compare_surface(surface, "7a35ba09e43cbaf591388ff1ef8de56157630c98");
3051 ok(match, "Surface does not match.\n");
3053 ID2D1RenderTarget_BeginDraw(rt);
3055 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
3056 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3057 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
3058 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
3059 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3060 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
3061 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
3062 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3064 ID2D1Bitmap_Release(bitmap);
3065 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3066 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3067 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3068 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
3070 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
3071 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
3072 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3073 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
3074 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
3075 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3076 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
3077 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
3078 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3080 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
3081 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3082 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
3083 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
3084 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3085 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
3086 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
3087 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3089 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3090 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3091 match = compare_surface(surface, "14f8ac64b70966c7c3c6281c59aaecdb17c3b16a");
3092 ok(match, "Surface does not match.\n");
3094 ID2D1RenderTarget_Release(rt);
3095 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3096 rt_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
3097 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
3098 rt_desc.dpiX = 0.0f;
3099 rt_desc.dpiY = 0.0f;
3100 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3101 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3102 rt = create_render_target_desc(surface, &rt_desc);
3103 ok(!!rt, "Failed to create render target.\n");
3105 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
3107 ID2D1Bitmap_Release(bitmap);
3108 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
3109 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3110 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3111 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
3113 ID2D1BitmapBrush_Release(bitmap_brush);
3114 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
3115 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3116 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
3117 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
3118 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
3120 ID2D1SolidColorBrush_Release(color_brush);
3121 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
3122 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
3123 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3125 ID2D1RenderTarget_BeginDraw(rt);
3126 ID2D1RenderTarget_Clear(rt, NULL);
3127 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3128 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3129 match = compare_surface(surface, "b44510bf2d2e61a8d7c0ad862de49a471f1fd13f");
3130 ok(match, "Surface does not match.\n");
3132 ID2D1RenderTarget_BeginDraw(rt);
3133 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
3134 ID2D1RenderTarget_Clear(rt, &color);
3135 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3136 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3137 match = compare_surface(surface, "2184f4a9198fc1de09ac85301b7a03eebadd9b81");
3138 ok(match, "Surface does not match.\n");
3140 ID2D1RenderTarget_BeginDraw(rt);
3141 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
3142 ID2D1RenderTarget_Clear(rt, &color);
3143 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3144 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3145 match = compare_surface(surface, "6527ec83b4039c895b50f9b3e144fe0cf90d1889");
3146 ok(match, "Surface does not match.\n");
3148 ID2D1RenderTarget_BeginDraw(rt);
3150 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
3151 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3152 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
3153 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
3154 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3155 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
3156 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
3157 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3159 ID2D1Bitmap_Release(bitmap);
3160 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3161 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3162 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3163 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
3165 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
3166 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
3167 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3168 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
3169 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
3170 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3171 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
3172 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
3173 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3175 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
3176 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3177 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
3178 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
3179 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3180 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
3181 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
3182 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3184 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3185 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3186 match = compare_surface(surface, "465f5a3190d7bde408b3206b4be939fb22f8a3d6");
3187 ok(match, "Surface does not match.\n");
3189 refcount = ID2D1Bitmap_Release(bitmap);
3190 ok(refcount == 1, "Bitmap has %u references left.\n", refcount);
3191 ID2D1SolidColorBrush_Release(color_brush);
3192 ID2D1BitmapBrush_Release(bitmap_brush);
3193 ID2D1RenderTarget_Release(rt);
3194 IDXGISurface_Release(surface);
3195 IDXGISwapChain_Release(swapchain);
3196 ID3D10Device1_Release(device);
3197 DestroyWindow(window);
3200 static void test_shared_bitmap(void)
3202 IDXGISwapChain *swapchain1, *swapchain2;
3203 IWICBitmap *wic_bitmap1, *wic_bitmap2;
3204 ID2D1GdiInteropRenderTarget *interop;
3205 D2D1_RENDER_TARGET_PROPERTIES desc;
3206 D2D1_BITMAP_PROPERTIES bitmap_desc;
3207 ID2D1RenderTarget *rt1, *rt2, *rt3;
3208 IDXGISurface *surface1, *surface2;
3209 ID2D1Factory *factory1, *factory2;
3210 ID3D10Device1 *device1, *device2;
3211 IWICImagingFactory *wic_factory;
3212 ID2D1Bitmap *bitmap1, *bitmap2;
3213 DXGI_SURFACE_DESC surface_desc;
3214 D2D1_SIZE_U size = {4, 4};
3215 IDXGISurface1 *surface3;
3216 HWND window1, window2;
3217 HRESULT hr;
3219 if (!(device1 = create_device()))
3221 skip("Failed to create device, skipping tests.\n");
3222 return;
3225 window1 = create_window();
3226 window2 = create_window();
3227 swapchain1 = create_swapchain(device1, window1, TRUE);
3228 swapchain2 = create_swapchain(device1, window2, TRUE);
3229 hr = IDXGISwapChain_GetBuffer(swapchain1, 0, &IID_IDXGISurface, (void **)&surface1);
3230 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3231 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
3232 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3234 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3235 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
3236 &IID_IWICImagingFactory, (void **)&wic_factory);
3237 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
3238 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
3239 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap1);
3240 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3241 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
3242 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap2);
3243 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3244 IWICImagingFactory_Release(wic_factory);
3246 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3247 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
3248 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3249 desc.dpiX = 0.0f;
3250 desc.dpiY = 0.0f;
3251 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3252 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3254 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3255 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3256 bitmap_desc.dpiX = 96.0f;
3257 bitmap_desc.dpiY = 96.0f;
3259 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory1);
3260 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3261 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
3262 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3264 /* DXGI surface render targets with the same device and factory. */
3265 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface1, &desc, &rt1);
3266 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3267 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
3268 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3270 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
3271 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3272 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3273 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3274 ID2D1Bitmap_Release(bitmap2);
3275 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IUnknown, bitmap1, NULL, &bitmap2);
3276 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
3277 ID2D1RenderTarget_Release(rt2);
3279 /* DXGI surface render targets with the same device but different factories. */
3280 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
3281 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3282 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3283 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
3284 ID2D1RenderTarget_Release(rt2);
3286 /* DXGI surface render targets with different devices but the same factory. */
3287 IDXGISurface_Release(surface2);
3288 IDXGISwapChain_Release(swapchain2);
3289 device2 = create_device();
3290 ok(!!device2, "Failed to create device.\n");
3291 swapchain2 = create_swapchain(device2, window2, TRUE);
3292 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
3293 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3295 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
3296 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3297 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3298 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
3299 ID2D1RenderTarget_Release(rt2);
3301 /* DXGI surface render targets with different devices and different factories. */
3302 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
3303 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3304 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3305 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
3306 ID2D1RenderTarget_Release(rt2);
3308 /* DXGI surface render target and WIC bitmap render target, same factory. */
3309 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
3310 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3311 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3312 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
3313 ID2D1RenderTarget_Release(rt2);
3315 /* WIC bitmap render targets on different D2D factories. */
3316 ID2D1Bitmap_Release(bitmap1);
3317 ID2D1RenderTarget_Release(rt1);
3318 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap1, &desc, &rt1);
3319 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3320 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
3321 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3323 hr = ID2D1RenderTarget_QueryInterface(rt1, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
3324 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
3325 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
3326 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
3327 ok(rt3 == rt1, "Unexpected render target\n");
3328 ID2D1RenderTarget_Release(rt3);
3329 ID2D1GdiInteropRenderTarget_Release(interop);
3331 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory2, wic_bitmap2, &desc, &rt2);
3332 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3333 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3334 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
3335 ID2D1RenderTarget_Release(rt2);
3337 /* WIC bitmap render targets on the same D2D factory. */
3338 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
3339 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3340 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3341 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3342 ID2D1Bitmap_Release(bitmap2);
3343 ID2D1RenderTarget_Release(rt2);
3345 /* Shared DXGI surface. */
3346 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3347 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3348 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3349 desc.dpiX = 0.0f;
3350 desc.dpiY = 0.0f;
3351 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3352 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3354 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
3355 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3357 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3358 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3359 bitmap_desc.dpiX = 0.0f;
3360 bitmap_desc.dpiY = 0.0f;
3362 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface, surface2, &bitmap_desc, &bitmap2);
3363 ok(SUCCEEDED(hr) || broken(hr == E_INVALIDARG) /* vista */, "Failed to create bitmap, hr %#x.\n", hr);
3365 if (SUCCEEDED(hr))
3367 size = ID2D1Bitmap_GetPixelSize(bitmap2);
3368 hr = IDXGISurface_GetDesc(surface2, &surface_desc);
3369 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
3370 ok(size.width == surface_desc.Width && size.height == surface_desc.Height, "Got wrong bitmap size.\n");
3372 ID2D1Bitmap_Release(bitmap2);
3374 /* IDXGISurface1 is supported too. */
3375 if (IDXGISurface_QueryInterface(surface2, &IID_IDXGISurface1, (void **)&surface3) == S_OK)
3377 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface1, surface3, &bitmap_desc, &bitmap2);
3378 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3380 ID2D1Bitmap_Release(bitmap2);
3381 IDXGISurface1_Release(surface3);
3385 ID2D1RenderTarget_Release(rt2);
3387 ID2D1Bitmap_Release(bitmap1);
3388 ID2D1RenderTarget_Release(rt1);
3389 ID2D1Factory_Release(factory2);
3390 ID2D1Factory_Release(factory1);
3391 IWICBitmap_Release(wic_bitmap2);
3392 IWICBitmap_Release(wic_bitmap1);
3393 IDXGISurface_Release(surface2);
3394 IDXGISurface_Release(surface1);
3395 IDXGISwapChain_Release(swapchain2);
3396 IDXGISwapChain_Release(swapchain1);
3397 ID3D10Device1_Release(device2);
3398 ID3D10Device1_Release(device1);
3399 DestroyWindow(window2);
3400 DestroyWindow(window1);
3401 CoUninitialize();
3404 static void test_bitmap_updates(void)
3406 D2D1_BITMAP_PROPERTIES bitmap_desc;
3407 IDXGISwapChain *swapchain;
3408 ID2D1RenderTarget *rt;
3409 ID3D10Device1 *device;
3410 IDXGISurface *surface;
3411 D2D1_RECT_U dst_rect;
3412 ID2D1Bitmap *bitmap;
3413 D2D1_COLOR_F color;
3414 D2D1_RECT_F rect;
3415 D2D1_SIZE_U size;
3416 HWND window;
3417 HRESULT hr;
3418 BOOL match;
3420 static const DWORD bitmap_data[] =
3422 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
3423 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
3424 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
3425 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
3428 if (!(device = create_device()))
3430 skip("Failed to create device, skipping tests.\n");
3431 return;
3433 window = create_window();
3434 swapchain = create_swapchain(device, window, TRUE);
3435 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3436 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3437 rt = create_render_target(surface);
3438 ok(!!rt, "Failed to create render target.\n");
3440 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
3442 ID2D1RenderTarget_BeginDraw(rt);
3443 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
3444 ID2D1RenderTarget_Clear(rt, &color);
3446 set_size_u(&size, 4, 4);
3447 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3448 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3449 bitmap_desc.dpiX = 96.0f;
3450 bitmap_desc.dpiY = 96.0f;
3451 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
3452 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3454 set_rect(&rect, 0.0f, 0.0f, 320.0f, 240.0f);
3455 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
3456 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
3458 ID2D1Bitmap_Release(bitmap);
3460 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
3461 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
3462 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3464 set_rect(&rect, 0.0f, 240.0f, 320.0f, 480.0f);
3465 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
3466 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
3468 set_rect_u(&dst_rect, 1, 1, 3, 3);
3469 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, 4 * sizeof(*bitmap_data));
3470 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3471 set_rect_u(&dst_rect, 0, 3, 3, 4);
3472 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[6], 4 * sizeof(*bitmap_data));
3473 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3474 set_rect_u(&dst_rect, 0, 0, 4, 1);
3475 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[10], 4 * sizeof(*bitmap_data));
3476 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3477 set_rect_u(&dst_rect, 0, 1, 1, 3);
3478 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[2], sizeof(*bitmap_data));
3479 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3480 set_rect_u(&dst_rect, 4, 4, 3, 1);
3481 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, sizeof(*bitmap_data));
3482 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3483 set_rect(&rect, 320.0f, 240.0f, 640.0f, 480.0f);
3484 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
3485 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
3487 hr = ID2D1Bitmap_CopyFromMemory(bitmap, NULL, bitmap_data, 4 * sizeof(*bitmap_data));
3488 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3489 set_rect(&rect, 320.0f, 0.0f, 640.0f, 240.0f);
3490 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
3491 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
3493 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3494 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3496 match = compare_surface(surface, "cb8136c91fbbdc76bb83b8c09edc1907b0a5d0a6");
3497 ok(match, "Surface does not match.\n");
3499 ID2D1Bitmap_Release(bitmap);
3500 ID2D1RenderTarget_Release(rt);
3501 IDXGISurface_Release(surface);
3502 IDXGISwapChain_Release(swapchain);
3503 ID3D10Device1_Release(device);
3504 DestroyWindow(window);
3507 static void test_opacity_brush(void)
3509 ID2D1BitmapBrush *bitmap_brush, *opacity_brush;
3510 D2D1_BITMAP_PROPERTIES bitmap_desc;
3511 ID2D1RectangleGeometry *geometry;
3512 ID2D1SolidColorBrush *color_brush;
3513 IDXGISwapChain *swapchain;
3514 D2D1_MATRIX_3X2_F matrix;
3515 ID2D1RenderTarget *rt;
3516 ID3D10Device1 *device;
3517 IDXGISurface *surface;
3518 ID2D1Factory *factory;
3519 ID2D1Bitmap *bitmap;
3520 D2D1_COLOR_F color;
3521 D2D1_RECT_F rect;
3522 D2D1_SIZE_U size;
3523 ULONG refcount;
3524 HWND window;
3525 HRESULT hr;
3526 BOOL match;
3528 static const DWORD bitmap_data[] =
3530 0xffff0000, 0x40ffff00, 0x4000ff00, 0xff00ffff,
3531 0x7f0000ff, 0x00ff00ff, 0x00000000, 0x7f7f7f7f,
3532 0x7fffffff, 0x00ffffff, 0x00ffffff, 0x7f000000,
3533 0xffffffff, 0x40000000, 0x40000000, 0xff000000,
3536 if (!(device = create_device()))
3538 skip("Failed to create device, skipping tests.\n");
3539 return;
3541 window = create_window();
3542 swapchain = create_swapchain(device, window, TRUE);
3543 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3544 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3545 rt = create_render_target(surface);
3546 ok(!!rt, "Failed to create render target.\n");
3547 ID2D1RenderTarget_GetFactory(rt, &factory);
3549 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
3550 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
3552 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
3553 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
3554 ok(SUCCEEDED(hr), "Failed to create color brush, hr %#x.\n", hr);
3556 set_size_u(&size, 4, 4);
3557 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3558 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3559 bitmap_desc.dpiX = 96.0f;
3560 bitmap_desc.dpiY = 96.0f;
3561 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3562 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3563 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &opacity_brush);
3564 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
3565 ID2D1BitmapBrush_SetInterpolationMode(opacity_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
3566 refcount = ID2D1Bitmap_Release(bitmap);
3567 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
3569 set_size_u(&size, 1, 1);
3570 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3571 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
3572 bitmap_desc.dpiX = 96.0f;
3573 bitmap_desc.dpiY = 96.0f;
3574 hr = ID2D1RenderTarget_CreateBitmap(rt, size, &bitmap_data[2], sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3575 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3576 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
3577 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
3578 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
3579 refcount = ID2D1Bitmap_Release(bitmap);
3580 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
3582 ID2D1RenderTarget_BeginDraw(rt);
3584 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
3585 ID2D1RenderTarget_Clear(rt, &color);
3587 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
3588 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3590 set_matrix_identity(&matrix);
3591 translate_matrix(&matrix, 120.0f, 120.0f);
3592 scale_matrix(&matrix, 20.0f, 60.0f);
3593 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3594 set_rect(&rect, 120.0f, 120.0f, 200.0f, 360.0f);
3595 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)opacity_brush);
3597 set_rect(&rect, 200.0f, 120.0f, 280.0f, 360.0f);
3598 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3600 set_matrix_identity(&matrix);
3601 translate_matrix(&matrix, 40.0f, 360.0f);
3602 scale_matrix(&matrix, 20.0f, 60.0f);
3603 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3604 set_rect(&rect, 40.0f, 360.0f, 120.0f, 600.0f);
3605 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3606 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3607 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
3608 ID2D1RectangleGeometry_Release(geometry);
3610 set_matrix_identity(&matrix);
3611 translate_matrix(&matrix, 120.0f, 360.0f);
3612 scale_matrix(&matrix, 20.0f, 60.0f);
3613 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3614 set_rect(&rect, 120.0f, 360.0f, 200.0f, 600.0f);
3615 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3616 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3617 (ID2D1Brush *)color_brush, (ID2D1Brush *)opacity_brush);
3618 ID2D1RectangleGeometry_Release(geometry);
3620 set_matrix_identity(&matrix);
3621 translate_matrix(&matrix, 200.0f, 360.0f);
3622 scale_matrix(&matrix, 20.0f, 60.0f);
3623 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3624 set_rect(&rect, 200.0f, 360.0f, 280.0f, 600.0f);
3625 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3626 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3627 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
3629 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3630 ok(hr == D2DERR_INCOMPATIBLE_BRUSH_TYPES, "Got unexpected hr %#x.\n", hr);
3631 match = compare_surface(surface, "7141c6c7b3decb91196428efb1856bcbf9872935");
3632 ok(match, "Surface does not match.\n");
3633 ID2D1RenderTarget_BeginDraw(rt);
3635 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3636 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
3637 ID2D1RectangleGeometry_Release(geometry);
3639 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.5f);
3640 set_matrix_identity(&matrix);
3641 translate_matrix(&matrix, 40.0f, 600.0f);
3642 scale_matrix(&matrix, 20.0f, 60.0f);
3643 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3644 set_rect(&rect, 40.0f, 600.0f, 120.0f, 840.0f);
3645 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3646 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3647 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
3648 ID2D1RectangleGeometry_Release(geometry);
3650 ID2D1BitmapBrush_SetOpacity(opacity_brush, 0.8f);
3651 set_matrix_identity(&matrix);
3652 translate_matrix(&matrix, 120.0f, 600.0f);
3653 scale_matrix(&matrix, 20.0f, 60.0f);
3654 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3655 set_rect(&rect, 120.0f, 600.0f, 200.0f, 840.0f);
3656 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3657 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3658 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)bitmap_brush);
3659 ID2D1RectangleGeometry_Release(geometry);
3661 set_matrix_identity(&matrix);
3662 translate_matrix(&matrix, 200.0f, 600.0f);
3663 scale_matrix(&matrix, 20.0f, 60.0f);
3664 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3665 set_rect(&rect, 200.0f, 600.0f, 280.0f, 840.0f);
3666 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3667 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3668 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
3669 ID2D1RectangleGeometry_Release(geometry);
3671 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3672 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3673 match = compare_surface(surface, "c3a5802d1750efa3e9122c1a92f6064df3872732");
3674 ok(match, "Surface does not match.\n");
3676 ID2D1BitmapBrush_Release(bitmap_brush);
3677 ID2D1BitmapBrush_Release(opacity_brush);
3678 ID2D1SolidColorBrush_Release(color_brush);
3679 ID2D1RenderTarget_Release(rt);
3680 refcount = ID2D1Factory_Release(factory);
3681 ok(!refcount, "Factory has %u references left.\n", refcount);
3682 IDXGISurface_Release(surface);
3683 IDXGISwapChain_Release(swapchain);
3684 ID3D10Device1_Release(device);
3685 DestroyWindow(window);
3688 static void test_create_target(void)
3690 IDXGISwapChain *swapchain;
3691 ID2D1Factory *factory;
3692 ID2D1RenderTarget *rt;
3693 ID3D10Device1 *device;
3694 IDXGISurface *surface;
3695 HWND window;
3696 HRESULT hr;
3697 static const struct
3699 float dpi_x, dpi_y;
3700 float rt_dpi_x, rt_dpi_y;
3701 HRESULT hr;
3703 create_dpi_tests[] =
3705 { 0.0f, 0.0f, 96.0f, 96.0f, S_OK },
3706 { 192.0f, 0.0f, 96.0f, 96.0f, E_INVALIDARG },
3707 { 0.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
3708 { 192.0f, -10.0f, 96.0f, 96.0f, E_INVALIDARG },
3709 { -10.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
3710 { 48.0f, 96.0f, 48.0f, 96.0f, S_OK },
3712 unsigned int i;
3714 if (!(device = create_device()))
3716 skip("Failed to create device, skipping tests.\n");
3717 return;
3719 window = create_window();
3720 swapchain = create_swapchain(device, window, TRUE);
3721 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3722 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3724 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
3725 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3727 for (i = 0; i < sizeof(create_dpi_tests) / sizeof(*create_dpi_tests); ++i)
3729 ID2D1GdiInteropRenderTarget *interop;
3730 D2D1_RENDER_TARGET_PROPERTIES desc;
3731 ID2D1RenderTarget *rt2;
3732 float dpi_x, dpi_y;
3733 IUnknown *unk;
3735 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3736 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
3737 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3738 desc.dpiX = create_dpi_tests[i].dpi_x;
3739 desc.dpiY = create_dpi_tests[i].dpi_y;
3740 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3741 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3743 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
3744 ok(hr == create_dpi_tests[i].hr, "Wrong return code, hr %#x, expected %#x, test %u.\n", hr,
3745 create_dpi_tests[i].hr, i);
3747 if (FAILED(hr))
3748 continue;
3750 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_IUnknown, (void **)&unk);
3751 ok(SUCCEEDED(hr), "Failed to get IUnknown, hr %#x.\n", hr);
3752 ok(unk == (IUnknown *)rt, "Expected same interface pointer.\n");
3753 IUnknown_Release(unk);
3755 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
3756 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
3757 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt2);
3758 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
3759 ok(rt2 == rt, "Unexpected render target\n");
3760 ID2D1RenderTarget_Release(rt2);
3761 ID2D1GdiInteropRenderTarget_Release(interop);
3763 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
3764 ok(dpi_x == create_dpi_tests[i].rt_dpi_x, "Wrong dpi_x %.8e, expected %.8e, test %u\n",
3765 dpi_x, create_dpi_tests[i].rt_dpi_x, i);
3766 ok(dpi_y == create_dpi_tests[i].rt_dpi_y, "Wrong dpi_y %.8e, expected %.8e, test %u\n",
3767 dpi_y, create_dpi_tests[i].rt_dpi_y, i);
3769 ID2D1RenderTarget_Release(rt);
3772 ID2D1Factory_Release(factory);
3773 IDXGISurface_Release(surface);
3774 IDXGISwapChain_Release(swapchain);
3775 ID3D10Device1_Release(device);
3776 DestroyWindow(window);
3779 static void test_draw_text_layout(void)
3781 static const struct
3783 D2D1_TEXT_ANTIALIAS_MODE aa_mode;
3784 DWRITE_RENDERING_MODE rendering_mode;
3785 HRESULT hr;
3787 antialias_mode_tests[] =
3789 { D2D1_TEXT_ANTIALIAS_MODE_DEFAULT, DWRITE_RENDERING_MODE_ALIASED },
3790 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_ALIASED },
3791 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_DEFAULT },
3792 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_OUTLINE },
3793 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_DEFAULT },
3794 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_OUTLINE },
3795 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL },
3796 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC },
3797 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL },
3798 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC },
3799 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_DEFAULT },
3800 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL },
3801 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC },
3802 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL },
3803 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC },
3804 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_OUTLINE, E_INVALIDARG },
3805 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_ALIASED, E_INVALIDARG },
3806 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_ALIASED, E_INVALIDARG },
3807 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL, E_INVALIDARG },
3808 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, E_INVALIDARG },
3809 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL, E_INVALIDARG },
3810 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC, E_INVALIDARG },
3812 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
3813 static const WCHAR textW[] = {'t','e','x','t',0};
3814 static const WCHAR emptyW[] = {0};
3815 D2D1_RENDER_TARGET_PROPERTIES desc;
3816 IDXGISwapChain *swapchain;
3817 ID2D1Factory *factory, *factory2;
3818 ID2D1RenderTarget *rt, *rt2;
3819 ID3D10Device1 *device;
3820 IDXGISurface *surface;
3821 HWND window;
3822 HRESULT hr;
3823 IDWriteFactory *dwrite_factory;
3824 IDWriteTextFormat *text_format;
3825 IDWriteTextLayout *text_layout;
3826 D2D1_POINT_2F origin;
3827 DWRITE_TEXT_RANGE range;
3828 D2D1_COLOR_F color;
3829 ID2D1SolidColorBrush *brush, *brush2;
3830 ID2D1RectangleGeometry *geometry;
3831 D2D1_RECT_F rect;
3832 unsigned int i;
3834 if (!(device = create_device()))
3836 skip("Failed to create device, skipping tests.\n");
3837 return;
3839 window = create_window();
3840 swapchain = create_swapchain(device, window, TRUE);
3841 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3842 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3844 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
3845 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3847 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
3848 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3849 ok(factory != factory2, "got same factory\n");
3851 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3852 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
3853 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3854 desc.dpiX = 0.0f;
3855 desc.dpiY = 0.0f;
3856 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3857 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3859 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
3860 ok(SUCCEEDED(hr), "Failed to create a target, hr %#x.\n", hr);
3862 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface, &desc, &rt2);
3863 ok(SUCCEEDED(hr), "Failed to create a target, hr %#x.\n", hr);
3865 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
3866 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3868 hr = IDWriteFactory_CreateTextFormat(dwrite_factory, tahomaW, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
3869 DWRITE_FONT_STRETCH_NORMAL, 10.0f, emptyW, &text_format);
3870 ok(SUCCEEDED(hr), "Failed to create text format, hr %#x.\n", hr);
3872 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, textW, 4, text_format, 100.0f, 100.0f, &text_layout);
3873 ok(SUCCEEDED(hr), "Failed to create text layout, hr %#x.\n", hr);
3875 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
3876 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
3877 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3879 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt2, &color, NULL, &brush2);
3880 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3882 /* effect brush is created from different factory */
3883 range.startPosition = 0;
3884 range.length = 4;
3885 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)brush2, range);
3886 ok(SUCCEEDED(hr), "Failed to set drawing effect, hr %#x.\n", hr);
3888 ID2D1RenderTarget_BeginDraw(rt);
3890 origin.x = origin.y = 0.0f;
3891 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
3893 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3894 todo_wine
3895 ok(hr == D2DERR_WRONG_FACTORY, "EndDraw failure expected, hr %#x.\n", hr);
3897 /* Effect is d2d resource, but not a brush. */
3898 set_rect(&rect, 0.0f, 0.0f, 10.0f, 10.0f);
3899 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3900 ok(SUCCEEDED(hr), "Failed to geometry, hr %#x.\n", hr);
3902 range.startPosition = 0;
3903 range.length = 4;
3904 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)geometry, range);
3905 ok(SUCCEEDED(hr), "Failed to set drawing effect, hr %#x.\n", hr);
3906 ID2D1RectangleGeometry_Release(geometry);
3908 ID2D1RenderTarget_BeginDraw(rt);
3910 origin.x = origin.y = 0.0f;
3911 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
3913 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3914 ok(hr == S_OK, "EndDraw failure expected, hr %#x.\n", hr);
3916 for (i = 0; i < sizeof(antialias_mode_tests)/sizeof(*antialias_mode_tests); i++)
3918 IDWriteRenderingParams *rendering_params;
3920 ID2D1RenderTarget_SetTextAntialiasMode(rt, antialias_mode_tests[i].aa_mode);
3922 hr = IDWriteFactory_CreateCustomRenderingParams(dwrite_factory, 2.0f, 1.0f, 0.0f, DWRITE_PIXEL_GEOMETRY_FLAT,
3923 antialias_mode_tests[i].rendering_mode, &rendering_params);
3924 ok(SUCCEEDED(hr), "Failed to create custom rendering params, hr %#x.\n", hr);
3926 ID2D1RenderTarget_SetTextRenderingParams(rt, rendering_params);
3928 ID2D1RenderTarget_BeginDraw(rt);
3930 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush *)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
3932 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3933 ok(hr == antialias_mode_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
3935 IDWriteRenderingParams_Release(rendering_params);
3938 IDWriteTextFormat_Release(text_format);
3939 IDWriteTextLayout_Release(text_layout);
3940 IDWriteFactory_Release(dwrite_factory);
3941 ID2D1RenderTarget_Release(rt);
3942 ID2D1RenderTarget_Release(rt2);
3944 ID2D1Factory_Release(factory);
3945 ID2D1Factory_Release(factory2);
3946 IDXGISurface_Release(surface);
3947 IDXGISwapChain_Release(swapchain);
3948 ID3D10Device1_Release(device);
3949 DestroyWindow(window);
3952 static void create_target_dibsection(HDC hdc, UINT32 width, UINT32 height)
3954 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
3955 BITMAPINFO *bmi = (BITMAPINFO*)bmibuf;
3956 HBITMAP hbm;
3958 memset(bmi, 0, sizeof(bmibuf));
3959 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
3960 bmi->bmiHeader.biHeight = -height;
3961 bmi->bmiHeader.biWidth = width;
3962 bmi->bmiHeader.biBitCount = 32;
3963 bmi->bmiHeader.biPlanes = 1;
3964 bmi->bmiHeader.biCompression = BI_RGB;
3966 hbm = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
3967 ok(hbm != NULL, "Failed to create a dib section.\n");
3969 DeleteObject(SelectObject(hdc, hbm));
3972 static void test_dc_target(void)
3974 static const D2D1_PIXEL_FORMAT invalid_formats[] =
3976 { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
3977 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN },
3978 { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
3980 D2D1_TEXT_ANTIALIAS_MODE text_aa_mode;
3981 ID2D1GdiInteropRenderTarget *interop;
3982 D2D1_RENDER_TARGET_PROPERTIES desc;
3983 D2D1_MATRIX_3X2_F matrix, matrix2;
3984 ID2D1DCRenderTarget *rt, *rt2;
3985 D2D1_ANTIALIAS_MODE aa_mode;
3986 ID2D1SolidColorBrush *brush;
3987 ID2D1RenderTarget *rt3;
3988 ID2D1Factory *factory;
3989 ID3D10Device1 *device;
3990 FLOAT dpi_x, dpi_y;
3991 D2D1_COLOR_F color;
3992 D2D1_SIZE_U sizeu;
3993 D2D1_SIZE_F size;
3994 D2D1_TAG t1, t2;
3995 unsigned int i;
3996 HDC hdc, hdc2;
3997 D2D_RECT_F r;
3998 COLORREF clr;
3999 HRESULT hr;
4000 RECT rect;
4002 if (!(device = create_device()))
4004 skip("Failed to create device, skipping tests.\n");
4005 return;
4007 ID3D10Device1_Release(device);
4009 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4010 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4012 for (i = 0; i < sizeof(invalid_formats) / sizeof(*invalid_formats); ++i)
4014 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4015 desc.pixelFormat = invalid_formats[i];
4016 desc.dpiX = 96.0f;
4017 desc.dpiY = 96.0f;
4018 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4019 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4021 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
4022 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x.\n", hr);
4025 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4026 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4027 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4028 desc.dpiX = 96.0f;
4029 desc.dpiY = 96.0f;
4030 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4031 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4032 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
4033 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
4035 hr = ID2D1DCRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
4036 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
4037 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
4038 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4039 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
4040 ID2D1RenderTarget_Release(rt3);
4041 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1DCRenderTarget, (void **)&rt2);
4042 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4043 ok(rt2 == rt, "Unexpected render target\n");
4044 ID2D1DCRenderTarget_Release(rt2);
4045 ID2D1GdiInteropRenderTarget_Release(interop);
4047 size = ID2D1DCRenderTarget_GetSize(rt);
4048 ok(size.width == 0.0f, "got width %.08e.\n", size.width);
4049 ok(size.height == 0.0f, "got height %.08e.\n", size.height);
4051 sizeu = ID2D1DCRenderTarget_GetPixelSize(rt);
4052 ok(sizeu.width == 0, "got width %u.\n", sizeu.width);
4053 ok(sizeu.height == 0, "got height %u.\n", sizeu.height);
4055 /* object creation methods work without BindDC() */
4056 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
4057 hr = ID2D1DCRenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
4058 ok(SUCCEEDED(hr), "Failed to create a brush, hr %#x.\n", hr);
4059 ID2D1SolidColorBrush_Release(brush);
4061 ID2D1DCRenderTarget_BeginDraw(rt);
4062 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
4063 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
4065 ID2D1DCRenderTarget_Release(rt);
4067 /* BindDC() */
4068 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
4069 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
4071 aa_mode = ID2D1DCRenderTarget_GetAntialiasMode(rt);
4072 ok(aa_mode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, "Got wrong default aa mode %d.\n", aa_mode);
4073 text_aa_mode = ID2D1DCRenderTarget_GetTextAntialiasMode(rt);
4074 ok(text_aa_mode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT, "Got wrong default text aa mode %d.\n", text_aa_mode);
4076 ID2D1DCRenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
4077 ok(dpi_x == 96.0f && dpi_y == 96.0f, "Got dpi_x %f, dpi_y %f.\n", dpi_x, dpi_y);
4079 hdc = CreateCompatibleDC(NULL);
4080 ok(hdc != NULL, "Failed to create an HDC.\n");
4082 create_target_dibsection(hdc, 16, 16);
4084 SetRect(&rect, 0, 0, 32, 32);
4085 hr = ID2D1DCRenderTarget_BindDC(rt, NULL, &rect);
4086 ok(hr == E_INVALIDARG, "BindDC() returned %#x.\n", hr);
4088 /* Target properties are retained during BindDC() */
4089 ID2D1DCRenderTarget_SetTags(rt, 1, 2);
4090 ID2D1DCRenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4091 ID2D1DCRenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
4093 set_matrix_identity(&matrix);
4094 translate_matrix(&matrix, 200.0f, 600.0f);
4095 ID2D1DCRenderTarget_SetTransform(rt, &matrix);
4097 hr = ID2D1DCRenderTarget_BindDC(rt, hdc, &rect);
4098 ok(hr == S_OK, "BindDC() returned %#x.\n", hr);
4100 ID2D1DCRenderTarget_GetTags(rt, &t1, &t2);
4101 ok(t1 == 1 && t2 == 2, "Got wrong tags.\n");
4103 aa_mode = ID2D1DCRenderTarget_GetAntialiasMode(rt);
4104 ok(aa_mode == D2D1_ANTIALIAS_MODE_ALIASED, "Got wrong aa mode %d.\n", aa_mode);
4106 text_aa_mode = ID2D1DCRenderTarget_GetTextAntialiasMode(rt);
4107 ok(text_aa_mode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, "Got wrong text aa mode %d.\n", text_aa_mode);
4109 ID2D1DCRenderTarget_GetTransform(rt, &matrix2);
4110 ok(!memcmp(&matrix, &matrix2, sizeof(matrix)), "Got wrong target transform.\n");
4112 set_matrix_identity(&matrix);
4113 ID2D1DCRenderTarget_SetTransform(rt, &matrix);
4115 /* target size comes from specified dimensions, not from selected bitmap size */
4116 size = ID2D1DCRenderTarget_GetSize(rt);
4117 ok(size.width == 32.0f, "got width %.08e.\n", size.width);
4118 ok(size.height == 32.0f, "got height %.08e.\n", size.height);
4120 /* clear one HDC to red, switch to another one, partially fill it and test contents */
4121 ID2D1DCRenderTarget_BeginDraw(rt);
4123 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
4124 ID2D1DCRenderTarget_Clear(rt, &color);
4126 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
4127 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
4129 clr = GetPixel(hdc, 0, 0);
4130 ok(clr == RGB(255, 0, 0), "Got color %#x\n", clr);
4132 hdc2 = CreateCompatibleDC(NULL);
4133 ok(hdc2 != NULL, "Failed to create an HDC.\n");
4135 create_target_dibsection(hdc2, 16, 16);
4137 hr = ID2D1DCRenderTarget_BindDC(rt, hdc2, &rect);
4138 ok(hr == S_OK, "BindDC() returned %#x.\n", hr);
4140 clr = GetPixel(hdc2, 0, 0);
4141 ok(clr == 0, "Got color %#x\n", clr);
4143 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
4144 hr = ID2D1DCRenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
4145 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4147 ID2D1DCRenderTarget_BeginDraw(rt);
4149 r.left = r.top = 0.0f;
4150 r.bottom = 16.0f;
4151 r.right = 8.0f;
4152 ID2D1DCRenderTarget_FillRectangle(rt, &r, (ID2D1Brush*)brush);
4154 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
4155 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
4157 ID2D1SolidColorBrush_Release(brush);
4159 clr = GetPixel(hdc2, 0, 0);
4160 ok(clr == RGB(0, 255, 0), "Got color %#x\n", clr);
4162 clr = GetPixel(hdc2, 10, 0);
4163 ok(clr == 0, "Got color %#x\n", clr);
4165 DeleteDC(hdc);
4166 DeleteDC(hdc2);
4167 ID2D1DCRenderTarget_Release(rt);
4168 ID2D1Factory_Release(factory);
4171 static void test_hwnd_target(void)
4173 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
4174 ID2D1GdiInteropRenderTarget *interop;
4175 D2D1_RENDER_TARGET_PROPERTIES desc;
4176 ID2D1HwndRenderTarget *rt, *rt2;
4177 ID2D1RenderTarget *rt3;
4178 ID2D1Factory *factory;
4179 ID3D10Device1 *device;
4180 D2D1_SIZE_U size;
4181 HRESULT hr;
4183 if (!(device = create_device()))
4185 skip("Failed to create device, skipping tests.\n");
4186 return;
4188 ID3D10Device1_Release(device);
4190 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4191 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4193 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4194 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4195 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4196 desc.dpiX = 0.0f;
4197 desc.dpiY = 0.0f;
4198 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4199 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4201 hwnd_rt_desc.hwnd = NULL;
4202 hwnd_rt_desc.pixelSize.width = 64;
4203 hwnd_rt_desc.pixelSize.height = 64;
4204 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
4206 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
4207 ok(FAILED(hr), "Target creation should fail, hr %#x.\n", hr);
4209 hwnd_rt_desc.hwnd = (HWND)0xdeadbeef;
4210 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
4211 ok(FAILED(hr), "Target creation should fail, hr %#x.\n", hr);
4213 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
4214 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
4215 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
4216 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4218 hr = ID2D1HwndRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
4219 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
4220 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
4221 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4222 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
4223 ID2D1RenderTarget_Release(rt3);
4224 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1HwndRenderTarget, (void **)&rt2);
4225 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4226 ok(rt2 == rt, "Unexpected render target\n");
4227 ID2D1HwndRenderTarget_Release(rt2);
4228 ID2D1GdiInteropRenderTarget_Release(interop);
4230 size.width = 128;
4231 size.height = 64;
4232 hr = ID2D1HwndRenderTarget_Resize(rt, &size);
4233 ok(SUCCEEDED(hr), "Failed to resize render target, hr %#x.\n", hr);
4235 ID2D1HwndRenderTarget_Release(rt);
4237 DestroyWindow(hwnd_rt_desc.hwnd);
4238 ID2D1Factory_Release(factory);
4241 static void test_bitmap_target(void)
4243 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
4244 ID2D1GdiInteropRenderTarget *interop;
4245 D2D1_SIZE_U pixel_size, pixel_size2;
4246 D2D1_RENDER_TARGET_PROPERTIES desc;
4247 ID2D1BitmapRenderTarget *rt, *rt2;
4248 ID2D1HwndRenderTarget *hwnd_rt;
4249 ID2D1Bitmap *bitmap, *bitmap2;
4250 ID2D1DCRenderTarget *dc_rt;
4251 D2D1_SIZE_F size, size2;
4252 ID2D1RenderTarget *rt3;
4253 ID2D1Factory *factory;
4254 ID3D10Device1 *device;
4255 float dpi[2], dpi2[2];
4256 D2D1_COLOR_F color;
4257 ULONG refcount;
4258 HRESULT hr;
4260 if (!(device = create_device()))
4262 skip("Failed to create device, skipping tests.\n");
4263 return;
4265 ID3D10Device1_Release(device);
4267 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4268 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4270 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4271 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4272 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4273 desc.dpiX = 96.0f;
4274 desc.dpiY = 192.0f;
4275 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4276 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4278 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
4279 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
4280 hwnd_rt_desc.pixelSize.width = 64;
4281 hwnd_rt_desc.pixelSize.height = 64;
4282 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
4284 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &hwnd_rt);
4285 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4287 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, NULL, NULL,
4288 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
4289 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4291 hr = ID2D1BitmapRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
4292 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
4293 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
4294 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4295 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
4296 ID2D1RenderTarget_Release(rt3);
4297 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1BitmapRenderTarget, (void **)&rt2);
4298 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4299 ok(rt2 == rt, "Unexpected render target\n");
4300 ID2D1BitmapRenderTarget_Release(rt2);
4301 ID2D1GdiInteropRenderTarget_Release(interop);
4303 /* See if parent target is referenced. */
4304 ID2D1HwndRenderTarget_AddRef(hwnd_rt);
4305 refcount = ID2D1HwndRenderTarget_Release(hwnd_rt);
4306 ok(refcount == 1, "Target should not have been referenced, got %u.\n", refcount);
4308 /* Size was not specified, should match parent. */
4309 pixel_size = ID2D1HwndRenderTarget_GetPixelSize(hwnd_rt);
4310 pixel_size2 = ID2D1BitmapRenderTarget_GetPixelSize(rt);
4311 ok(!memcmp(&pixel_size, &pixel_size2, sizeof(pixel_size)), "Got target pixel size mismatch.\n");
4313 size = ID2D1HwndRenderTarget_GetSize(hwnd_rt);
4314 size2 = ID2D1BitmapRenderTarget_GetSize(rt);
4315 ok(!memcmp(&size, &size2, sizeof(size)), "Got target DIP size mismatch.\n");
4317 ID2D1HwndRenderTarget_GetDpi(hwnd_rt, dpi, dpi + 1);
4318 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
4319 ok(!memcmp(dpi, dpi2, sizeof(dpi)), "Got dpi mismatch.\n");
4321 ID2D1BitmapRenderTarget_Release(rt);
4323 /* Pixel size specified. */
4324 set_size_u(&pixel_size, 32, 32);
4325 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, &pixel_size, NULL,
4326 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
4327 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4329 pixel_size2 = ID2D1BitmapRenderTarget_GetPixelSize(rt);
4330 ok(!memcmp(&pixel_size, &pixel_size2, sizeof(pixel_size)), "Got target pixel size mismatch.\n");
4332 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
4333 ok(!memcmp(dpi, dpi2, sizeof(dpi)), "Got dpi mismatch.\n");
4335 ID2D1BitmapRenderTarget_Release(rt);
4337 /* Both pixel size and DIP size are specified. */
4338 set_size_u(&pixel_size, 128, 128);
4339 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, &size, &pixel_size, NULL,
4340 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
4341 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4343 /* Doubled pixel size dimensions with the same DIP size give doubled dpi. */
4344 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
4345 ok(dpi[0] == dpi2[0] / 2.0f && dpi[1] == dpi2[1] / 2.0f, "Got dpi mismatch.\n");
4347 ID2D1BitmapRenderTarget_Release(rt);
4349 /* DIP size is specified, fractional. */
4350 set_size_f(&size, 70.1f, 70.4f);
4351 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, &size, NULL, NULL,
4352 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
4353 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4355 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
4357 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt);
4358 ok(pixel_size.width == ceilf(size.width * dpi[0] / 96.0f)
4359 && pixel_size.height == ceilf(size.height * dpi[1] / 96.0f), "Wrong pixel size %ux%u\n",
4360 pixel_size.width, pixel_size.height);
4362 dpi[0] *= (pixel_size.width / size.width) * (96.0f / dpi[0]);
4363 dpi[1] *= (pixel_size.height / size.height) * (96.0f / dpi[1]);
4365 ok(compare_float(dpi[0], dpi2[0], 1) && compare_float(dpi[1], dpi2[1], 1), "Got dpi mismatch.\n");
4367 ID2D1HwndRenderTarget_Release(hwnd_rt);
4369 /* Check if GetBitmap() returns same instance. */
4370 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap);
4371 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
4372 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap2);
4373 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
4374 ok(bitmap == bitmap2, "Got different bitmap instances.\n");
4376 /* Draw something, see if bitmap instance is retained. */
4377 ID2D1BitmapRenderTarget_BeginDraw(rt);
4378 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
4379 ID2D1BitmapRenderTarget_Clear(rt, &color);
4380 hr = ID2D1BitmapRenderTarget_EndDraw(rt, NULL, NULL);
4381 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
4383 ID2D1Bitmap_Release(bitmap2);
4384 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap2);
4385 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
4386 ok(bitmap == bitmap2, "Got different bitmap instances.\n");
4388 ID2D1Bitmap_Release(bitmap);
4389 ID2D1Bitmap_Release(bitmap2);
4391 refcount = ID2D1BitmapRenderTarget_Release(rt);
4392 ok(!refcount, "Target should be released, got %u.\n", refcount);
4394 DestroyWindow(hwnd_rt_desc.hwnd);
4396 /* Compatible target created from a DC target without associated HDC */
4397 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4398 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4399 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4400 desc.dpiX = 96.0f;
4401 desc.dpiY = 96.0f;
4402 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4403 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4404 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &dc_rt);
4405 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
4407 hr = ID2D1DCRenderTarget_CreateCompatibleRenderTarget(dc_rt, NULL, NULL, NULL,
4408 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
4409 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4411 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt);
4412 todo_wine
4413 ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
4415 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap);
4416 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
4417 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
4418 todo_wine
4419 ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
4420 ID2D1Bitmap_Release(bitmap);
4422 ID2D1BitmapRenderTarget_Release(rt);
4423 ID2D1DCRenderTarget_Release(dc_rt);
4425 ID2D1Factory_Release(factory);
4428 static void test_desktop_dpi(void)
4430 ID2D1Factory *factory;
4431 float dpi_x, dpi_y;
4432 HRESULT hr;
4434 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4435 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4437 dpi_x = dpi_y = 0.0f;
4438 ID2D1Factory_GetDesktopDpi(factory, &dpi_x, &dpi_y);
4439 ok(dpi_x > 0.0f && dpi_y > 0.0f, "Got wrong dpi %f x %f.\n", dpi_x, dpi_y);
4441 ID2D1Factory_Release(factory);
4444 static void test_stroke_style(void)
4446 static const struct
4448 D2D1_DASH_STYLE dash_style;
4449 UINT32 dash_count;
4450 float dashes[6];
4452 dash_style_tests[] =
4454 {D2D1_DASH_STYLE_SOLID, 0},
4455 {D2D1_DASH_STYLE_DASH, 2, {2.0f, 2.0f}},
4456 {D2D1_DASH_STYLE_DOT, 2, {0.0f, 2.0f}},
4457 {D2D1_DASH_STYLE_DASH_DOT, 4, {2.0f, 2.0f, 0.0f, 2.0f}},
4458 {D2D1_DASH_STYLE_DASH_DOT_DOT, 6, {2.0f, 2.0f, 0.0f, 2.0f, 0.0f, 2.0f}},
4460 D2D1_STROKE_STYLE_PROPERTIES desc;
4461 ID2D1StrokeStyle *style;
4462 ID2D1Factory *factory;
4463 UINT32 count;
4464 HRESULT hr;
4465 D2D1_CAP_STYLE cap_style;
4466 D2D1_LINE_JOIN line_join;
4467 float miter_limit, dash_offset;
4468 D2D1_DASH_STYLE dash_style;
4469 unsigned int i;
4470 float dashes[2];
4472 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4473 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4475 desc.startCap = D2D1_CAP_STYLE_SQUARE;
4476 desc.endCap = D2D1_CAP_STYLE_ROUND;
4477 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
4478 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
4479 desc.miterLimit = 1.5f;
4480 desc.dashStyle = D2D1_DASH_STYLE_DOT;
4481 desc.dashOffset = -1.0f;
4483 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
4484 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
4486 cap_style = ID2D1StrokeStyle_GetStartCap(style);
4487 ok(cap_style == D2D1_CAP_STYLE_SQUARE, "Unexpected cap style %d.\n", cap_style);
4488 cap_style = ID2D1StrokeStyle_GetEndCap(style);
4489 ok(cap_style == D2D1_CAP_STYLE_ROUND, "Unexpected cap style %d.\n", cap_style);
4490 cap_style = ID2D1StrokeStyle_GetDashCap(style);
4491 ok(cap_style == D2D1_CAP_STYLE_TRIANGLE, "Unexpected cap style %d.\n", cap_style);
4492 line_join = ID2D1StrokeStyle_GetLineJoin(style);
4493 ok(line_join == D2D1_LINE_JOIN_BEVEL, "Unexpected line joind %d.\n", line_join);
4494 miter_limit = ID2D1StrokeStyle_GetMiterLimit(style);
4495 ok(miter_limit == 1.5f, "Unexpected miter limit %f.\n", miter_limit);
4496 dash_style = ID2D1StrokeStyle_GetDashStyle(style);
4497 ok(dash_style == D2D1_DASH_STYLE_DOT, "Unexpected dash style %d.\n", dash_style);
4498 dash_offset = ID2D1StrokeStyle_GetDashOffset(style);
4499 ok(dash_offset == -1.0f, "Unexpected dash offset %f.\n", dash_offset);
4501 /* Custom dash pattern, no dashes data specified. */
4502 desc.startCap = D2D1_CAP_STYLE_SQUARE;
4503 desc.endCap = D2D1_CAP_STYLE_ROUND;
4504 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
4505 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
4506 desc.miterLimit = 1.5f;
4507 desc.dashStyle = D2D1_DASH_STYLE_CUSTOM;
4508 desc.dashOffset = 0.0f;
4510 ID2D1StrokeStyle_Release(style);
4512 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
4513 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
4515 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 0, &style);
4516 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
4518 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
4519 ok(hr == S_OK, "Unexpected return value, %#x.\n", hr);
4520 ID2D1StrokeStyle_Release(style);
4522 /* Builtin style, dashes are specified. */
4523 desc.dashStyle = D2D1_DASH_STYLE_DOT;
4524 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
4525 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
4527 /* Invalid style. */
4528 desc.dashStyle = 100;
4529 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
4530 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
4532 /* Test returned dash pattern for builtin styles. */
4533 desc.startCap = D2D1_CAP_STYLE_SQUARE;
4534 desc.endCap = D2D1_CAP_STYLE_ROUND;
4535 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
4536 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
4537 desc.miterLimit = 1.5f;
4538 desc.dashOffset = 0.0f;
4540 for (i = 0; i < sizeof(dash_style_tests)/sizeof(dash_style_tests[0]); i++)
4542 float dashes[10];
4543 UINT dash_count;
4545 desc.dashStyle = dash_style_tests[i].dash_style;
4547 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
4548 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
4550 dash_count = ID2D1StrokeStyle_GetDashesCount(style);
4551 ok(dash_count == dash_style_tests[i].dash_count, "%u: unexpected dash count %u, expected %u.\n",
4552 i, dash_count, dash_style_tests[i].dash_count);
4553 ok(dash_count < sizeof(dashes)/sizeof(dashes[0]), "%u: unexpectedly large dash count %u.\n", i, dash_count);
4554 if (dash_count == dash_style_tests[i].dash_count)
4556 unsigned int j;
4558 ID2D1StrokeStyle_GetDashes(style, dashes, dash_count);
4559 ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
4560 "%u: unexpected dash array.\n", i);
4562 /* Ask for more dashes than style actually has. */
4563 memset(dashes, 0xcc, sizeof(dashes));
4564 ID2D1StrokeStyle_GetDashes(style, dashes, sizeof(dashes)/sizeof(dashes[0]));
4565 ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
4566 "%u: unexpected dash array.\n", i);
4568 for (j = dash_count; j < sizeof(dashes)/sizeof(dashes[0]); j++)
4569 ok(dashes[j] == 0.0f, "%u: unexpected dash value at %u.\n", i, j);
4572 ID2D1StrokeStyle_Release(style);
4575 /* NULL dashes array, non-zero length. */
4576 memset(&desc, 0, sizeof(desc));
4577 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 1, &style);
4578 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
4580 count = ID2D1StrokeStyle_GetDashesCount(style);
4581 ok(count == 0, "Unexpected dashes count %u.\n", count);
4583 ID2D1StrokeStyle_Release(style);
4585 ID2D1Factory_Release(factory);
4588 static void test_gradient(void)
4590 ID2D1GradientStopCollection *gradient;
4591 D2D1_GRADIENT_STOP stops[3], stops2[3];
4592 IDXGISwapChain *swapchain;
4593 ID2D1RenderTarget *rt;
4594 ID3D10Device1 *device;
4595 IDXGISurface *surface;
4596 D2D1_COLOR_F color;
4597 unsigned int i;
4598 UINT32 count;
4599 HWND window;
4600 HRESULT hr;
4602 if (!(device = create_device()))
4604 skip("Failed to create device, skipping tests.\n");
4605 return;
4607 window = create_window();
4608 swapchain = create_swapchain(device, window, TRUE);
4609 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
4610 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4611 rt = create_render_target(surface);
4612 ok(!!rt, "Failed to create render target.\n");
4614 stops2[0].position = 0.5f;
4615 set_color(&stops2[0].color, 1.0f, 1.0f, 0.0f, 1.0f);
4616 stops2[1] = stops2[0];
4617 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops2, 2, D2D1_GAMMA_2_2,
4618 D2D1_EXTEND_MODE_CLAMP, &gradient);
4619 ok(SUCCEEDED(hr), "Failed to create stop collection, hr %#x.\n", hr);
4621 count = ID2D1GradientStopCollection_GetGradientStopCount(gradient);
4622 ok(count == 2, "Unexpected stop count %u.\n", count);
4624 /* Request more stops than collection has. */
4625 stops[0].position = 123.4f;
4626 set_color(&stops[0].color, 1.0f, 0.5f, 0.4f, 1.0f);
4627 color = stops[0].color;
4628 stops[2] = stops[1] = stops[0];
4629 ID2D1GradientStopCollection_GetGradientStops(gradient, stops, sizeof(stops)/sizeof(stops[0]));
4630 ok(!memcmp(stops, stops2, sizeof(*stops) * count), "Unexpected gradient stops array.\n");
4631 for (i = count; i < sizeof(stops)/sizeof(stops[0]); i++)
4633 ok(stops[i].position == 123.4f, "%u: unexpected stop position %f.\n", i, stops[i].position);
4634 ok(!memcmp(&stops[i].color, &color, sizeof(color)), "%u: unexpected stop color.\n", i);
4637 ID2D1GradientStopCollection_Release(gradient);
4638 ID2D1RenderTarget_Release(rt);
4640 IDXGISurface_Release(surface);
4641 IDXGISwapChain_Release(swapchain);
4642 ID3D10Device1_Release(device);
4643 DestroyWindow(window);
4646 static void test_draw_geometry(void)
4648 ID2D1TransformedGeometry *transformed_geometry[4];
4649 ID2D1RectangleGeometry *rect_geometry[2];
4650 D2D1_POINT_2F point = {0.0f, 0.0f};
4651 ID2D1SolidColorBrush *brush;
4652 ID2D1PathGeometry *geometry;
4653 IDXGISwapChain *swapchain;
4654 D2D1_MATRIX_3X2_F matrix;
4655 ID2D1GeometrySink *sink;
4656 ID2D1RenderTarget *rt;
4657 ID3D10Device1 *device;
4658 IDXGISurface *surface;
4659 ID2D1Factory *factory;
4660 D2D1_POINT_2F p0, p1;
4661 D2D1_ELLIPSE ellipse;
4662 D2D1_COLOR_F color;
4663 D2D1_RECT_F rect;
4664 ULONG refcount;
4665 HWND window;
4666 HRESULT hr;
4667 BOOL match;
4669 if (!(device = create_device()))
4671 skip("Failed to create device, skipping tests.\n");
4672 return;
4674 window = create_window();
4675 swapchain = create_swapchain(device, window, TRUE);
4676 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
4677 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4678 rt = create_render_target(surface);
4679 ok(!!rt, "Failed to create render target.\n");
4680 ID2D1RenderTarget_GetFactory(rt, &factory);
4682 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
4683 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4684 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
4685 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
4686 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4688 ID2D1RenderTarget_BeginDraw(rt);
4689 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
4690 ID2D1RenderTarget_Clear(rt, &color);
4692 set_point(&p0, 40.0f, 160.0f);
4693 ID2D1RenderTarget_DrawLine(rt, p0, p0, (ID2D1Brush *)brush, 10.0f, NULL);
4694 set_point(&p0, 100.0f, 160.0f);
4695 set_point(&p1, 140.0f, 160.0f);
4696 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
4697 set_point(&p0, 200.0f, 80.0f);
4698 set_point(&p1, 200.0f, 240.0f);
4699 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
4700 set_point(&p0, 260.0f, 240.0f);
4701 set_point(&p1, 300.0f, 80.0f);
4702 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
4704 set_rect(&rect, 40.0f, 480.0f, 40.0f, 480.0f);
4705 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
4706 set_rect(&rect, 100.0f, 480.0f, 140.0f, 480.0f);
4707 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
4708 set_rect(&rect, 200.0f, 400.0f, 200.0f, 560.0f);
4709 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
4710 set_rect(&rect, 260.0f, 560.0f, 300.0f, 400.0f);
4711 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
4713 set_ellipse(&ellipse, 40.0f, 800.0f, 0.0f, 0.0f);
4714 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
4715 set_ellipse(&ellipse, 120.0f, 800.0f, 20.0f, 0.0f);
4716 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
4717 set_ellipse(&ellipse, 200.0f, 800.0f, 0.0f, 80.0f);
4718 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
4719 set_ellipse(&ellipse, 280.0f, 800.0f, 20.0f, 80.0f);
4720 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
4722 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4723 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4725 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "");
4726 ok(match, "Figure does not match.\n");
4727 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "yGBQUFBQUFBQUFDoYQAA");
4728 ok(match, "Figure does not match.\n");
4729 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0,
4730 "xjIUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4731 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4732 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4733 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4734 "jAEUjAEUjAEUjAEUxjIA");
4735 ok(match, "Figure does not match.\n");
4736 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 2,
4737 "zjECnQETjAEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
4738 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
4739 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
4740 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
4741 "igEVigEVigEVigEVjAETnQECzjEA");
4742 ok(match, "Figure does not match.\n");
4744 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "5mAUjAEUjAEUjAEUjAEUhmIA");
4745 todo_wine ok(match, "Figure does not match.\n");
4746 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0, "vmBkPGQ8ZDxkPGTeYQAA");
4747 todo_wine ok(match, "Figure does not match.\n");
4748 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0,
4749 "5i4UjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4750 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4751 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4752 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4753 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUhjAA");
4754 todo_wine ok(match, "Figure does not match.\n");
4755 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 0,
4756 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
4757 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
4758 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
4759 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
4760 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
4761 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
4762 ok(match, "Figure does not match.\n");
4764 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
4765 todo_wine ok(match, "Figure does not match.\n");
4766 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
4767 todo_wine ok(match, "Figure does not match.\n");
4768 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0,
4769 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4770 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4771 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4772 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4773 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
4774 todo_wine ok(match, "Figure does not match.\n");
4775 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 10,
4776 "hDAYgwEieyh1LnAybBcIF2gWDhZkFhIWYRUWFV4VGhVbFRwVWRUeFVcVIBVVFCQUUxQmFFEUKBRP"
4777 "FSgVTRUqFUwULBRLFC4USRQwFEgUMBRHFDIURhQyFEUUNBREFDQUQxQ2FEIUNhRBFDgUQBQ4FEAU"
4778 "OBQ/FDoUPhQ6FD4UOhQ+FDoUPhQ6FD0UPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
4779 "FDwUPBQ8FDwUPBQ8FD0UOhQ+FDoUPhQ6FD4UOhQ+FDoUPxQ4FEAUOBRAFDgUQRQ2FEIUNhRDFDQU"
4780 "RBQ0FEUUMhRGFDIURxQwFEgUMBRJFC4USxQsFEwVKhVNFSgVTxQoFFEUJhRTFCQUVRUgFVcVHhVZ"
4781 "FRwVWxUaFV4VFhVhFhIWZBYOFmgXCBdsMnAudSh7IoMBGIQw");
4782 todo_wine ok(match, "Figure does not match.\n");
4784 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
4785 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
4786 hr = ID2D1PathGeometry_Open(geometry, &sink);
4787 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
4789 set_point(&point, 40.0f, 160.0f);
4790 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4791 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
4793 set_point(&point, 120.0f, 160.0f);
4794 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4795 line_to(sink, 120.0f, 160.0f);
4796 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
4798 set_point(&point, 200.0f, 160.0f);
4799 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4800 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
4802 set_point(&point, 280.0f, 160.0f);
4803 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4804 line_to(sink, 280.0f, 160.0f);
4805 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
4807 set_point(&point, 20.0f, 480.0f);
4808 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4809 line_to(sink, 60.0f, 480.0f);
4810 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
4812 set_point(&point, 120.0f, 400.0f);
4813 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4814 line_to(sink, 120.0f, 560.0f);
4815 line_to(sink, 120.0f, 400.0f);
4816 line_to(sink, 120.0f, 560.0f);
4817 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
4819 set_point(&point, 180.0f, 480.0f);
4820 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4821 line_to(sink, 220.0f, 480.0f);
4822 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
4824 set_point(&point, 280.0f, 400.0f);
4825 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4826 line_to(sink, 280.0f, 560.0f);
4827 line_to(sink, 280.0f, 400.0f);
4828 line_to(sink, 280.0f, 560.0f);
4829 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
4831 set_point(&point, 20.0f, 880.0f);
4832 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4833 line_to(sink, 40.0f, 720.0f);
4834 line_to(sink, 60.0f, 880.0f);
4835 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
4837 set_point(&point, 100.0f, 720.0f);
4838 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4839 line_to(sink, 120.0f, 880.0f);
4840 line_to(sink, 140.0f, 720.0f);
4841 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
4843 set_point(&point, 180.0f, 880.0f);
4844 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4845 line_to(sink, 200.0f, 720.0f);
4846 line_to(sink, 220.0f, 880.0f);
4847 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
4849 set_point(&point, 260.0f, 720.0f);
4850 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
4851 line_to(sink, 280.0f, 880.0f);
4852 line_to(sink, 300.0f, 720.0f);
4853 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
4855 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
4856 hr = ID2D1GeometrySink_Close(sink);
4857 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
4858 ID2D1GeometrySink_Release(sink);
4860 ID2D1RenderTarget_BeginDraw(rt);
4861 ID2D1RenderTarget_Clear(rt, &color);
4862 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, 5.0f, NULL);
4863 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4864 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4865 ID2D1PathGeometry_Release(geometry);
4867 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "");
4868 ok(match, "Figure does not match.\n");
4869 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "");
4870 ok(match, "Figure does not match.\n");
4871 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0, "");
4872 ok(match, "Figure does not match.\n");
4873 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 0, "q2MKlgEKq2MA");
4874 todo_wine ok(match, "Figure does not match.\n");
4876 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "iGNQUFCIYwAA");
4877 ok(match, "Figure does not match.\n");
4878 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0,
4879 "qyIKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
4880 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
4881 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKQQpLCkEKSwqWAQqW"
4882 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
4883 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
4884 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQrLIwAA");
4885 ok(match, "Figure does not match.\n");
4886 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0, "4GLAAuBi");
4887 ok(match, "Figure does not match.\n");
4888 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 0,
4889 "qyIKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
4890 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
4891 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKSwpBCksKQQqWAQqWAQqW"
4892 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
4893 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
4894 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQrLIwAA");
4895 ok(match, "Figure does not match.\n");
4897 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0,
4898 "rycCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
4899 "jAEUiwEKAgqKAQoCCokBCgQKiAEKBAqHAQoGCoYBCgYKhQEKCAqEAQoICoMBCgoKggEKCgqBAQoM"
4900 "CoABCgwKfwoOCn4KDgp9ChAKfAoQCnsKEgp6ChIKeQoUCngKFAp3ChYKdgoWCnUKGAp0ChgKcwoa"
4901 "CnIKGgpxChwKcAocCm8KHgpuCh4KbQogCmwKIAprCiIKagoiCmkKJApoCiQKZwomCmYKJgplCigK"
4902 "ZAooCmMKKgpiCioKYQosCmAKLApfCi4KXgouCl0KMApcCjAKWwoyCloKMgpZCjQKWAo0ClcKNgpW"
4903 "CjYKVQo4ClQKOApTCjoKUgo6ClEKPApQCjwKTwo+Ck4KPgpNCkAKTApACksKQgpKCkIKSQpECkgK"
4904 "RApHCkYKozIA");
4905 ok(match, "Figure does not match.\n");
4906 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0,
4907 "ozIKRgpHCkQKSApECkkKQgpKCkIKSwpACkwKQApNCj4KTgo+Ck8KPApQCjwKUQo6ClIKOgpTCjgK"
4908 "VAo4ClUKNgpWCjYKVwo0ClgKNApZCjIKWgoyClsKMApcCjAKXQouCl4KLgpfCiwKYAosCmEKKgpi"
4909 "CioKYwooCmQKKAplCiYKZgomCmcKJApoCiQKaQoiCmoKIgprCiAKbAogCm0KHgpuCh4KbwocCnAK"
4910 "HApxChoKcgoaCnMKGAp0ChgKdQoWCnYKFgp3ChQKeAoUCnkKEgp6ChIKewoQCnwKEAp9Cg4KfgoO"
4911 "Cn8KDAqAAQoMCoEBCgoKggEKCgqDAQoICoQBCggKhQEKBgqGAQoGCocBCgQKiAEKBAqJAQoCCooB"
4912 "CgIKiwEUjAEUjQESjgESjwEQkAEQkQEOkgEOkwEMlAEMlQEKlgEKlwEImAEImQEGmgEGmwEEnAEE"
4913 "nQECngECrycA");
4914 ok(match, "Figure does not match.\n");
4915 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0,
4916 "rycCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
4917 "jAEUiwEKAgqKAQoCCokBCgQKiAEKBAqHAQoGCoYBCgYKhQEKCAqEAQoICoMBCgoKggEKCgqBAQoM"
4918 "CoABCgwKfwoOCn4KDgp9ChAKfAoQCnsKEgp6ChIKeQoUCngKFAp3ChYKdgoWCnUKGAp0ChgKcwoa"
4919 "CnIKGgpxChwKcAocCm8KHgpuCh4KbQogCmwKIAprCiIKagoiCmkKJApoCiQKZwomCmYKJgplCigK"
4920 "ZAooCmMKKgpiCioKYQosCmAKLApfCi4KXgouCl0KMApcCjAKWwoyCloKMgpZCjQKWAo0ClcKNgpW"
4921 "CjYKVQo4ClQKOApTCjoKUgo6ClEKPApQCjwKTwo+Ck4KPgpNCkAKTApACksKQgpKCkIKSQpECkgK"
4922 "RApHWkZagzEA");
4923 ok(match, "Figure does not match.\n");
4924 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 0,
4925 "gzFaRlpHCkQKSApECkkKQgpKCkIKSwpACkwKQApNCj4KTgo+Ck8KPApQCjwKUQo6ClIKOgpTCjgK"
4926 "VAo4ClUKNgpWCjYKVwo0ClgKNApZCjIKWgoyClsKMApcCjAKXQouCl4KLgpfCiwKYAosCmEKKgpi"
4927 "CioKYwooCmQKKAplCiYKZgomCmcKJApoCiQKaQoiCmoKIgprCiAKbAogCm0KHgpuCh4KbwocCnAK"
4928 "HApxChoKcgoaCnMKGAp0ChgKdQoWCnYKFgp3ChQKeAoUCnkKEgp6ChIKewoQCnwKEAp9Cg4KfgoO"
4929 "Cn8KDAqAAQoMCoEBCgoKggEKCgqDAQoICoQBCggKhQEKBgqGAQoGCocBCgQKiAEKBAqJAQoCCooB"
4930 "CgIKiwEUjAEUjQESjgESjwEQkAEQkQEOkgEOkwEMlAEMlQEKlgEKlwEImAEImQEGmgEGmwEEnAEE"
4931 "nQECngECrycA");
4932 ok(match, "Figure does not match.\n");
4934 set_rect(&rect, 20.0f, 80.0f, 60.0f, 240.0f);
4935 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[0]);
4936 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
4938 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
4939 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[1]);
4940 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
4942 set_matrix_identity(&matrix);
4943 translate_matrix(&matrix, 160.0f, 640.0f);
4944 scale_matrix(&matrix, 40.0f, 160.0f);
4945 rotate_matrix(&matrix, M_PI / -5.0f);
4946 hr = ID2D1Factory_CreateTransformedGeometry(factory,
4947 (ID2D1Geometry *)rect_geometry[1], &matrix, &transformed_geometry[0]);
4948 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
4950 set_matrix_identity(&matrix);
4951 scale_matrix(&matrix, 0.5f, 1.0f);
4952 translate_matrix(&matrix, -80.0f, 0.0f);
4953 hr = ID2D1Factory_CreateTransformedGeometry(factory,
4954 (ID2D1Geometry *)transformed_geometry[0], &matrix, &transformed_geometry[1]);
4955 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
4957 set_matrix_identity(&matrix);
4958 rotate_matrix(&matrix, M_PI / 2.0f);
4959 translate_matrix(&matrix, 80.0f, -320.0f);
4960 scale_matrix(&matrix, 2.0f, 0.25f);
4961 hr = ID2D1Factory_CreateTransformedGeometry(factory,
4962 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
4963 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
4965 ID2D1RenderTarget_BeginDraw(rt);
4966 ID2D1RenderTarget_Clear(rt, &color);
4967 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)rect_geometry[0], (ID2D1Brush *)brush, 10.0f, NULL);
4968 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, 10.0f, NULL);
4969 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, 5.0f, NULL);
4970 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, 15.0f, NULL);
4971 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4972 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4973 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
4974 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
4975 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
4976 ID2D1RectangleGeometry_Release(rect_geometry[1]);
4977 ID2D1RectangleGeometry_Release(rect_geometry[0]);
4979 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0,
4980 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
4981 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
4982 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
4983 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
4984 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
4985 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
4986 ok(match, "Figure does not match.\n");
4987 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 32,
4988 "8XYGtQIOrAIXpAIfmwIokwIwigI4gwJA+gFJ8gFR6QEzAiXhATMKJdgBMxMl0AEzGyXHATMkJb8B"
4989 "MysmtgEzNCWvATM8JaYBM0UlngEzTSWVATNWJY0BM14lhAEzZyV8M28lczN4JWszgAElYjOIASZa"
4990 "M5ABJVgtmQElWCWhASVYJaEBJVgloQElWCWhASVYJaEBJVgloQElWCWhASVYJaEBJVglmQEtWCWQ"
4991 "ATNaJogBM2IlgAEzayV4M3MlbzN8JWczhAElXjONASVWM5UBJU0zngElRTOmASU8M68BJTQztgEm"
4992 "KzO/ASUkM8cBJRsz0AElEzPYASUKM+EBJQIz6QFR8gFJ+gFAgwI4igIwkwIomwIfpAIXrAIOtQIG"
4993 "8XYA");
4994 ok(match, "Figure does not match.\n");
4995 match = compare_figure(surface, 0, 160, 160, 320, 0xff652e89, 32,
4996 "ujEBngECnQEDnQEEmwEFmgEHmQEHmAEIlwEKlgEKlQELlAENkwENkgEOkQEQjwERjwESjQETjAEU"
4997 "jAEKAQqKAQoCCokBCgMKiQEKBAqHAQoFCoYBCgYKhgEKBwqEAQoICoMBCgkKgwEKCgqBAQoLCoAB"
4998 "Cg0KfgsNCn4KDgp9ChAKewsQCnsKEQp6ChMKeAoUCngKFAp3ChYKdQoXCnUKGApzChkKcgoaCnIK"
4999 "GwpwChwKbwodCm4LHgptCh8KbAogCmsLIQpqCiIKaQokCmcKJQpnCiUKZgonCmQKKApkCigKYwoq"
5000 "CmEKKwphCisKYAotCl4KLgpdCy8KXAowClsKMQpaCzIKWQozClgKNApXCjYKVgo2ClUKNwpUCjkK"
5001 "Uwo5ClIKOwpQCjwKTws8Ck8KPgpNCj8KTAs/CkwKQQpKCkIKSQtCCkkKRApHCkUKRgpHCkUKRwpE"
5002 "CkgKQwpKCkIKSgpBCksKQApNCj4LTQo+Ck4KPQpQCjsLUAo7ClIKOQpTCjgLUwo4ClUKNgpWCjUK"
5003 "Vwo1ClgKMwpZCjQKWAo0ClkKMwpZCjQKWQozClkKMwpZCjQKWQozClkKMwpZCjQKWQozClkKNApY"
5004 "CjQKWQozClkKNApZCjMKWQozClkKNApZCjMKWQozClkKNApZCjMKWQo0ClgKNApZCjMKWQo0ClkK"
5005 "MwpZCjMKWQo0ClkKMwpZCjMKWQo0ClkKMwpZCjQKWAo0ClkKMwpYCjUKVwo1ClYKNgpVCjgKUws4"
5006 "ClMKOQpSCjsKUAs7ClAKPQpOCj4KTQs+Ck0KQApLCkEKSgpCCkoKQwpICkQKRwpFCkcKRgpFCkcK"
5007 "RApJCkILSQpCCkoKQQpMCj8LTAo/Ck0KPgpPCjwLTwo8ClAKOwpSCjkKUwo5ClQKNwpVCjYKVgo2"
5008 "ClcKNApYCjMKWQoyC1oKMQpbCjAKXAovC10KLgpeCi0KYAorCmEKKwphCioKYwooCmQKKApkCicK"
5009 "ZgolCmcKJQpnCiQKaQoiCmoKIQtrCiAKbAofCm0KHgtuCh0KbwocCnAKGwpyChoKcgoZCnMKGAp1"
5010 "ChcKdQoWCncKFAp4ChQKeAoTCnoKEQp7ChALewoQCn0KDgp+Cg0LfgoNCoABCgsKgQEKCgqDAQoJ"
5011 "CoMBCggKhAEKBwqGAQoGCoYBCgUKhwEKBAqJAQoDCokBCgIKigEKAQqMARSMARONARKPARGPARCR"
5012 "AQ6SAQ2TAQ2UAQuVAQqWAQqXAQiYAQeZAQeaAQWbAQSdAQOdAQKeAQG6MQAA");
5013 ok(match, "Figure does not match.\n");
5014 match = compare_figure(surface, 160, 160, 320, 320, 0xff652e89, 64,
5015 "82ICvQIEugIHuAIJtgIKtAINsgIPsAIRrQITrAIVqQIYpwIZpgIbowIeoQIgnwIhnQIkmwImmAIp"
5016 "lgIVARSVAhUDFJICFQUVkAIVBxSPAhUJFIwCFQwUigIVDRWHAhYPFIYCFRIUhAIVFBSBAhUWFf8B"
5017 "FRgU/gEVGhT7ARUcFfkBFR4U9wEWIBT1ARUjFPMBFSQV8AEVJxTvARUpFOwBFisU6gEVLRXoARUv"
5018 "FOYBFjEU5AEVMxXiARU1FOABFTgU3gEVOhTbARY7FdkBFT4U2AEVQBTVARZCFNMBFUQV0QEVRhTP"
5019 "ARVJFM0BFUoVygEWTBTJARVPFMcBFVEUxAEVUxXCARVVFMEBFVcUvgEVWRW8ARVbFbkBFl0UuAEV"
5020 "YBS2ARVhFbMBFWQUsgEVZhSwARVoFK0BFWoVqwEVbBSpARZuFKcBFXAVpQEVchWiARV1FKEBFXcU"
5021 "nwEVeBWcARV7FJsBFX0UmAEWfxSWARWBARWUARWDARSSARWGARSQARWHARWOARWJARWLARWMARSK"
5022 "ARWOARSHARaPARWFARWSARSEARWUARSBARWXARR/FZgBFX0VmgEUexWdARR5FZ4BFXYWoAEVdBWj"
5023 "ARRzFaUBFHAVpwEVbhWpARRtFasBFGoVrgEUaBWvARVmFbEBFGcUsgEUZxSxARVmFbEBFWYUsgEU"
5024 "ZxSyARRnFLEBFWYVsQEUZxSyARRnFLIBFGcUsQEVZhWxARRnFLIBFGcUsQEVZhWxARVmFLIBFGcU"
5025 "sgEUZxSxARVmFbEBFGcUsgEUZxSyARRmFbEBFWYVsQEUZxSyARRnFLEBFWYVsQEUZxSyARRnFLIB"
5026 "FGcUsQEVZhWxARRnFLIBFGcUsgEUZhWxARVmFbEBFGcUsgEUZxSxARVmFa8BFWgUrgEVahSrARVt"
5027 "FKkBFW4VpwEVcBSlARVzFKMBFXQVoAEWdhWeARV5FJ0BFXsUmgEVfRWYARV/FJcBFYEBFJQBFYQB"
5028 "FJIBFYUBFY8BFocBFI4BFYoBFIwBFYsBFYkBFY4BFYcBFZABFIYBFZIBFIMBFZQBFYEBFZYBFH8W"
5029 "mAEUfRWbARR7FZwBFXgVnwEUdxWhARR1FaIBFXIVpQEVcBWnARRuFqkBFGwVqwEVahWtARRoFbAB"
5030 "FGYVsgEUZBWzARVhFbYBFGAVuAEUXRa5ARVbFbwBFVkVvgEUVxXBARRVFcIBFVMVxAEUURXHARRP"
5031 "FckBFEwWygEVShXNARRJFc8BFEYV0QEVRBXTARRCFtUBFEAV2AEUPhXZARU7FtsBFDoV3gEUOBXg"
5032 "ARQ1FeIBFTMV5AEUMRbmARQvFegBFS0V6gEUKxbsARQpFe8BFCcV8AEVJBXzARQjFfUBFCAW9wEU"
5033 "HhX5ARUcFfsBFBoV/gEUGBX/ARUWFYECFBQVhAIUEhWGAhQPFocCFQ0VigIUDBWMAhQJFY8CFAcV"
5034 "kAIVBRWSAhQDFZUCFAEVlgIpmAImmwIknQIhnwIgoQIeowIbpgIZpwIYqQIVrAITrQIRsAIPsgIN"
5035 "tAIKtgIJuAIHugIEvQIC82IA");
5036 ok(match, "Figure does not match.\n");
5038 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
5039 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
5040 hr = ID2D1PathGeometry_Open(geometry, &sink);
5041 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
5043 set_point(&point, 20.0f, 80.0f);
5044 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5045 quadratic_to(sink, 40.0f, 80.0f, 60.0f, 80.0f);
5046 quadratic_to(sink, 60.0f, 160.0f, 60.0f, 240.0f);
5047 quadratic_to(sink, 40.0f, 240.0f, 20.0f, 240.0f);
5048 quadratic_to(sink, 20.0f, 160.0f, 20.0f, 80.0f);
5049 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5051 set_point(&point, 100.0f, 80.0f);
5052 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5053 quadratic_to(sink, 105.0f, 80.0f, 140.0f, 80.0f);
5054 quadratic_to(sink, 140.0f, 100.0f, 140.0f, 240.0f);
5055 quadratic_to(sink, 135.0f, 240.0f, 100.0f, 240.0f);
5056 quadratic_to(sink, 100.0f, 220.0f, 100.0f, 80.0f);
5057 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5059 set_point(&point, 180.0f, 80.0f);
5060 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5061 quadratic_to(sink, 215.0f, 80.0f, 220.0f, 80.0f);
5062 quadratic_to(sink, 220.0f, 220.0f, 220.0f, 240.0f);
5063 quadratic_to(sink, 185.0f, 240.0f, 180.0f, 240.0f);
5064 quadratic_to(sink, 180.0f, 100.0f, 180.0f, 80.0f);
5065 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5067 set_point(&point, 260.0f, 80.0f);
5068 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5069 quadratic_to(sink, 280.0f, 80.0f, 300.0f, 80.0f);
5070 quadratic_to(sink, 300.0f, 160.0f, 300.0f, 240.0f);
5071 quadratic_to(sink, 280.0f, 240.0f, 260.0f, 240.0f);
5072 quadratic_to(sink, 260.0f, 160.0f, 260.0f, 80.0f);
5073 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5075 set_point(&point, 20.0f, 400.0f);
5076 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5077 quadratic_to(sink, 40.0f, 420.0f, 60.0f, 400.0f);
5078 quadratic_to(sink, 55.0f, 480.0f, 60.0f, 560.0f);
5079 quadratic_to(sink, 40.0f, 540.0f, 20.0f, 560.0f);
5080 quadratic_to(sink, 25.0f, 480.0f, 20.0f, 400.0f);
5081 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5083 set_point(&point, 100.0f, 400.0f);
5084 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5085 quadratic_to(sink, 105.0f, 420.0f, 140.0f, 400.0f);
5086 quadratic_to(sink, 135.0f, 420.0f, 140.0f, 560.0f);
5087 quadratic_to(sink, 135.0f, 540.0f, 100.0f, 560.0f);
5088 quadratic_to(sink, 105.0f, 540.0f, 100.0f, 400.0f);
5089 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5091 set_point(&point, 180.0f, 400.0f);
5092 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5093 quadratic_to(sink, 215.0f, 420.0f, 220.0f, 400.0f);
5094 quadratic_to(sink, 215.0f, 540.0f, 220.0f, 560.0f);
5095 quadratic_to(sink, 185.0f, 540.0f, 180.0f, 560.0f);
5096 quadratic_to(sink, 185.0f, 420.0f, 180.0f, 400.0f);
5097 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5099 set_point(&point, 260.0f, 400.0f);
5100 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5101 quadratic_to(sink, 280.0f, 420.0f, 300.0f, 400.0f);
5102 quadratic_to(sink, 295.0f, 480.0f, 300.0f, 560.0f);
5103 quadratic_to(sink, 280.0f, 540.0f, 260.0f, 560.0f);
5104 quadratic_to(sink, 265.0f, 480.0f, 260.0f, 400.0f);
5105 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5107 set_point(&point, 20.0f, 720.0f);
5108 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5109 quadratic_to(sink, 40.0f, 700.0f, 60.0f, 720.0f);
5110 quadratic_to(sink, 65.0f, 800.0f, 60.0f, 880.0f);
5111 quadratic_to(sink, 40.0f, 900.0f, 20.0f, 880.0f);
5112 quadratic_to(sink, 15.0f, 800.0f, 20.0f, 720.0f);
5113 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5115 set_point(&point, 100.0f, 720.0f);
5116 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5117 quadratic_to(sink, 105.0f, 700.0f, 140.0f, 720.0f);
5118 quadratic_to(sink, 145.0f, 740.0f, 140.0f, 880.0f);
5119 quadratic_to(sink, 135.0f, 900.0f, 100.0f, 880.0f);
5120 quadratic_to(sink, 95.0f, 860.0f, 100.0f, 720.0f);
5121 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5123 set_point(&point, 180.0f, 720.0f);
5124 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5125 quadratic_to(sink, 215.0f, 700.0f, 220.0f, 720.0f);
5126 quadratic_to(sink, 225.0f, 860.0f, 220.0f, 880.0f);
5127 quadratic_to(sink, 185.0f, 900.0f, 180.0f, 880.0f);
5128 quadratic_to(sink, 175.0f, 740.0f, 180.0f, 720.0f);
5129 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5131 set_point(&point, 260.0f, 720.0f);
5132 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5133 quadratic_to(sink, 280.0f, 700.0f, 300.0f, 720.0f);
5134 quadratic_to(sink, 305.0f, 800.0f, 300.0f, 880.0f);
5135 quadratic_to(sink, 280.0f, 900.0f, 260.0f, 880.0f);
5136 quadratic_to(sink, 255.0f, 800.0f, 260.0f, 720.0f);
5137 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5139 hr = ID2D1GeometrySink_Close(sink);
5140 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
5141 ID2D1GeometrySink_Release(sink);
5143 ID2D1RenderTarget_BeginDraw(rt);
5144 ID2D1RenderTarget_Clear(rt, &color);
5145 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, 10.0f, NULL);
5146 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5147 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5148 ID2D1PathGeometry_Release(geometry);
5150 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0,
5151 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5152 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5153 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5154 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5155 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5156 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
5157 ok(match, "Figure does not match.\n");
5158 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0,
5159 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5160 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5161 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5162 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5163 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5164 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
5165 ok(match, "Figure does not match.\n");
5166 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0,
5167 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5168 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5169 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5170 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5171 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5172 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
5173 ok(match, "Figure does not match.\n");
5174 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 0,
5175 "yC5aRlpGWjxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5176 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5177 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5178 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5179 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5180 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
5181 ok(match, "Figure does not match.\n");
5183 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 64,
5184 "3SoDYAM6B1gHOgtQCzoPSA87EkASPBc2FzwcLBw8IiAiPWI+Yj5iPhQBOAEUPhQKJgoUPxQ4FEAU"
5185 "OBRAFDgUQBQ4FEAUOBRBFDYUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRDFDQURBQ0FEQUNBREFDQURBQ0"
5186 "FEQUNBREFDQURBQ0FEQUNBREFDQURRQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIU"
5187 "RhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRG"
5188 "FDIURRQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEMUNhRCFDYUQhQ2FEIU"
5189 "NhRCFDYUQhQ2FEEUOBRAFDgUQBQ4FEAUOBRAFDgUPxQKJgoUPhQBOAEUPmI+Yj5iPSIgIjwcLBw8"
5190 "FzYXPBJAEjsPSA86C1ALOgdYBzoDYAPdKgAA");
5191 ok(match, "Figure does not match.\n");
5192 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 1024,
5193 "uxUBnwECngEDnQEEnAEFmwEGmwEGmgEHmQEImAEJlwEKlgELlQEMlQEMlAENkwEOkgEPkQEQkAER"
5194 "VQQ2Ek0KOBJFEDkTPRY6FDUcOxUrJDwYHi09Yj5iP2BAQwkUQDgUFEAUOBRAFDcUQRQ3FEEUNxRC"
5195 "FDYUQhQ2FEIUNhRCFDUUQxQ1FEMUNRRDFDUUQxQ1FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQU"
5196 "NBREFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQ0"
5197 "FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQ0FEQUNBREFDQU"
5198 "RBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRDFDUUQxQ1FEMUNRRDFDUUQhQ2FEIUNhRC"
5199 "FDYUQhQ3FEEUNxRBFDcUQBQ4FEAUFDhAFAlDQGA/Yj5iPS0eGDwkKxU7HDUUOhY9EzkQRRI4Ck0S"
5200 "NgRVEZABEJEBD5IBDpMBDZQBDJUBDJUBC5YBCpcBCZgBCJkBB5oBBpsBBpsBBZwBBJ0BA54BAp8B"
5201 "AbsV");
5202 ok(match, "Figure does not match.\n");
5203 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 1024,
5204 "pBYBngECnQEDnAEEmwEFmgEGmQEGmQEHmAEIlwEJlgEKlQELlAEMkwEMkwENkgEOkQEPkAEQNgRV"
5205 "ETcKTRI4EEUSOhY9EzscNRQ8JCsVPS0eGD5iPmI/YEAUCUNAFBQ4QBQ4FEEUNxRBFDcUQRQ3FEEU"
5206 "NhRCFDYUQhQ2FEMUNRRDFDUUQxQ1FEMUNRRDFDUUQxQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0"
5207 "FEQUNBREFDQURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxREFDQU"
5208 "RBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxREFDQURBQ0FEQUNBRE"
5209 "FDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQUQxQ1FEMUNRRDFDUUQxQ1FEMUNRRDFDYUQhQ2FEIU"
5210 "NhRBFDcUQRQ3FEEUNxRBFDgUQDgUFEBDCRRAYD9iPmI+GB4tPRUrJDwUNRw7Ez0WOhJFEDgSTQo3"
5211 "EVUENhCQAQ+RAQ6SAQ2TAQyTAQyUAQuVAQqWAQmXAQiYAQeZAQaZAQaaAQWbAQScAQOdAQKeAQGk"
5212 "FgAA");
5213 ok(match, "Figure does not match.\n");
5214 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 64,
5215 "wCsDmQEHlQELkQEPSwJAEkgLNhc8HCwcPCIgIj1iPmI+Yj4UATgBFD4UCiYKFD8UOBRAFDgUQBQ4"
5216 "FEAUOBRAFDgUQRQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDYUQxQ0FEQUNBREFDQURBQ0FEQUNBREFDQU"
5217 "RBQ0FEQUNBREFDQURBQ0FEUUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRG"
5218 "FDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEUU"
5219 "NBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBRDFDYUQhQ2FEIUNhRCFDYUQhQ2"
5220 "FEIUNhRBFDgUQBQ4FEAUOBRAFDgUQBQ4FD8UCiYKFD4UATgBFD5iPmI+Yj0iICI8HCwcPBc2FzwS"
5221 "QBI7D0gPOgtQCzoHWAc6A2AD3SoA");
5222 ok(match, "Figure does not match.\n");
5224 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 64,
5225 "3SkmcThiRFdOTVhEICAgPhwsHDwXNhc8FDwUOxQ+FDoUPhQ6FD4UOhQ+FDoUPhQ5FEAUOBRAFDgU"
5226 "QBQ4FEAUOBRAFDcUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDUURBQ0FEQUNBREFDQURBQ0FEQUNBRE"
5227 "FDQURBQ0FEQUNBREFDQURBQzFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYU"
5228 "MhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQz"
5229 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRCFDYUQhQ2FEIUNhRCFDYU"
5230 "QhQ2FEIUNxRAFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPhQ6FD4UOhQ+FDsUPBQ8FzYXPBws"
5231 "HD4gICBEWE1OV0RiOHEm3SkA");
5232 ok(match, "Figure does not match.\n");
5233 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 1024,
5234 "zykoczhkRVhQTlpEFx4tPRUrJDwUNRw7FDwVOxQ+FDoUPhQ5FEAUOBRAFDgUQBQ4FEAUOBRBFDcU"
5235 "QRQ3FEEUNhRCFDYUQhQ2FEIUNhRDFDUUQxQ1FEMUNRRDFDUUQxQ0FEQUNBREFDQURBQ0FEQUNBRE"
5236 "FDQURBQ0FEQUNBREFDQURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUU"
5237 "MxRFFDMURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURBQ0"
5238 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEMUNRRDFDUUQxQ1FEMUNRRDFDYU"
5239 "QhQ2FEIUNhRCFDYUQRQ3FEEUNxRBFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDsVPBQ7HDUUPCQr"
5240 "FT0tHhdEWk5QWEVkOHMozykA");
5241 ok(match, "Figure does not match.\n");
5242 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 1024,
5243 "6SkobThfRVNQSFpALR4XPSQrFTscNRQ7FTwUOhQ+FDoUPhQ5FEAUOBRAFDgUQBQ4FEAUNxRBFDcU"
5244 "QRQ3FEEUNxRCFDYUQhQ2FEIUNRRDFDUUQxQ1FEMUNRRDFDUUQxQ1FEQUNBREFDQURBQ0FEQUNBRE"
5245 "FDQURBQ0FEQUNBREFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUU"
5246 "MxRFFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDQURBQ0"
5247 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ1FEMUNRRDFDUUQxQ1FEMUNRRDFDUU"
5248 "QhQ2FEIUNhRCFDcUQRQ3FEEUNxRBFDcUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPBU7FDUcOxUr"
5249 "JD0XHi1AWkhQU0VfOG0o6SkA");
5250 ok(match, "Figure does not match.\n");
5251 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 64,
5252 "3SkmcThiRFdOTVhGHiAgRhQsHDwXNhc8FDwUOxQ+FDoUPhQ6FD4UOhQ+FDoUPhQ5FEAUOBRAFDgU"
5253 "QBQ4FEAUOBRAFDcUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDUURBQ0FEQUNBREFDQURBQ0FEQUNBRE"
5254 "FDQURBQ0FEQUNBREFDQURBQzFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYU"
5255 "MhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQz"
5256 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRCFDYUQhQ2FEIUNhRCFDYU"
5257 "QhQ2FEIUNxRAFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPhQ6FD4UOhQ+FDsUPBQ8FzYXPBws"
5258 "HD4gICBEWE1OV0RiOHEm3SkA");
5259 ok(match, "Figure does not match.\n");
5261 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
5262 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
5263 hr = ID2D1PathGeometry_Open(geometry, &sink);
5264 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
5266 set_point(&point, -0.402914f, 0.915514f);
5267 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5268 quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
5269 quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f);
5270 quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f);
5271 quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f);
5272 quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f);
5273 quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f);
5274 quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f);
5275 quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f);
5276 quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f);
5277 quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f);
5278 quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f);
5279 quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f);
5280 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5282 hr = ID2D1GeometrySink_Close(sink);
5283 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
5284 ID2D1GeometrySink_Release(sink);
5286 set_matrix_identity(&matrix);
5287 translate_matrix(&matrix, 40.0f, 160.0f);
5288 scale_matrix(&matrix, 20.0f, 80.0f);
5289 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5290 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]);
5291 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5293 set_matrix_identity(&matrix);
5294 translate_matrix(&matrix, 160.0f, 640.0f);
5295 scale_matrix(&matrix, 40.0f, 160.0f);
5296 rotate_matrix(&matrix, M_PI / -5.0f);
5297 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5298 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]);
5299 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5300 ID2D1PathGeometry_Release(geometry);
5302 set_matrix_identity(&matrix);
5303 scale_matrix(&matrix, 0.5f, 1.0f);
5304 translate_matrix(&matrix, -80.0f, 0.0f);
5305 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5306 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
5307 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5309 set_matrix_identity(&matrix);
5310 rotate_matrix(&matrix, M_PI / 2.0f);
5311 translate_matrix(&matrix, 80.0f, -320.0f);
5312 scale_matrix(&matrix, 2.0f, 0.25f);
5313 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5314 (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]);
5315 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5317 ID2D1RenderTarget_BeginDraw(rt);
5318 ID2D1RenderTarget_Clear(rt, &color);
5319 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, 2.0f, NULL);
5320 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, 10.0f, NULL);
5321 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, 5.0f, NULL);
5322 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[3], (ID2D1Brush *)brush, 15.0f, NULL);
5323 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5324 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5325 ID2D1TransformedGeometry_Release(transformed_geometry[3]);
5326 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
5327 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
5328 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
5330 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 128,
5331 "yjIJkQEHBwaIAQUSBYMBBBYEggEEFgSCAQQWBIIBBBYEggEEFgSCAQQWBIIBBBYEggEEFgSCAQQW"
5332 "BIIBBBYEggEEFgSDAQQVBIMBBBUEgwEEFQSDAQQVBIMBBBUEgwEEFQSDAQQVBIMBBBUEgwEEFQSD"
5333 "AQQVBIQBBBQEhAEEFASEAQQTBIUBBBMEhQEEEwSFAQQTBIUBBBMEhQEEEwSGAQQSBIYBBBIEhgEE"
5334 "EgSGAQQSBIYBBBIEhgEEEgSGAQQRBIgBBBAEiAEEEASIAQQQBIkBBA4EigEEDgSLAQQMBIwBBAwE"
5335 "jQEECgSOAQQJBJABBAgEkAEFBgSSAQQGBJMBBAQElAEEBASVAQQDBJUBBAIElwEEAQSXAQiZAQeZ"
5336 "AQaaAQaaAQaaAQabAQWbAQWbAQWbAQWaAQeZAQeZAQeZAQiXAQQBBJYBBAMElQEEAwWRAQUGBY0B"
5337 "BQwFhwEFEgSCAQUXBYABBBoFfgUYBIIBBhEFiAEUpTEA");
5338 ok(match, "Figure does not match.\n");
5339 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 512,
5340 "yJIBArkCDa4CGKMCIZoCK5ECM4gCO4ECQ/gBS/EBUesBLAYl5QEsDiPeASwWIdkBLBwh0wEsISHO"
5341 "ASsgKMsBKR4vyAEnHDPIASUaNMsBIxg1mQEFMCIUN54BCygiDzijAREhIgY9qAEYGWGuAR4RXbMB"
5342 "JAhbuQGAAcABesYBc84Ba9YBTvQBP4MCOIoCNI4CM5ACMZICL5QCLZYCK5kCKJsCJ54CI6MCHq8C"
5343 "EraSAQAA");
5344 ok(match, "Figure does not match.\n");
5345 match = compare_figure(surface, 0, 160, 160, 320, 0xff652e89, 512,
5346 "xWkCmwEFmAEJlQELlAENkgEOkQEPjwESjQETjAEVigELAQqJAQsCCogBCwQKhwEKBQqGAQoGCoYB"
5347 "CgcKhAEKCAqEAQoIC4IBCgoKggEKCgqBAQoMCoABCgwKfwoNCn8KDgp9Cg8KfQoPCnwKEQp7ChEK"
5348 "egoSCnoKEwp4ChQKeAoUCncLFQp2ChYKdgoWCnYKFwp2ChYKdgoWCncKFgp2ChYKdgoWCncKFQt2"
5349 "ChYKdwoVCncKFQp4ChUKdwoVCncKFQp4ChUKdwoVCngKFAp4ChUKeAoUCngKFAp4CxMKeQoUCngK"
5350 "FAp5ChMKeQoUCnkKEwp5ChMKegoSC3kKEwp6ChIKegoSCnoLEgp6ChIKegoSCnsKEQp7ChEKfAoQ"
5351 "CnwKEAp9Cg8KfQoPCn4KDgp+Cg4KfwoOCn4KDgp/Cg0KfwoNCoABCgwKgAEKDAqBAQoLCoEBCgsK"
5352 "gQELCgqCAQoKCoIBCwkKgwEKCQqDAQoJCoQBCggKhAEKCQqEAQsHCoUBCwYKhgELBQqHAQsECogB"
5353 "CwMKiQELAgqLAQoBCowBFI0BE44BE44BEo8BEZABEJEBD5IBDpMBDpMBDZMBDZQBDJQBDZQBDJQB"
5354 "DBUCfgwSBH4MEQV/DA4GgAEMDAiAAQ0KCYEBDAgLgQENBQ2BAQ0EDoIBDQEPgwEdgwEdgwEdgwEc"
5355 "hAEKAgQCCoUBCgYKhgEKBgqGAQoFC4YBCgUKhwEKBAqIAQoECogBCgMKiQEKAwqIAQoDCokBCgMK"
5356 "iQEKAgqJAQoCCooBCgIKiQEKAgqKAQoBCosBCgEKigEKAQqLARSMARSLARSMAROMARONARKOARGO"
5357 "ARGPARCQAQ6RAQ2YAQTEZAAA");
5358 ok(match, "Figure does not match.\n");
5359 match = compare_figure(surface, 160, 160, 320, 320, 0xff652e89, 1024,
5360 "ytABA7gCCbICD60CFKkCF6cCGqMCHqACIZ0CJJoCJpgCKZUCFgIUkgIWBBWPAhYHFI4CFQoUjAIV"
5361 "DBSKAhUNFYgCFQ8UhwIVERSFAhUTFIMCFRQVgQIUFxSAAhQZFP4BFBoV/AEUHBT7ARQeFPkBFB8V"
5362 "9wEUIRT2ARQjFPQBFSMV8gEVJRTxARUnFPABFCgV7gEUKhTtARQsFOwBFCwV7AEULBTsARUsFOwB"
5363 "FSsV7AEULBTtARQsFO0BFCsU7QEVKxTtARUqFe0BFSoU7gEUKxTuARQqFe4BFCoU7wEUKhTuARUp"
5364 "FO8BFSkU7wEVKBXvARUoFPABFCkU8AEUKBTxARQoFPEBFCcV8QEUJxTxARUnFPEBFSYU8gEVJhTy"
5365 "ARUlFfIBFSUU8wEUJRXzARQlFPQBFCUU9AEUJBT1ARQkFPUBFCMU9gEUIhT2ARUhFPcBFSAU+AEV"
5366 "HxT5ARUeFPoBFR4U+gEVHRT7ARUcFPwBFRsU/QEVGhT+ARUZFP8BFBkUgAIUGBSBAhQXFIICFBcU"
5367 "ggIUFhSDAhQVFIQCFBQUhQIUExSGAhQSFIcCFBIUhwIUERSIAhUPFIkCFg0UigIXCxSNAhYJFI8C"
5368 "FggUkAIXBRSSAhcDFJQCFwEUlgIrlwIpmgImnAIkngIjnwIhoQIfowIepAIcpgIbpgIaqAIZqAIZ"
5369 "qAIYKwP7ARgnBf0BGCMI/QEZHgz+ARgbD/8BGBcSgAIYEhaAAhoNGIICGggcgwIaBB+DAjyEAjyF"
5370 "AjqGAjmIAjiIAiECFIkCFAIIBBSKAhQNFIsCFAwUjAIUCxSNAhQKFI4CFAkUjwIUBxWQAhQGFZEC"
5371 "FAUVkQIUBRWRAhQFFZECFQMVkwIUAxWTAhQDFZMCFAIVlAIVARWVAiqVAimWAimWAiiYAiaZAiaZ"
5372 "AiWaAiScAiKdAiGeAh+hAhyjAhmuAg3GxgEA");
5373 ok(match, "Figure does not match.\n");
5375 ID2D1SolidColorBrush_Release(brush);
5376 ID2D1RenderTarget_Release(rt);
5377 refcount = ID2D1Factory_Release(factory);
5378 ok(!refcount, "Factory has %u references left.\n", refcount);
5379 IDXGISurface_Release(surface);
5380 IDXGISwapChain_Release(swapchain);
5381 ID3D10Device1_Release(device);
5382 DestroyWindow(window);
5385 static void test_gdi_interop(void)
5387 ID2D1GdiInteropRenderTarget *interop;
5388 D2D1_RENDER_TARGET_PROPERTIES desc;
5389 IWICImagingFactory *wic_factory;
5390 IWICBitmapLock *wic_lock;
5391 IWICBitmap *wic_bitmap;
5392 ID2D1RenderTarget *rt;
5393 ID2D1Factory *factory;
5394 ID3D10Device1 *device;
5395 D2D1_COLOR_F color;
5396 HRESULT hr;
5397 BOOL match;
5398 RECT rect;
5399 HDC dc;
5401 if (!(device = create_device()))
5403 skip("Failed to create device, skipping tests.\n");
5404 return;
5407 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5408 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
5410 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
5411 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
5412 &IID_IWICImagingFactory, (void **)&wic_factory);
5413 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
5414 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
5415 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
5416 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
5417 IWICImagingFactory_Release(wic_factory);
5419 /* WIC target, default usage */
5420 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5421 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
5422 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5423 desc.dpiX = 0.0f;
5424 desc.dpiY = 0.0f;
5425 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5426 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5428 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory, wic_bitmap, &desc, &rt);
5429 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5431 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5432 ok(SUCCEEDED(hr), "Failed to get gdi interop interface, hr %#x.\n", hr);
5434 ID2D1RenderTarget_BeginDraw(rt);
5435 dc = (void *)0xdeadbeef;
5436 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
5437 ok(FAILED(hr), "GetDC() was expected to fail, hr %#x.\n", hr);
5438 todo_wine
5439 ok(dc == NULL, "Expected NULL dc, got %p.\n", dc);
5440 ID2D1GdiInteropRenderTarget_Release(interop);
5441 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5443 ID2D1RenderTarget_Release(rt);
5445 /* WIC target, gdi compatible */
5446 desc.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
5448 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory, wic_bitmap, &desc, &rt);
5449 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5451 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5452 ok(SUCCEEDED(hr), "Failed to get gdi interop interface, hr %#x.\n", hr);
5454 ID2D1RenderTarget_BeginDraw(rt);
5455 dc = NULL;
5456 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
5457 ok(SUCCEEDED(hr), "GetDC() was expected to succeed, hr %#x.\n", hr);
5458 ok(dc != NULL, "Expected NULL dc, got %p.\n", dc);
5459 ID2D1GdiInteropRenderTarget_ReleaseDC(interop, NULL);
5460 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5462 ID2D1RenderTarget_BeginDraw(rt);
5463 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
5464 ID2D1RenderTarget_Clear(rt, &color);
5465 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5467 match = compare_wic_bitmap(wic_bitmap, "54034063dbc1c1bb61cb60ec57e4498678dc2b13");
5468 ok(match, "Bitmap does not match.\n");
5470 /* Do solid fill using GDI */
5471 ID2D1RenderTarget_BeginDraw(rt);
5473 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
5474 ok(SUCCEEDED(hr), "GetDC() was expected to succeed, hr %#x.\n", hr);
5476 SetRect(&rect, 0, 0, 16, 16);
5477 FillRect(dc, &rect, GetStockObject(BLACK_BRUSH));
5478 ID2D1GdiInteropRenderTarget_ReleaseDC(interop, NULL);
5480 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5482 match = compare_wic_bitmap(wic_bitmap, "60cacbf3d72e1e7834203da608037b1bf83b40e8");
5483 ok(match, "Bitmap does not match.\n");
5485 /* Bitmap is locked at BeginDraw(). */
5486 hr = IWICBitmap_Lock(wic_bitmap, NULL, WICBitmapLockRead, &wic_lock);
5487 ok(SUCCEEDED(hr), "Expected bitmap to be unlocked, hr %#x.\n", hr);
5488 IWICBitmapLock_Release(wic_lock);
5490 ID2D1RenderTarget_BeginDraw(rt);
5491 hr = IWICBitmap_Lock(wic_bitmap, NULL, WICBitmapLockRead, &wic_lock);
5492 todo_wine
5493 ok(hr == WINCODEC_ERR_ALREADYLOCKED, "Expected bitmap to be locked, hr %#x.\n", hr);
5494 if (SUCCEEDED(hr))
5495 IWICBitmapLock_Release(wic_lock);
5496 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5498 ID2D1GdiInteropRenderTarget_Release(interop);
5499 ID2D1RenderTarget_Release(rt);
5501 IWICBitmap_Release(wic_bitmap);
5502 ID2D1Factory_Release(factory);
5505 static void test_layer(void)
5507 ID2D1Factory *factory, *layer_factory;
5508 IDXGISwapChain *swapchain;
5509 ID2D1RenderTarget *rt;
5510 ID3D10Device1 *device;
5511 IDXGISurface *surface;
5512 ID2D1Layer *layer;
5513 D2D1_SIZE_F size;
5514 ULONG refcount;
5515 HWND window;
5516 HRESULT hr;
5518 if (!(device = create_device()))
5520 skip("Failed to create device, skipping tests.\n");
5521 return;
5523 window = create_window();
5524 swapchain = create_swapchain(device, window, TRUE);
5525 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
5526 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
5527 rt = create_render_target(surface);
5528 ok(!!rt, "Failed to create render target.\n");
5529 ID2D1RenderTarget_GetFactory(rt, &factory);
5531 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
5532 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
5534 hr = ID2D1RenderTarget_CreateLayer(rt, NULL, &layer);
5535 ok(SUCCEEDED(hr), "Failed to create layer, hr %#x.\n", hr);
5536 ID2D1Layer_GetFactory(layer, &layer_factory);
5537 ok(layer_factory == factory, "Got unexpected layer factory %p, expected %p.\n", layer_factory, factory);
5538 ID2D1Factory_Release(layer_factory);
5539 size = ID2D1Layer_GetSize(layer);
5540 ok(size.width == 0.0f, "Got unexpected width %.8e.\n", size.width);
5541 ok(size.height == 0.0f, "Got unexpected height %.8e.\n", size.height);
5542 ID2D1Layer_Release(layer);
5544 set_size_f(&size, 800.0f, 600.0f);
5545 hr = ID2D1RenderTarget_CreateLayer(rt, &size, &layer);
5546 ok(SUCCEEDED(hr), "Failed to create layer, hr %#x.\n", hr);
5547 size = ID2D1Layer_GetSize(layer);
5548 ok(size.width == 800.0f, "Got unexpected width %.8e.\n", size.width);
5549 ok(size.height == 600.0f, "Got unexpected height %.8e.\n", size.height);
5550 ID2D1Layer_Release(layer);
5552 ID2D1RenderTarget_Release(rt);
5553 refcount = ID2D1Factory_Release(factory);
5554 ok(!refcount, "Factory has %u references left.\n", refcount);
5555 IDXGISurface_Release(surface);
5556 IDXGISwapChain_Release(swapchain);
5557 ID3D10Device1_Release(device);
5558 DestroyWindow(window);
5561 static void test_bezier_intersect(void)
5563 D2D1_POINT_2F point = {0.0f, 0.0f};
5564 ID2D1SolidColorBrush *brush;
5565 ID2D1PathGeometry *geometry;
5566 IDXGISwapChain *swapchain;
5567 ID2D1GeometrySink *sink;
5568 ID2D1RenderTarget *rt;
5569 ID3D10Device1 *device;
5570 IDXGISurface *surface;
5571 ID2D1Factory *factory;
5572 D2D1_COLOR_F color;
5573 ULONG refcount;
5574 HWND window;
5575 HRESULT hr;
5576 BOOL match;
5578 if (!(device = create_device()))
5580 skip("Failed to create device, skipping tests.\n");
5581 return;
5583 window = create_window();
5584 swapchain = create_swapchain(device, window, TRUE);
5585 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
5586 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
5587 rt = create_render_target(surface);
5588 ok(!!rt, "Failed to create render target.\n");
5589 ID2D1RenderTarget_GetFactory(rt, &factory);
5591 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
5592 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
5593 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
5594 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
5595 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
5597 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
5598 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
5599 hr = ID2D1PathGeometry_Open(geometry, &sink);
5600 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
5602 set_point(&point, 160.0f, 720.0f);
5603 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5604 cubic_to(sink, 119.0f, 720.0f, 83.0f, 600.0f, 80.0f, 474.0f);
5605 cubic_to(sink, 78.0f, 349.0f, 108.0f, 245.0f, 135.0f, 240.0f);
5606 cubic_to(sink, 163.0f, 235.0f, 180.0f, 318.0f, 176.0f, 370.0f);
5607 cubic_to(sink, 171.0f, 422.0f, 149.0f, 422.0f, 144.0f, 370.0f);
5608 cubic_to(sink, 140.0f, 318.0f, 157.0f, 235.0f, 185.0f, 240.0f);
5609 cubic_to(sink, 212.0f, 245.0f, 242.0f, 349.0f, 240.0f, 474.0f);
5610 cubic_to(sink, 238.0f, 600.0f, 201.0f, 720.0f, 160.0f, 720.0f);
5611 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5613 set_point(&point, 160.0f, 240.0f);
5614 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5615 line_to(sink, 240.0f, 240.0f);
5616 line_to(sink, 240.0f, 720.0f);
5617 line_to(sink, 160.0f, 720.0f);
5618 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5620 hr = ID2D1GeometrySink_Close(sink);
5621 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
5622 ID2D1GeometrySink_Release(sink);
5624 ID2D1RenderTarget_BeginDraw(rt);
5625 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
5626 ID2D1RenderTarget_Clear(rt, &color);
5627 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
5628 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5629 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5630 ID2D1PathGeometry_Release(geometry);
5632 match = compare_figure(surface, 160, 120, 320, 240, 0xff652e89, 2048,
5633 "aRQjIxRpYiIcHCJiXSwXFyxdWTQTEzRZVTsQEDtVUkIMDEJST0cKCkdPTUsICEtNSlEFBVFKSFUD"
5634 "A1VIRlkBAVlGRFsBAVtEQlwCAlxCQFwEBFxAPl0FBV0+PF0HB108Ol4ICF46OV0KCl05N14LC143"
5635 "Nl4MDF42NF8NDV80M14PD14zMV8QEF8xMF8REV8wL18SEl8vLWATE2AtLGAUFGAsK2EUFGErKWIV"
5636 "FWIpKGIWFmIoJ2IXF2InJmIYGGImJWMYGGMlJGMZGWMkI2MaGmMjImQaGmQiIWQbG2QhIGQcHGQg"
5637 "H2UcHGUfHmUdHWUeHWYdHWYdHGcdHWccG2ceHmcbGmgeHmgaGWgfH2gZGWgfH2gZGGkfH2kYF2kg"
5638 "IGkXFmogIGoWFmogIGoWFWsgIGsVFGshIWsUE2whIWwTE2whIWwTEm0hIW0SEW4hIW4REW4hIW4R"
5639 "EG8hIW8QD3AhIXAPD3AhIXAPDnEhIXEODnEhIXEODXIhIXINDHQgIHQMDHQgIHQMC3UgIHULC3Yf"
5640 "H3YLCncfH3cKCngeHngKCXkeHnkJCXodHXoJCXscHHsJCHwcHHwICH0bG30IB38aGn8HB4ABGRmA"
5641 "AQcHgQEYGIEBBwaEARYWhAEGBoUBFRWFAQYFiAETE4gBBQWKARERigEFBYwBDw+MAQUEkAEMDJAB"
5642 "BASTAQkJkwEEBJwBnAEEA50BnQEDA50BnQEDA50BnQEDA50BnQEDAp4BngECAp4BngECAp4BngEC"
5643 "Ap4BngECAp4BngECAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwGhAaAB"
5644 "oAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGg"
5645 "AaABoAGgAaABoAGgAaABoAGhAZ8BoQGfAZ8BAQGfAZ8BAQGfAZ8BAQGfAZ8BAQGfAZ8BAQKeAZ8B"
5646 "AQKeAZ4BAgKeAZ4BAgKeAZ4BAgOdAZ4BAgOdAZ4BAgOdAZ0BAwScAZ0BAwScAZ0BAwScAZ0BAwSc"
5647 "AZwBBAWbAZwBBAWbAZwBBAWbAZsBBQaaAZsBBQaaAZoBBgeZAZoBBgeZAZoBBgeZAZkBBwiYAZkB"
5648 "BwiYAZgBCAmXAZgBCAmXAZgBCAmXAZcBCQqWAZcBCQqWAZYBCguVAZYBCguVAZUBCwyUAZUBCw2T"
5649 "AZQBDA2TAZQBDA6SAZMBDQ6SAZMBDQ+RAZIBDg+RAZIBDhCQAZEBDxCQAZABEBGPAZABEBKOAY8B"
5650 "ERONAY4BEhONAY4BEhSMAY0BExWLAYwBFBWLAYwBFBaKAYsBFReJAYoBFheJAYoBFhiIAYkBFxmH"
5651 "AYgBGBqGAYcBGRuFAYYBGhuFAYUBGxyEAYUBGx2DAYQBHB6CAYMBHR+BAYIBHiCAAYEBHyF/gAEg"
5652 "In5/ISJ+fiIjfX0jJHx8JCV7eyUmenomJ3l5Jyh4eCgpd3cpK3V2Kix0dSstc3QsLnJzLS9xci4w"
5653 "cHAwMm5vMTNtbjI0bG0zNWtrNTdpajY4aGk3OmZnOTtlZjo8ZGQ8PmJjPT9hYj5BX2BAQl5eQkRc"
5654 "XUNGWltFR1lZR0lXWEhLVVZKTVNUTE9RUk5RT1BQUk5OUlRMTFRWSkpWWUdIWFtFRVteQkNdYEBA"
5655 "YGI+PmJlOztlaDg4aGs1NWtuMjJuci4vcXUrK3V6JiZ6fiIifoMBHR2DAYsBFRWLAZUBCwuVAQAA");
5656 todo_wine ok(match, "Figure does not match.\n");
5658 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
5659 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
5660 hr = ID2D1PathGeometry_Open(geometry, &sink);
5661 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
5663 set_point(&point, 240.0f, 720.0f);
5664 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5665 cubic_to(sink, 152.0f, 720.0f, 80.0f, 613.0f, 80.0f, 480.0f);
5666 cubic_to(sink, 80.0f, 347.0f, 152.0f, 240.0f, 240.0f, 240.0f);
5667 cubic_to(sink, 152.0f, 339.0f, 134.0f, 528.0f, 200.0f, 660.0f);
5668 cubic_to(sink, 212.0f, 683.0f, 225.0f, 703.0f, 240.0f, 720.0f);
5669 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5671 hr = ID2D1GeometrySink_Close(sink);
5672 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
5673 ID2D1GeometrySink_Release(sink);
5675 ID2D1RenderTarget_BeginDraw(rt);
5676 ID2D1RenderTarget_Clear(rt, &color);
5677 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
5678 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5679 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5680 ID2D1PathGeometry_Release(geometry);
5682 match = compare_figure(surface, 160, 120, 320, 240, 0xff652e89, 2048,
5683 "pQIZkgIrhAI5/QE/9gFH7wFO6wFS5wFW4gFb3gFf2wFi2AFl1gFn1AFp0gFszwFuzQFxywFyyQF1"
5684 "xwF2xgF4xAF5xAF6wgF8wAF+vwF+vwF/vQGBAbwBggG7AYMBugGEAbkBhQG4AYYBtwGHAbcBiAG1"
5685 "AYkBtAGKAbQBigGzAYsBswGMAbEBjQGxAY0BsQGOAa8BjwGvAZABrgGQAa4BkQGtAZEBrQGSAawB"
5686 "kgGsAZMBqwGTAasBlAGrAZQBqgGVAakBlQGqAZUBqQGWAagBlwGoAZYBqAGXAagBlwGnAZgBpwGY"
5687 "AaYBmQGmAZkBpgGZAaUBmgGlAZoBpQGaAaUBmgGkAZsBpAGbAaQBmwGkAZsBpAGcAaMBnAGjAZwB"
5688 "owGcAaMBnAGjAZ0BogGdAaIBnQGiAZ4BoQGeAaEBngGiAZ4BoQGeAaEBnwGgAZ8BoQGeAaEBnwGh"
5689 "AZ4BoQGfAaABnwGhAZ8BoAGgAaABnwGgAaABoAGfAaABoAGgAaABnwGgAaABoAGgAaABnwGgAaAB"
5690 "oAGgAaABnwGhAZ8BoQGfAaABoAGgAaABoAGfAaEBnwGhAZ8BoQGfAaEBnwGhAZ8BoQGfAaABoAGg"
5691 "AaABoAGgAaEBnwGhAZ8BoQGfAaEBnwGhAaABoAGgAaABoAGgAaABoAGgAaEBoAGgAaABoAGgAaAB"
5692 "oQGgAaABoAGgAaABoQGfAaEBoAGhAZ8BoQGfAaIBnwGhAZ8BogGfAaEBnwGiAZ8BogGeAaIBnwGi"
5693 "AZ4BogGfAaIBngGjAZ4BowGdAaMBngGjAZ4BowGdAaQBnQGkAZ0BpAGcAaUBnAGlAZwBpQGcAaUB"
5694 "mwGmAZsBpgGbAaYBmwGmAZsBpgGbAacBmgGnAZkBqAGZAagBmQGpAZgBqQGZAagBmQGpAZgBqQGY"
5695 "AaoBlwGqAZcBqwGWAasBlgGsAZUBrQGVAawBlQGtAZQBrgGUAa0BlAGuAZMBrwGTAa8BkgGwAZEB"
5696 "sQGRAbEBkAGyAZABsgGPAbMBjwG0AY4BtAGNAbUBjQG2AYwBtgGLAbgBigG4AYoBuQGJAboBhwG7"
5697 "AYcBvAGGAb0BhQG+AYQBvwGDAcABggHBAYIBwgGAAcMBf8QBfsYBfMgBe8gBesoBeMwBd80BddAB"
5698 "c9EBcdQBb9YBbNkBatsBaN0BZeEBYuQBX+gBW+0BVvEBUvUBTvwBR4QCQIoCOZgCK6oCGQIA");
5699 todo_wine ok(match, "Figure does not match.\n");
5701 ID2D1SolidColorBrush_Release(brush);
5702 ID2D1RenderTarget_Release(rt);
5703 refcount = ID2D1Factory_Release(factory);
5704 ok(!refcount, "Factory has %u references left.\n", refcount);
5705 IDXGISurface_Release(surface);
5706 IDXGISwapChain_Release(swapchain);
5707 ID3D10Device1_Release(device);
5708 DestroyWindow(window);
5711 START_TEST(d2d1)
5713 test_clip();
5714 test_state_block();
5715 test_color_brush();
5716 test_bitmap_brush();
5717 test_path_geometry();
5718 test_rectangle_geometry();
5719 test_rounded_rectangle_geometry();
5720 test_bitmap_formats();
5721 test_alpha_mode();
5722 test_shared_bitmap();
5723 test_bitmap_updates();
5724 test_opacity_brush();
5725 test_create_target();
5726 test_draw_text_layout();
5727 test_dc_target();
5728 test_hwnd_target();
5729 test_bitmap_target();
5730 test_desktop_dpi();
5731 test_stroke_style();
5732 test_gradient();
5733 test_draw_geometry();
5734 test_gdi_interop();
5735 test_layer();
5736 test_bezier_intersect();