d2d1/tests: Add some bitmap brush tests for skew transformations and transformed...
[wine.git] / dlls / d2d1 / tests / d2d1.c
blob2cb15e6bc79646e3921cb19fdb8d892e761a0653
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 resource_readback
31 ID3D10Resource *resource;
32 D3D10_MAPPED_TEXTURE2D map_desc;
33 unsigned int width, height;
36 struct figure
38 unsigned int *spans;
39 unsigned int spans_size;
40 unsigned int span_count;
43 struct geometry_sink
45 ID2D1SimplifiedGeometrySink ID2D1SimplifiedGeometrySink_iface;
47 struct geometry_figure
49 D2D1_FIGURE_BEGIN begin;
50 D2D1_FIGURE_END end;
51 D2D1_POINT_2F start_point;
52 struct geometry_segment
54 enum
56 SEGMENT_BEZIER,
57 SEGMENT_LINE,
58 } type;
59 union
61 D2D1_BEZIER_SEGMENT bezier;
62 D2D1_POINT_2F line;
63 } u;
64 DWORD flags;
65 } *segments;
66 unsigned int segments_size;
67 unsigned int segment_count;
68 } *figures;
69 unsigned int figures_size;
70 unsigned int figure_count;
72 D2D1_FILL_MODE fill_mode;
73 DWORD segment_flags;
74 BOOL closed;
77 struct expected_geometry_figure
79 D2D1_FIGURE_BEGIN begin;
80 D2D1_FIGURE_END end;
81 D2D1_POINT_2F start_point;
82 unsigned int segment_count;
83 const struct geometry_segment *segments;
86 static void set_point(D2D1_POINT_2F *point, float x, float y)
88 point->x = x;
89 point->y = y;
92 static void set_quadratic(D2D1_QUADRATIC_BEZIER_SEGMENT *quadratic, float x1, float y1, float x2, float y2)
94 quadratic->point1.x = x1;
95 quadratic->point1.y = y1;
96 quadratic->point2.x = x2;
97 quadratic->point2.y = y2;
100 static void set_rect(D2D1_RECT_F *rect, float left, float top, float right, float bottom)
102 rect->left = left;
103 rect->top = top;
104 rect->right = right;
105 rect->bottom = bottom;
108 static void set_rounded_rect(D2D1_ROUNDED_RECT *rect, float left, float top, float right, float bottom,
109 float radius_x, float radius_y)
111 set_rect(&rect->rect, left, top, right, bottom);
112 rect->radiusX = radius_x;
113 rect->radiusY = radius_y;
116 static void set_rect_u(D2D1_RECT_U *rect, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
118 rect->left = left;
119 rect->top = top;
120 rect->right = right;
121 rect->bottom = bottom;
124 static void set_ellipse(D2D1_ELLIPSE *ellipse, float x, float y, float rx, float ry)
126 set_point(&ellipse->point, x, y);
127 ellipse->radiusX = rx;
128 ellipse->radiusY = ry;
131 static void set_color(D2D1_COLOR_F *color, float r, float g, float b, float a)
133 color->r = r;
134 color->g = g;
135 color->b = b;
136 color->a = a;
139 static void set_size_u(D2D1_SIZE_U *size, unsigned int w, unsigned int h)
141 size->width = w;
142 size->height = h;
145 static void set_size_f(D2D1_SIZE_F *size, float w, float h)
147 size->width = w;
148 size->height = h;
151 static void set_matrix_identity(D2D1_MATRIX_3X2_F *matrix)
153 matrix->_11 = 1.0f;
154 matrix->_12 = 0.0f;
155 matrix->_21 = 0.0f;
156 matrix->_22 = 1.0f;
157 matrix->_31 = 0.0f;
158 matrix->_32 = 0.0f;
161 static void rotate_matrix(D2D1_MATRIX_3X2_F *matrix, float theta)
163 float sin_theta, cos_theta, tmp_11, tmp_12;
165 sin_theta = sinf(theta);
166 cos_theta = cosf(theta);
167 tmp_11 = matrix->_11;
168 tmp_12 = matrix->_12;
170 matrix->_11 = cos_theta * tmp_11 + sin_theta * matrix->_21;
171 matrix->_12 = cos_theta * tmp_12 + sin_theta * matrix->_22;
172 matrix->_21 = -sin_theta * tmp_11 + cos_theta * matrix->_21;
173 matrix->_22 = -sin_theta * tmp_12 + cos_theta * matrix->_22;
176 static void skew_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
178 float tmp_11, tmp_12;
180 tmp_11 = matrix->_11;
181 tmp_12 = matrix->_12;
183 matrix->_11 += y * matrix->_21;
184 matrix->_12 += y * matrix->_22;
185 matrix->_21 += x * tmp_11;
186 matrix->_22 += x * tmp_12;
189 static void scale_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
191 matrix->_11 *= x;
192 matrix->_12 *= x;
193 matrix->_21 *= y;
194 matrix->_22 *= y;
197 static void translate_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
199 matrix->_31 += x * matrix->_11 + y * matrix->_21;
200 matrix->_32 += x * matrix->_12 + y * matrix->_22;
203 static void line_to(ID2D1GeometrySink *sink, float x, float y)
205 D2D1_POINT_2F point;
207 set_point(&point, x, y);
208 ID2D1GeometrySink_AddLine(sink, point);
211 static void quadratic_to(ID2D1GeometrySink *sink, float x1, float y1, float x2, float y2)
213 D2D1_QUADRATIC_BEZIER_SEGMENT quadratic;
215 set_quadratic(&quadratic, x1, y1, x2, y2);
216 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
219 static void cubic_to(ID2D1GeometrySink *sink, float x1, float y1, float x2, float y2, float x3, float y3)
221 D2D1_BEZIER_SEGMENT b;
223 b.point1.x = x1;
224 b.point1.y = y1;
225 b.point2.x = x2;
226 b.point2.y = y2;
227 b.point3.x = x3;
228 b.point3.y = y3;
229 ID2D1GeometrySink_AddBezier(sink, &b);
232 static void get_surface_readback(IDXGISurface *surface, struct resource_readback *rb)
234 D3D10_TEXTURE2D_DESC texture_desc;
235 DXGI_SURFACE_DESC surface_desc;
236 ID3D10Resource *src_resource;
237 ID3D10Device *device;
238 HRESULT hr;
240 hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
241 ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
242 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
243 ok(SUCCEEDED(hr), "Failed to query resource interface, hr %#x.\n", hr);
245 hr = IDXGISurface_GetDesc(surface, &surface_desc);
246 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
247 texture_desc.Width = surface_desc.Width;
248 texture_desc.Height = surface_desc.Height;
249 texture_desc.MipLevels = 1;
250 texture_desc.ArraySize = 1;
251 texture_desc.Format = surface_desc.Format;
252 texture_desc.SampleDesc = surface_desc.SampleDesc;
253 texture_desc.Usage = D3D10_USAGE_STAGING;
254 texture_desc.BindFlags = 0;
255 texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
256 texture_desc.MiscFlags = 0;
257 hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, (ID3D10Texture2D **)&rb->resource);
258 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
260 rb->width = texture_desc.Width;
261 rb->height = texture_desc.Height;
263 ID3D10Device_CopyResource(device, rb->resource, src_resource);
264 ID3D10Resource_Release(src_resource);
265 ID3D10Device_Release(device);
267 hr = ID3D10Texture2D_Map((ID3D10Texture2D *)rb->resource, 0, D3D10_MAP_READ, 0, &rb->map_desc);
268 ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr);
271 static void release_resource_readback(struct resource_readback *rb)
273 ID3D10Texture2D_Unmap((ID3D10Texture2D *)rb->resource, 0);
274 ID3D10Resource_Release(rb->resource);
277 static BOOL compare_float(float f, float g, unsigned int ulps)
279 int x = *(int *)&f;
280 int y = *(int *)&g;
282 if (x < 0)
283 x = INT_MIN - x;
284 if (y < 0)
285 y = INT_MIN - y;
287 if (abs(x - y) > ulps)
288 return FALSE;
290 return TRUE;
293 static BOOL compare_point(const D2D1_POINT_2F *point, float x, float y, unsigned int ulps)
295 return compare_float(point->x, x, ulps)
296 && compare_float(point->y, y, ulps);
299 static BOOL compare_rect(const D2D1_RECT_F *rect, float left, float top, float right, float bottom, unsigned int ulps)
301 return compare_float(rect->left, left, ulps)
302 && compare_float(rect->top, top, ulps)
303 && compare_float(rect->right, right, ulps)
304 && compare_float(rect->bottom, bottom, ulps);
307 static BOOL compare_bezier_segment(const D2D1_BEZIER_SEGMENT *b, float x1, float y1,
308 float x2, float y2, float x3, float y3, unsigned int ulps)
310 return compare_point(&b->point1, x1, y1, ulps)
311 && compare_point(&b->point2, x2, y2, ulps)
312 && compare_point(&b->point3, x3, y3, ulps);
315 static BOOL compare_sha1(void *data, unsigned int pitch, unsigned int bpp,
316 unsigned int w, unsigned int h, const char *ref_sha1)
318 static const char hex_chars[] = "0123456789abcdef";
319 HCRYPTPROV provider;
320 BYTE hash_data[20];
321 HCRYPTHASH hash;
322 unsigned int i;
323 char sha1[41];
324 BOOL ret;
326 ret = CryptAcquireContextW(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
327 ok(ret, "Failed to acquire crypt context.\n");
328 ret = CryptCreateHash(provider, CALG_SHA1, 0, 0, &hash);
329 ok(ret, "Failed to create hash.\n");
331 for (i = 0; i < h; ++i)
333 if (!(ret = CryptHashData(hash, (BYTE *)data + pitch * i, w * bpp, 0)))
334 break;
336 ok(ret, "Failed to hash data.\n");
338 i = sizeof(hash_data);
339 ret = CryptGetHashParam(hash, HP_HASHVAL, hash_data, &i, 0);
340 ok(ret, "Failed to get hash value.\n");
341 ok(i == sizeof(hash_data), "Got unexpected hash size %u.\n", i);
343 ret = CryptDestroyHash(hash);
344 ok(ret, "Failed to destroy hash.\n");
345 ret = CryptReleaseContext(provider, 0);
346 ok(ret, "Failed to release crypt context.\n");
348 for (i = 0; i < 20; ++i)
350 sha1[i * 2] = hex_chars[hash_data[i] >> 4];
351 sha1[i * 2 + 1] = hex_chars[hash_data[i] & 0xf];
353 sha1[40] = 0;
355 return !strcmp(ref_sha1, (char *)sha1);
358 static BOOL compare_surface(IDXGISurface *surface, const char *ref_sha1)
360 struct resource_readback rb;
361 BOOL ret;
363 get_surface_readback(surface, &rb);
364 ret = compare_sha1(rb.map_desc.pData, rb.map_desc.RowPitch, 4,
365 rb.width, rb.height, ref_sha1);
366 release_resource_readback(&rb);
368 return ret;
371 static BOOL compare_wic_bitmap(IWICBitmap *bitmap, const char *ref_sha1)
373 UINT stride, width, height, buffer_size;
374 IWICBitmapLock *lock;
375 BYTE *data;
376 HRESULT hr;
377 BOOL ret;
379 hr = IWICBitmap_Lock(bitmap, NULL, WICBitmapLockRead, &lock);
380 ok(SUCCEEDED(hr), "Failed to lock bitmap, hr %#x.\n", hr);
382 hr = IWICBitmapLock_GetDataPointer(lock, &buffer_size, &data);
383 ok(SUCCEEDED(hr), "Failed to get bitmap data, hr %#x.\n", hr);
385 hr = IWICBitmapLock_GetStride(lock, &stride);
386 ok(SUCCEEDED(hr), "Failed to get bitmap stride, hr %#x.\n", hr);
388 hr = IWICBitmapLock_GetSize(lock, &width, &height);
389 ok(SUCCEEDED(hr), "Failed to get bitmap size, hr %#x.\n", hr);
391 ret = compare_sha1(data, stride, 4, width, height, ref_sha1);
393 IWICBitmapLock_Release(lock);
395 return ret;
398 static void serialize_figure(struct figure *figure)
400 static const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
401 unsigned int i, j, k, span;
402 char output[76];
403 char t[3];
404 char *p;
406 for (i = 0, j = 0, k = 0, p = output; i < figure->span_count; ++i)
408 span = figure->spans[i];
409 while (span)
411 t[j] = span & 0x7f;
412 if (span > 0x7f)
413 t[j] |= 0x80;
414 span >>= 7;
415 if (++j == 3)
417 p[0] = lookup[(t[0] & 0xfc) >> 2];
418 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
419 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
420 p[3] = lookup[t[2] & 0x3f];
421 p += 4;
422 if (++k == 19)
424 trace("%.76s\n", output);
425 p = output;
426 k = 0;
428 j = 0;
432 if (j)
434 for (i = j; i < 3; ++i)
435 t[i] = 0;
436 p[0] = lookup[(t[0] & 0xfc) >> 2];
437 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
438 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
439 p[3] = lookup[t[2] & 0x3f];
440 ++k;
442 if (k)
443 trace("%.*s\n", k * 4, output);
446 static void figure_add_span(struct figure *figure, unsigned int span)
448 if (figure->span_count == figure->spans_size)
450 figure->spans_size *= 2;
451 figure->spans = HeapReAlloc(GetProcessHeap(), 0, figure->spans,
452 figure->spans_size * sizeof(*figure->spans));
455 figure->spans[figure->span_count++] = span;
458 static void deserialize_span(struct figure *figure, unsigned int *current, unsigned int *shift, unsigned int c)
460 *current |= (c & 0x7f) << *shift;
461 if (c & 0x80)
463 *shift += 7;
464 return;
467 if (*current)
468 figure_add_span(figure, *current);
469 *current = 0;
470 *shift = 0;
473 static void deserialize_figure(struct figure *figure, const BYTE *s)
475 static const BYTE lookup[] =
477 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
478 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
479 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
480 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
481 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
482 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
483 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
484 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
486 unsigned int current = 0, shift = 0;
487 const BYTE *ptr;
488 BYTE x, y;
490 figure->span_count = 0;
491 figure->spans_size = 64;
492 figure->spans = HeapAlloc(GetProcessHeap(), 0, figure->spans_size * sizeof(*figure->spans));
494 for (ptr = s; *ptr; ptr += 4)
496 x = lookup[ptr[0]];
497 y = lookup[ptr[1]];
498 deserialize_span(figure, &current, &shift, ((x & 0x3f) << 2) | ((y & 0x3f) >> 4));
499 x = lookup[ptr[2]];
500 deserialize_span(figure, &current, &shift, ((y & 0x0f) << 4) | ((x & 0x3f) >> 2));
501 y = lookup[ptr[3]];
502 deserialize_span(figure, &current, &shift, ((x & 0x03) << 6) | (y & 0x3f));
506 static void read_figure(struct figure *figure, BYTE *data, unsigned int pitch,
507 unsigned int x, unsigned int y, unsigned int w, unsigned int h, DWORD prev)
509 unsigned int i, j, span;
511 figure->span_count = 0;
512 for (i = 0, span = 0; i < h; ++i)
514 const DWORD *row = (DWORD *)&data[(y + i) * pitch + x * 4];
515 for (j = 0; j < w; ++j, ++span)
517 if ((i || j) && prev != row[j])
519 figure_add_span(figure, span);
520 prev = row[j];
521 span = 0;
525 if (span)
526 figure_add_span(figure, span);
529 static BOOL compare_figure(IDXGISurface *surface, unsigned int x, unsigned int y,
530 unsigned int w, unsigned int h, DWORD prev, unsigned int max_diff, const char *ref)
532 struct figure ref_figure, figure;
533 unsigned int i, j, span, diff;
534 struct resource_readback rb;
536 get_surface_readback(surface, &rb);
538 figure.span_count = 0;
539 figure.spans_size = 64;
540 figure.spans = HeapAlloc(GetProcessHeap(), 0, figure.spans_size * sizeof(*figure.spans));
542 read_figure(&figure, rb.map_desc.pData, rb.map_desc.RowPitch, x, y, w, h, prev);
544 deserialize_figure(&ref_figure, (BYTE *)ref);
545 span = w * h;
546 for (i = 0; i < ref_figure.span_count; ++i)
548 span -= ref_figure.spans[i];
550 if (span)
551 figure_add_span(&ref_figure, span);
553 for (i = 0, j = 0, diff = 0; i < figure.span_count && j < ref_figure.span_count;)
555 if (figure.spans[i] == ref_figure.spans[j])
557 if ((i ^ j) & 1)
558 diff += ref_figure.spans[j];
559 ++i;
560 ++j;
562 else if (figure.spans[i] > ref_figure.spans[j])
564 if ((i ^ j) & 1)
565 diff += ref_figure.spans[j];
566 figure.spans[i] -= ref_figure.spans[j];
567 ++j;
569 else
571 if ((i ^ j) & 1)
572 diff += figure.spans[i];
573 ref_figure.spans[j] -= figure.spans[i];
574 ++i;
577 if (diff > max_diff)
579 trace("diff %u > max_diff %u.\n", diff, max_diff);
580 read_figure(&figure, rb.map_desc.pData, rb.map_desc.RowPitch, x, y, w, h, prev);
581 serialize_figure(&figure);
584 HeapFree(GetProcessHeap(), 0, ref_figure.spans);
585 HeapFree(GetProcessHeap(), 0, figure.spans);
586 release_resource_readback(&rb);
588 return diff <= max_diff;
591 static ID3D10Device1 *create_device(void)
593 ID3D10Device1 *device;
595 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL,
596 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
597 return device;
598 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_WARP, NULL,
599 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
600 return device;
601 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL,
602 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
603 return device;
605 return NULL;
608 static HWND create_window(void)
610 RECT r = {0, 0, 640, 480};
612 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
614 return CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
615 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
618 static IDXGISwapChain *create_swapchain(ID3D10Device1 *device, HWND window, BOOL windowed)
620 IDXGISwapChain *swapchain;
621 DXGI_SWAP_CHAIN_DESC desc;
622 IDXGIDevice *dxgi_device;
623 IDXGIAdapter *adapter;
624 IDXGIFactory *factory;
625 HRESULT hr;
627 hr = ID3D10Device1_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
628 ok(SUCCEEDED(hr), "Failed to get DXGI device, hr %#x.\n", hr);
629 hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter);
630 ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr);
631 IDXGIDevice_Release(dxgi_device);
632 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
633 ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr);
634 IDXGIAdapter_Release(adapter);
636 desc.BufferDesc.Width = 640;
637 desc.BufferDesc.Height = 480;
638 desc.BufferDesc.RefreshRate.Numerator = 60;
639 desc.BufferDesc.RefreshRate.Denominator = 1;
640 desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
641 desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
642 desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
643 desc.SampleDesc.Count = 1;
644 desc.SampleDesc.Quality = 0;
645 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
646 desc.BufferCount = 1;
647 desc.OutputWindow = window;
648 desc.Windowed = windowed;
649 desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
650 desc.Flags = 0;
652 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &desc, &swapchain);
653 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
654 IDXGIFactory_Release(factory);
656 return swapchain;
659 static ID2D1RenderTarget *create_render_target_desc(IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
661 ID2D1RenderTarget *render_target;
662 ID2D1Factory *factory;
663 HRESULT hr;
665 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
666 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
667 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, desc, &render_target);
668 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
669 ID2D1Factory_Release(factory);
671 return render_target;
674 static ID2D1RenderTarget *create_render_target(IDXGISurface *surface)
676 D2D1_RENDER_TARGET_PROPERTIES desc;
678 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
679 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
680 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
681 desc.dpiX = 0.0f;
682 desc.dpiY = 0.0f;
683 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
684 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
686 return create_render_target_desc(surface, &desc);
689 static inline struct geometry_sink *impl_from_ID2D1SimplifiedGeometrySink(ID2D1SimplifiedGeometrySink *iface)
691 return CONTAINING_RECORD(iface, struct geometry_sink, ID2D1SimplifiedGeometrySink_iface);
694 static HRESULT STDMETHODCALLTYPE geometry_sink_QueryInterface(ID2D1SimplifiedGeometrySink *iface,
695 REFIID iid, void **out)
697 if (IsEqualGUID(iid, &IID_ID2D1SimplifiedGeometrySink)
698 || IsEqualGUID(iid, &IID_IUnknown))
700 *out = iface;
701 return S_OK;
704 *out = NULL;
705 return E_NOINTERFACE;
708 static ULONG STDMETHODCALLTYPE geometry_sink_AddRef(ID2D1SimplifiedGeometrySink *iface)
710 return 0;
713 static ULONG STDMETHODCALLTYPE geometry_sink_Release(ID2D1SimplifiedGeometrySink *iface)
715 return 0;
718 static void STDMETHODCALLTYPE geometry_sink_SetFillMode(ID2D1SimplifiedGeometrySink *iface, D2D1_FILL_MODE mode)
720 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
722 sink->fill_mode = mode;
725 static void STDMETHODCALLTYPE geometry_sink_SetSegmentFlags(ID2D1SimplifiedGeometrySink *iface,
726 D2D1_PATH_SEGMENT flags)
728 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
730 sink->segment_flags = flags;
733 static void STDMETHODCALLTYPE geometry_sink_BeginFigure(ID2D1SimplifiedGeometrySink *iface,
734 D2D1_POINT_2F start_point, D2D1_FIGURE_BEGIN figure_begin)
736 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
737 struct geometry_figure *figure;
739 if (sink->figure_count == sink->figures_size)
741 sink->figures_size *= 2;
742 sink->figures = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sink->figures,
743 sink->figures_size * sizeof(*sink->figures));
745 figure = &sink->figures[sink->figure_count++];
747 figure->begin = figure_begin;
748 figure->start_point = start_point;
749 figure->segments_size = 4;
750 figure->segments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
751 figure->segments_size * sizeof(*figure->segments));
754 static struct geometry_segment *geometry_figure_add_segment(struct geometry_figure *figure)
756 if (figure->segment_count == figure->segments_size)
758 figure->segments_size *= 2;
759 figure->segments = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, figure->segments,
760 figure->segments_size * sizeof(*figure->segments));
762 return &figure->segments[figure->segment_count++];
765 static void STDMETHODCALLTYPE geometry_sink_AddLines(ID2D1SimplifiedGeometrySink *iface,
766 const D2D1_POINT_2F *points, UINT32 count)
768 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
769 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
770 struct geometry_segment *segment;
771 unsigned int i;
773 for (i = 0; i < count; ++i)
775 segment = geometry_figure_add_segment(figure);
776 segment->type = SEGMENT_LINE;
777 segment->u.line = points[i];
778 segment->flags = sink->segment_flags;
782 static void STDMETHODCALLTYPE geometry_sink_AddBeziers(ID2D1SimplifiedGeometrySink *iface,
783 const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
785 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
786 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
787 struct geometry_segment *segment;
788 unsigned int i;
790 for (i = 0; i < count; ++i)
792 segment = geometry_figure_add_segment(figure);
793 segment->type = SEGMENT_BEZIER;
794 segment->u.bezier = beziers[i];
795 segment->flags = sink->segment_flags;
799 static void STDMETHODCALLTYPE geometry_sink_EndFigure(ID2D1SimplifiedGeometrySink *iface,
800 D2D1_FIGURE_END figure_end)
802 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
803 struct geometry_figure *figure = &sink->figures[sink->figure_count - 1];
805 figure->end = figure_end;
808 static HRESULT STDMETHODCALLTYPE geometry_sink_Close(ID2D1SimplifiedGeometrySink *iface)
810 struct geometry_sink *sink = impl_from_ID2D1SimplifiedGeometrySink(iface);
812 sink->closed = TRUE;
814 return S_OK;
817 static const struct ID2D1SimplifiedGeometrySinkVtbl geometry_sink_vtbl =
819 geometry_sink_QueryInterface,
820 geometry_sink_AddRef,
821 geometry_sink_Release,
822 geometry_sink_SetFillMode,
823 geometry_sink_SetSegmentFlags,
824 geometry_sink_BeginFigure,
825 geometry_sink_AddLines,
826 geometry_sink_AddBeziers,
827 geometry_sink_EndFigure,
828 geometry_sink_Close,
831 static void geometry_sink_init(struct geometry_sink *sink)
833 memset(sink, 0, sizeof(*sink));
834 sink->ID2D1SimplifiedGeometrySink_iface.lpVtbl = &geometry_sink_vtbl;
835 sink->figures_size = 4;
836 sink->figures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
837 sink->figures_size * sizeof(*sink->figures));
840 static void geometry_sink_cleanup(struct geometry_sink *sink)
842 unsigned int i;
844 for (i = 0; i < sink->figure_count; ++i)
846 HeapFree(GetProcessHeap(), 0, sink->figures[i].segments);
848 HeapFree(GetProcessHeap(), 0, sink->figures);
851 #define geometry_sink_check(a, b, c, d, e) geometry_sink_check_(__LINE__, a, b, c, d, e)
852 static void geometry_sink_check_(unsigned int line, const struct geometry_sink *sink, D2D1_FILL_MODE fill_mode,
853 unsigned int figure_count, const struct expected_geometry_figure *expected_figures, unsigned int ulps)
855 const struct geometry_segment *segment, *expected_segment;
856 const struct expected_geometry_figure *expected_figure;
857 const struct geometry_figure *figure;
858 unsigned int i, j;
859 BOOL match;
861 ok_(__FILE__, line)(sink->fill_mode == fill_mode,
862 "Got unexpected fill mode %#x.\n", sink->fill_mode);
863 ok_(__FILE__, line)(sink->figure_count == figure_count,
864 "Got unexpected figure count %u, expected %u.\n", sink->figure_count, figure_count);
865 ok_(__FILE__, line)(!sink->closed, "Sink is closed.\n");
867 for (i = 0; i < figure_count; ++i)
869 expected_figure = &expected_figures[i];
870 figure = &sink->figures[i];
872 ok_(__FILE__, line)(figure->begin == expected_figure->begin,
873 "Got unexpected figure %u begin %#x, expected %#x.\n",
874 i, figure->begin, expected_figure->begin);
875 ok_(__FILE__, line)(figure->end == expected_figure->end,
876 "Got unexpected figure %u end %#x, expected %#x.\n",
877 i, figure->end, expected_figure->end);
878 match = compare_point(&figure->start_point,
879 expected_figure->start_point.x, expected_figure->start_point.y, ulps);
880 ok_(__FILE__, line)(match, "Got unexpected figure %u start point {%.8e, %.8e}, expected {%.8e, %.8e}.\n",
881 i, figure->start_point.x, figure->start_point.y,
882 expected_figure->start_point.x, expected_figure->start_point.y);
883 ok_(__FILE__, line)(figure->segment_count == expected_figure->segment_count,
884 "Got unexpected figure %u segment count %u, expected %u.\n",
885 i, figure->segment_count, expected_figure->segment_count);
887 for (j = 0; j < figure->segment_count; ++j)
889 expected_segment = &expected_figure->segments[j];
890 segment = &figure->segments[j];
891 ok_(__FILE__, line)(segment->type == expected_segment->type,
892 "Got unexpected figure %u, segment %u type %#x, expected %#x.\n",
893 i, j, segment->type, expected_segment->type);
894 ok_(__FILE__, line)(segment->flags == expected_segment->flags,
895 "Got unexpected figure %u, segment %u flags %#x, expected %#x.\n",
896 i, j, segment->flags, expected_segment->flags);
897 switch (segment->type)
899 case SEGMENT_LINE:
900 match = compare_point(&segment->u.line,
901 expected_segment->u.line.x, expected_segment->u.line.y, ulps);
902 ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u {%.8e, %.8e}, "
903 "expected {%.8e, %.8e}.\n",
904 i, j, segment->u.line.x, segment->u.line.y,
905 expected_segment->u.line.x, expected_segment->u.line.y);
906 break;
908 case SEGMENT_BEZIER:
909 match = compare_bezier_segment(&segment->u.bezier,
910 expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
911 expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
912 expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y,
913 ulps);
914 ok_(__FILE__, line)(match, "Got unexpected figure %u segment %u "
915 "{%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}, "
916 "expected {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
917 i, j, segment->u.bezier.point1.x, segment->u.bezier.point1.y,
918 segment->u.bezier.point2.x, segment->u.bezier.point2.y,
919 segment->u.bezier.point3.x, segment->u.bezier.point3.y,
920 expected_segment->u.bezier.point1.x, expected_segment->u.bezier.point1.y,
921 expected_segment->u.bezier.point2.x, expected_segment->u.bezier.point2.y,
922 expected_segment->u.bezier.point3.x, expected_segment->u.bezier.point3.y);
923 break;
929 static void test_clip(void)
931 IDXGISwapChain *swapchain;
932 D2D1_MATRIX_3X2_F matrix;
933 D2D1_SIZE_U pixel_size;
934 ID2D1RenderTarget *rt;
935 ID3D10Device1 *device;
936 IDXGISurface *surface;
937 D2D1_POINT_2F point;
938 D2D1_COLOR_F color;
939 float dpi_x, dpi_y;
940 D2D1_RECT_F rect;
941 D2D1_SIZE_F size;
942 HWND window;
943 HRESULT hr;
944 BOOL match;
945 static const D2D1_MATRIX_3X2_F identity =
947 1.0f, 0.0f,
948 0.0f, 1.0f,
949 0.0f, 0.0f,
952 if (!(device = create_device()))
954 skip("Failed to create device, skipping tests.\n");
955 return;
957 window = create_window();
958 swapchain = create_swapchain(device, window, TRUE);
959 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
960 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
961 rt = create_render_target(surface);
962 ok(!!rt, "Failed to create render target.\n");
964 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
965 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
966 ok(dpi_y == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
967 size = ID2D1RenderTarget_GetSize(rt);
968 ok(size.width == 640.0f, "Got unexpected width %.8e.\n", size.width);
969 ok(size.height == 480.0f, "Got unexpected height %.8e.\n", size.height);
970 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
971 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
972 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
974 ID2D1RenderTarget_GetTransform(rt, &matrix);
975 ok(!memcmp(&matrix, &identity, sizeof(matrix)),
976 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
977 matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32);
979 ID2D1RenderTarget_BeginDraw(rt);
981 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
982 ID2D1RenderTarget_Clear(rt, &color);
984 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
985 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
986 ok(dpi_x == 48.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
987 ok(dpi_y == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
988 size = ID2D1RenderTarget_GetSize(rt);
989 ok(size.width == 1280.0f, "Got unexpected width %.8e.\n", size.width);
990 ok(size.height == 240.0f, "Got unexpected height %.8e.\n", size.height);
991 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
992 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
993 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
995 /* The effective clip rect is the intersection of all currently pushed
996 * clip rects. Clip rects are in DIPs. */
997 set_rect(&rect, 0.0f, 0.0f, 1280.0f, 80.0f);
998 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
999 set_rect(&rect, 0.0f, 0.0f, 426.0f, 240.0f);
1000 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1002 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
1003 ID2D1RenderTarget_Clear(rt, &color);
1004 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1005 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1007 ID2D1RenderTarget_SetDpi(rt, 0.0f, 0.0f);
1008 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1009 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1010 ok(dpi_y == 96.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1012 ID2D1RenderTarget_SetDpi(rt, 192.0f, 192.0f);
1013 ID2D1RenderTarget_SetDpi(rt, 0.0f, 96.0f);
1014 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1015 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1016 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1018 ID2D1RenderTarget_SetDpi(rt, -10.0f, 96.0f);
1019 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1020 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1021 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1023 ID2D1RenderTarget_SetDpi(rt, 96.0f, -10.0f);
1024 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1025 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1026 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1028 ID2D1RenderTarget_SetDpi(rt, 96.0f, 0.0f);
1029 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
1030 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
1031 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
1033 ID2D1RenderTarget_SetDpi(rt, 96.0f, 96.0f);
1035 /* Transformations apply to clip rects, the effective clip rect is the
1036 * (axis-aligned) bounding box of the transformed clip rect. */
1037 set_point(&point, 320.0f, 240.0f);
1038 D2D1MakeRotateMatrix(30.0f, point, &matrix);
1039 ID2D1RenderTarget_SetTransform(rt, &matrix);
1040 set_rect(&rect, 215.0f, 208.0f, 425.0f, 272.0f);
1041 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1042 set_color(&color, 1.0f, 1.0f, 1.0f, 1.0f);
1043 ID2D1RenderTarget_Clear(rt, &color);
1044 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1046 /* Transformations are applied when pushing the clip rect, transformations
1047 * set afterwards have no effect on the current clip rect. This includes
1048 * SetDpi(). */
1049 ID2D1RenderTarget_SetTransform(rt, &identity);
1050 set_rect(&rect, 427.0f, 320.0f, 640.0f, 480.0f);
1051 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1052 ID2D1RenderTarget_SetTransform(rt, &matrix);
1053 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
1054 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
1055 ID2D1RenderTarget_Clear(rt, &color);
1056 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1058 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1059 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1060 match = compare_surface(surface, "035a44d4198d6e422e9de6185b5b2c2bac5e33c9");
1061 ok(match, "Surface does not match.\n");
1063 /* Fractional clip rectangle coordinates, aliased mode. */
1064 set_matrix_identity(&matrix);
1065 ID2D1RenderTarget_SetTransform(rt, &matrix);
1066 ID2D1RenderTarget_SetDpi(rt, 96.0f, 96.0f);
1068 ID2D1RenderTarget_BeginDraw(rt);
1070 set_color(&color, 0.0f, 0.0f, 0.0f, 1.0f);
1071 ID2D1RenderTarget_Clear(rt, &color);
1073 scale_matrix(&matrix, 2.0f, 2.0f);
1074 ID2D1RenderTarget_SetTransform(rt, &matrix);
1075 set_rect(&rect, 0.0f, 0.5f, 200.0f, 100.5f);
1076 set_color(&color, 1.0f, 0.0f, 1.0f, 1.0f);
1077 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1078 ID2D1RenderTarget_Clear(rt, &color);
1079 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1081 set_matrix_identity(&matrix);
1082 ID2D1RenderTarget_SetTransform(rt, &matrix);
1083 set_rect(&rect, 0.0f, 0.5f, 100.0f, 200.5f);
1084 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
1085 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1086 ID2D1RenderTarget_Clear(rt, &color);
1087 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1089 ID2D1RenderTarget_SetTransform(rt, &matrix);
1090 set_rect(&rect, 0.5f, 250.0f, 100.5f, 300.0f);
1091 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
1092 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1093 ID2D1RenderTarget_Clear(rt, &color);
1094 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1096 translate_matrix(&matrix, 0.1f, 0.0f);
1097 ID2D1RenderTarget_SetTransform(rt, &matrix);
1098 set_rect(&rect, 110.0f, 250.25f, 150.0f, 300.25f);
1099 set_color(&color, 0.0f, 0.5f, 1.0f, 1.0f);
1100 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1101 ID2D1RenderTarget_Clear(rt, &color);
1102 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1104 set_rect(&rect, 160.0f, 250.75f, 200.0f, 300.75f);
1105 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1106 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1107 ID2D1RenderTarget_Clear(rt, &color);
1108 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1110 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
1111 set_rect(&rect, 160.25f, 0.0f, 200.25f, 100.0f);
1112 set_color(&color, 1.0f, 0.0f, 1.0f, 1.0f);
1113 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1114 ID2D1RenderTarget_Clear(rt, &color);
1115 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1117 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1118 set_rect(&rect, 160.75f, 100.0f, 200.75f, 120.0f);
1119 set_color(&color, 0.0f, 1.0f, 1.0f, 1.0f);
1120 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
1121 ID2D1RenderTarget_Clear(rt, &color);
1122 ID2D1RenderTarget_PopAxisAlignedClip(rt);
1124 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1125 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1126 match = compare_surface(surface, "a958d1fe69ee880200d47b206948e4c1ef382748");
1127 ok(match, "Surface does not match.\n");
1129 ID2D1RenderTarget_Release(rt);
1130 IDXGISurface_Release(surface);
1131 IDXGISwapChain_Release(swapchain);
1132 ID3D10Device1_Release(device);
1133 DestroyWindow(window);
1136 static void test_state_block(void)
1138 IDWriteRenderingParams *text_rendering_params1, *text_rendering_params2;
1139 D2D1_DRAWING_STATE_DESCRIPTION drawing_state;
1140 ID2D1DrawingStateBlock *state_block;
1141 IDWriteFactory *dwrite_factory;
1142 IDXGISwapChain *swapchain;
1143 ID2D1RenderTarget *rt;
1144 ID3D10Device1 *device;
1145 IDXGISurface *surface;
1146 ID2D1Factory *factory;
1147 ULONG refcount;
1148 HWND window;
1149 HRESULT hr;
1150 static const D2D1_MATRIX_3X2_F identity =
1152 1.0f, 0.0f,
1153 0.0f, 1.0f,
1154 0.0f, 0.0f,
1156 static const D2D1_MATRIX_3X2_F transform1 =
1158 1.0f, 2.0f,
1159 3.0f, 4.0f,
1160 5.0f, 6.0f,
1162 static const D2D1_MATRIX_3X2_F transform2 =
1164 7.0f, 8.0f,
1165 9.0f, 10.0f,
1166 11.0f, 12.0f,
1169 if (!(device = create_device()))
1171 skip("Failed to create device, skipping tests.\n");
1172 return;
1174 window = create_window();
1175 swapchain = create_swapchain(device, window, TRUE);
1176 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1177 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1178 rt = create_render_target(surface);
1179 ok(!!rt, "Failed to create render target.\n");
1180 ID2D1RenderTarget_GetFactory(rt, &factory);
1181 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
1182 ok(SUCCEEDED(hr), "Failed to create dwrite factory, hr %#x.\n", hr);
1183 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &text_rendering_params1);
1184 ok(SUCCEEDED(hr), "Failed to create dwrite rendering params, hr %#x.\n", hr);
1185 IDWriteFactory_Release(dwrite_factory);
1187 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1188 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1189 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1190 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1191 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
1192 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1193 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1194 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %s:%s.\n",
1195 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1196 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1197 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
1198 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1199 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1200 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1201 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1202 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1204 hr = ID2D1Factory_CreateDrawingStateBlock(factory, NULL, NULL, &state_block);
1205 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
1206 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1207 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1208 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1209 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
1210 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1211 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %s:%s.\n",
1212 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1213 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
1214 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1215 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1216 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1217 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1218 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1219 ID2D1DrawingStateBlock_Release(state_block);
1221 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
1222 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
1223 drawing_state.tag1 = 0xdead;
1224 drawing_state.tag2 = 0xbeef;
1225 drawing_state.transform = transform1;
1226 hr = ID2D1Factory_CreateDrawingStateBlock(factory, &drawing_state, text_rendering_params1, &state_block);
1227 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
1229 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1230 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1231 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1232 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
1233 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1234 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %s:%s.\n",
1235 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1236 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1237 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1238 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1239 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1240 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1241 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1242 text_rendering_params2, text_rendering_params1);
1243 IDWriteRenderingParams_Release(text_rendering_params2);
1245 ID2D1RenderTarget_RestoreDrawingState(rt, state_block);
1247 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1248 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1249 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1250 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1251 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
1252 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1253 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1254 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %s:%s.\n",
1255 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1256 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1257 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1258 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1259 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1260 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1261 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1262 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1263 text_rendering_params2, text_rendering_params1);
1264 IDWriteRenderingParams_Release(text_rendering_params2);
1266 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
1267 ID2D1RenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
1268 ID2D1RenderTarget_SetTags(rt, 1, 2);
1269 ID2D1RenderTarget_SetTransform(rt, &transform2);
1270 ID2D1RenderTarget_SetTextRenderingParams(rt, NULL);
1272 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
1273 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1274 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1275 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
1276 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
1277 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1278 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
1279 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %s:%s.\n",
1280 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1281 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
1282 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
1283 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1284 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1285 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1286 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
1287 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1289 ID2D1RenderTarget_SaveDrawingState(rt, state_block);
1291 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1292 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
1293 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1294 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
1295 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1296 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %s:%s.\n",
1297 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1298 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
1299 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1300 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1301 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1302 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1303 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
1305 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
1306 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1307 drawing_state.tag1 = 3;
1308 drawing_state.tag2 = 4;
1309 drawing_state.transform = transform1;
1310 ID2D1DrawingStateBlock_SetDescription(state_block, &drawing_state);
1311 ID2D1DrawingStateBlock_SetTextRenderingParams(state_block, text_rendering_params1);
1313 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
1314 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
1315 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
1316 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE,
1317 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
1318 ok(drawing_state.tag1 == 3 && drawing_state.tag2 == 4, "Got unexpected tags %s:%s.\n",
1319 wine_dbgstr_longlong(drawing_state.tag1), wine_dbgstr_longlong(drawing_state.tag2));
1320 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
1321 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1322 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
1323 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
1324 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
1325 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
1326 text_rendering_params2, text_rendering_params1);
1327 IDWriteRenderingParams_Release(text_rendering_params2);
1329 ID2D1DrawingStateBlock_Release(state_block);
1331 refcount = IDWriteRenderingParams_Release(text_rendering_params1);
1332 ok(!refcount, "Rendering params %u references left.\n", refcount);
1333 ID2D1Factory_Release(factory);
1334 ID2D1RenderTarget_Release(rt);
1335 IDXGISurface_Release(surface);
1336 IDXGISwapChain_Release(swapchain);
1337 ID3D10Device1_Release(device);
1338 DestroyWindow(window);
1341 static void test_color_brush(void)
1343 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1344 D2D1_BRUSH_PROPERTIES brush_desc;
1345 D2D1_COLOR_F color, tmp_color;
1346 ID2D1SolidColorBrush *brush;
1347 IDXGISwapChain *swapchain;
1348 ID2D1RenderTarget *rt;
1349 ID3D10Device1 *device;
1350 IDXGISurface *surface;
1351 D2D1_RECT_F rect;
1352 float opacity;
1353 HWND window;
1354 HRESULT hr;
1355 BOOL match;
1357 if (!(device = create_device()))
1359 skip("Failed to create device, skipping tests.\n");
1360 return;
1362 window = create_window();
1363 swapchain = create_swapchain(device, window, TRUE);
1364 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1365 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1366 rt = create_render_target(surface);
1367 ok(!!rt, "Failed to create render target.\n");
1369 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1370 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1372 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
1373 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
1374 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1375 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
1376 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
1377 set_matrix_identity(&matrix);
1378 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
1379 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1380 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1381 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1382 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1383 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
1384 ok(!memcmp(&tmp_color, &color, sizeof(color)),
1385 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
1386 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
1387 ID2D1SolidColorBrush_Release(brush);
1389 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
1390 brush_desc.opacity = 0.3f;
1391 set_matrix_identity(&matrix);
1392 scale_matrix(&matrix, 2.0f, 2.0f);
1393 brush_desc.transform = matrix;
1394 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, &brush_desc, &brush);
1395 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1396 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
1397 ok(opacity == 0.3f, "Got unexpected opacity %.8e.\n", opacity);
1398 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
1399 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1400 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1401 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1402 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1403 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
1404 ok(!memcmp(&tmp_color, &color, sizeof(color)),
1405 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
1406 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
1408 ID2D1RenderTarget_BeginDraw(rt);
1410 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1411 ID2D1RenderTarget_Clear(rt, &color);
1413 ID2D1SolidColorBrush_SetOpacity(brush, 1.0f);
1414 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
1415 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
1417 set_matrix_identity(&matrix);
1418 scale_matrix(&matrix, 0.5f, 2.0f);
1419 translate_matrix(&matrix, 320.0f, 240.0f);
1420 rotate_matrix(&matrix, M_PI / 4.0f);
1421 ID2D1RenderTarget_SetTransform(rt, &matrix);
1422 set_color(&color, 1.0f, 0.0f, 0.0f, 0.625f);
1423 ID2D1SolidColorBrush_SetColor(brush, &color);
1424 ID2D1SolidColorBrush_SetOpacity(brush, 0.75f);
1425 set_rect(&rect, -80.0f, -60.0f, 80.0f, 60.0f);
1426 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
1428 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1429 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1430 match = compare_surface(surface, "6d1218fca5e21fb7e287b3a439d60dbc251f5ceb");
1431 ok(match, "Surface does not match.\n");
1433 ID2D1SolidColorBrush_Release(brush);
1434 ID2D1RenderTarget_Release(rt);
1435 IDXGISurface_Release(surface);
1436 IDXGISwapChain_Release(swapchain);
1437 ID3D10Device1_Release(device);
1438 DestroyWindow(window);
1441 static void test_bitmap_brush(void)
1443 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode;
1444 ID2D1TransformedGeometry *transformed_geometry;
1445 ID2D1RectangleGeometry *rectangle_geometry;
1446 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1447 D2D1_BITMAP_PROPERTIES bitmap_desc;
1448 ID2D1Bitmap *bitmap, *tmp_bitmap;
1449 D2D1_RECT_F src_rect, dst_rect;
1450 D2D1_EXTEND_MODE extend_mode;
1451 IDXGISwapChain *swapchain;
1452 ID2D1BitmapBrush *brush;
1453 ID2D1RenderTarget *rt;
1454 ID3D10Device1 *device;
1455 IDXGISurface *surface;
1456 ID2D1Factory *factory;
1457 D2D1_COLOR_F color;
1458 D2D1_SIZE_U size;
1459 unsigned int i;
1460 ULONG refcount;
1461 float opacity;
1462 HWND window;
1463 HRESULT hr;
1464 BOOL match;
1466 static const struct
1468 D2D1_EXTEND_MODE extend_mode_x;
1469 D2D1_EXTEND_MODE extend_mode_y;
1470 float translate_x;
1471 float translate_y;
1472 D2D1_RECT_F rect;
1474 extend_mode_tests[] =
1476 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_MIRROR, -7.0f, 1.0f, {-4.0f, 0.0f, -8.0f, 4.0f}},
1477 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_MIRROR, -3.0f, 1.0f, {-4.0f, 4.0f, 0.0f, 0.0f}},
1478 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_MIRROR, 1.0f, 1.0f, { 4.0f, 0.0f, 0.0f, 4.0f}},
1479 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_WRAP, -7.0f, 5.0f, {-8.0f, 8.0f, -4.0f, 4.0f}},
1480 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP, -3.0f, 5.0f, { 0.0f, 4.0f, -4.0f, 8.0f}},
1481 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_WRAP, 1.0f, 5.0f, { 0.0f, 8.0f, 4.0f, 4.0f}},
1482 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_CLAMP, -7.0f, 9.0f, {-4.0f, 8.0f, -8.0f, 12.0f}},
1483 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, -3.0f, 9.0f, {-4.0f, 12.0f, 0.0f, 8.0f}},
1484 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_CLAMP, 1.0f, 9.0f, { 4.0f, 8.0f, 0.0f, 12.0f}},
1486 static const DWORD bitmap_data[] =
1488 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
1489 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
1490 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
1491 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
1494 if (!(device = create_device()))
1496 skip("Failed to create device, skipping tests.\n");
1497 return;
1499 window = create_window();
1500 swapchain = create_swapchain(device, window, TRUE);
1501 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1502 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1503 rt = create_render_target(surface);
1504 ok(!!rt, "Failed to create render target.\n");
1506 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1507 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1509 set_size_u(&size, 4, 4);
1510 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1511 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1512 bitmap_desc.dpiX = 96.0f;
1513 bitmap_desc.dpiY = 96.0f;
1514 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1515 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1517 /* Creating a brush with a NULL bitmap crashes on Vista, but works fine on
1518 * Windows 7+. */
1519 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1520 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1521 ID2D1BitmapBrush_GetBitmap(brush, &tmp_bitmap);
1522 ok(tmp_bitmap == bitmap, "Got unexpected bitmap %p, expected %p.\n", tmp_bitmap, bitmap);
1523 ID2D1Bitmap_Release(tmp_bitmap);
1524 opacity = ID2D1BitmapBrush_GetOpacity(brush);
1525 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
1526 set_matrix_identity(&matrix);
1527 ID2D1BitmapBrush_GetTransform(brush, &tmp_matrix);
1528 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1529 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1530 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1531 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1532 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1533 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1534 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1535 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1536 interpolation_mode = ID2D1BitmapBrush_GetInterpolationMode(brush);
1537 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
1538 "Got unexpected interpolation mode %#x.\n", interpolation_mode);
1539 ID2D1BitmapBrush_Release(brush);
1541 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1542 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1543 set_matrix_identity(&matrix);
1544 translate_matrix(&matrix, 40.0f, 120.0f);
1545 scale_matrix(&matrix, 20.0f, 60.0f);
1546 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1547 ID2D1BitmapBrush_SetInterpolationMode(brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1549 ID2D1RenderTarget_BeginDraw(rt);
1551 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1552 ID2D1RenderTarget_Clear(rt, &color);
1554 set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
1555 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1557 set_matrix_identity(&matrix);
1558 scale_matrix(&matrix, 0.5f, 2.0f);
1559 translate_matrix(&matrix, 320.0f, 240.0f);
1560 rotate_matrix(&matrix, M_PI / 4.0f);
1561 ID2D1RenderTarget_SetTransform(rt, &matrix);
1562 set_matrix_identity(&matrix);
1563 translate_matrix(&matrix, -80.0f, -60.0f);
1564 scale_matrix(&matrix, 64.0f, 32.0f);
1565 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1566 ID2D1BitmapBrush_SetOpacity(brush, 0.75f);
1567 set_rect(&dst_rect, -80.0f, -60.0f, 80.0f, 60.0f);
1568 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1570 set_matrix_identity(&matrix);
1571 translate_matrix(&matrix, 200.0f, 120.0f);
1572 scale_matrix(&matrix, 20.0f, 60.0f);
1573 ID2D1RenderTarget_SetTransform(rt, &matrix);
1574 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f,
1575 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1576 set_rect(&dst_rect, -4.0f, 12.0f, -8.0f, 8.0f);
1577 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 0.75f,
1578 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1579 set_rect(&dst_rect, 0.0f, 8.0f, 4.0f, 12.0f);
1580 set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
1581 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1582 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1584 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1585 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1586 match = compare_surface(surface, "9437f4447d98feaad41a1c4202ee90aadc718ee6");
1587 ok(match, "Surface does not match.\n");
1589 ID2D1RenderTarget_BeginDraw(rt);
1591 ID2D1RenderTarget_Clear(rt, &color);
1593 ID2D1BitmapBrush_SetOpacity(brush, 1.0f);
1594 for (i = 0; i < sizeof(extend_mode_tests) / sizeof(*extend_mode_tests); ++i)
1596 ID2D1BitmapBrush_SetExtendModeX(brush, extend_mode_tests[i].extend_mode_x);
1597 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1598 ok(extend_mode == extend_mode_tests[i].extend_mode_x,
1599 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1600 i, extend_mode, extend_mode_tests[i].extend_mode_x);
1601 ID2D1BitmapBrush_SetExtendModeY(brush, extend_mode_tests[i].extend_mode_y);
1602 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1603 ok(extend_mode == extend_mode_tests[i].extend_mode_y,
1604 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1605 i, extend_mode, extend_mode_tests[i].extend_mode_y);
1606 set_matrix_identity(&matrix);
1607 translate_matrix(&matrix, extend_mode_tests[i].translate_x, extend_mode_tests[i].translate_y);
1608 scale_matrix(&matrix, 0.5f, 0.5f);
1609 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1610 ID2D1RenderTarget_FillRectangle(rt, &extend_mode_tests[i].rect, (ID2D1Brush *)brush);
1613 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1614 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1615 match = compare_surface(surface, "b4b775afecdae2d26642001f4faff73663bb8b31");
1616 ok(match, "Surface does not match.\n");
1618 ID2D1Bitmap_Release(bitmap);
1619 bitmap_desc.dpiX = 96.0f / 20.0f;
1620 bitmap_desc.dpiY = 96.0f / 60.0f;
1621 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1622 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1623 ID2D1BitmapBrush_SetBitmap(brush, bitmap);
1625 ID2D1RenderTarget_BeginDraw(rt);
1627 ID2D1RenderTarget_Clear(rt, &color);
1629 set_matrix_identity(&matrix);
1630 translate_matrix(&matrix, 40.0f, 120.0f);
1631 skew_matrix(&matrix, 0.125f, 2.0f);
1632 ID2D1RenderTarget_SetTransform(rt, &matrix);
1633 set_matrix_identity(&matrix);
1634 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1635 set_rect(&dst_rect, 0.0f, 0.0f, 80.0f, 240.0f);
1636 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1638 ID2D1RenderTarget_GetFactory(rt, &factory);
1640 set_rect(&dst_rect, -1.0f, -1.0f, 1.0f, 1.0f);
1641 hr = ID2D1Factory_CreateRectangleGeometry(factory, &dst_rect, &rectangle_geometry);
1642 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
1644 set_matrix_identity(&matrix);
1645 translate_matrix(&matrix, 240.0f, 720.0f);
1646 scale_matrix(&matrix, 40.0f, 120.0f);
1647 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)rectangle_geometry,
1648 &matrix, &transformed_geometry);
1649 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
1650 ID2D1RectangleGeometry_Release(rectangle_geometry);
1652 set_matrix_identity(&matrix);
1653 ID2D1RenderTarget_SetTransform(rt, &matrix);
1654 set_matrix_identity(&matrix);
1655 translate_matrix(&matrix, 200.0f, 600.0f);
1656 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1657 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1658 ID2D1TransformedGeometry_Release(transformed_geometry);
1660 ID2D1Factory_Release(factory);
1662 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1663 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1664 match = compare_surface(surface, "cf7b90ba7b139fdfbe9347e1907d635cfb4ed197");
1665 ok(match, "Surface does not match.\n");
1667 ID2D1BitmapBrush_Release(brush);
1668 refcount = ID2D1Bitmap_Release(bitmap);
1669 ok(!refcount, "Bitmap has %u references left.\n", refcount);
1670 ID2D1RenderTarget_Release(rt);
1671 IDXGISurface_Release(surface);
1672 IDXGISwapChain_Release(swapchain);
1673 ID3D10Device1_Release(device);
1674 DestroyWindow(window);
1677 static void fill_geometry_sink(ID2D1GeometrySink *sink)
1679 D2D1_POINT_2F point;
1681 set_point(&point, 15.0f, 20.0f);
1682 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1683 line_to(sink, 55.0f, 20.0f);
1684 line_to(sink, 55.0f, 220.0f);
1685 line_to(sink, 25.0f, 220.0f);
1686 line_to(sink, 25.0f, 100.0f);
1687 line_to(sink, 75.0f, 100.0f);
1688 line_to(sink, 75.0f, 300.0f);
1689 line_to(sink, 5.0f, 300.0f);
1690 line_to(sink, 5.0f, 60.0f);
1691 line_to(sink, 45.0f, 60.0f);
1692 line_to(sink, 45.0f, 180.0f);
1693 line_to(sink, 35.0f, 180.0f);
1694 line_to(sink, 35.0f, 140.0f);
1695 line_to(sink, 65.0f, 140.0f);
1696 line_to(sink, 65.0f, 260.0f);
1697 line_to(sink, 15.0f, 260.0f);
1698 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1700 set_point(&point, 155.0f, 300.0f);
1701 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1702 line_to(sink, 155.0f, 160.0f);
1703 line_to(sink, 85.0f, 160.0f);
1704 line_to(sink, 85.0f, 300.0f);
1705 line_to(sink, 120.0f, 300.0f);
1706 line_to(sink, 120.0f, 20.0f);
1707 line_to(sink, 155.0f, 20.0f);
1708 line_to(sink, 155.0f, 160.0f);
1709 line_to(sink, 85.0f, 160.0f);
1710 line_to(sink, 85.0f, 20.0f);
1711 line_to(sink, 120.0f, 20.0f);
1712 line_to(sink, 120.0f, 300.0f);
1713 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1715 set_point(&point, 165.0f, 20.0f);
1716 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1717 line_to(sink, 165.0f, 300.0f);
1718 line_to(sink, 235.0f, 300.0f);
1719 line_to(sink, 235.0f, 20.0f);
1720 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1721 set_point(&point, 225.0f, 60.0f);
1722 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1723 line_to(sink, 225.0f, 260.0f);
1724 line_to(sink, 175.0f, 260.0f);
1725 line_to(sink, 175.0f, 60.0f);
1726 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1727 set_point(&point, 215.0f, 220.0f);
1728 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1729 line_to(sink, 185.0f, 220.0f);
1730 line_to(sink, 185.0f, 100.0f);
1731 line_to(sink, 215.0f, 100.0f);
1732 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1733 set_point(&point, 195.0f, 180.0f);
1734 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1735 line_to(sink, 205.0f, 180.0f);
1736 line_to(sink, 205.0f, 140.0f);
1737 line_to(sink, 195.0f, 140.0f);
1738 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1741 static void fill_geometry_sink_bezier(ID2D1GeometrySink *sink)
1743 D2D1_POINT_2F point;
1745 set_point(&point, 5.0f, 160.0f);
1746 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1747 quadratic_to(sink, 40.0f, 160.0f, 40.0f, 20.0f);
1748 quadratic_to(sink, 40.0f, 160.0f, 75.0f, 160.0f);
1749 quadratic_to(sink, 40.0f, 160.0f, 40.0f, 300.0f);
1750 quadratic_to(sink, 40.0f, 160.0f, 5.0f, 160.0f);
1751 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1753 set_point(&point, 20.0f, 160.0f);
1754 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1755 quadratic_to(sink, 20.0f, 80.0f, 40.0f, 80.0f);
1756 quadratic_to(sink, 60.0f, 80.0f, 60.0f, 160.0f);
1757 quadratic_to(sink, 60.0f, 240.0f, 40.0f, 240.0f);
1758 quadratic_to(sink, 20.0f, 240.0f, 20.0f, 160.0f);
1759 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1761 set_point(&point, 5.0f, 612.0f);
1762 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1763 quadratic_to(sink, 40.0f, 612.0f, 40.0f, 752.0f);
1764 quadratic_to(sink, 40.0f, 612.0f, 75.0f, 612.0f);
1765 quadratic_to(sink, 40.0f, 612.0f, 40.0f, 472.0f);
1766 quadratic_to(sink, 40.0f, 612.0f, 5.0f, 612.0f);
1767 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1769 set_point(&point, 20.0f, 612.0f);
1770 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1771 quadratic_to(sink, 20.0f, 692.0f, 40.0f, 692.0f);
1772 quadratic_to(sink, 60.0f, 692.0f, 60.0f, 612.0f);
1773 quadratic_to(sink, 60.0f, 532.0f, 40.0f, 532.0f);
1774 quadratic_to(sink, 20.0f, 532.0f, 20.0f, 612.0f);
1775 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1778 static void test_path_geometry(void)
1780 ID2D1TransformedGeometry *transformed_geometry;
1781 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1782 ID2D1GeometrySink *sink, *tmp_sink;
1783 struct geometry_sink simplify_sink;
1784 D2D1_POINT_2F point = {0.0f, 0.0f};
1785 ID2D1SolidColorBrush *brush;
1786 ID2D1PathGeometry *geometry;
1787 ID2D1Geometry *tmp_geometry;
1788 IDXGISwapChain *swapchain;
1789 ID2D1RenderTarget *rt;
1790 ID3D10Device1 *device;
1791 IDXGISurface *surface;
1792 ID2D1Factory *factory;
1793 BOOL match, contains;
1794 D2D1_COLOR_F color;
1795 D2D1_RECT_F rect;
1796 ULONG refcount;
1797 UINT32 count;
1798 HWND window;
1799 HRESULT hr;
1801 static const struct geometry_segment expected_segments[] =
1803 /* Figure 0. */
1804 {SEGMENT_LINE, {{{ 55.0f, 20.0f}}}},
1805 {SEGMENT_LINE, {{{ 55.0f, 220.0f}}}},
1806 {SEGMENT_LINE, {{{ 25.0f, 220.0f}}}},
1807 {SEGMENT_LINE, {{{ 25.0f, 100.0f}}}},
1808 {SEGMENT_LINE, {{{ 75.0f, 100.0f}}}},
1809 {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}},
1810 {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}},
1811 {SEGMENT_LINE, {{{ 5.0f, 60.0f}}}},
1812 {SEGMENT_LINE, {{{ 45.0f, 60.0f}}}},
1813 {SEGMENT_LINE, {{{ 45.0f, 180.0f}}}},
1814 {SEGMENT_LINE, {{{ 35.0f, 180.0f}}}},
1815 {SEGMENT_LINE, {{{ 35.0f, 140.0f}}}},
1816 {SEGMENT_LINE, {{{ 65.0f, 140.0f}}}},
1817 {SEGMENT_LINE, {{{ 65.0f, 260.0f}}}},
1818 {SEGMENT_LINE, {{{ 15.0f, 260.0f}}}},
1819 /* Figure 1. */
1820 {SEGMENT_LINE, {{{155.0f, 160.0f}}}},
1821 {SEGMENT_LINE, {{{ 85.0f, 160.0f}}}},
1822 {SEGMENT_LINE, {{{ 85.0f, 300.0f}}}},
1823 {SEGMENT_LINE, {{{120.0f, 300.0f}}}},
1824 {SEGMENT_LINE, {{{120.0f, 20.0f}}}},
1825 {SEGMENT_LINE, {{{155.0f, 20.0f}}}},
1826 {SEGMENT_LINE, {{{155.0f, 160.0f}}}},
1827 {SEGMENT_LINE, {{{ 85.0f, 160.0f}}}},
1828 {SEGMENT_LINE, {{{ 85.0f, 20.0f}}}},
1829 {SEGMENT_LINE, {{{120.0f, 20.0f}}}},
1830 {SEGMENT_LINE, {{{120.0f, 300.0f}}}},
1831 /* Figure 2. */
1832 {SEGMENT_LINE, {{{165.0f, 300.0f}}}},
1833 {SEGMENT_LINE, {{{235.0f, 300.0f}}}},
1834 {SEGMENT_LINE, {{{235.0f, 20.0f}}}},
1835 /* Figure 3. */
1836 {SEGMENT_LINE, {{{225.0f, 260.0f}}}},
1837 {SEGMENT_LINE, {{{175.0f, 260.0f}}}},
1838 {SEGMENT_LINE, {{{175.0f, 60.0f}}}},
1839 /* Figure 4. */
1840 {SEGMENT_LINE, {{{185.0f, 220.0f}}}},
1841 {SEGMENT_LINE, {{{185.0f, 100.0f}}}},
1842 {SEGMENT_LINE, {{{215.0f, 100.0f}}}},
1843 /* Figure 5. */
1844 {SEGMENT_LINE, {{{205.0f, 180.0f}}}},
1845 {SEGMENT_LINE, {{{205.0f, 140.0f}}}},
1846 {SEGMENT_LINE, {{{195.0f, 140.0f}}}},
1847 /* Figure 6. */
1848 {SEGMENT_LINE, {{{135.0f, 620.0f}}}},
1849 {SEGMENT_LINE, {{{135.0f, 420.0f}}}},
1850 {SEGMENT_LINE, {{{105.0f, 420.0f}}}},
1851 {SEGMENT_LINE, {{{105.0f, 540.0f}}}},
1852 {SEGMENT_LINE, {{{155.0f, 540.0f}}}},
1853 {SEGMENT_LINE, {{{155.0f, 340.0f}}}},
1854 {SEGMENT_LINE, {{{ 85.0f, 340.0f}}}},
1855 {SEGMENT_LINE, {{{ 85.0f, 580.0f}}}},
1856 {SEGMENT_LINE, {{{125.0f, 580.0f}}}},
1857 {SEGMENT_LINE, {{{125.0f, 460.0f}}}},
1858 {SEGMENT_LINE, {{{115.0f, 460.0f}}}},
1859 {SEGMENT_LINE, {{{115.0f, 500.0f}}}},
1860 {SEGMENT_LINE, {{{145.0f, 500.0f}}}},
1861 {SEGMENT_LINE, {{{145.0f, 380.0f}}}},
1862 {SEGMENT_LINE, {{{ 95.0f, 380.0f}}}},
1863 /* Figure 7. */
1864 {SEGMENT_LINE, {{{235.0f, 480.0f}}}},
1865 {SEGMENT_LINE, {{{165.0f, 480.0f}}}},
1866 {SEGMENT_LINE, {{{165.0f, 340.0f}}}},
1867 {SEGMENT_LINE, {{{200.0f, 340.0f}}}},
1868 {SEGMENT_LINE, {{{200.0f, 620.0f}}}},
1869 {SEGMENT_LINE, {{{235.0f, 620.0f}}}},
1870 {SEGMENT_LINE, {{{235.0f, 480.0f}}}},
1871 {SEGMENT_LINE, {{{165.0f, 480.0f}}}},
1872 {SEGMENT_LINE, {{{165.0f, 620.0f}}}},
1873 {SEGMENT_LINE, {{{200.0f, 620.0f}}}},
1874 {SEGMENT_LINE, {{{200.0f, 340.0f}}}},
1875 /* Figure 8. */
1876 {SEGMENT_LINE, {{{245.0f, 340.0f}}}},
1877 {SEGMENT_LINE, {{{315.0f, 340.0f}}}},
1878 {SEGMENT_LINE, {{{315.0f, 620.0f}}}},
1879 /* Figure 9. */
1880 {SEGMENT_LINE, {{{305.0f, 380.0f}}}},
1881 {SEGMENT_LINE, {{{255.0f, 380.0f}}}},
1882 {SEGMENT_LINE, {{{255.0f, 580.0f}}}},
1883 /* Figure 10. */
1884 {SEGMENT_LINE, {{{265.0f, 420.0f}}}},
1885 {SEGMENT_LINE, {{{265.0f, 540.0f}}}},
1886 {SEGMENT_LINE, {{{295.0f, 540.0f}}}},
1887 /* Figure 11. */
1888 {SEGMENT_LINE, {{{285.0f, 460.0f}}}},
1889 {SEGMENT_LINE, {{{285.0f, 500.0f}}}},
1890 {SEGMENT_LINE, {{{275.0f, 500.0f}}}},
1891 /* Figure 12. */
1892 {SEGMENT_BEZIER, {{{2.83333340e+01f, 1.60000000e+02f},
1893 {4.00000000e+01f, 1.13333336e+02f},
1894 {4.00000000e+01f, 2.00000000e+01f}}}},
1895 {SEGMENT_BEZIER, {{{4.00000000e+01f, 1.13333336e+02f},
1896 {5.16666641e+01f, 1.60000000e+02f},
1897 {7.50000000e+01f, 1.60000000e+02f}}}},
1898 {SEGMENT_BEZIER, {{{5.16666641e+01f, 1.60000000e+02f},
1899 {4.00000000e+01f, 2.06666656e+02f},
1900 {4.00000000e+01f, 3.00000000e+02f}}}},
1901 {SEGMENT_BEZIER, {{{4.00000000e+01f, 2.06666656e+02f},
1902 {2.83333340e+01f, 1.60000000e+02f},
1903 {5.00000000e+00f, 1.60000000e+02f}}}},
1904 /* Figure 13. */
1905 {SEGMENT_BEZIER, {{{2.00000000e+01f, 1.06666664e+02f},
1906 {2.66666660e+01f, 8.00000000e+01f},
1907 {4.00000000e+01f, 8.00000000e+01f}}}},
1908 {SEGMENT_BEZIER, {{{5.33333321e+01f, 8.00000000e+01f},
1909 {6.00000000e+01f, 1.06666664e+02f},
1910 {6.00000000e+01f, 1.60000000e+02f}}}},
1911 {SEGMENT_BEZIER, {{{6.00000000e+01f, 2.13333328e+02f},
1912 {5.33333321e+01f, 2.40000000e+02f},
1913 {4.00000000e+01f, 2.40000000e+02f}}}},
1914 {SEGMENT_BEZIER, {{{2.66666660e+01f, 2.40000000e+02f},
1915 {2.00000000e+01f, 2.13333328e+02f},
1916 {2.00000000e+01f, 1.60000000e+02f}}}},
1917 /* Figure 14. */
1918 {SEGMENT_BEZIER, {{{2.83333340e+01f, 6.12000000e+02f},
1919 {4.00000000e+01f, 6.58666687e+02f},
1920 {4.00000000e+01f, 7.52000000e+02f}}}},
1921 {SEGMENT_BEZIER, {{{4.00000000e+01f, 6.58666687e+02f},
1922 {5.16666641e+01f, 6.12000000e+02f},
1923 {7.50000000e+01f, 6.12000000e+02f}}}},
1924 {SEGMENT_BEZIER, {{{5.16666641e+01f, 6.12000000e+02f},
1925 {4.00000000e+01f, 5.65333313e+02f},
1926 {4.00000000e+01f, 4.72000000e+02f}}}},
1927 {SEGMENT_BEZIER, {{{4.00000000e+01f, 5.65333313e+02f},
1928 {2.83333340e+01f, 6.12000000e+02f},
1929 {5.00000000e+00f, 6.12000000e+02f}}}},
1930 /* Figure 15. */
1931 {SEGMENT_BEZIER, {{{2.00000000e+01f, 6.65333313e+02f},
1932 {2.66666660e+01f, 6.92000000e+02f},
1933 {4.00000000e+01f, 6.92000000e+02f}}}},
1934 {SEGMENT_BEZIER, {{{5.33333321e+01f, 6.92000000e+02f},
1935 {6.00000000e+01f, 6.65333313e+02f},
1936 {6.00000000e+01f, 6.12000000e+02f}}}},
1937 {SEGMENT_BEZIER, {{{6.00000000e+01f, 5.58666687e+02f},
1938 {5.33333321e+01f, 5.32000000e+02f},
1939 {4.00000000e+01f, 5.32000000e+02f}}}},
1940 {SEGMENT_BEZIER, {{{2.66666660e+01f, 5.32000000e+02f},
1941 {2.00000000e+01f, 5.58666687e+02f},
1942 {2.00000000e+01f, 6.12000000e+02f}}}},
1943 /* Figure 16. */
1944 {SEGMENT_BEZIER, {{{1.91750427e+02f, 1.27275856e+02f},
1945 {2.08249573e+02f, 1.27275856e+02f},
1946 {2.24748734e+02f, 6.12792168e+01f}}}},
1947 {SEGMENT_BEZIER, {{{2.08249573e+02f, 1.27275856e+02f},
1948 {2.08249573e+02f, 1.93272476e+02f},
1949 {2.24748734e+02f, 2.59269104e+02f}}}},
1950 {SEGMENT_BEZIER, {{{2.08249573e+02f, 1.93272476e+02f},
1951 {1.91750427e+02f, 1.93272476e+02f},
1952 {1.75251266e+02f, 2.59269104e+02f}}}},
1953 {SEGMENT_BEZIER, {{{1.91750427e+02f, 1.93272476e+02f},
1954 {1.91750427e+02f, 1.27275856e+02f},
1955 {1.75251266e+02f, 6.12792168e+01f}}}},
1956 /* Figure 17. */
1957 {SEGMENT_BEZIER, {{{1.95285950e+02f, 6.59932632e+01f},
1958 {2.04714050e+02f, 6.59932632e+01f},
1959 {2.14142136e+02f, 1.03705627e+02f}}}},
1960 {SEGMENT_BEZIER, {{{2.23570221e+02f, 1.41417984e+02f},
1961 {2.23570221e+02f, 1.79130356e+02f},
1962 {2.14142136e+02f, 2.16842712e+02f}}}},
1963 {SEGMENT_BEZIER, {{{2.04714050e+02f, 2.54555069e+02f},
1964 {1.95285950e+02f, 2.54555069e+02f},
1965 {1.85857864e+02f, 2.16842712e+02f}}}},
1966 {SEGMENT_BEZIER, {{{1.76429779e+02f, 1.79130356e+02f},
1967 {1.76429779e+02f, 1.41417984e+02f},
1968 {1.85857864e+02f, 1.03705627e+02f}}}},
1969 /* Figure 18. */
1970 {SEGMENT_BEZIER, {{{1.11847351e+02f, 4.46888092e+02f},
1971 {1.11847351e+02f, 5.12884705e+02f},
1972 {9.53481979e+01f, 5.78881348e+02f}}}},
1973 {SEGMENT_BEZIER, {{{1.11847351e+02f, 5.12884705e+02f},
1974 {1.28346512e+02f, 5.12884705e+02f},
1975 {1.44845673e+02f, 5.78881348e+02f}}}},
1976 {SEGMENT_BEZIER, {{{1.28346512e+02f, 5.12884705e+02f},
1977 {1.28346512e+02f, 4.46888092e+02f},
1978 {1.44845673e+02f, 3.80891479e+02f}}}},
1979 {SEGMENT_BEZIER, {{{1.28346512e+02f, 4.46888092e+02f},
1980 {1.11847351e+02f, 4.46888092e+02f},
1981 {9.53481979e+01f, 3.80891479e+02f}}}},
1982 /* Figure 19. */
1983 {SEGMENT_BEZIER, {{{9.65267105e+01f, 4.61030243e+02f},
1984 {9.65267105e+01f, 4.98742584e+02f},
1985 {1.05954803e+02f, 5.36454956e+02f}}}},
1986 {SEGMENT_BEZIER, {{{1.15382889e+02f, 5.74167297e+02f},
1987 {1.24810982e+02f, 5.74167297e+02f},
1988 {1.34239075e+02f, 5.36454956e+02f}}}},
1989 {SEGMENT_BEZIER, {{{1.43667160e+02f, 4.98742584e+02f},
1990 {1.43667160e+02f, 4.61030243e+02f},
1991 {1.34239075e+02f, 4.23317871e+02f}}}},
1992 {SEGMENT_BEZIER, {{{1.24810982e+02f, 3.85605499e+02f},
1993 {1.15382889e+02f, 3.85605499e+02f},
1994 {1.05954803e+02f, 4.23317871e+02f}}}},
1995 /* Figure 20. */
1996 {SEGMENT_LINE, {{{ 40.0f, 20.0f}}}},
1997 {SEGMENT_LINE, {{{ 75.0f, 160.0f}}}},
1998 {SEGMENT_LINE, {{{ 40.0f, 300.0f}}}},
1999 {SEGMENT_LINE, {{{ 5.0f, 160.0f}}}},
2000 /* Figure 21. */
2001 {SEGMENT_LINE, {{{ 40.0f, 80.0f}}}},
2002 {SEGMENT_LINE, {{{ 60.0f, 160.0f}}}},
2003 {SEGMENT_LINE, {{{ 40.0f, 240.0f}}}},
2004 {SEGMENT_LINE, {{{ 20.0f, 160.0f}}}},
2005 /* Figure 22. */
2006 {SEGMENT_LINE, {{{ 40.0f, 752.0f}}}},
2007 {SEGMENT_LINE, {{{ 75.0f, 612.0f}}}},
2008 {SEGMENT_LINE, {{{ 40.0f, 472.0f}}}},
2009 {SEGMENT_LINE, {{{ 5.0f, 612.0f}}}},
2010 /* Figure 23. */
2011 {SEGMENT_LINE, {{{ 40.0f, 692.0f}}}},
2012 {SEGMENT_LINE, {{{ 60.0f, 612.0f}}}},
2013 {SEGMENT_LINE, {{{ 40.0f, 532.0f}}}},
2014 {SEGMENT_LINE, {{{ 20.0f, 612.0f}}}},
2015 /* Figure 24. */
2016 {SEGMENT_LINE, {{{2.03125019e+01f, 1.51250000e+02f}}}},
2017 {SEGMENT_LINE, {{{3.12500019e+01f, 1.25000008e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2018 {SEGMENT_LINE, {{{3.78125000e+01f, 8.12500076e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2019 {SEGMENT_LINE, {{{4.00000000e+01f, 2.00000000e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2020 {SEGMENT_LINE, {{{4.21875000e+01f, 8.12500076e+01f}}}},
2021 {SEGMENT_LINE, {{{4.87500000e+01f, 1.25000008e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2022 {SEGMENT_LINE, {{{5.96875000e+01f, 1.51250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2023 {SEGMENT_LINE, {{{7.50000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2024 {SEGMENT_LINE, {{{5.96875000e+01f, 1.68750000e+02f}}}},
2025 {SEGMENT_LINE, {{{4.87500000e+01f, 1.95000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2026 {SEGMENT_LINE, {{{4.21875000e+01f, 2.38750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2027 {SEGMENT_LINE, {{{4.00000000e+01f, 3.00000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2028 {SEGMENT_LINE, {{{3.78125000e+01f, 2.38750000e+02f}}}},
2029 {SEGMENT_LINE, {{{3.12500019e+01f, 1.95000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2030 {SEGMENT_LINE, {{{2.03125019e+01f, 1.68750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2031 {SEGMENT_LINE, {{{5.00000000e+00f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2032 /* Figure 25. */
2033 {SEGMENT_LINE, {{{2.50000000e+01f, 1.00000000e+02f}}}},
2034 {SEGMENT_LINE, {{{4.00000000e+01f, 8.00000000e+01f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2035 {SEGMENT_LINE, {{{5.50000000e+01f, 1.00000000e+02f}}}},
2036 {SEGMENT_LINE, {{{6.00000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2037 {SEGMENT_LINE, {{{5.50000000e+01f, 2.20000000e+02f}}}},
2038 {SEGMENT_LINE, {{{4.00000000e+01f, 2.40000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2039 {SEGMENT_LINE, {{{2.50000000e+01f, 2.20000000e+02f}}}},
2040 {SEGMENT_LINE, {{{2.00000000e+01f, 1.60000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2041 /* Figure 26. */
2042 {SEGMENT_LINE, {{{2.03125019e+01f, 6.20750000e+02f}}}},
2043 {SEGMENT_LINE, {{{3.12500019e+01f, 6.47000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2044 {SEGMENT_LINE, {{{3.78125000e+01f, 6.90750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2045 {SEGMENT_LINE, {{{4.00000000e+01f, 7.52000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2046 {SEGMENT_LINE, {{{4.21875000e+01f, 6.90750000e+02f}}}},
2047 {SEGMENT_LINE, {{{4.87500000e+01f, 6.47000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2048 {SEGMENT_LINE, {{{5.96875000e+01f, 6.20750000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2049 {SEGMENT_LINE, {{{7.50000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2050 {SEGMENT_LINE, {{{5.96875000e+01f, 6.03250000e+02f}}}},
2051 {SEGMENT_LINE, {{{4.87500000e+01f, 5.77000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2052 {SEGMENT_LINE, {{{4.21875000e+01f, 5.33250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2053 {SEGMENT_LINE, {{{4.00000000e+01f, 4.72000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2054 {SEGMENT_LINE, {{{3.78125000e+01f, 5.33250000e+02f}}}},
2055 {SEGMENT_LINE, {{{3.12500019e+01f, 5.77000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2056 {SEGMENT_LINE, {{{2.03125019e+01f, 6.03250000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2057 {SEGMENT_LINE, {{{5.00000000e+00f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2058 /* Figure 27. */
2059 {SEGMENT_LINE, {{{2.50000000e+01f, 6.72000000e+02f}}}},
2060 {SEGMENT_LINE, {{{4.00000000e+01f, 6.92000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2061 {SEGMENT_LINE, {{{5.50000000e+01f, 6.72000000e+02f}}}},
2062 {SEGMENT_LINE, {{{6.00000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2063 {SEGMENT_LINE, {{{5.50000000e+01f, 5.52000000e+02f}}}},
2064 {SEGMENT_LINE, {{{4.00000000e+01f, 5.32000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2065 {SEGMENT_LINE, {{{2.50000000e+01f, 5.52000000e+02f}}}},
2066 {SEGMENT_LINE, {{{2.00000000e+01f, 6.12000000e+02f}}}, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN},
2067 /* Figure 28. */
2068 {SEGMENT_LINE, {{{ 75.0f, 300.0f}}}},
2069 {SEGMENT_LINE, {{{ 5.0f, 300.0f}}}},
2071 static const struct expected_geometry_figure expected_figures[] =
2073 /* 0 */
2074 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 15.0f, 20.0f}, 15, &expected_segments[0]},
2075 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {155.0f, 300.0f}, 11, &expected_segments[15]},
2076 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {165.0f, 20.0f}, 3, &expected_segments[26]},
2077 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {225.0f, 60.0f}, 3, &expected_segments[29]},
2078 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {215.0f, 220.0f}, 3, &expected_segments[32]},
2079 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {195.0f, 180.0f}, 3, &expected_segments[35]},
2080 /* 6 */
2081 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 95.0f, 620.0f}, 15, &expected_segments[38]},
2082 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {235.0f, 340.0f}, 11, &expected_segments[53]},
2083 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {245.0f, 620.0f}, 3, &expected_segments[64]},
2084 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {305.0f, 580.0f}, 3, &expected_segments[67]},
2085 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {295.0f, 420.0f}, 3, &expected_segments[70]},
2086 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {275.0f, 460.0f}, 3, &expected_segments[73]},
2087 /* 12 */
2088 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 4, &expected_segments[76]},
2089 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 4, &expected_segments[80]},
2090 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 4, &expected_segments[84]},
2091 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 4, &expected_segments[88]},
2092 /* 16 */
2093 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
2094 {1.75251266e+02f, 6.12792168e+01f}, 4, &expected_segments[92]},
2095 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
2096 {1.85857864e+02f, 1.03705627e+02f}, 4, &expected_segments[96]},
2097 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
2098 {9.53481979e+01f, 3.80891479e+02f}, 4, &expected_segments[100]},
2099 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED,
2100 {1.05954803e+02f, 4.23317871e+02f}, 4, &expected_segments[104]},
2101 /* 20 */
2102 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 4, &expected_segments[108]},
2103 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 4, &expected_segments[112]},
2104 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 4, &expected_segments[116]},
2105 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 4, &expected_segments[120]},
2106 /* 24 */
2107 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 160.0f}, 16, &expected_segments[124]},
2108 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 160.0f}, 8, &expected_segments[140]},
2109 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 5.0f, 612.0f}, 16, &expected_segments[148]},
2110 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 20.0f, 612.0f}, 8, &expected_segments[164]},
2111 /* 28 */
2112 {D2D1_FIGURE_BEGIN_HOLLOW, D2D1_FIGURE_END_OPEN, { 40.0f, 20.0f}, 2, &expected_segments[172]},
2115 if (!(device = create_device()))
2117 skip("Failed to create device, skipping tests.\n");
2118 return;
2120 window = create_window();
2121 swapchain = create_swapchain(device, window, TRUE);
2122 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2123 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2124 rt = create_render_target(surface);
2125 ok(!!rt, "Failed to create render target.\n");
2126 ID2D1RenderTarget_GetFactory(rt, &factory);
2128 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
2129 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2130 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
2131 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
2132 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2134 /* Close() when closed. */
2135 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2136 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2137 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2138 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2139 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2140 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2141 hr = ID2D1PathGeometry_Open(geometry, &sink);
2142 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2143 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2144 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2145 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2146 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2147 hr = ID2D1GeometrySink_Close(sink);
2148 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2149 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2150 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2151 ok(!count, "Got unexpected figure count %u.\n", count);
2152 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2153 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2154 ok(!count, "Got unexpected segment count %u.\n", count);
2155 hr = ID2D1GeometrySink_Close(sink);
2156 ok(hr == D2DERR_WRONG_STATE, "Got unexpected 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, "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, "Got unexpected segment count %u.\n", count);
2164 ID2D1PathGeometry_Release(geometry);
2166 /* Open() when closed. */
2167 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2168 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2169 hr = ID2D1PathGeometry_Open(geometry, &sink);
2170 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2171 hr = ID2D1GeometrySink_Close(sink);
2172 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2173 ID2D1GeometrySink_Release(sink);
2174 hr = ID2D1PathGeometry_Open(geometry, &sink);
2175 ok(hr == D2DERR_WRONG_STATE, "Got unexpected 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, "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 ok(!count, "Got unexpected segment count %u.\n", count);
2182 ID2D1PathGeometry_Release(geometry);
2184 /* Open() when open. */
2185 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2186 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2187 hr = ID2D1PathGeometry_Open(geometry, &sink);
2188 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2189 hr = ID2D1PathGeometry_Open(geometry, &tmp_sink);
2190 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2191 hr = ID2D1GeometrySink_Close(sink);
2192 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2193 ID2D1GeometrySink_Release(sink);
2194 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2195 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2196 ok(!count, "Got unexpected figure count %u.\n", count);
2197 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2198 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2199 ok(!count, "Got unexpected segment count %u.\n", count);
2200 ID2D1PathGeometry_Release(geometry);
2202 /* BeginFigure() without EndFigure(). */
2203 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2204 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2205 hr = ID2D1PathGeometry_Open(geometry, &sink);
2206 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2207 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2208 hr = ID2D1GeometrySink_Close(sink);
2209 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2210 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2211 hr = ID2D1GeometrySink_Close(sink);
2212 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2213 ID2D1GeometrySink_Release(sink);
2214 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2215 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2216 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2217 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2218 ID2D1PathGeometry_Release(geometry);
2220 /* EndFigure() without BeginFigure(). */
2221 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2222 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2223 hr = ID2D1PathGeometry_Open(geometry, &sink);
2224 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2225 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2226 hr = ID2D1GeometrySink_Close(sink);
2227 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2228 ID2D1GeometrySink_Release(sink);
2229 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2230 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2231 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2232 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2233 ID2D1PathGeometry_Release(geometry);
2235 /* BeginFigure()/EndFigure() mismatch. */
2236 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2237 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2238 hr = ID2D1PathGeometry_Open(geometry, &sink);
2239 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2240 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2241 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2242 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2243 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2244 hr = ID2D1GeometrySink_Close(sink);
2245 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2246 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2247 hr = ID2D1GeometrySink_Close(sink);
2248 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2249 ID2D1GeometrySink_Release(sink);
2250 ID2D1PathGeometry_Release(geometry);
2252 /* AddLine() outside BeginFigure()/EndFigure(). */
2253 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2254 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2255 hr = ID2D1PathGeometry_Open(geometry, &sink);
2256 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2257 ID2D1GeometrySink_AddLine(sink, point);
2258 hr = ID2D1GeometrySink_Close(sink);
2259 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2260 ID2D1GeometrySink_AddLine(sink, point);
2261 ID2D1GeometrySink_Release(sink);
2262 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2263 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2264 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2265 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2266 ID2D1PathGeometry_Release(geometry);
2268 /* Empty figure. */
2269 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2270 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2271 hr = ID2D1PathGeometry_Open(geometry, &sink);
2272 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2273 set_point(&point, 123.0f, 456.0f);
2274 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2275 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2276 hr = ID2D1GeometrySink_Close(sink);
2277 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2278 ID2D1GeometrySink_Release(sink);
2279 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2280 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2281 ok(count == 1, "Got unexpected figure count %u.\n", count);
2282 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2283 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2284 ok(count == 1, "Got unexpected segment count %u.\n", count);
2286 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
2287 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
2288 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
2289 match = compare_rect(&rect, 123.0f, 456.0f, 123.0f, 456.0f, 0);
2290 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2291 rect.left, rect.top, rect.right, rect.bottom);
2293 set_matrix_identity(&matrix);
2294 translate_matrix(&matrix, 80.0f, 640.0f);
2295 scale_matrix(&matrix, 2.0f, 0.5f);
2296 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
2297 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
2298 match = compare_rect(&rect, 326.0f, 868.0f, 326.0f, 868.0f, 0);
2299 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2300 rect.left, rect.top, rect.right, rect.bottom);
2302 ID2D1PathGeometry_Release(geometry);
2304 /* Close right after Open(). */
2305 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2306 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2308 /* Not open yet. */
2309 set_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f);
2310 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
2311 ok(hr == D2DERR_WRONG_STATE, "Unexpected hr %#x.\n", hr);
2312 match = compare_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0);
2313 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2314 rect.left, rect.top, rect.right, rect.bottom);
2316 hr = ID2D1PathGeometry_Open(geometry, &sink);
2317 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2319 /* Open, not closed. */
2320 set_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f);
2321 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
2322 ok(hr == D2DERR_WRONG_STATE, "Unexpected hr %#x.\n", hr);
2323 match = compare_rect(&rect, 1.0f, 2.0f, 3.0f, 4.0f, 0);
2324 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2325 rect.left, rect.top, rect.right, rect.bottom);
2327 hr = ID2D1GeometrySink_Close(sink);
2328 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2329 ID2D1GeometrySink_Release(sink);
2330 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2331 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2332 ok(count == 0, "Got unexpected figure count %u.\n", count);
2333 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2334 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2335 ok(count == 0, "Got unexpected segment count %u.\n", count);
2337 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
2338 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
2339 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
2340 ok(rect.left > rect.right && rect.top > rect.bottom,
2341 "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom);
2343 set_matrix_identity(&matrix);
2344 translate_matrix(&matrix, 10.0f, 20.0f);
2345 scale_matrix(&matrix, 10.0f, 20.0f);
2346 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
2347 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
2348 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
2349 ok(rect.left > rect.right && rect.top > rect.bottom,
2350 "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n", rect.left, rect.top, rect.right, rect.bottom);
2352 ID2D1PathGeometry_Release(geometry);
2354 /* GetBounds() with bezier segments. */
2355 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2356 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2357 hr = ID2D1PathGeometry_Open(geometry, &sink);
2358 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2359 fill_geometry_sink_bezier(sink);
2360 hr = ID2D1GeometrySink_Close(sink);
2361 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2362 ID2D1GeometrySink_Release(sink);
2364 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
2365 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
2366 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
2367 match = compare_rect(&rect, 5.0f, 20.0f, 75.0f, 752.0f, 0);
2368 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2369 rect.left, rect.top, rect.right, rect.bottom);
2371 set_matrix_identity(&matrix);
2372 translate_matrix(&matrix, 80.0f, 640.0f);
2373 scale_matrix(&matrix, 2.0f, 0.5f);
2374 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
2375 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
2376 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
2377 match = compare_rect(&rect, 90.0f, 650.0f, 230.0f, 1016.0f, 0);
2378 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2379 rect.left, rect.top, rect.right, rect.bottom);
2381 ID2D1PathGeometry_Release(geometry);
2383 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2384 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2385 hr = ID2D1PathGeometry_Open(geometry, &sink);
2386 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2387 /* The fillmode that's used is the last one set before the sink is closed. */
2388 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
2389 fill_geometry_sink(sink);
2390 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
2391 hr = ID2D1GeometrySink_Close(sink);
2392 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2393 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2394 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2395 ok(count == 6, "Got unexpected figure count %u.\n", count);
2396 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2397 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2398 /* Intersections don't create extra segments. */
2399 ok(count == 44, "Got unexpected segment count %u.\n", count);
2400 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
2401 ID2D1GeometrySink_Release(sink);
2403 geometry_sink_init(&simplify_sink);
2404 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2405 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2406 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2407 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[0], 0);
2408 geometry_sink_cleanup(&simplify_sink);
2409 geometry_sink_init(&simplify_sink);
2410 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2411 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2412 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2413 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[0], 0);
2414 geometry_sink_cleanup(&simplify_sink);
2416 set_matrix_identity(&matrix);
2417 translate_matrix(&matrix, 80.0f, 640.0f);
2418 scale_matrix(&matrix, 1.0f, -1.0f);
2419 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
2420 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
2422 geometry_sink_init(&simplify_sink);
2423 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2424 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2425 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2426 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[6], 0);
2427 geometry_sink_cleanup(&simplify_sink);
2429 ID2D1TransformedGeometry_GetSourceGeometry(transformed_geometry, &tmp_geometry);
2430 ok(tmp_geometry == (ID2D1Geometry *)geometry,
2431 "Got unexpected source geometry %p, expected %p.\n", tmp_geometry, geometry);
2432 ID2D1TransformedGeometry_GetTransform(transformed_geometry, &tmp_matrix);
2433 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
2434 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
2435 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
2436 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
2437 geometry_sink_init(&simplify_sink);
2438 hr = ID2D1Geometry_Simplify(tmp_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2439 &tmp_matrix, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2440 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2441 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 6, &expected_figures[6], 0);
2442 geometry_sink_cleanup(&simplify_sink);
2443 ID2D1Geometry_Release(tmp_geometry);
2445 ID2D1RenderTarget_BeginDraw(rt);
2446 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
2447 ID2D1RenderTarget_Clear(rt, &color);
2448 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
2449 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2450 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2451 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2452 match = compare_surface(surface, "3aace1b22aae111cb577614fed16e4eb1650dba5");
2453 ok(match, "Surface does not match.\n");
2455 /* Edge test. */
2456 set_point(&point, 94.0f, 620.0f);
2457 contains = TRUE;
2458 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, NULL, 0.0f, &contains);
2459 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
2460 ok(!contains, "Got unexpected contains %#x.\n", contains);
2462 set_point(&point, 95.0f, 620.0f);
2463 contains = FALSE;
2464 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, NULL, 0.0f, &contains);
2465 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
2466 ok(contains == TRUE, "Got unexpected contains %#x.\n", contains);
2468 /* With transformation matrix. */
2469 set_matrix_identity(&matrix);
2470 translate_matrix(&matrix, -10.0f, 0.0f);
2471 set_point(&point, 85.0f, 620.0f);
2472 contains = FALSE;
2473 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, &matrix, 0.0f, &contains);
2474 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
2475 ok(contains == TRUE, "Got unexpected contains %#x.\n", contains);
2477 ID2D1TransformedGeometry_Release(transformed_geometry);
2478 ID2D1PathGeometry_Release(geometry);
2480 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2481 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2482 hr = ID2D1PathGeometry_Open(geometry, &sink);
2483 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2484 fill_geometry_sink(sink);
2485 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
2486 hr = ID2D1GeometrySink_Close(sink);
2487 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2488 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2489 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2490 ok(count == 6, "Got unexpected figure count %u.\n", count);
2491 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2492 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2493 ok(count == 44, "Got unexpected segment count %u.\n", count);
2494 ID2D1GeometrySink_Release(sink);
2496 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
2497 hr = ID2D1PathGeometry_GetBounds(geometry, NULL, &rect);
2498 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
2499 match = compare_rect(&rect, 5.0f, 20.0f, 235.0f, 300.0f, 0);
2500 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2501 rect.left, rect.top, rect.right, rect.bottom);
2503 set_matrix_identity(&matrix);
2504 translate_matrix(&matrix, 100.0f, 50.0f);
2505 scale_matrix(&matrix, 2.0f, 1.5f);
2506 rotate_matrix(&matrix, M_PI / 4.0f);
2507 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
2508 hr = ID2D1PathGeometry_GetBounds(geometry, &matrix, &rect);
2509 ok(SUCCEEDED(hr), "Failed to get geometry bounds, hr %#x.\n", hr);
2510 match = compare_rect(&rect, -3.17192993e+02f, 8.71231079e+01f, 4.04055908e+02f, 6.17453125e+02f, 1);
2511 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2512 rect.left, rect.top, rect.right, rect.bottom);
2514 geometry_sink_init(&simplify_sink);
2515 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2516 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2517 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2518 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 6, &expected_figures[0], 0);
2519 geometry_sink_cleanup(&simplify_sink);
2521 set_matrix_identity(&matrix);
2522 translate_matrix(&matrix, 320.0f, 320.0f);
2523 scale_matrix(&matrix, -1.0f, 1.0f);
2524 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
2525 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
2527 ID2D1RenderTarget_BeginDraw(rt);
2528 ID2D1RenderTarget_Clear(rt, &color);
2529 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
2530 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2531 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2532 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2533 match = compare_surface(surface, "bfb40a1f007694fa07dbd3b854f3f5d9c3e1d76b");
2534 ok(match, "Surface does not match.\n");
2535 ID2D1TransformedGeometry_Release(transformed_geometry);
2536 ID2D1PathGeometry_Release(geometry);
2538 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2539 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2540 hr = ID2D1PathGeometry_Open(geometry, &sink);
2541 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2542 fill_geometry_sink_bezier(sink);
2543 hr = ID2D1GeometrySink_Close(sink);
2544 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2545 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2546 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2547 ok(count == 4, "Got unexpected figure count %u.\n", count);
2548 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2549 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2550 ok(count == 20, "Got unexpected segment count %u.\n", count);
2551 ID2D1GeometrySink_Release(sink);
2553 geometry_sink_init(&simplify_sink);
2554 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2555 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2556 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2557 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[12], 1);
2558 geometry_sink_cleanup(&simplify_sink);
2559 geometry_sink_init(&simplify_sink);
2560 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2561 NULL, 100.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2562 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2563 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[20], 1);
2564 geometry_sink_cleanup(&simplify_sink);
2565 geometry_sink_init(&simplify_sink);
2566 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2567 NULL, 10.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2568 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2569 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[24], 1);
2570 geometry_sink_cleanup(&simplify_sink);
2572 set_matrix_identity(&matrix);
2573 scale_matrix(&matrix, 0.5f, 2.0f);
2574 translate_matrix(&matrix, 400.0f, -33.0f);
2575 rotate_matrix(&matrix, M_PI / 4.0f);
2576 scale_matrix(&matrix, 2.0f, 0.5f);
2577 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
2578 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
2580 geometry_sink_init(&simplify_sink);
2581 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2582 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2583 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2584 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 4, &expected_figures[16], 4);
2585 geometry_sink_cleanup(&simplify_sink);
2587 ID2D1RenderTarget_BeginDraw(rt);
2588 ID2D1RenderTarget_Clear(rt, &color);
2589 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
2590 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2591 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2592 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2593 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
2594 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
2595 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
2596 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
2597 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
2598 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
2599 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
2600 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
2601 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
2602 ok(match, "Figure does not match.\n");
2603 match = compare_figure(surface, 0, 226, 160, 160, 0xff652e89, 64,
2604 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
2605 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
2606 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
2607 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
2608 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
2609 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
2610 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
2611 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
2612 ok(match, "Figure does not match.\n");
2613 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
2614 "gVQBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQEjDCMB7AECHhQeAu0BAxoYGgPvAQMWHhYD8QEDFCAU"
2615 "A/MBBBAkEAT0AQUOJw0F9QEGCioKBvcBBggsCAb4AQgFLgUI+QEJATIBCfsBCAIwAgj8AQcFLAUH"
2616 "/QEFCCgIBf4BBAwiDAT/AQIQHBAClwISlwIBPgGAAgI8Av8BAzwD/QEEPAT7AQY6BvkBBzoH+AEI"
2617 "OAj3AQk4CfYBCTgK9AELNgvzAQw2DPIBDDYM8QEONA7wAQ40DvABDjQO7wEPNA/uAQ80D+4BEDIQ"
2618 "7QERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewB"
2619 "ETIR7AERMhHsAREyEe0BEDIQ7gEQMw/uAQ80D+4BDzQP7wEONA7wAQ40DvEBDDYM8gEMNgzzAQs2"
2620 "C/QBCzcK9QEJOAn3AQg4CfcBBzoH+QEGOgb7AQU6BfwBBDwE/QEDPAP/AQE+AZkCDpkCAhIYEgKA"
2621 "AgMNIA0D/wEFCSYJBf4BBgYqBgf8AQgDLgMI+wFG+gEIAzADCPkBBwYuBgf3AQYKKgoG9gEFDCgM"
2622 "BfUBBBAlDwTzAQQSIhIE8QEDFh4WA/ABAhkaGQLvAQIcFhwC7QECIBAgAusBASgEKAHpAQFWAecB"
2623 "AVgB5QEBWgHAAgHhUgAA");
2624 ok(match, "Figure does not match.\n");
2625 match = compare_figure(surface, 160, 160, 320, 160, 0xff652e89, 64,
2626 "/VUB5QEBWAHnAQFWAekBAVQB6wECIQ8hAe0BAh0VHQLuAQIZGhkD7wEDFh4WA/EBBBMhEwPzAQQQ"
2627 "JQ8F9AEFDCgNBfUBBgoqCgb3AQcHLQcG+QEIBC8ECPkBPAEJ+wEIAy8CCP0BBgYrBQf9AQUJJgkF"
2628 "/wEDDSANBP8BAhEaEQKYAhAXAYACAT4BgAICPQL+AQM8BPwBBTsE+wEGOgb6AQc5B/gBCDgJ9gEJ"
2629 "OAn2AQo3CvQBCzcK8wEMNgzyAQ01DPIBDTUN8AEONA7wAQ40D+4BDzQP7gEQMw/uARAzEO0BEDIR"
2630 "7AERMhHsAREyEewBETIR7AERMhLrAREyEusBETIS6wERMhLrAREyEusBETIS6wERMhHsAREyEewB"
2631 "ETIR7QEQMhHtARAzEO0BEDMP7gEPNA/vAQ40D+8BDjQO8QENNQ3xAQ01DPMBCzYM8wELNwr1AQo3"
2632 "CvUBCTgJ9wEIOAn4AQc5B/kBBjoG+wEFOwT9AQM8BP4BAj0C/wEBPgGYAhAXAYACAhEaEQKAAgMN"
2633 "IA0E/gEFCSYJBf4BBgYrBQf8AQgDLwII+wE8AQn6AQgELwQI+AEHBy0HBvcBBgoqCgb2AQUNJw0F"
2634 "9AEEECQQBfIBBBMhEwPxAQMWHhYD8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB"
2635 "wAIBwlYA");
2636 ok(match, "Figure does not match.\n");
2637 ID2D1TransformedGeometry_Release(transformed_geometry);
2638 ID2D1PathGeometry_Release(geometry);
2640 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2641 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2642 hr = ID2D1PathGeometry_Open(geometry, &sink);
2643 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2644 fill_geometry_sink_bezier(sink);
2645 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
2646 hr = ID2D1GeometrySink_Close(sink);
2647 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2648 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2649 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2650 ok(count == 4, "Got unexpected figure count %u.\n", count);
2651 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2652 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2653 ok(count == 20, "Got unexpected segment count %u.\n", count);
2654 ID2D1GeometrySink_Release(sink);
2656 geometry_sink_init(&simplify_sink);
2657 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2658 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2659 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2660 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[12], 1);
2661 geometry_sink_cleanup(&simplify_sink);
2662 geometry_sink_init(&simplify_sink);
2663 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2664 NULL, 100.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2665 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2666 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[20], 1);
2667 geometry_sink_cleanup(&simplify_sink);
2668 geometry_sink_init(&simplify_sink);
2669 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2670 NULL, 10.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2671 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2672 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_WINDING, 4, &expected_figures[24], 1);
2673 geometry_sink_cleanup(&simplify_sink);
2675 set_matrix_identity(&matrix);
2676 scale_matrix(&matrix, 0.5f, 2.0f);
2677 translate_matrix(&matrix, 127.0f, 80.0f);
2678 rotate_matrix(&matrix, M_PI / -4.0f);
2679 scale_matrix(&matrix, 2.0f, 0.5f);
2680 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
2681 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
2683 ID2D1RenderTarget_BeginDraw(rt);
2684 ID2D1RenderTarget_Clear(rt, &color);
2685 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
2686 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
2687 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2688 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2689 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
2690 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
2691 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
2692 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
2693 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
2694 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
2695 ok(match, "Figure does not match.\n");
2696 match = compare_figure(surface, 0, 226, 160, 160, 0xff652e89, 64,
2697 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
2698 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
2699 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
2700 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
2701 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
2702 ok(match, "Figure does not match.\n");
2703 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
2704 "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQIhDiIB7QECHRUdAu4BAhkaGQPvAQMWHhYD8QEEEyET"
2705 "A/MBBBAkEAT1AQUMKA0F9QEGCioKBvcBBwctBwb5AQgELwQI+QEJATIBCfsBRP0BQ/0BQv8BQf8B"
2706 "QIECP4ACQIACQf4BQ/wBRPsBRvoBR/gBSPcBSvYBS/QBTPMBTvIBTvIBT/ABUPABUe4BUu4BUu4B"
2707 "U+0BU+wBVOwBVOwBVOwBVOwBVesBVesBVesBVesBVOwBVOwBVOwBVO0BU+0BU+0BUu4BUu8BUe8B"
2708 "UPEBT/EBTvIBTvMBTPUBS/UBSvcBSfcBSPkBRvsBRP0BQ/4BQf8BQIECP4ACQIACQf4BQv4BQ/wB"
2709 "RPsBCQEyAQn6AQgELwQI+AEHBy0GB/cBBgoqCgb2AQUMKA0F9AEEECUPBPMBBBIiEwPxAQMWHhYD"
2710 "8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB5QEBWgHAAgEA");
2711 ok(match, "Figure does not match.\n");
2712 match = compare_figure(surface, 160, 160, 320, 160, 0xff652e89, 64,
2713 "gVQBXAHjAQFaAeUBAVgB5wEBVgHpAQEpAikB6wECIBAgAu0BAhwWHALvAQIZGhkC8AEDFh4WA/EB"
2714 "BBIiEgTzAQQPJRAE9QEFDCgMBfYBBgoqCgb3AQcGLgYH+QEIAzADCPoBRvsBRPwBRP0BQv8BQIAC"
2715 "QIECPoECQP8BQv0BRPwBRPsBRvkBSPgBSPcBSvUBTPQBTPMBTvIBTvEBUPABUO8BUu4BUu4BUu4B"
2716 "Uu0BVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVOwBVO0BUu4BUu4BUu8BUPAB"
2717 "UPABUPEBTvIBTvMBTPQBS/YBSvcBSPgBSPkBRvsBRP0BQv8BQIACQIECPoECQP8BQv4BQv0BRPwB"
2718 "RPsBCQEyAQn5AQgFLgUI+AEGCCwIBvcBBgoqCgb1AQUNJw4F9AEEECQQBPMBAxQgFAPxAQMWHhYD"
2719 "7wEDGhgaA+0BAh4UHgLsAQEjDCMB6wEBVAHpAQFWAecBAVgB5QEBWgGiVQAA");
2720 ok(match, "Figure does not match.\n");
2721 ID2D1TransformedGeometry_Release(transformed_geometry);
2722 ID2D1PathGeometry_Release(geometry);
2724 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2725 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2726 hr = ID2D1PathGeometry_Open(geometry, &sink);
2727 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2729 set_point(&point, 40.0f, 20.0f);
2730 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2731 line_to(sink, 75.0f, 300.0f);
2732 line_to(sink, 5.0f, 300.0f);
2733 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2735 set_point(&point, 40.0f, 290.0f);
2736 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
2737 line_to(sink, 55.0f, 160.0f);
2738 line_to(sink, 25.0f, 160.0f);
2739 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
2741 hr = ID2D1GeometrySink_Close(sink);
2742 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2743 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
2744 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
2745 ok(count == 2, "Got unexpected figure count %u.\n", count);
2746 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2747 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2748 ok(count == 6, "Got unexpected segment count %u.\n", count);
2749 ID2D1GeometrySink_Release(sink);
2751 ID2D1RenderTarget_BeginDraw(rt);
2752 ID2D1RenderTarget_Clear(rt, &color);
2753 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
2754 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2755 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2756 match = compare_surface(surface, "a875e68e0cb9c055927b1b50b879f90b24e38470");
2757 ok(match, "Surface does not match.\n");
2758 ID2D1PathGeometry_Release(geometry);
2760 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
2761 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
2762 hr = ID2D1PathGeometry_Open(geometry, &sink);
2763 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
2764 set_point(&point, 40.0f, 20.0f);
2765 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
2766 line_to(sink, 75.0f, 300.0f);
2767 line_to(sink, 5.0f, 300.0f);
2768 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
2769 hr = ID2D1GeometrySink_Close(sink);
2770 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
2771 ID2D1GeometrySink_Release(sink);
2772 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
2773 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
2774 ok(count == 2, "Got unexpected segment count %u.\n", count);
2776 geometry_sink_init(&simplify_sink);
2777 hr = ID2D1PathGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2778 NULL, 0.0f, &simplify_sink.ID2D1SimplifiedGeometrySink_iface);
2779 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2780 geometry_sink_check(&simplify_sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[28], 1);
2781 geometry_sink_cleanup(&simplify_sink);
2783 ID2D1PathGeometry_Release(geometry);
2785 ID2D1SolidColorBrush_Release(brush);
2786 ID2D1RenderTarget_Release(rt);
2787 refcount = ID2D1Factory_Release(factory);
2788 ok(!refcount, "Factory has %u references left.\n", refcount);
2789 IDXGISurface_Release(surface);
2790 IDXGISwapChain_Release(swapchain);
2791 ID3D10Device1_Release(device);
2792 DestroyWindow(window);
2795 static void test_rectangle_geometry(void)
2797 ID2D1TransformedGeometry *transformed_geometry;
2798 ID2D1RectangleGeometry *geometry;
2799 struct geometry_sink sink;
2800 D2D1_MATRIX_3X2_F matrix;
2801 D2D1_RECT_F rect, rect2;
2802 ID2D1Factory *factory;
2803 D2D1_POINT_2F point;
2804 BOOL contains;
2805 HRESULT hr;
2806 BOOL match;
2808 static const struct geometry_segment expected_segments[] =
2810 /* Figure 0. */
2811 {SEGMENT_LINE, {{{10.0f, 0.0f}}}},
2812 {SEGMENT_LINE, {{{10.0f, 20.0f}}}},
2813 {SEGMENT_LINE, {{{ 0.0f, 20.0f}}}},
2814 /* Figure 1. */
2815 {SEGMENT_LINE, {{{4.42705116e+01f, 1.82442951e+01f}}}},
2816 {SEGMENT_LINE, {{{7.95376282e+01f, 5.06049728e+01f}}}},
2817 {SEGMENT_LINE, {{{5.52671127e+01f, 6.23606796e+01f}}}},
2818 /* Figure 2. */
2819 {SEGMENT_LINE, {{{25.0f, 15.0f}}}},
2820 {SEGMENT_LINE, {{{25.0f, 55.0f}}}},
2821 {SEGMENT_LINE, {{{25.0f, 55.0f}}}},
2822 /* Figure 3. */
2823 {SEGMENT_LINE, {{{35.0f, 45.0f}}}},
2824 {SEGMENT_LINE, {{{35.0f, 45.0f}}}},
2825 {SEGMENT_LINE, {{{30.0f, 45.0f}}}},
2826 /* Figure 4. */
2827 {SEGMENT_LINE, {{{ 1.07179585e+01f, 2.23205078e+02f}}}},
2828 {SEGMENT_LINE, {{{-5.85640755e+01f, 2.73205078e+02f}}}},
2829 {SEGMENT_LINE, {{{-7.85640717e+01f, 2.29903809e+02f}}}},
2830 /* Figure 5. */
2831 {SEGMENT_LINE, {{{40.0f, 20.0f}}}},
2832 {SEGMENT_LINE, {{{40.0f, 40.0f}}}},
2833 {SEGMENT_LINE, {{{30.0f, 40.0f}}}},
2834 /* Figure 6. */
2835 {SEGMENT_LINE, {{{ 2.14359169e+01f, 0.0f}}}},
2836 {SEGMENT_LINE, {{{-1.17128151e+02f, 0.0f}}}},
2837 {SEGMENT_LINE, {{{-1.57128143e+02f, 0.0f}}}},
2838 /* Figure 7. */
2839 {SEGMENT_LINE, {{{0.0f, 1.11602539e+02f}}}},
2840 {SEGMENT_LINE, {{{0.0f, 1.36602539e+02f}}}},
2841 {SEGMENT_LINE, {{{0.0f, 1.14951904e+02f}}}},
2843 static const struct expected_geometry_figure expected_figures[] =
2845 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, { 0.0f, 0.0f}, 3, &expected_segments[0]},
2846 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {20.0f, 30.0f}, 3, &expected_segments[3]},
2847 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {25.0f, 15.0f}, 3, &expected_segments[6]},
2848 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {30.0f, 45.0f}, 3, &expected_segments[9]},
2849 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {-9.28203964e+00f, 1.79903809e+02f},
2850 3, &expected_segments[12]},
2851 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {30.0f, 20.0f}, 3, &expected_segments[15]},
2852 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {-1.85640793e+01f, 0.0f}, 3, &expected_segments[18]},
2853 {D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END_CLOSED, {0.0f, 8.99519043e+01f}, 3, &expected_segments[21]},
2856 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
2857 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2859 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
2860 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2861 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2862 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
2863 match = compare_rect(&rect2, 0.0f, 0.0f, 0.0f, 0.0f, 0);
2864 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2865 rect2.left, rect2.top, rect2.right, rect2.bottom);
2866 ID2D1RectangleGeometry_Release(geometry);
2868 set_rect(&rect, 50.0f, 0.0f, 40.0f, 100.0f);
2869 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2870 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2871 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
2872 match = compare_rect(&rect2, 50.0f, 0.0f, 40.0f, 100.0f, 0);
2873 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2874 rect2.left, rect2.top, rect2.right, rect2.bottom);
2875 ID2D1RectangleGeometry_Release(geometry);
2877 set_rect(&rect, 0.0f, 100.0f, 40.0f, 50.0f);
2878 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2879 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2880 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
2881 match = compare_rect(&rect2, 0.0f, 100.0f, 40.0f, 50.0f, 0);
2882 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2883 rect2.left, rect2.top, rect2.right, rect2.bottom);
2884 ID2D1RectangleGeometry_Release(geometry);
2886 set_rect(&rect, 50.0f, 100.0f, 40.0f, 50.0f);
2887 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2888 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2889 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
2890 match = compare_rect(&rect2, 50.0f, 100.0f, 40.0f, 50.0f, 0);
2891 ok(match, "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
2892 rect2.left, rect2.top, rect2.right, rect2.bottom);
2893 ID2D1RectangleGeometry_Release(geometry);
2895 set_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f);
2896 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2897 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
2899 /* Edge. */
2900 contains = FALSE;
2901 set_point(&point, 0.0f, 0.0f);
2902 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2903 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2904 ok(!!contains, "Got wrong hit test result %d.\n", contains);
2906 /* Within tolerance limit around corner. */
2907 contains = TRUE;
2908 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE, 0.0f);
2909 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2910 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2911 ok(!contains, "Got wrong hit test result %d.\n", contains);
2913 contains = FALSE;
2914 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE + 0.01f, 0.0f);
2915 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2916 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2917 ok(!!contains, "Got wrong hit test result %d.\n", contains);
2919 contains = TRUE;
2920 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE - 0.01f, 0.0f);
2921 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2922 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2923 ok(!contains, "Got wrong hit test result %d.\n", contains);
2925 contains = TRUE;
2926 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE, -D2D1_DEFAULT_FLATTENING_TOLERANCE);
2927 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2928 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2929 ok(!contains, "Got wrong hit test result %d.\n", contains);
2931 /* Inside. */
2932 contains = FALSE;
2933 set_point(&point, 5.0f, 5.0f);
2934 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
2935 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
2936 ok(!!contains, "Got wrong hit test result %d.\n", contains);
2938 /* Test GetBounds() and Simplify(). */
2939 hr = ID2D1RectangleGeometry_GetBounds(geometry, NULL, &rect);
2940 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2941 match = compare_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f, 0);
2942 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2943 rect.left, rect.top, rect.right, rect.bottom);
2944 geometry_sink_init(&sink);
2945 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2946 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2947 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2948 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[0], 0);
2949 geometry_sink_cleanup(&sink);
2950 geometry_sink_init(&sink);
2951 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2952 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2953 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2954 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[0], 0);
2955 geometry_sink_cleanup(&sink);
2957 set_matrix_identity(&matrix);
2958 translate_matrix(&matrix, 20.0f, 30.0f);
2959 scale_matrix(&matrix, 3.0f, 2.0f);
2960 rotate_matrix(&matrix, M_PI / -5.0f);
2961 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
2962 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2963 match = compare_rect(&rect, 2.00000000e+01f, 1.82442951e+01f, 7.95376282e+01f, 6.23606796e+01f, 0);
2964 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2965 rect.left, rect.top, rect.right, rect.bottom);
2966 geometry_sink_init(&sink);
2967 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
2968 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2969 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2970 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[1], 1);
2971 geometry_sink_cleanup(&sink);
2973 set_matrix_identity(&matrix);
2974 translate_matrix(&matrix, 25.0f, 15.0f);
2975 scale_matrix(&matrix, 0.0f, 2.0f);
2976 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
2977 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2978 match = compare_rect(&rect, 25.0f, 15.0f, 25.0f, 55.0f, 0);
2979 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2980 rect.left, rect.top, rect.right, rect.bottom);
2981 geometry_sink_init(&sink);
2982 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2983 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2984 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
2985 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[2], 0);
2986 geometry_sink_cleanup(&sink);
2988 set_matrix_identity(&matrix);
2989 translate_matrix(&matrix, 30.0f, 45.0f);
2990 scale_matrix(&matrix, 0.5f, 0.0f);
2991 hr = ID2D1RectangleGeometry_GetBounds(geometry, &matrix, &rect);
2992 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
2993 match = compare_rect(&rect, 30.0f, 45.0f, 35.0f, 45.0f, 0);
2994 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
2995 rect.left, rect.top, rect.right, rect.bottom);
2996 geometry_sink_init(&sink);
2997 hr = ID2D1RectangleGeometry_Simplify(geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
2998 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
2999 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3000 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[3], 0);
3001 geometry_sink_cleanup(&sink);
3003 set_matrix_identity(&matrix);
3004 scale_matrix(&matrix, 4.0f, 5.0f);
3005 rotate_matrix(&matrix, M_PI / 3.0f);
3006 translate_matrix(&matrix, 30.0f, 20.0f);
3007 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
3008 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
3010 ID2D1TransformedGeometry_GetBounds(transformed_geometry, NULL, &rect);
3011 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3012 match = compare_rect(&rect, -7.85640717e+01f, 1.79903809e+02f, 1.07179594e+01f, 2.73205078e+02f, 1);
3013 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3014 rect.left, rect.top, rect.right, rect.bottom);
3015 geometry_sink_init(&sink);
3016 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3017 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3018 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3019 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[4], 1);
3020 geometry_sink_cleanup(&sink);
3021 geometry_sink_init(&sink);
3022 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3023 NULL, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3024 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3025 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[4], 1);
3026 geometry_sink_cleanup(&sink);
3028 set_matrix_identity(&matrix);
3029 rotate_matrix(&matrix, M_PI / -3.0f);
3030 scale_matrix(&matrix, 0.25f, 0.2f);
3031 ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
3032 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3033 match = compare_rect(&rect, 30.0f, 20.0f, 40.0f, 40.0f, 2);
3034 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3035 rect.left, rect.top, rect.right, rect.bottom);
3036 geometry_sink_init(&sink);
3037 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES,
3038 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3039 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3040 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[5], 4);
3041 geometry_sink_cleanup(&sink);
3043 set_matrix_identity(&matrix);
3044 scale_matrix(&matrix, 2.0f, 0.0f);
3045 ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
3046 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3047 match = compare_rect(&rect, -1.57128143e+02f, 0.00000000e+00f, 2.14359188e+01f, 0.00000000e+00f, 1);
3048 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3049 rect.left, rect.top, rect.right, rect.bottom);
3050 geometry_sink_init(&sink);
3051 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3052 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3053 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3054 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[6], 1);
3055 geometry_sink_cleanup(&sink);
3057 set_matrix_identity(&matrix);
3058 scale_matrix(&matrix, 0.0f, 0.5f);
3059 ID2D1TransformedGeometry_GetBounds(transformed_geometry, &matrix, &rect);
3060 ok(SUCCEEDED(hr), "Failed to get bounds.\n");
3061 match = compare_rect(&rect, 0.00000000e+00f, 8.99519043e+01f, 0.00000000e+00, 1.36602539e+02f, 1);
3062 ok(match, "Got unexpected bounds {%.8e, %.8e, %.8e, %.8e}.\n",
3063 rect.left, rect.top, rect.right, rect.bottom);
3064 geometry_sink_init(&sink);
3065 hr = ID2D1TransformedGeometry_Simplify(transformed_geometry, D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
3066 &matrix, 0.0f, &sink.ID2D1SimplifiedGeometrySink_iface);
3067 ok(SUCCEEDED(hr), "Failed to simplify geometry, hr %#x.\n", hr);
3068 geometry_sink_check(&sink, D2D1_FILL_MODE_ALTERNATE, 1, &expected_figures[7], 1);
3069 geometry_sink_cleanup(&sink);
3071 ID2D1TransformedGeometry_Release(transformed_geometry);
3072 ID2D1RectangleGeometry_Release(geometry);
3073 ID2D1Factory_Release(factory);
3076 static void test_rounded_rectangle_geometry(void)
3078 ID2D1RoundedRectangleGeometry *geometry;
3079 D2D1_ROUNDED_RECT rect, rect2;
3080 ID2D1Factory *factory;
3081 HRESULT hr;
3083 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
3084 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3086 set_rounded_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
3087 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
3088 todo_wine
3089 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
3090 if (FAILED(hr))
3092 ID2D1Factory_Release(factory);
3093 return;
3096 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
3097 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
3098 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
3099 ID2D1RoundedRectangleGeometry_Release(geometry);
3101 /* X radius larger than half width. */
3102 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 30.0f, 5.0f);
3103 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
3104 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
3105 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
3106 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
3107 ID2D1RoundedRectangleGeometry_Release(geometry);
3109 /* Y radius larger than half height. */
3110 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 5.0f, 30.0f);
3111 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
3112 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
3113 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
3114 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
3115 ID2D1RoundedRectangleGeometry_Release(geometry);
3117 /* Both exceed rectangle size. */
3118 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 30.0f, 25.0f);
3119 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
3120 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
3121 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
3122 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
3123 ID2D1RoundedRectangleGeometry_Release(geometry);
3125 ID2D1Factory_Release(factory);
3128 static void test_bitmap_formats(void)
3130 D2D1_BITMAP_PROPERTIES bitmap_desc;
3131 IDXGISwapChain *swapchain;
3132 D2D1_SIZE_U size = {4, 4};
3133 ID2D1RenderTarget *rt;
3134 ID3D10Device1 *device;
3135 IDXGISurface *surface;
3136 ID2D1Bitmap *bitmap;
3137 unsigned int i, j;
3138 HWND window;
3139 HRESULT hr;
3141 static const struct
3143 DXGI_FORMAT format;
3144 DWORD mask;
3146 bitmap_formats[] =
3148 {DXGI_FORMAT_R32G32B32A32_FLOAT, 0x8a},
3149 {DXGI_FORMAT_R16G16B16A16_FLOAT, 0x8a},
3150 {DXGI_FORMAT_R16G16B16A16_UNORM, 0x8a},
3151 {DXGI_FORMAT_R8G8B8A8_TYPELESS, 0x00},
3152 {DXGI_FORMAT_R8G8B8A8_UNORM, 0x0a},
3153 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0x8a},
3154 {DXGI_FORMAT_R8G8B8A8_UINT, 0x00},
3155 {DXGI_FORMAT_R8G8B8A8_SNORM, 0x00},
3156 {DXGI_FORMAT_R8G8B8A8_SINT, 0x00},
3157 {DXGI_FORMAT_A8_UNORM, 0x06},
3158 {DXGI_FORMAT_B8G8R8A8_UNORM, 0x0a},
3159 {DXGI_FORMAT_B8G8R8X8_UNORM, 0x88},
3160 {DXGI_FORMAT_B8G8R8A8_TYPELESS, 0x00},
3161 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 0x8a},
3164 if (!(device = create_device()))
3166 skip("Failed to create device, skipping tests.\n");
3167 return;
3169 window = create_window();
3170 swapchain = create_swapchain(device, window, TRUE);
3171 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3172 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3173 rt = create_render_target(surface);
3174 ok(!!rt, "Failed to create render target.\n");
3176 bitmap_desc.dpiX = 96.0f;
3177 bitmap_desc.dpiY = 96.0f;
3178 for (i = 0; i < sizeof(bitmap_formats) / sizeof(*bitmap_formats); ++i)
3180 for (j = 0; j < 4; ++j)
3182 if ((bitmap_formats[i].mask & (0x80 | (1u << j))) == (0x80 | (1u << j)))
3183 continue;
3185 bitmap_desc.pixelFormat.format = bitmap_formats[i].format;
3186 bitmap_desc.pixelFormat.alphaMode = j;
3187 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
3188 if (bitmap_formats[i].mask & (1u << j))
3189 ok(hr == S_OK, "Got unexpected hr %#x, for format %#x/%#x.\n",
3190 hr, bitmap_formats[i].format, j);
3191 else
3192 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x, for format %#x/%#x.\n",
3193 hr, bitmap_formats[i].format, j);
3194 if (SUCCEEDED(hr))
3195 ID2D1Bitmap_Release(bitmap);
3199 ID2D1RenderTarget_Release(rt);
3200 IDXGISurface_Release(surface);
3201 IDXGISwapChain_Release(swapchain);
3202 ID3D10Device1_Release(device);
3203 DestroyWindow(window);
3206 static void test_alpha_mode(void)
3208 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
3209 D2D1_BITMAP_PROPERTIES bitmap_desc;
3210 ID2D1SolidColorBrush *color_brush;
3211 ID2D1BitmapBrush *bitmap_brush;
3212 IDXGISwapChain *swapchain;
3213 ID2D1RenderTarget *rt;
3214 ID3D10Device1 *device;
3215 IDXGISurface *surface;
3216 ID2D1Bitmap *bitmap;
3217 D2D1_COLOR_F color;
3218 D2D1_RECT_F rect;
3219 D2D1_SIZE_U size;
3220 ULONG refcount;
3221 HWND window;
3222 HRESULT hr;
3223 BOOL match;
3225 static const DWORD bitmap_data[] =
3227 0x7f7f0000, 0x7f7f7f00, 0x7f007f00, 0x7f007f7f,
3228 0x7f00007f, 0x7f7f007f, 0x7f000000, 0x7f404040,
3229 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f000000,
3230 0x7f7f7f7f, 0x7f000000, 0x7f000000, 0x7f000000,
3233 if (!(device = create_device()))
3235 skip("Failed to create device, skipping tests.\n");
3236 return;
3238 window = create_window();
3239 swapchain = create_swapchain(device, window, TRUE);
3240 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3241 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3242 rt = create_render_target(surface);
3243 ok(!!rt, "Failed to create render target.\n");
3245 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
3247 set_size_u(&size, 4, 4);
3248 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3249 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
3250 bitmap_desc.dpiX = 96.0f / 40.0f;
3251 bitmap_desc.dpiY = 96.0f / 30.0f;
3252 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3253 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3255 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
3256 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3257 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
3258 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
3259 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
3261 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
3262 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
3263 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3265 ID2D1RenderTarget_BeginDraw(rt);
3266 ID2D1RenderTarget_Clear(rt, NULL);
3267 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3268 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3269 match = compare_surface(surface, "48c41aff3a130a17ee210866b2ab7d36763934d5");
3270 ok(match, "Surface does not match.\n");
3272 ID2D1RenderTarget_BeginDraw(rt);
3273 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
3274 ID2D1RenderTarget_Clear(rt, &color);
3275 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3276 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3277 match = compare_surface(surface, "6487e683730fb5a77c1911388d00b04664c5c4e4");
3278 ok(match, "Surface does not match.\n");
3280 ID2D1RenderTarget_BeginDraw(rt);
3281 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
3282 ID2D1RenderTarget_Clear(rt, &color);
3283 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3284 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3285 match = compare_surface(surface, "7a35ba09e43cbaf591388ff1ef8de56157630c98");
3286 ok(match, "Surface does not match.\n");
3288 ID2D1RenderTarget_BeginDraw(rt);
3290 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
3291 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3292 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
3293 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
3294 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3295 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
3296 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
3297 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3299 ID2D1Bitmap_Release(bitmap);
3300 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3301 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3302 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3303 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
3305 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
3306 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
3307 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3308 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
3309 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
3310 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3311 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
3312 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
3313 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3315 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
3316 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3317 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
3318 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
3319 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3320 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
3321 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
3322 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3324 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3325 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3326 match = compare_surface(surface, "14f8ac64b70966c7c3c6281c59aaecdb17c3b16a");
3327 ok(match, "Surface does not match.\n");
3329 ID2D1RenderTarget_Release(rt);
3330 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3331 rt_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
3332 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
3333 rt_desc.dpiX = 0.0f;
3334 rt_desc.dpiY = 0.0f;
3335 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3336 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3337 rt = create_render_target_desc(surface, &rt_desc);
3338 ok(!!rt, "Failed to create render target.\n");
3340 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
3342 ID2D1Bitmap_Release(bitmap);
3343 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
3344 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3345 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3346 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
3348 ID2D1BitmapBrush_Release(bitmap_brush);
3349 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
3350 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3351 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
3352 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
3353 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
3355 ID2D1SolidColorBrush_Release(color_brush);
3356 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
3357 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
3358 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3360 ID2D1RenderTarget_BeginDraw(rt);
3361 ID2D1RenderTarget_Clear(rt, NULL);
3362 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3363 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3364 match = compare_surface(surface, "b44510bf2d2e61a8d7c0ad862de49a471f1fd13f");
3365 ok(match, "Surface does not match.\n");
3367 ID2D1RenderTarget_BeginDraw(rt);
3368 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
3369 ID2D1RenderTarget_Clear(rt, &color);
3370 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3371 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3372 match = compare_surface(surface, "2184f4a9198fc1de09ac85301b7a03eebadd9b81");
3373 ok(match, "Surface does not match.\n");
3375 ID2D1RenderTarget_BeginDraw(rt);
3376 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
3377 ID2D1RenderTarget_Clear(rt, &color);
3378 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3379 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3380 match = compare_surface(surface, "6527ec83b4039c895b50f9b3e144fe0cf90d1889");
3381 ok(match, "Surface does not match.\n");
3383 ID2D1RenderTarget_BeginDraw(rt);
3385 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
3386 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3387 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
3388 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
3389 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3390 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
3391 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
3392 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3394 ID2D1Bitmap_Release(bitmap);
3395 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3396 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3397 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3398 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
3400 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
3401 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
3402 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3403 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
3404 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
3405 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3406 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
3407 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
3408 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3410 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
3411 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3412 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
3413 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
3414 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3415 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
3416 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
3417 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3419 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3420 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3421 match = compare_surface(surface, "465f5a3190d7bde408b3206b4be939fb22f8a3d6");
3422 ok(match, "Surface does not match.\n");
3424 refcount = ID2D1Bitmap_Release(bitmap);
3425 ok(refcount == 1, "Bitmap has %u references left.\n", refcount);
3426 ID2D1SolidColorBrush_Release(color_brush);
3427 ID2D1BitmapBrush_Release(bitmap_brush);
3428 ID2D1RenderTarget_Release(rt);
3429 IDXGISurface_Release(surface);
3430 IDXGISwapChain_Release(swapchain);
3431 ID3D10Device1_Release(device);
3432 DestroyWindow(window);
3435 static void test_shared_bitmap(void)
3437 IDXGISwapChain *swapchain1, *swapchain2;
3438 IWICBitmap *wic_bitmap1, *wic_bitmap2;
3439 ID2D1GdiInteropRenderTarget *interop;
3440 D2D1_RENDER_TARGET_PROPERTIES desc;
3441 D2D1_BITMAP_PROPERTIES bitmap_desc;
3442 ID2D1RenderTarget *rt1, *rt2, *rt3;
3443 IDXGISurface *surface1, *surface2;
3444 ID2D1Factory *factory1, *factory2;
3445 ID3D10Device1 *device1, *device2;
3446 IWICImagingFactory *wic_factory;
3447 ID2D1Bitmap *bitmap1, *bitmap2;
3448 DXGI_SURFACE_DESC surface_desc;
3449 D2D1_SIZE_U size = {4, 4};
3450 IDXGISurface1 *surface3;
3451 HWND window1, window2;
3452 HRESULT hr;
3454 if (!(device1 = create_device()))
3456 skip("Failed to create device, skipping tests.\n");
3457 return;
3460 window1 = create_window();
3461 window2 = create_window();
3462 swapchain1 = create_swapchain(device1, window1, TRUE);
3463 swapchain2 = create_swapchain(device1, window2, TRUE);
3464 hr = IDXGISwapChain_GetBuffer(swapchain1, 0, &IID_IDXGISurface, (void **)&surface1);
3465 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3466 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
3467 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3469 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3470 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
3471 &IID_IWICImagingFactory, (void **)&wic_factory);
3472 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
3473 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
3474 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap1);
3475 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3476 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
3477 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap2);
3478 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3479 IWICImagingFactory_Release(wic_factory);
3481 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3482 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
3483 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3484 desc.dpiX = 0.0f;
3485 desc.dpiY = 0.0f;
3486 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3487 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3489 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3490 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3491 bitmap_desc.dpiX = 96.0f;
3492 bitmap_desc.dpiY = 96.0f;
3494 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory1);
3495 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3496 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
3497 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3499 /* DXGI surface render targets with the same device and factory. */
3500 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface1, &desc, &rt1);
3501 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3502 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
3503 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3505 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
3506 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3507 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3508 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3509 ID2D1Bitmap_Release(bitmap2);
3510 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IUnknown, bitmap1, NULL, &bitmap2);
3511 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
3512 ID2D1RenderTarget_Release(rt2);
3514 /* DXGI surface render targets with the same device but different factories. */
3515 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
3516 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3517 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3518 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
3519 ID2D1RenderTarget_Release(rt2);
3521 /* DXGI surface render targets with different devices but the same factory. */
3522 IDXGISurface_Release(surface2);
3523 IDXGISwapChain_Release(swapchain2);
3524 device2 = create_device();
3525 ok(!!device2, "Failed to create device.\n");
3526 swapchain2 = create_swapchain(device2, window2, TRUE);
3527 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
3528 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3530 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
3531 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3532 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3533 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
3534 ID2D1RenderTarget_Release(rt2);
3536 /* DXGI surface render targets with different devices and different factories. */
3537 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
3538 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3539 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3540 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
3541 ID2D1RenderTarget_Release(rt2);
3543 /* DXGI surface render target and WIC bitmap render target, same factory. */
3544 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
3545 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3546 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3547 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
3548 ID2D1RenderTarget_Release(rt2);
3550 /* WIC bitmap render targets on different D2D factories. */
3551 ID2D1Bitmap_Release(bitmap1);
3552 ID2D1RenderTarget_Release(rt1);
3553 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap1, &desc, &rt1);
3554 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3555 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
3556 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3558 hr = ID2D1RenderTarget_QueryInterface(rt1, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
3559 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
3560 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
3561 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
3562 ok(rt3 == rt1, "Unexpected render target\n");
3563 ID2D1RenderTarget_Release(rt3);
3564 ID2D1GdiInteropRenderTarget_Release(interop);
3566 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory2, wic_bitmap2, &desc, &rt2);
3567 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3568 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3569 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
3570 ID2D1RenderTarget_Release(rt2);
3572 /* WIC bitmap render targets on the same D2D factory. */
3573 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
3574 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3575 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
3576 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3577 ID2D1Bitmap_Release(bitmap2);
3578 ID2D1RenderTarget_Release(rt2);
3580 /* Shared DXGI surface. */
3581 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3582 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3583 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3584 desc.dpiX = 0.0f;
3585 desc.dpiY = 0.0f;
3586 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3587 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3589 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
3590 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3592 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3593 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3594 bitmap_desc.dpiX = 0.0f;
3595 bitmap_desc.dpiY = 0.0f;
3597 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface, surface2, &bitmap_desc, &bitmap2);
3598 ok(SUCCEEDED(hr) || broken(hr == E_INVALIDARG) /* vista */, "Failed to create bitmap, hr %#x.\n", hr);
3600 if (SUCCEEDED(hr))
3602 size = ID2D1Bitmap_GetPixelSize(bitmap2);
3603 hr = IDXGISurface_GetDesc(surface2, &surface_desc);
3604 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
3605 ok(size.width == surface_desc.Width && size.height == surface_desc.Height, "Got wrong bitmap size.\n");
3607 ID2D1Bitmap_Release(bitmap2);
3609 /* IDXGISurface1 is supported too. */
3610 if (IDXGISurface_QueryInterface(surface2, &IID_IDXGISurface1, (void **)&surface3) == S_OK)
3612 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface1, surface3, &bitmap_desc, &bitmap2);
3613 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3615 ID2D1Bitmap_Release(bitmap2);
3616 IDXGISurface1_Release(surface3);
3620 ID2D1RenderTarget_Release(rt2);
3622 ID2D1Bitmap_Release(bitmap1);
3623 ID2D1RenderTarget_Release(rt1);
3624 ID2D1Factory_Release(factory2);
3625 ID2D1Factory_Release(factory1);
3626 IWICBitmap_Release(wic_bitmap2);
3627 IWICBitmap_Release(wic_bitmap1);
3628 IDXGISurface_Release(surface2);
3629 IDXGISurface_Release(surface1);
3630 IDXGISwapChain_Release(swapchain2);
3631 IDXGISwapChain_Release(swapchain1);
3632 ID3D10Device1_Release(device2);
3633 ID3D10Device1_Release(device1);
3634 DestroyWindow(window2);
3635 DestroyWindow(window1);
3636 CoUninitialize();
3639 static void test_bitmap_updates(void)
3641 D2D1_BITMAP_PROPERTIES bitmap_desc;
3642 IDXGISwapChain *swapchain;
3643 ID2D1RenderTarget *rt;
3644 ID3D10Device1 *device;
3645 IDXGISurface *surface;
3646 D2D1_RECT_U dst_rect;
3647 ID2D1Bitmap *bitmap;
3648 D2D1_COLOR_F color;
3649 D2D1_RECT_F rect;
3650 D2D1_SIZE_U size;
3651 HWND window;
3652 HRESULT hr;
3653 BOOL match;
3655 static const DWORD bitmap_data[] =
3657 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
3658 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
3659 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
3660 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
3663 if (!(device = create_device()))
3665 skip("Failed to create device, skipping tests.\n");
3666 return;
3668 window = create_window();
3669 swapchain = create_swapchain(device, window, TRUE);
3670 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3671 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3672 rt = create_render_target(surface);
3673 ok(!!rt, "Failed to create render target.\n");
3675 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
3677 ID2D1RenderTarget_BeginDraw(rt);
3678 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
3679 ID2D1RenderTarget_Clear(rt, &color);
3681 set_size_u(&size, 4, 4);
3682 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3683 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3684 bitmap_desc.dpiX = 96.0f;
3685 bitmap_desc.dpiY = 96.0f;
3686 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
3687 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3689 set_rect(&rect, 0.0f, 0.0f, 320.0f, 240.0f);
3690 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
3691 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
3693 ID2D1Bitmap_Release(bitmap);
3695 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
3696 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
3697 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3699 set_rect(&rect, 0.0f, 240.0f, 320.0f, 480.0f);
3700 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
3701 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
3703 set_rect_u(&dst_rect, 1, 1, 3, 3);
3704 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, 4 * sizeof(*bitmap_data));
3705 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3706 set_rect_u(&dst_rect, 0, 3, 3, 4);
3707 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[6], 4 * sizeof(*bitmap_data));
3708 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3709 set_rect_u(&dst_rect, 0, 0, 4, 1);
3710 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[10], 4 * sizeof(*bitmap_data));
3711 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3712 set_rect_u(&dst_rect, 0, 1, 1, 3);
3713 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[2], sizeof(*bitmap_data));
3714 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3715 set_rect_u(&dst_rect, 4, 4, 3, 1);
3716 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, sizeof(*bitmap_data));
3717 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3718 set_rect(&rect, 320.0f, 240.0f, 640.0f, 480.0f);
3719 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
3720 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
3722 hr = ID2D1Bitmap_CopyFromMemory(bitmap, NULL, bitmap_data, 4 * sizeof(*bitmap_data));
3723 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
3724 set_rect(&rect, 320.0f, 0.0f, 640.0f, 240.0f);
3725 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
3726 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
3728 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3729 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3731 match = compare_surface(surface, "cb8136c91fbbdc76bb83b8c09edc1907b0a5d0a6");
3732 ok(match, "Surface does not match.\n");
3734 ID2D1Bitmap_Release(bitmap);
3735 ID2D1RenderTarget_Release(rt);
3736 IDXGISurface_Release(surface);
3737 IDXGISwapChain_Release(swapchain);
3738 ID3D10Device1_Release(device);
3739 DestroyWindow(window);
3742 static void test_opacity_brush(void)
3744 ID2D1BitmapBrush *bitmap_brush, *opacity_brush;
3745 D2D1_BITMAP_PROPERTIES bitmap_desc;
3746 ID2D1RectangleGeometry *geometry;
3747 ID2D1SolidColorBrush *color_brush;
3748 IDXGISwapChain *swapchain;
3749 D2D1_MATRIX_3X2_F matrix;
3750 ID2D1RenderTarget *rt;
3751 ID3D10Device1 *device;
3752 IDXGISurface *surface;
3753 ID2D1Factory *factory;
3754 ID2D1Bitmap *bitmap;
3755 D2D1_COLOR_F color;
3756 D2D1_RECT_F rect;
3757 D2D1_SIZE_U size;
3758 ULONG refcount;
3759 HWND window;
3760 HRESULT hr;
3761 BOOL match;
3763 static const DWORD bitmap_data[] =
3765 0xffff0000, 0x40ffff00, 0x4000ff00, 0xff00ffff,
3766 0x7f0000ff, 0x00ff00ff, 0x00000000, 0x7f7f7f7f,
3767 0x7fffffff, 0x00ffffff, 0x00ffffff, 0x7f000000,
3768 0xffffffff, 0x40000000, 0x40000000, 0xff000000,
3771 if (!(device = create_device()))
3773 skip("Failed to create device, skipping tests.\n");
3774 return;
3776 window = create_window();
3777 swapchain = create_swapchain(device, window, TRUE);
3778 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3779 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3780 rt = create_render_target(surface);
3781 ok(!!rt, "Failed to create render target.\n");
3782 ID2D1RenderTarget_GetFactory(rt, &factory);
3784 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
3785 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
3787 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
3788 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
3789 ok(SUCCEEDED(hr), "Failed to create color brush, hr %#x.\n", hr);
3791 set_size_u(&size, 4, 4);
3792 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3793 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3794 bitmap_desc.dpiX = 96.0f;
3795 bitmap_desc.dpiY = 96.0f;
3796 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3797 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3798 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &opacity_brush);
3799 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
3800 ID2D1BitmapBrush_SetInterpolationMode(opacity_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
3801 refcount = ID2D1Bitmap_Release(bitmap);
3802 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
3804 set_size_u(&size, 1, 1);
3805 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3806 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
3807 bitmap_desc.dpiX = 96.0f;
3808 bitmap_desc.dpiY = 96.0f;
3809 hr = ID2D1RenderTarget_CreateBitmap(rt, size, &bitmap_data[2], sizeof(*bitmap_data), &bitmap_desc, &bitmap);
3810 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
3811 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
3812 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
3813 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
3814 refcount = ID2D1Bitmap_Release(bitmap);
3815 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
3817 ID2D1RenderTarget_BeginDraw(rt);
3819 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
3820 ID2D1RenderTarget_Clear(rt, &color);
3822 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
3823 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
3825 set_matrix_identity(&matrix);
3826 translate_matrix(&matrix, 120.0f, 120.0f);
3827 scale_matrix(&matrix, 20.0f, 60.0f);
3828 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3829 set_rect(&rect, 120.0f, 120.0f, 200.0f, 360.0f);
3830 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)opacity_brush);
3832 set_rect(&rect, 200.0f, 120.0f, 280.0f, 360.0f);
3833 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
3835 set_matrix_identity(&matrix);
3836 translate_matrix(&matrix, 40.0f, 360.0f);
3837 scale_matrix(&matrix, 20.0f, 60.0f);
3838 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3839 set_rect(&rect, 40.0f, 360.0f, 120.0f, 600.0f);
3840 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3841 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3842 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
3843 ID2D1RectangleGeometry_Release(geometry);
3845 set_matrix_identity(&matrix);
3846 translate_matrix(&matrix, 120.0f, 360.0f);
3847 scale_matrix(&matrix, 20.0f, 60.0f);
3848 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3849 set_rect(&rect, 120.0f, 360.0f, 200.0f, 600.0f);
3850 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3851 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3852 (ID2D1Brush *)color_brush, (ID2D1Brush *)opacity_brush);
3853 ID2D1RectangleGeometry_Release(geometry);
3855 set_matrix_identity(&matrix);
3856 translate_matrix(&matrix, 200.0f, 360.0f);
3857 scale_matrix(&matrix, 20.0f, 60.0f);
3858 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3859 set_rect(&rect, 200.0f, 360.0f, 280.0f, 600.0f);
3860 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3861 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3862 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
3864 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3865 ok(hr == D2DERR_INCOMPATIBLE_BRUSH_TYPES, "Got unexpected hr %#x.\n", hr);
3866 match = compare_surface(surface, "7141c6c7b3decb91196428efb1856bcbf9872935");
3867 ok(match, "Surface does not match.\n");
3868 ID2D1RenderTarget_BeginDraw(rt);
3870 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3871 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
3872 ID2D1RectangleGeometry_Release(geometry);
3874 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.5f);
3875 set_matrix_identity(&matrix);
3876 translate_matrix(&matrix, 40.0f, 600.0f);
3877 scale_matrix(&matrix, 20.0f, 60.0f);
3878 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3879 set_rect(&rect, 40.0f, 600.0f, 120.0f, 840.0f);
3880 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3881 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3882 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
3883 ID2D1RectangleGeometry_Release(geometry);
3885 ID2D1BitmapBrush_SetOpacity(opacity_brush, 0.8f);
3886 set_matrix_identity(&matrix);
3887 translate_matrix(&matrix, 120.0f, 600.0f);
3888 scale_matrix(&matrix, 20.0f, 60.0f);
3889 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3890 set_rect(&rect, 120.0f, 600.0f, 200.0f, 840.0f);
3891 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3892 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3893 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)bitmap_brush);
3894 ID2D1RectangleGeometry_Release(geometry);
3896 set_matrix_identity(&matrix);
3897 translate_matrix(&matrix, 200.0f, 600.0f);
3898 scale_matrix(&matrix, 20.0f, 60.0f);
3899 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
3900 set_rect(&rect, 200.0f, 600.0f, 280.0f, 840.0f);
3901 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
3902 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
3903 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
3904 ID2D1RectangleGeometry_Release(geometry);
3906 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
3907 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
3908 match = compare_surface(surface, "c3a5802d1750efa3e9122c1a92f6064df3872732");
3909 ok(match, "Surface does not match.\n");
3911 ID2D1BitmapBrush_Release(bitmap_brush);
3912 ID2D1BitmapBrush_Release(opacity_brush);
3913 ID2D1SolidColorBrush_Release(color_brush);
3914 ID2D1RenderTarget_Release(rt);
3915 refcount = ID2D1Factory_Release(factory);
3916 ok(!refcount, "Factory has %u references left.\n", refcount);
3917 IDXGISurface_Release(surface);
3918 IDXGISwapChain_Release(swapchain);
3919 ID3D10Device1_Release(device);
3920 DestroyWindow(window);
3923 static void test_create_target(void)
3925 IDXGISwapChain *swapchain;
3926 ID2D1Factory *factory;
3927 ID2D1RenderTarget *rt;
3928 ID3D10Device1 *device;
3929 IDXGISurface *surface;
3930 HWND window;
3931 HRESULT hr;
3932 static const struct
3934 float dpi_x, dpi_y;
3935 float rt_dpi_x, rt_dpi_y;
3936 HRESULT hr;
3938 create_dpi_tests[] =
3940 { 0.0f, 0.0f, 96.0f, 96.0f, S_OK },
3941 { 192.0f, 0.0f, 96.0f, 96.0f, E_INVALIDARG },
3942 { 0.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
3943 { 192.0f, -10.0f, 96.0f, 96.0f, E_INVALIDARG },
3944 { -10.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
3945 { 48.0f, 96.0f, 48.0f, 96.0f, S_OK },
3947 unsigned int i;
3949 if (!(device = create_device()))
3951 skip("Failed to create device, skipping tests.\n");
3952 return;
3954 window = create_window();
3955 swapchain = create_swapchain(device, window, TRUE);
3956 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
3957 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
3959 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
3960 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3962 for (i = 0; i < sizeof(create_dpi_tests) / sizeof(*create_dpi_tests); ++i)
3964 ID2D1GdiInteropRenderTarget *interop;
3965 D2D1_RENDER_TARGET_PROPERTIES desc;
3966 ID2D1RenderTarget *rt2;
3967 float dpi_x, dpi_y;
3968 IUnknown *unk;
3970 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3971 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
3972 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3973 desc.dpiX = create_dpi_tests[i].dpi_x;
3974 desc.dpiY = create_dpi_tests[i].dpi_y;
3975 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3976 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3978 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
3979 ok(hr == create_dpi_tests[i].hr, "Wrong return code, hr %#x, expected %#x, test %u.\n", hr,
3980 create_dpi_tests[i].hr, i);
3982 if (FAILED(hr))
3983 continue;
3985 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_IUnknown, (void **)&unk);
3986 ok(SUCCEEDED(hr), "Failed to get IUnknown, hr %#x.\n", hr);
3987 ok(unk == (IUnknown *)rt, "Expected same interface pointer.\n");
3988 IUnknown_Release(unk);
3990 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
3991 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
3992 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt2);
3993 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
3994 ok(rt2 == rt, "Unexpected render target\n");
3995 ID2D1RenderTarget_Release(rt2);
3996 ID2D1GdiInteropRenderTarget_Release(interop);
3998 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
3999 ok(dpi_x == create_dpi_tests[i].rt_dpi_x, "Wrong dpi_x %.8e, expected %.8e, test %u\n",
4000 dpi_x, create_dpi_tests[i].rt_dpi_x, i);
4001 ok(dpi_y == create_dpi_tests[i].rt_dpi_y, "Wrong dpi_y %.8e, expected %.8e, test %u\n",
4002 dpi_y, create_dpi_tests[i].rt_dpi_y, i);
4004 ID2D1RenderTarget_Release(rt);
4007 ID2D1Factory_Release(factory);
4008 IDXGISurface_Release(surface);
4009 IDXGISwapChain_Release(swapchain);
4010 ID3D10Device1_Release(device);
4011 DestroyWindow(window);
4014 static void test_draw_text_layout(void)
4016 static const struct
4018 D2D1_TEXT_ANTIALIAS_MODE aa_mode;
4019 DWRITE_RENDERING_MODE rendering_mode;
4020 HRESULT hr;
4022 antialias_mode_tests[] =
4024 { D2D1_TEXT_ANTIALIAS_MODE_DEFAULT, DWRITE_RENDERING_MODE_ALIASED },
4025 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_ALIASED },
4026 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_DEFAULT },
4027 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_OUTLINE },
4028 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_DEFAULT },
4029 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_OUTLINE },
4030 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL },
4031 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC },
4032 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL },
4033 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC },
4034 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_DEFAULT },
4035 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL },
4036 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC },
4037 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL },
4038 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC },
4039 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_OUTLINE, E_INVALIDARG },
4040 { D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE, DWRITE_RENDERING_MODE_ALIASED, E_INVALIDARG },
4041 { D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, DWRITE_RENDERING_MODE_ALIASED, E_INVALIDARG },
4042 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL, E_INVALIDARG },
4043 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, E_INVALIDARG },
4044 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL, E_INVALIDARG },
4045 { D2D1_TEXT_ANTIALIAS_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC, E_INVALIDARG },
4047 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
4048 static const WCHAR textW[] = {'t','e','x','t',0};
4049 static const WCHAR emptyW[] = {0};
4050 D2D1_RENDER_TARGET_PROPERTIES desc;
4051 IDXGISwapChain *swapchain;
4052 ID2D1Factory *factory, *factory2;
4053 ID2D1RenderTarget *rt, *rt2;
4054 ID3D10Device1 *device;
4055 IDXGISurface *surface;
4056 HWND window;
4057 HRESULT hr;
4058 IDWriteFactory *dwrite_factory;
4059 IDWriteTextFormat *text_format;
4060 IDWriteTextLayout *text_layout;
4061 D2D1_POINT_2F origin;
4062 DWRITE_TEXT_RANGE range;
4063 D2D1_COLOR_F color;
4064 ID2D1SolidColorBrush *brush, *brush2;
4065 ID2D1RectangleGeometry *geometry;
4066 D2D1_RECT_F rect;
4067 unsigned int i;
4069 if (!(device = create_device()))
4071 skip("Failed to create device, skipping tests.\n");
4072 return;
4074 window = create_window();
4075 swapchain = create_swapchain(device, window, TRUE);
4076 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
4077 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4079 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4080 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4082 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
4083 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4084 ok(factory != factory2, "got same factory\n");
4086 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4087 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
4088 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4089 desc.dpiX = 0.0f;
4090 desc.dpiY = 0.0f;
4091 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4092 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4094 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
4095 ok(SUCCEEDED(hr), "Failed to create a target, hr %#x.\n", hr);
4097 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface, &desc, &rt2);
4098 ok(SUCCEEDED(hr), "Failed to create a target, hr %#x.\n", hr);
4100 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
4101 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4103 hr = IDWriteFactory_CreateTextFormat(dwrite_factory, tahomaW, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
4104 DWRITE_FONT_STRETCH_NORMAL, 10.0f, emptyW, &text_format);
4105 ok(SUCCEEDED(hr), "Failed to create text format, hr %#x.\n", hr);
4107 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, textW, 4, text_format, 100.0f, 100.0f, &text_layout);
4108 ok(SUCCEEDED(hr), "Failed to create text layout, hr %#x.\n", hr);
4110 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
4111 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
4112 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4114 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt2, &color, NULL, &brush2);
4115 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4117 /* effect brush is created from different factory */
4118 range.startPosition = 0;
4119 range.length = 4;
4120 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)brush2, range);
4121 ok(SUCCEEDED(hr), "Failed to set drawing effect, hr %#x.\n", hr);
4123 ID2D1RenderTarget_BeginDraw(rt);
4125 origin.x = origin.y = 0.0f;
4126 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
4128 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4129 todo_wine
4130 ok(hr == D2DERR_WRONG_FACTORY, "EndDraw failure expected, hr %#x.\n", hr);
4132 /* Effect is d2d resource, but not a brush. */
4133 set_rect(&rect, 0.0f, 0.0f, 10.0f, 10.0f);
4134 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
4135 ok(SUCCEEDED(hr), "Failed to geometry, hr %#x.\n", hr);
4137 range.startPosition = 0;
4138 range.length = 4;
4139 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)geometry, range);
4140 ok(SUCCEEDED(hr), "Failed to set drawing effect, hr %#x.\n", hr);
4141 ID2D1RectangleGeometry_Release(geometry);
4143 ID2D1RenderTarget_BeginDraw(rt);
4145 origin.x = origin.y = 0.0f;
4146 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
4148 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4149 ok(hr == S_OK, "EndDraw failure expected, hr %#x.\n", hr);
4151 for (i = 0; i < sizeof(antialias_mode_tests)/sizeof(*antialias_mode_tests); i++)
4153 IDWriteRenderingParams *rendering_params;
4155 ID2D1RenderTarget_SetTextAntialiasMode(rt, antialias_mode_tests[i].aa_mode);
4157 hr = IDWriteFactory_CreateCustomRenderingParams(dwrite_factory, 2.0f, 1.0f, 0.0f, DWRITE_PIXEL_GEOMETRY_FLAT,
4158 antialias_mode_tests[i].rendering_mode, &rendering_params);
4159 ok(SUCCEEDED(hr), "Failed to create custom rendering params, hr %#x.\n", hr);
4161 ID2D1RenderTarget_SetTextRenderingParams(rt, rendering_params);
4163 ID2D1RenderTarget_BeginDraw(rt);
4165 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush *)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
4167 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4168 ok(hr == antialias_mode_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
4170 IDWriteRenderingParams_Release(rendering_params);
4173 IDWriteTextFormat_Release(text_format);
4174 IDWriteTextLayout_Release(text_layout);
4175 IDWriteFactory_Release(dwrite_factory);
4176 ID2D1RenderTarget_Release(rt);
4177 ID2D1RenderTarget_Release(rt2);
4179 ID2D1Factory_Release(factory);
4180 ID2D1Factory_Release(factory2);
4181 IDXGISurface_Release(surface);
4182 IDXGISwapChain_Release(swapchain);
4183 ID3D10Device1_Release(device);
4184 DestroyWindow(window);
4187 static void create_target_dibsection(HDC hdc, UINT32 width, UINT32 height)
4189 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
4190 BITMAPINFO *bmi = (BITMAPINFO*)bmibuf;
4191 HBITMAP hbm;
4193 memset(bmi, 0, sizeof(bmibuf));
4194 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
4195 bmi->bmiHeader.biHeight = -height;
4196 bmi->bmiHeader.biWidth = width;
4197 bmi->bmiHeader.biBitCount = 32;
4198 bmi->bmiHeader.biPlanes = 1;
4199 bmi->bmiHeader.biCompression = BI_RGB;
4201 hbm = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
4202 ok(hbm != NULL, "Failed to create a dib section.\n");
4204 DeleteObject(SelectObject(hdc, hbm));
4207 static void test_dc_target(void)
4209 static const D2D1_PIXEL_FORMAT invalid_formats[] =
4211 { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
4212 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN },
4213 { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
4215 D2D1_TEXT_ANTIALIAS_MODE text_aa_mode;
4216 ID2D1GdiInteropRenderTarget *interop;
4217 D2D1_RENDER_TARGET_PROPERTIES desc;
4218 D2D1_MATRIX_3X2_F matrix, matrix2;
4219 ID2D1DCRenderTarget *rt, *rt2;
4220 D2D1_ANTIALIAS_MODE aa_mode;
4221 ID2D1SolidColorBrush *brush;
4222 ID2D1RenderTarget *rt3;
4223 ID2D1Factory *factory;
4224 ID3D10Device1 *device;
4225 FLOAT dpi_x, dpi_y;
4226 D2D1_COLOR_F color;
4227 D2D1_SIZE_U sizeu;
4228 D2D1_SIZE_F size;
4229 D2D1_TAG t1, t2;
4230 unsigned int i;
4231 HDC hdc, hdc2;
4232 D2D_RECT_F r;
4233 COLORREF clr;
4234 HRESULT hr;
4235 RECT rect;
4237 if (!(device = create_device()))
4239 skip("Failed to create device, skipping tests.\n");
4240 return;
4242 ID3D10Device1_Release(device);
4244 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4245 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4247 for (i = 0; i < sizeof(invalid_formats) / sizeof(*invalid_formats); ++i)
4249 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4250 desc.pixelFormat = invalid_formats[i];
4251 desc.dpiX = 96.0f;
4252 desc.dpiY = 96.0f;
4253 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4254 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4256 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
4257 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x.\n", hr);
4260 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4261 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4262 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4263 desc.dpiX = 96.0f;
4264 desc.dpiY = 96.0f;
4265 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4266 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4267 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
4268 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
4270 hr = ID2D1DCRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
4271 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
4272 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
4273 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4274 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
4275 ID2D1RenderTarget_Release(rt3);
4276 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1DCRenderTarget, (void **)&rt2);
4277 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4278 ok(rt2 == rt, "Unexpected render target\n");
4279 ID2D1DCRenderTarget_Release(rt2);
4280 ID2D1GdiInteropRenderTarget_Release(interop);
4282 size = ID2D1DCRenderTarget_GetSize(rt);
4283 ok(size.width == 0.0f, "got width %.08e.\n", size.width);
4284 ok(size.height == 0.0f, "got height %.08e.\n", size.height);
4286 sizeu = ID2D1DCRenderTarget_GetPixelSize(rt);
4287 ok(sizeu.width == 0, "got width %u.\n", sizeu.width);
4288 ok(sizeu.height == 0, "got height %u.\n", sizeu.height);
4290 /* object creation methods work without BindDC() */
4291 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
4292 hr = ID2D1DCRenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
4293 ok(SUCCEEDED(hr), "Failed to create a brush, hr %#x.\n", hr);
4294 ID2D1SolidColorBrush_Release(brush);
4296 ID2D1DCRenderTarget_BeginDraw(rt);
4297 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
4298 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
4300 ID2D1DCRenderTarget_Release(rt);
4302 /* BindDC() */
4303 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
4304 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
4306 aa_mode = ID2D1DCRenderTarget_GetAntialiasMode(rt);
4307 ok(aa_mode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, "Got wrong default aa mode %d.\n", aa_mode);
4308 text_aa_mode = ID2D1DCRenderTarget_GetTextAntialiasMode(rt);
4309 ok(text_aa_mode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT, "Got wrong default text aa mode %d.\n", text_aa_mode);
4311 ID2D1DCRenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
4312 ok(dpi_x == 96.0f && dpi_y == 96.0f, "Got dpi_x %f, dpi_y %f.\n", dpi_x, dpi_y);
4314 hdc = CreateCompatibleDC(NULL);
4315 ok(hdc != NULL, "Failed to create an HDC.\n");
4317 create_target_dibsection(hdc, 16, 16);
4319 SetRect(&rect, 0, 0, 32, 32);
4320 hr = ID2D1DCRenderTarget_BindDC(rt, NULL, &rect);
4321 ok(hr == E_INVALIDARG, "BindDC() returned %#x.\n", hr);
4323 /* Target properties are retained during BindDC() */
4324 ID2D1DCRenderTarget_SetTags(rt, 1, 2);
4325 ID2D1DCRenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4326 ID2D1DCRenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
4328 set_matrix_identity(&matrix);
4329 translate_matrix(&matrix, 200.0f, 600.0f);
4330 ID2D1DCRenderTarget_SetTransform(rt, &matrix);
4332 hr = ID2D1DCRenderTarget_BindDC(rt, hdc, &rect);
4333 ok(hr == S_OK, "BindDC() returned %#x.\n", hr);
4335 ID2D1DCRenderTarget_GetTags(rt, &t1, &t2);
4336 ok(t1 == 1 && t2 == 2, "Got wrong tags.\n");
4338 aa_mode = ID2D1DCRenderTarget_GetAntialiasMode(rt);
4339 ok(aa_mode == D2D1_ANTIALIAS_MODE_ALIASED, "Got wrong aa mode %d.\n", aa_mode);
4341 text_aa_mode = ID2D1DCRenderTarget_GetTextAntialiasMode(rt);
4342 ok(text_aa_mode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, "Got wrong text aa mode %d.\n", text_aa_mode);
4344 ID2D1DCRenderTarget_GetTransform(rt, &matrix2);
4345 ok(!memcmp(&matrix, &matrix2, sizeof(matrix)), "Got wrong target transform.\n");
4347 set_matrix_identity(&matrix);
4348 ID2D1DCRenderTarget_SetTransform(rt, &matrix);
4350 /* target size comes from specified dimensions, not from selected bitmap size */
4351 size = ID2D1DCRenderTarget_GetSize(rt);
4352 ok(size.width == 32.0f, "got width %.08e.\n", size.width);
4353 ok(size.height == 32.0f, "got height %.08e.\n", size.height);
4355 /* clear one HDC to red, switch to another one, partially fill it and test contents */
4356 ID2D1DCRenderTarget_BeginDraw(rt);
4358 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
4359 ID2D1DCRenderTarget_Clear(rt, &color);
4361 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
4362 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
4364 clr = GetPixel(hdc, 0, 0);
4365 ok(clr == RGB(255, 0, 0), "Got color %#x\n", clr);
4367 hdc2 = CreateCompatibleDC(NULL);
4368 ok(hdc2 != NULL, "Failed to create an HDC.\n");
4370 create_target_dibsection(hdc2, 16, 16);
4372 hr = ID2D1DCRenderTarget_BindDC(rt, hdc2, &rect);
4373 ok(hr == S_OK, "BindDC() returned %#x.\n", hr);
4375 clr = GetPixel(hdc2, 0, 0);
4376 ok(clr == 0, "Got color %#x\n", clr);
4378 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
4379 hr = ID2D1DCRenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
4380 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4382 ID2D1DCRenderTarget_BeginDraw(rt);
4384 r.left = r.top = 0.0f;
4385 r.bottom = 16.0f;
4386 r.right = 8.0f;
4387 ID2D1DCRenderTarget_FillRectangle(rt, &r, (ID2D1Brush*)brush);
4389 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
4390 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
4392 ID2D1SolidColorBrush_Release(brush);
4394 clr = GetPixel(hdc2, 0, 0);
4395 ok(clr == RGB(0, 255, 0), "Got color %#x\n", clr);
4397 clr = GetPixel(hdc2, 10, 0);
4398 ok(clr == 0, "Got color %#x\n", clr);
4400 DeleteDC(hdc);
4401 DeleteDC(hdc2);
4402 ID2D1DCRenderTarget_Release(rt);
4403 ID2D1Factory_Release(factory);
4406 static void test_hwnd_target(void)
4408 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
4409 ID2D1GdiInteropRenderTarget *interop;
4410 D2D1_RENDER_TARGET_PROPERTIES desc;
4411 ID2D1HwndRenderTarget *rt, *rt2;
4412 ID2D1RenderTarget *rt3;
4413 ID2D1Factory *factory;
4414 ID3D10Device1 *device;
4415 D2D1_SIZE_U size;
4416 HRESULT hr;
4418 if (!(device = create_device()))
4420 skip("Failed to create device, skipping tests.\n");
4421 return;
4423 ID3D10Device1_Release(device);
4425 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4426 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4428 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4429 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4430 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4431 desc.dpiX = 0.0f;
4432 desc.dpiY = 0.0f;
4433 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4434 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4436 hwnd_rt_desc.hwnd = NULL;
4437 hwnd_rt_desc.pixelSize.width = 64;
4438 hwnd_rt_desc.pixelSize.height = 64;
4439 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
4441 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
4442 ok(FAILED(hr), "Target creation should fail, hr %#x.\n", hr);
4444 hwnd_rt_desc.hwnd = (HWND)0xdeadbeef;
4445 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
4446 ok(FAILED(hr), "Target creation should fail, hr %#x.\n", hr);
4448 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
4449 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
4450 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
4451 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4453 hr = ID2D1HwndRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
4454 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
4455 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
4456 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4457 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
4458 ID2D1RenderTarget_Release(rt3);
4459 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1HwndRenderTarget, (void **)&rt2);
4460 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4461 ok(rt2 == rt, "Unexpected render target\n");
4462 ID2D1HwndRenderTarget_Release(rt2);
4463 ID2D1GdiInteropRenderTarget_Release(interop);
4465 size.width = 128;
4466 size.height = 64;
4467 hr = ID2D1HwndRenderTarget_Resize(rt, &size);
4468 ok(SUCCEEDED(hr), "Failed to resize render target, hr %#x.\n", hr);
4470 ID2D1HwndRenderTarget_Release(rt);
4472 DestroyWindow(hwnd_rt_desc.hwnd);
4473 ID2D1Factory_Release(factory);
4476 static void test_bitmap_target(void)
4478 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
4479 ID2D1GdiInteropRenderTarget *interop;
4480 D2D1_SIZE_U pixel_size, pixel_size2;
4481 D2D1_RENDER_TARGET_PROPERTIES desc;
4482 ID2D1BitmapRenderTarget *rt, *rt2;
4483 ID2D1HwndRenderTarget *hwnd_rt;
4484 ID2D1Bitmap *bitmap, *bitmap2;
4485 ID2D1DCRenderTarget *dc_rt;
4486 D2D1_SIZE_F size, size2;
4487 ID2D1RenderTarget *rt3;
4488 ID2D1Factory *factory;
4489 ID3D10Device1 *device;
4490 float dpi[2], dpi2[2];
4491 D2D1_COLOR_F color;
4492 ULONG refcount;
4493 HRESULT hr;
4495 if (!(device = create_device()))
4497 skip("Failed to create device, skipping tests.\n");
4498 return;
4500 ID3D10Device1_Release(device);
4502 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4503 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4505 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4506 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4507 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4508 desc.dpiX = 96.0f;
4509 desc.dpiY = 192.0f;
4510 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4511 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4513 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
4514 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
4515 hwnd_rt_desc.pixelSize.width = 64;
4516 hwnd_rt_desc.pixelSize.height = 64;
4517 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
4519 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &hwnd_rt);
4520 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4522 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, NULL, NULL,
4523 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
4524 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4526 hr = ID2D1BitmapRenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
4527 ok(SUCCEEDED(hr), "Failed to get interop target, hr %#x.\n", hr);
4528 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1RenderTarget, (void **)&rt3);
4529 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4530 ok(rt3 == (ID2D1RenderTarget *)rt, "Unexpected render target\n");
4531 ID2D1RenderTarget_Release(rt3);
4532 hr = ID2D1GdiInteropRenderTarget_QueryInterface(interop, &IID_ID2D1BitmapRenderTarget, (void **)&rt2);
4533 ok(SUCCEEDED(hr), "Failed to get render target back, %#x.\n", hr);
4534 ok(rt2 == rt, "Unexpected render target\n");
4535 ID2D1BitmapRenderTarget_Release(rt2);
4536 ID2D1GdiInteropRenderTarget_Release(interop);
4538 /* See if parent target is referenced. */
4539 ID2D1HwndRenderTarget_AddRef(hwnd_rt);
4540 refcount = ID2D1HwndRenderTarget_Release(hwnd_rt);
4541 ok(refcount == 1, "Target should not have been referenced, got %u.\n", refcount);
4543 /* Size was not specified, should match parent. */
4544 pixel_size = ID2D1HwndRenderTarget_GetPixelSize(hwnd_rt);
4545 pixel_size2 = ID2D1BitmapRenderTarget_GetPixelSize(rt);
4546 ok(!memcmp(&pixel_size, &pixel_size2, sizeof(pixel_size)), "Got target pixel size mismatch.\n");
4548 size = ID2D1HwndRenderTarget_GetSize(hwnd_rt);
4549 size2 = ID2D1BitmapRenderTarget_GetSize(rt);
4550 ok(!memcmp(&size, &size2, sizeof(size)), "Got target DIP size mismatch.\n");
4552 ID2D1HwndRenderTarget_GetDpi(hwnd_rt, dpi, dpi + 1);
4553 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
4554 ok(!memcmp(dpi, dpi2, sizeof(dpi)), "Got dpi mismatch.\n");
4556 ID2D1BitmapRenderTarget_Release(rt);
4558 /* Pixel size specified. */
4559 set_size_u(&pixel_size, 32, 32);
4560 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, &pixel_size, NULL,
4561 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
4562 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4564 pixel_size2 = ID2D1BitmapRenderTarget_GetPixelSize(rt);
4565 ok(!memcmp(&pixel_size, &pixel_size2, sizeof(pixel_size)), "Got target pixel size mismatch.\n");
4567 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
4568 ok(!memcmp(dpi, dpi2, sizeof(dpi)), "Got dpi mismatch.\n");
4570 ID2D1BitmapRenderTarget_Release(rt);
4572 /* Both pixel size and DIP size are specified. */
4573 set_size_u(&pixel_size, 128, 128);
4574 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, &size, &pixel_size, NULL,
4575 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
4576 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4578 /* Doubled pixel size dimensions with the same DIP size give doubled dpi. */
4579 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
4580 ok(dpi[0] == dpi2[0] / 2.0f && dpi[1] == dpi2[1] / 2.0f, "Got dpi mismatch.\n");
4582 ID2D1BitmapRenderTarget_Release(rt);
4584 /* DIP size is specified, fractional. */
4585 set_size_f(&size, 70.1f, 70.4f);
4586 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, &size, NULL, NULL,
4587 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
4588 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4590 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
4592 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt);
4593 ok(pixel_size.width == ceilf(size.width * dpi[0] / 96.0f)
4594 && pixel_size.height == ceilf(size.height * dpi[1] / 96.0f), "Wrong pixel size %ux%u\n",
4595 pixel_size.width, pixel_size.height);
4597 dpi[0] *= (pixel_size.width / size.width) * (96.0f / dpi[0]);
4598 dpi[1] *= (pixel_size.height / size.height) * (96.0f / dpi[1]);
4600 ok(compare_float(dpi[0], dpi2[0], 1) && compare_float(dpi[1], dpi2[1], 1), "Got dpi mismatch.\n");
4602 ID2D1HwndRenderTarget_Release(hwnd_rt);
4604 /* Check if GetBitmap() returns same instance. */
4605 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap);
4606 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
4607 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap2);
4608 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
4609 ok(bitmap == bitmap2, "Got different bitmap instances.\n");
4611 /* Draw something, see if bitmap instance is retained. */
4612 ID2D1BitmapRenderTarget_BeginDraw(rt);
4613 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
4614 ID2D1BitmapRenderTarget_Clear(rt, &color);
4615 hr = ID2D1BitmapRenderTarget_EndDraw(rt, NULL, NULL);
4616 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
4618 ID2D1Bitmap_Release(bitmap2);
4619 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap2);
4620 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
4621 ok(bitmap == bitmap2, "Got different bitmap instances.\n");
4623 ID2D1Bitmap_Release(bitmap);
4624 ID2D1Bitmap_Release(bitmap2);
4626 refcount = ID2D1BitmapRenderTarget_Release(rt);
4627 ok(!refcount, "Target should be released, got %u.\n", refcount);
4629 DestroyWindow(hwnd_rt_desc.hwnd);
4631 /* Compatible target created from a DC target without associated HDC */
4632 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
4633 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
4634 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
4635 desc.dpiX = 96.0f;
4636 desc.dpiY = 96.0f;
4637 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
4638 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
4639 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &dc_rt);
4640 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
4642 hr = ID2D1DCRenderTarget_CreateCompatibleRenderTarget(dc_rt, NULL, NULL, NULL,
4643 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
4644 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4646 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt);
4647 todo_wine
4648 ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
4650 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap);
4651 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
4652 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
4653 todo_wine
4654 ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
4655 ID2D1Bitmap_Release(bitmap);
4657 ID2D1BitmapRenderTarget_Release(rt);
4658 ID2D1DCRenderTarget_Release(dc_rt);
4660 ID2D1Factory_Release(factory);
4663 static void test_desktop_dpi(void)
4665 ID2D1Factory *factory;
4666 float dpi_x, dpi_y;
4667 HRESULT hr;
4669 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4670 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4672 dpi_x = dpi_y = 0.0f;
4673 ID2D1Factory_GetDesktopDpi(factory, &dpi_x, &dpi_y);
4674 ok(dpi_x > 0.0f && dpi_y > 0.0f, "Got wrong dpi %f x %f.\n", dpi_x, dpi_y);
4676 ID2D1Factory_Release(factory);
4679 static void test_stroke_style(void)
4681 static const struct
4683 D2D1_DASH_STYLE dash_style;
4684 UINT32 dash_count;
4685 float dashes[6];
4687 dash_style_tests[] =
4689 {D2D1_DASH_STYLE_SOLID, 0},
4690 {D2D1_DASH_STYLE_DASH, 2, {2.0f, 2.0f}},
4691 {D2D1_DASH_STYLE_DOT, 2, {0.0f, 2.0f}},
4692 {D2D1_DASH_STYLE_DASH_DOT, 4, {2.0f, 2.0f, 0.0f, 2.0f}},
4693 {D2D1_DASH_STYLE_DASH_DOT_DOT, 6, {2.0f, 2.0f, 0.0f, 2.0f, 0.0f, 2.0f}},
4695 D2D1_STROKE_STYLE_PROPERTIES desc;
4696 ID2D1StrokeStyle *style;
4697 ID2D1Factory *factory;
4698 UINT32 count;
4699 HRESULT hr;
4700 D2D1_CAP_STYLE cap_style;
4701 D2D1_LINE_JOIN line_join;
4702 float miter_limit, dash_offset;
4703 D2D1_DASH_STYLE dash_style;
4704 unsigned int i;
4705 float dashes[2];
4707 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
4708 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
4710 desc.startCap = D2D1_CAP_STYLE_SQUARE;
4711 desc.endCap = D2D1_CAP_STYLE_ROUND;
4712 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
4713 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
4714 desc.miterLimit = 1.5f;
4715 desc.dashStyle = D2D1_DASH_STYLE_DOT;
4716 desc.dashOffset = -1.0f;
4718 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
4719 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
4721 cap_style = ID2D1StrokeStyle_GetStartCap(style);
4722 ok(cap_style == D2D1_CAP_STYLE_SQUARE, "Unexpected cap style %d.\n", cap_style);
4723 cap_style = ID2D1StrokeStyle_GetEndCap(style);
4724 ok(cap_style == D2D1_CAP_STYLE_ROUND, "Unexpected cap style %d.\n", cap_style);
4725 cap_style = ID2D1StrokeStyle_GetDashCap(style);
4726 ok(cap_style == D2D1_CAP_STYLE_TRIANGLE, "Unexpected cap style %d.\n", cap_style);
4727 line_join = ID2D1StrokeStyle_GetLineJoin(style);
4728 ok(line_join == D2D1_LINE_JOIN_BEVEL, "Unexpected line joind %d.\n", line_join);
4729 miter_limit = ID2D1StrokeStyle_GetMiterLimit(style);
4730 ok(miter_limit == 1.5f, "Unexpected miter limit %f.\n", miter_limit);
4731 dash_style = ID2D1StrokeStyle_GetDashStyle(style);
4732 ok(dash_style == D2D1_DASH_STYLE_DOT, "Unexpected dash style %d.\n", dash_style);
4733 dash_offset = ID2D1StrokeStyle_GetDashOffset(style);
4734 ok(dash_offset == -1.0f, "Unexpected dash offset %f.\n", dash_offset);
4736 /* Custom dash pattern, no dashes data specified. */
4737 desc.startCap = D2D1_CAP_STYLE_SQUARE;
4738 desc.endCap = D2D1_CAP_STYLE_ROUND;
4739 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
4740 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
4741 desc.miterLimit = 1.5f;
4742 desc.dashStyle = D2D1_DASH_STYLE_CUSTOM;
4743 desc.dashOffset = 0.0f;
4745 ID2D1StrokeStyle_Release(style);
4747 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
4748 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
4750 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 0, &style);
4751 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
4753 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
4754 ok(hr == S_OK, "Unexpected return value, %#x.\n", hr);
4755 ID2D1StrokeStyle_Release(style);
4757 /* Builtin style, dashes are specified. */
4758 desc.dashStyle = D2D1_DASH_STYLE_DOT;
4759 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
4760 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
4762 /* Invalid style. */
4763 desc.dashStyle = 100;
4764 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
4765 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
4767 /* Test returned dash pattern for builtin styles. */
4768 desc.startCap = D2D1_CAP_STYLE_SQUARE;
4769 desc.endCap = D2D1_CAP_STYLE_ROUND;
4770 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
4771 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
4772 desc.miterLimit = 1.5f;
4773 desc.dashOffset = 0.0f;
4775 for (i = 0; i < sizeof(dash_style_tests)/sizeof(dash_style_tests[0]); i++)
4777 float dashes[10];
4778 UINT dash_count;
4780 desc.dashStyle = dash_style_tests[i].dash_style;
4782 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
4783 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
4785 dash_count = ID2D1StrokeStyle_GetDashesCount(style);
4786 ok(dash_count == dash_style_tests[i].dash_count, "%u: unexpected dash count %u, expected %u.\n",
4787 i, dash_count, dash_style_tests[i].dash_count);
4788 ok(dash_count < sizeof(dashes)/sizeof(dashes[0]), "%u: unexpectedly large dash count %u.\n", i, dash_count);
4789 if (dash_count == dash_style_tests[i].dash_count)
4791 unsigned int j;
4793 ID2D1StrokeStyle_GetDashes(style, dashes, dash_count);
4794 ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
4795 "%u: unexpected dash array.\n", i);
4797 /* Ask for more dashes than style actually has. */
4798 memset(dashes, 0xcc, sizeof(dashes));
4799 ID2D1StrokeStyle_GetDashes(style, dashes, sizeof(dashes)/sizeof(dashes[0]));
4800 ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
4801 "%u: unexpected dash array.\n", i);
4803 for (j = dash_count; j < sizeof(dashes)/sizeof(dashes[0]); j++)
4804 ok(dashes[j] == 0.0f, "%u: unexpected dash value at %u.\n", i, j);
4807 ID2D1StrokeStyle_Release(style);
4810 /* NULL dashes array, non-zero length. */
4811 memset(&desc, 0, sizeof(desc));
4812 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 1, &style);
4813 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
4815 count = ID2D1StrokeStyle_GetDashesCount(style);
4816 ok(count == 0, "Unexpected dashes count %u.\n", count);
4818 ID2D1StrokeStyle_Release(style);
4820 ID2D1Factory_Release(factory);
4823 static void test_gradient(void)
4825 ID2D1GradientStopCollection *gradient;
4826 D2D1_GRADIENT_STOP stops[3], stops2[3];
4827 IDXGISwapChain *swapchain;
4828 ID2D1RenderTarget *rt;
4829 ID3D10Device1 *device;
4830 IDXGISurface *surface;
4831 D2D1_COLOR_F color;
4832 unsigned int i;
4833 UINT32 count;
4834 HWND window;
4835 HRESULT hr;
4837 if (!(device = create_device()))
4839 skip("Failed to create device, skipping tests.\n");
4840 return;
4842 window = create_window();
4843 swapchain = create_swapchain(device, window, TRUE);
4844 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
4845 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4846 rt = create_render_target(surface);
4847 ok(!!rt, "Failed to create render target.\n");
4849 stops2[0].position = 0.5f;
4850 set_color(&stops2[0].color, 1.0f, 1.0f, 0.0f, 1.0f);
4851 stops2[1] = stops2[0];
4852 hr = ID2D1RenderTarget_CreateGradientStopCollection(rt, stops2, 2, D2D1_GAMMA_2_2,
4853 D2D1_EXTEND_MODE_CLAMP, &gradient);
4854 ok(SUCCEEDED(hr), "Failed to create stop collection, hr %#x.\n", hr);
4856 count = ID2D1GradientStopCollection_GetGradientStopCount(gradient);
4857 ok(count == 2, "Unexpected stop count %u.\n", count);
4859 /* Request more stops than collection has. */
4860 stops[0].position = 123.4f;
4861 set_color(&stops[0].color, 1.0f, 0.5f, 0.4f, 1.0f);
4862 color = stops[0].color;
4863 stops[2] = stops[1] = stops[0];
4864 ID2D1GradientStopCollection_GetGradientStops(gradient, stops, sizeof(stops)/sizeof(stops[0]));
4865 ok(!memcmp(stops, stops2, sizeof(*stops) * count), "Unexpected gradient stops array.\n");
4866 for (i = count; i < sizeof(stops)/sizeof(stops[0]); i++)
4868 ok(stops[i].position == 123.4f, "%u: unexpected stop position %f.\n", i, stops[i].position);
4869 ok(!memcmp(&stops[i].color, &color, sizeof(color)), "%u: unexpected stop color.\n", i);
4872 ID2D1GradientStopCollection_Release(gradient);
4873 ID2D1RenderTarget_Release(rt);
4875 IDXGISurface_Release(surface);
4876 IDXGISwapChain_Release(swapchain);
4877 ID3D10Device1_Release(device);
4878 DestroyWindow(window);
4881 static void test_draw_geometry(void)
4883 ID2D1TransformedGeometry *transformed_geometry[4];
4884 ID2D1RectangleGeometry *rect_geometry[2];
4885 D2D1_POINT_2F point = {0.0f, 0.0f};
4886 ID2D1SolidColorBrush *brush;
4887 ID2D1PathGeometry *geometry;
4888 IDXGISwapChain *swapchain;
4889 D2D1_MATRIX_3X2_F matrix;
4890 ID2D1GeometrySink *sink;
4891 ID2D1RenderTarget *rt;
4892 ID3D10Device1 *device;
4893 IDXGISurface *surface;
4894 ID2D1Factory *factory;
4895 D2D1_POINT_2F p0, p1;
4896 D2D1_ELLIPSE ellipse;
4897 D2D1_COLOR_F color;
4898 D2D1_RECT_F rect;
4899 ULONG refcount;
4900 HWND window;
4901 HRESULT hr;
4902 BOOL match;
4904 if (!(device = create_device()))
4906 skip("Failed to create device, skipping tests.\n");
4907 return;
4909 window = create_window();
4910 swapchain = create_swapchain(device, window, TRUE);
4911 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
4912 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
4913 rt = create_render_target(surface);
4914 ok(!!rt, "Failed to create render target.\n");
4915 ID2D1RenderTarget_GetFactory(rt, &factory);
4917 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
4918 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
4919 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
4920 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
4921 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
4923 ID2D1RenderTarget_BeginDraw(rt);
4924 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
4925 ID2D1RenderTarget_Clear(rt, &color);
4927 set_point(&p0, 40.0f, 160.0f);
4928 ID2D1RenderTarget_DrawLine(rt, p0, p0, (ID2D1Brush *)brush, 10.0f, NULL);
4929 set_point(&p0, 100.0f, 160.0f);
4930 set_point(&p1, 140.0f, 160.0f);
4931 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
4932 set_point(&p0, 200.0f, 80.0f);
4933 set_point(&p1, 200.0f, 240.0f);
4934 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
4935 set_point(&p0, 260.0f, 240.0f);
4936 set_point(&p1, 300.0f, 80.0f);
4937 ID2D1RenderTarget_DrawLine(rt, p0, p1, (ID2D1Brush *)brush, 10.0f, NULL);
4939 set_rect(&rect, 40.0f, 480.0f, 40.0f, 480.0f);
4940 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
4941 set_rect(&rect, 100.0f, 480.0f, 140.0f, 480.0f);
4942 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
4943 set_rect(&rect, 200.0f, 400.0f, 200.0f, 560.0f);
4944 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
4945 set_rect(&rect, 260.0f, 560.0f, 300.0f, 400.0f);
4946 ID2D1RenderTarget_DrawRectangle(rt, &rect, (ID2D1Brush *)brush, 10.0f, NULL);
4948 set_ellipse(&ellipse, 40.0f, 800.0f, 0.0f, 0.0f);
4949 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
4950 set_ellipse(&ellipse, 120.0f, 800.0f, 20.0f, 0.0f);
4951 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
4952 set_ellipse(&ellipse, 200.0f, 800.0f, 0.0f, 80.0f);
4953 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
4954 set_ellipse(&ellipse, 280.0f, 800.0f, 20.0f, 80.0f);
4955 ID2D1RenderTarget_DrawEllipse(rt, &ellipse, (ID2D1Brush *)brush, 10.0f, NULL);
4957 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
4958 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
4960 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "");
4961 ok(match, "Figure does not match.\n");
4962 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "yGBQUFBQUFBQUFDoYQAA");
4963 ok(match, "Figure does not match.\n");
4964 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0,
4965 "xjIUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4966 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4967 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4968 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4969 "jAEUjAEUjAEUjAEUxjIA");
4970 ok(match, "Figure does not match.\n");
4971 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 2,
4972 "zjECnQETjAEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
4973 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
4974 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
4975 "igEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEVigEV"
4976 "igEVigEVigEVigEVjAETnQECzjEA");
4977 ok(match, "Figure does not match.\n");
4979 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "5mAUjAEUjAEUjAEUjAEUhmIA");
4980 todo_wine ok(match, "Figure does not match.\n");
4981 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0, "vmBkPGQ8ZDxkPGTeYQAA");
4982 todo_wine ok(match, "Figure does not match.\n");
4983 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0,
4984 "5i4UjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4985 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4986 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4987 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
4988 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUhjAA");
4989 todo_wine ok(match, "Figure does not match.\n");
4990 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 0,
4991 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
4992 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
4993 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
4994 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
4995 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
4996 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
4997 ok(match, "Figure does not match.\n");
4999 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0, "iGIQjgEUjAEUjgEQiGIA");
5000 todo_wine ok(match, "Figure does not match.\n");
5001 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0, "yGBQSGA+ZDxkPmDgYQAA");
5002 todo_wine ok(match, "Figure does not match.\n");
5003 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0,
5004 "iDAQjgEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5005 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5006 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5007 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEUjAEU"
5008 "jAEUjAEUjAEUjAEUjAEUjAEUjAEUjgEQiDAA");
5009 todo_wine ok(match, "Figure does not match.\n");
5010 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 10,
5011 "hDAYgwEieyh1LnAybBcIF2gWDhZkFhIWYRUWFV4VGhVbFRwVWRUeFVcVIBVVFCQUUxQmFFEUKBRP"
5012 "FSgVTRUqFUwULBRLFC4USRQwFEgUMBRHFDIURhQyFEUUNBREFDQUQxQ2FEIUNhRBFDgUQBQ4FEAU"
5013 "OBQ/FDoUPhQ6FD4UOhQ+FDoUPhQ6FD0UPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5014 "FDwUPBQ8FDwUPBQ8FD0UOhQ+FDoUPhQ6FD4UOhQ+FDoUPxQ4FEAUOBRAFDgUQRQ2FEIUNhRDFDQU"
5015 "RBQ0FEUUMhRGFDIURxQwFEgUMBRJFC4USxQsFEwVKhVNFSgVTxQoFFEUJhRTFCQUVRUgFVcVHhVZ"
5016 "FRwVWxUaFV4VFhVhFhIWZBYOFmgXCBdsMnAudSh7IoMBGIQw");
5017 todo_wine ok(match, "Figure does not match.\n");
5019 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
5020 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
5021 hr = ID2D1PathGeometry_Open(geometry, &sink);
5022 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
5024 set_point(&point, 40.0f, 160.0f);
5025 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5026 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5028 set_point(&point, 120.0f, 160.0f);
5029 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5030 line_to(sink, 120.0f, 160.0f);
5031 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5033 set_point(&point, 200.0f, 160.0f);
5034 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5035 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5037 set_point(&point, 280.0f, 160.0f);
5038 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5039 line_to(sink, 280.0f, 160.0f);
5040 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5042 set_point(&point, 20.0f, 480.0f);
5043 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5044 line_to(sink, 60.0f, 480.0f);
5045 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5047 set_point(&point, 120.0f, 400.0f);
5048 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5049 line_to(sink, 120.0f, 560.0f);
5050 line_to(sink, 120.0f, 400.0f);
5051 line_to(sink, 120.0f, 560.0f);
5052 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5054 set_point(&point, 180.0f, 480.0f);
5055 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5056 line_to(sink, 220.0f, 480.0f);
5057 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5059 set_point(&point, 280.0f, 400.0f);
5060 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5061 line_to(sink, 280.0f, 560.0f);
5062 line_to(sink, 280.0f, 400.0f);
5063 line_to(sink, 280.0f, 560.0f);
5064 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5066 set_point(&point, 20.0f, 880.0f);
5067 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5068 line_to(sink, 40.0f, 720.0f);
5069 line_to(sink, 60.0f, 880.0f);
5070 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5072 set_point(&point, 100.0f, 720.0f);
5073 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5074 line_to(sink, 120.0f, 880.0f);
5075 line_to(sink, 140.0f, 720.0f);
5076 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5078 set_point(&point, 180.0f, 880.0f);
5079 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5080 line_to(sink, 200.0f, 720.0f);
5081 line_to(sink, 220.0f, 880.0f);
5082 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5084 set_point(&point, 260.0f, 720.0f);
5085 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5086 line_to(sink, 280.0f, 880.0f);
5087 line_to(sink, 300.0f, 720.0f);
5088 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5090 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
5091 hr = ID2D1GeometrySink_Close(sink);
5092 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
5093 ID2D1GeometrySink_Release(sink);
5095 ID2D1RenderTarget_BeginDraw(rt);
5096 ID2D1RenderTarget_Clear(rt, &color);
5097 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, 5.0f, NULL);
5098 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5099 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5100 ID2D1PathGeometry_Release(geometry);
5102 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0, "");
5103 ok(match, "Figure does not match.\n");
5104 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0, "");
5105 ok(match, "Figure does not match.\n");
5106 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0, "");
5107 ok(match, "Figure does not match.\n");
5108 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 0, "q2MKlgEKq2MA");
5109 todo_wine ok(match, "Figure does not match.\n");
5111 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 0, "iGNQUFCIYwAA");
5112 ok(match, "Figure does not match.\n");
5113 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 0,
5114 "qyIKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
5115 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
5116 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKQQpLCkEKSwqWAQqW"
5117 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
5118 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
5119 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQrLIwAA");
5120 ok(match, "Figure does not match.\n");
5121 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 0, "4GLAAuBi");
5122 ok(match, "Figure does not match.\n");
5123 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 0,
5124 "qyIKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
5125 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEK"
5126 "lgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKlgEKSwpBCksKQQqWAQqWAQqW"
5127 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
5128 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqW"
5129 "AQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQqWAQrLIwAA");
5130 ok(match, "Figure does not match.\n");
5132 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 0,
5133 "rycCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
5134 "jAEUiwEKAgqKAQoCCokBCgQKiAEKBAqHAQoGCoYBCgYKhQEKCAqEAQoICoMBCgoKggEKCgqBAQoM"
5135 "CoABCgwKfwoOCn4KDgp9ChAKfAoQCnsKEgp6ChIKeQoUCngKFAp3ChYKdgoWCnUKGAp0ChgKcwoa"
5136 "CnIKGgpxChwKcAocCm8KHgpuCh4KbQogCmwKIAprCiIKagoiCmkKJApoCiQKZwomCmYKJgplCigK"
5137 "ZAooCmMKKgpiCioKYQosCmAKLApfCi4KXgouCl0KMApcCjAKWwoyCloKMgpZCjQKWAo0ClcKNgpW"
5138 "CjYKVQo4ClQKOApTCjoKUgo6ClEKPApQCjwKTwo+Ck4KPgpNCkAKTApACksKQgpKCkIKSQpECkgK"
5139 "RApHCkYKozIA");
5140 ok(match, "Figure does not match.\n");
5141 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 0,
5142 "ozIKRgpHCkQKSApECkkKQgpKCkIKSwpACkwKQApNCj4KTgo+Ck8KPApQCjwKUQo6ClIKOgpTCjgK"
5143 "VAo4ClUKNgpWCjYKVwo0ClgKNApZCjIKWgoyClsKMApcCjAKXQouCl4KLgpfCiwKYAosCmEKKgpi"
5144 "CioKYwooCmQKKAplCiYKZgomCmcKJApoCiQKaQoiCmoKIgprCiAKbAogCm0KHgpuCh4KbwocCnAK"
5145 "HApxChoKcgoaCnMKGAp0ChgKdQoWCnYKFgp3ChQKeAoUCnkKEgp6ChIKewoQCnwKEAp9Cg4KfgoO"
5146 "Cn8KDAqAAQoMCoEBCgoKggEKCgqDAQoICoQBCggKhQEKBgqGAQoGCocBCgQKiAEKBAqJAQoCCooB"
5147 "CgIKiwEUjAEUjQESjgESjwEQkAEQkQEOkgEOkwEMlAEMlQEKlgEKlwEImAEImQEGmgEGmwEEnAEE"
5148 "nQECngECrycA");
5149 ok(match, "Figure does not match.\n");
5150 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 0,
5151 "rycCngECnQEEnAEEmwEGmgEGmQEImAEIlwEKlgEKlQEMlAEMkwEOkgEOkQEQkAEQjwESjgESjQEU"
5152 "jAEUiwEKAgqKAQoCCokBCgQKiAEKBAqHAQoGCoYBCgYKhQEKCAqEAQoICoMBCgoKggEKCgqBAQoM"
5153 "CoABCgwKfwoOCn4KDgp9ChAKfAoQCnsKEgp6ChIKeQoUCngKFAp3ChYKdgoWCnUKGAp0ChgKcwoa"
5154 "CnIKGgpxChwKcAocCm8KHgpuCh4KbQogCmwKIAprCiIKagoiCmkKJApoCiQKZwomCmYKJgplCigK"
5155 "ZAooCmMKKgpiCioKYQosCmAKLApfCi4KXgouCl0KMApcCjAKWwoyCloKMgpZCjQKWAo0ClcKNgpW"
5156 "CjYKVQo4ClQKOApTCjoKUgo6ClEKPApQCjwKTwo+Ck4KPgpNCkAKTApACksKQgpKCkIKSQpECkgK"
5157 "RApHWkZagzEA");
5158 ok(match, "Figure does not match.\n");
5159 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 0,
5160 "gzFaRlpHCkQKSApECkkKQgpKCkIKSwpACkwKQApNCj4KTgo+Ck8KPApQCjwKUQo6ClIKOgpTCjgK"
5161 "VAo4ClUKNgpWCjYKVwo0ClgKNApZCjIKWgoyClsKMApcCjAKXQouCl4KLgpfCiwKYAosCmEKKgpi"
5162 "CioKYwooCmQKKAplCiYKZgomCmcKJApoCiQKaQoiCmoKIgprCiAKbAogCm0KHgpuCh4KbwocCnAK"
5163 "HApxChoKcgoaCnMKGAp0ChgKdQoWCnYKFgp3ChQKeAoUCnkKEgp6ChIKewoQCnwKEAp9Cg4KfgoO"
5164 "Cn8KDAqAAQoMCoEBCgoKggEKCgqDAQoICoQBCggKhQEKBgqGAQoGCocBCgQKiAEKBAqJAQoCCooB"
5165 "CgIKiwEUjAEUjQESjgESjwEQkAEQkQEOkgEOkwEMlAEMlQEKlgEKlwEImAEImQEGmgEGmwEEnAEE"
5166 "nQECngECrycA");
5167 ok(match, "Figure does not match.\n");
5169 set_rect(&rect, 20.0f, 80.0f, 60.0f, 240.0f);
5170 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[0]);
5171 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5173 set_rect(&rect, -1.0f, -1.0f, 1.0f, 1.0f);
5174 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &rect_geometry[1]);
5175 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5177 set_matrix_identity(&matrix);
5178 translate_matrix(&matrix, 160.0f, 640.0f);
5179 scale_matrix(&matrix, 40.0f, 160.0f);
5180 rotate_matrix(&matrix, M_PI / -5.0f);
5181 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5182 (ID2D1Geometry *)rect_geometry[1], &matrix, &transformed_geometry[0]);
5183 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5185 set_matrix_identity(&matrix);
5186 scale_matrix(&matrix, 0.5f, 1.0f);
5187 translate_matrix(&matrix, -80.0f, 0.0f);
5188 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5189 (ID2D1Geometry *)transformed_geometry[0], &matrix, &transformed_geometry[1]);
5190 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5192 set_matrix_identity(&matrix);
5193 rotate_matrix(&matrix, M_PI / 2.0f);
5194 translate_matrix(&matrix, 80.0f, -320.0f);
5195 scale_matrix(&matrix, 2.0f, 0.25f);
5196 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5197 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
5198 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5200 ID2D1RenderTarget_BeginDraw(rt);
5201 ID2D1RenderTarget_Clear(rt, &color);
5202 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)rect_geometry[0], (ID2D1Brush *)brush, 10.0f, NULL);
5203 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, 10.0f, NULL);
5204 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, 5.0f, NULL);
5205 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, 15.0f, NULL);
5206 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5207 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5208 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
5209 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
5210 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
5211 ID2D1RectangleGeometry_Release(rect_geometry[1]);
5212 ID2D1RectangleGeometry_Release(rect_geometry[0]);
5214 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0,
5215 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5216 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5217 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5218 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5219 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5220 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
5221 ok(match, "Figure does not match.\n");
5222 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 32,
5223 "8XYGtQIOrAIXpAIfmwIokwIwigI4gwJA+gFJ8gFR6QEzAiXhATMKJdgBMxMl0AEzGyXHATMkJb8B"
5224 "MysmtgEzNCWvATM8JaYBM0UlngEzTSWVATNWJY0BM14lhAEzZyV8M28lczN4JWszgAElYjOIASZa"
5225 "M5ABJVgtmQElWCWhASVYJaEBJVgloQElWCWhASVYJaEBJVgloQElWCWhASVYJaEBJVglmQEtWCWQ"
5226 "ATNaJogBM2IlgAEzayV4M3MlbzN8JWczhAElXjONASVWM5UBJU0zngElRTOmASU8M68BJTQztgEm"
5227 "KzO/ASUkM8cBJRsz0AElEzPYASUKM+EBJQIz6QFR8gFJ+gFAgwI4igIwkwIomwIfpAIXrAIOtQIG"
5228 "8XYA");
5229 ok(match, "Figure does not match.\n");
5230 match = compare_figure(surface, 0, 160, 160, 320, 0xff652e89, 32,
5231 "ujEBngECnQEDnQEEmwEFmgEHmQEHmAEIlwEKlgEKlQELlAENkwENkgEOkQEQjwERjwESjQETjAEU"
5232 "jAEKAQqKAQoCCokBCgMKiQEKBAqHAQoFCoYBCgYKhgEKBwqEAQoICoMBCgkKgwEKCgqBAQoLCoAB"
5233 "Cg0KfgsNCn4KDgp9ChAKewsQCnsKEQp6ChMKeAoUCngKFAp3ChYKdQoXCnUKGApzChkKcgoaCnIK"
5234 "GwpwChwKbwodCm4LHgptCh8KbAogCmsLIQpqCiIKaQokCmcKJQpnCiUKZgonCmQKKApkCigKYwoq"
5235 "CmEKKwphCisKYAotCl4KLgpdCy8KXAowClsKMQpaCzIKWQozClgKNApXCjYKVgo2ClUKNwpUCjkK"
5236 "Uwo5ClIKOwpQCjwKTws8Ck8KPgpNCj8KTAs/CkwKQQpKCkIKSQtCCkkKRApHCkUKRgpHCkUKRwpE"
5237 "CkgKQwpKCkIKSgpBCksKQApNCj4LTQo+Ck4KPQpQCjsLUAo7ClIKOQpTCjgLUwo4ClUKNgpWCjUK"
5238 "Vwo1ClgKMwpZCjQKWAo0ClkKMwpZCjQKWQozClkKMwpZCjQKWQozClkKMwpZCjQKWQozClkKNApY"
5239 "CjQKWQozClkKNApZCjMKWQozClkKNApZCjMKWQozClkKNApZCjMKWQo0ClgKNApZCjMKWQo0ClkK"
5240 "MwpZCjMKWQo0ClkKMwpZCjMKWQo0ClkKMwpZCjQKWAo0ClkKMwpYCjUKVwo1ClYKNgpVCjgKUws4"
5241 "ClMKOQpSCjsKUAs7ClAKPQpOCj4KTQs+Ck0KQApLCkEKSgpCCkoKQwpICkQKRwpFCkcKRgpFCkcK"
5242 "RApJCkILSQpCCkoKQQpMCj8LTAo/Ck0KPgpPCjwLTwo8ClAKOwpSCjkKUwo5ClQKNwpVCjYKVgo2"
5243 "ClcKNApYCjMKWQoyC1oKMQpbCjAKXAovC10KLgpeCi0KYAorCmEKKwphCioKYwooCmQKKApkCicK"
5244 "ZgolCmcKJQpnCiQKaQoiCmoKIQtrCiAKbAofCm0KHgtuCh0KbwocCnAKGwpyChoKcgoZCnMKGAp1"
5245 "ChcKdQoWCncKFAp4ChQKeAoTCnoKEQp7ChALewoQCn0KDgp+Cg0LfgoNCoABCgsKgQEKCgqDAQoJ"
5246 "CoMBCggKhAEKBwqGAQoGCoYBCgUKhwEKBAqJAQoDCokBCgIKigEKAQqMARSMARONARKPARGPARCR"
5247 "AQ6SAQ2TAQ2UAQuVAQqWAQqXAQiYAQeZAQeaAQWbAQSdAQOdAQKeAQG6MQAA");
5248 ok(match, "Figure does not match.\n");
5249 match = compare_figure(surface, 160, 160, 320, 320, 0xff652e89, 64,
5250 "82ICvQIEugIHuAIJtgIKtAINsgIPsAIRrQITrAIVqQIYpwIZpgIbowIeoQIgnwIhnQIkmwImmAIp"
5251 "lgIVARSVAhUDFJICFQUVkAIVBxSPAhUJFIwCFQwUigIVDRWHAhYPFIYCFRIUhAIVFBSBAhUWFf8B"
5252 "FRgU/gEVGhT7ARUcFfkBFR4U9wEWIBT1ARUjFPMBFSQV8AEVJxTvARUpFOwBFisU6gEVLRXoARUv"
5253 "FOYBFjEU5AEVMxXiARU1FOABFTgU3gEVOhTbARY7FdkBFT4U2AEVQBTVARZCFNMBFUQV0QEVRhTP"
5254 "ARVJFM0BFUoVygEWTBTJARVPFMcBFVEUxAEVUxXCARVVFMEBFVcUvgEVWRW8ARVbFbkBFl0UuAEV"
5255 "YBS2ARVhFbMBFWQUsgEVZhSwARVoFK0BFWoVqwEVbBSpARZuFKcBFXAVpQEVchWiARV1FKEBFXcU"
5256 "nwEVeBWcARV7FJsBFX0UmAEWfxSWARWBARWUARWDARSSARWGARSQARWHARWOARWJARWLARWMARSK"
5257 "ARWOARSHARaPARWFARWSARSEARWUARSBARWXARR/FZgBFX0VmgEUexWdARR5FZ4BFXYWoAEVdBWj"
5258 "ARRzFaUBFHAVpwEVbhWpARRtFasBFGoVrgEUaBWvARVmFbEBFGcUsgEUZxSxARVmFbEBFWYUsgEU"
5259 "ZxSyARRnFLEBFWYVsQEUZxSyARRnFLIBFGcUsQEVZhWxARRnFLIBFGcUsQEVZhWxARVmFLIBFGcU"
5260 "sgEUZxSxARVmFbEBFGcUsgEUZxSyARRmFbEBFWYVsQEUZxSyARRnFLEBFWYVsQEUZxSyARRnFLIB"
5261 "FGcUsQEVZhWxARRnFLIBFGcUsgEUZhWxARVmFbEBFGcUsgEUZxSxARVmFa8BFWgUrgEVahSrARVt"
5262 "FKkBFW4VpwEVcBSlARVzFKMBFXQVoAEWdhWeARV5FJ0BFXsUmgEVfRWYARV/FJcBFYEBFJQBFYQB"
5263 "FJIBFYUBFY8BFocBFI4BFYoBFIwBFYsBFYkBFY4BFYcBFZABFIYBFZIBFIMBFZQBFYEBFZYBFH8W"
5264 "mAEUfRWbARR7FZwBFXgVnwEUdxWhARR1FaIBFXIVpQEVcBWnARRuFqkBFGwVqwEVahWtARRoFbAB"
5265 "FGYVsgEUZBWzARVhFbYBFGAVuAEUXRa5ARVbFbwBFVkVvgEUVxXBARRVFcIBFVMVxAEUURXHARRP"
5266 "FckBFEwWygEVShXNARRJFc8BFEYV0QEVRBXTARRCFtUBFEAV2AEUPhXZARU7FtsBFDoV3gEUOBXg"
5267 "ARQ1FeIBFTMV5AEUMRbmARQvFegBFS0V6gEUKxbsARQpFe8BFCcV8AEVJBXzARQjFfUBFCAW9wEU"
5268 "HhX5ARUcFfsBFBoV/gEUGBX/ARUWFYECFBQVhAIUEhWGAhQPFocCFQ0VigIUDBWMAhQJFY8CFAcV"
5269 "kAIVBRWSAhQDFZUCFAEVlgIpmAImmwIknQIhnwIgoQIeowIbpgIZpwIYqQIVrAITrQIRsAIPsgIN"
5270 "tAIKtgIJuAIHugIEvQIC82IA");
5271 ok(match, "Figure does not match.\n");
5273 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
5274 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
5275 hr = ID2D1PathGeometry_Open(geometry, &sink);
5276 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
5278 set_point(&point, 20.0f, 80.0f);
5279 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5280 quadratic_to(sink, 40.0f, 80.0f, 60.0f, 80.0f);
5281 quadratic_to(sink, 60.0f, 160.0f, 60.0f, 240.0f);
5282 quadratic_to(sink, 40.0f, 240.0f, 20.0f, 240.0f);
5283 quadratic_to(sink, 20.0f, 160.0f, 20.0f, 80.0f);
5284 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5286 set_point(&point, 100.0f, 80.0f);
5287 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5288 quadratic_to(sink, 105.0f, 80.0f, 140.0f, 80.0f);
5289 quadratic_to(sink, 140.0f, 100.0f, 140.0f, 240.0f);
5290 quadratic_to(sink, 135.0f, 240.0f, 100.0f, 240.0f);
5291 quadratic_to(sink, 100.0f, 220.0f, 100.0f, 80.0f);
5292 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5294 set_point(&point, 180.0f, 80.0f);
5295 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5296 quadratic_to(sink, 215.0f, 80.0f, 220.0f, 80.0f);
5297 quadratic_to(sink, 220.0f, 220.0f, 220.0f, 240.0f);
5298 quadratic_to(sink, 185.0f, 240.0f, 180.0f, 240.0f);
5299 quadratic_to(sink, 180.0f, 100.0f, 180.0f, 80.0f);
5300 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5302 set_point(&point, 260.0f, 80.0f);
5303 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5304 quadratic_to(sink, 280.0f, 80.0f, 300.0f, 80.0f);
5305 quadratic_to(sink, 300.0f, 160.0f, 300.0f, 240.0f);
5306 quadratic_to(sink, 280.0f, 240.0f, 260.0f, 240.0f);
5307 quadratic_to(sink, 260.0f, 160.0f, 260.0f, 80.0f);
5308 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5310 set_point(&point, 20.0f, 400.0f);
5311 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5312 quadratic_to(sink, 40.0f, 420.0f, 60.0f, 400.0f);
5313 quadratic_to(sink, 55.0f, 480.0f, 60.0f, 560.0f);
5314 quadratic_to(sink, 40.0f, 540.0f, 20.0f, 560.0f);
5315 quadratic_to(sink, 25.0f, 480.0f, 20.0f, 400.0f);
5316 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5318 set_point(&point, 100.0f, 400.0f);
5319 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5320 quadratic_to(sink, 105.0f, 420.0f, 140.0f, 400.0f);
5321 quadratic_to(sink, 135.0f, 420.0f, 140.0f, 560.0f);
5322 quadratic_to(sink, 135.0f, 540.0f, 100.0f, 560.0f);
5323 quadratic_to(sink, 105.0f, 540.0f, 100.0f, 400.0f);
5324 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5326 set_point(&point, 180.0f, 400.0f);
5327 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5328 quadratic_to(sink, 215.0f, 420.0f, 220.0f, 400.0f);
5329 quadratic_to(sink, 215.0f, 540.0f, 220.0f, 560.0f);
5330 quadratic_to(sink, 185.0f, 540.0f, 180.0f, 560.0f);
5331 quadratic_to(sink, 185.0f, 420.0f, 180.0f, 400.0f);
5332 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5334 set_point(&point, 260.0f, 400.0f);
5335 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5336 quadratic_to(sink, 280.0f, 420.0f, 300.0f, 400.0f);
5337 quadratic_to(sink, 295.0f, 480.0f, 300.0f, 560.0f);
5338 quadratic_to(sink, 280.0f, 540.0f, 260.0f, 560.0f);
5339 quadratic_to(sink, 265.0f, 480.0f, 260.0f, 400.0f);
5340 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5342 set_point(&point, 20.0f, 720.0f);
5343 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5344 quadratic_to(sink, 40.0f, 700.0f, 60.0f, 720.0f);
5345 quadratic_to(sink, 65.0f, 800.0f, 60.0f, 880.0f);
5346 quadratic_to(sink, 40.0f, 900.0f, 20.0f, 880.0f);
5347 quadratic_to(sink, 15.0f, 800.0f, 20.0f, 720.0f);
5348 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5350 set_point(&point, 100.0f, 720.0f);
5351 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5352 quadratic_to(sink, 105.0f, 700.0f, 140.0f, 720.0f);
5353 quadratic_to(sink, 145.0f, 740.0f, 140.0f, 880.0f);
5354 quadratic_to(sink, 135.0f, 900.0f, 100.0f, 880.0f);
5355 quadratic_to(sink, 95.0f, 860.0f, 100.0f, 720.0f);
5356 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5358 set_point(&point, 180.0f, 720.0f);
5359 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5360 quadratic_to(sink, 215.0f, 700.0f, 220.0f, 720.0f);
5361 quadratic_to(sink, 225.0f, 860.0f, 220.0f, 880.0f);
5362 quadratic_to(sink, 185.0f, 900.0f, 180.0f, 880.0f);
5363 quadratic_to(sink, 175.0f, 740.0f, 180.0f, 720.0f);
5364 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5366 set_point(&point, 260.0f, 720.0f);
5367 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5368 quadratic_to(sink, 280.0f, 700.0f, 300.0f, 720.0f);
5369 quadratic_to(sink, 305.0f, 800.0f, 300.0f, 880.0f);
5370 quadratic_to(sink, 280.0f, 900.0f, 260.0f, 880.0f);
5371 quadratic_to(sink, 255.0f, 800.0f, 260.0f, 720.0f);
5372 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
5374 hr = ID2D1GeometrySink_Close(sink);
5375 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
5376 ID2D1GeometrySink_Release(sink);
5378 ID2D1RenderTarget_BeginDraw(rt);
5379 ID2D1RenderTarget_Clear(rt, &color);
5380 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, 10.0f, NULL);
5381 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5382 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5383 ID2D1PathGeometry_Release(geometry);
5385 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 0,
5386 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5387 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5388 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5389 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5390 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5391 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
5392 ok(match, "Figure does not match.\n");
5393 match = compare_figure(surface, 160, 0, 160, 160, 0xff652e89, 0,
5394 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5395 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5396 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5397 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5398 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5399 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
5400 ok(match, "Figure does not match.\n");
5401 match = compare_figure(surface, 320, 0, 160, 160, 0xff652e89, 0,
5402 "vi5kPGQ8ZDxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5403 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5404 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5405 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5406 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5407 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
5408 ok(match, "Figure does not match.\n");
5409 match = compare_figure(surface, 480, 0, 160, 160, 0xff652e89, 0,
5410 "yC5aRlpGWjxkPGQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5411 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5412 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5413 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8"
5414 "FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwU"
5415 "PBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8FDwUPBQ8ZDxkPGQ8ZDxk3i8A");
5416 ok(match, "Figure does not match.\n");
5418 match = compare_figure(surface, 0, 160, 160, 160, 0xff652e89, 64,
5419 "3SoDYAM6B1gHOgtQCzoPSA87EkASPBc2FzwcLBw8IiAiPWI+Yj5iPhQBOAEUPhQKJgoUPxQ4FEAU"
5420 "OBRAFDgUQBQ4FEAUOBRBFDYUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRDFDQURBQ0FEQUNBREFDQURBQ0"
5421 "FEQUNBREFDQURBQ0FEQUNBREFDQURRQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIU"
5422 "RhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRG"
5423 "FDIURRQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEMUNhRCFDYUQhQ2FEIU"
5424 "NhRCFDYUQhQ2FEEUOBRAFDgUQBQ4FEAUOBRAFDgUPxQKJgoUPhQBOAEUPmI+Yj5iPSIgIjwcLBw8"
5425 "FzYXPBJAEjsPSA86C1ALOgdYBzoDYAPdKgAA");
5426 ok(match, "Figure does not match.\n");
5427 match = compare_figure(surface, 160, 160, 160, 160, 0xff652e89, 1024,
5428 "uxUBnwECngEDnQEEnAEFmwEGmwEGmgEHmQEImAEJlwEKlgELlQEMlQEMlAENkwEOkgEPkQEQkAER"
5429 "VQQ2Ek0KOBJFEDkTPRY6FDUcOxUrJDwYHi09Yj5iP2BAQwkUQDgUFEAUOBRAFDcUQRQ3FEEUNxRC"
5430 "FDYUQhQ2FEIUNhRCFDUUQxQ1FEMUNRRDFDUUQxQ1FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQU"
5431 "NBREFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQ0"
5432 "FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQ0FEQUNBREFDQU"
5433 "RBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRDFDUUQxQ1FEMUNRRDFDUUQhQ2FEIUNhRC"
5434 "FDYUQhQ3FEEUNxRBFDcUQBQ4FEAUFDhAFAlDQGA/Yj5iPS0eGDwkKxU7HDUUOhY9EzkQRRI4Ck0S"
5435 "NgRVEZABEJEBD5IBDpMBDZQBDJUBDJUBC5YBCpcBCZgBCJkBB5oBBpsBBpsBBZwBBJ0BA54BAp8B"
5436 "AbsV");
5437 ok(match, "Figure does not match.\n");
5438 match = compare_figure(surface, 320, 160, 160, 160, 0xff652e89, 1024,
5439 "pBYBngECnQEDnAEEmwEFmgEGmQEGmQEHmAEIlwEJlgEKlQELlAEMkwEMkwENkgEOkQEPkAEQNgRV"
5440 "ETcKTRI4EEUSOhY9EzscNRQ8JCsVPS0eGD5iPmI/YEAUCUNAFBQ4QBQ4FEEUNxRBFDcUQRQ3FEEU"
5441 "NhRCFDYUQhQ2FEMUNRRDFDUUQxQ1FEMUNRRDFDUUQxQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0"
5442 "FEQUNBREFDQURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxREFDQU"
5443 "RBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxREFDQURBQ0FEQUNBRE"
5444 "FDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQUQxQ1FEMUNRRDFDUUQxQ1FEMUNRRDFDYUQhQ2FEIU"
5445 "NhRBFDcUQRQ3FEEUNxRBFDgUQDgUFEBDCRRAYD9iPmI+GB4tPRUrJDwUNRw7Ez0WOhJFEDgSTQo3"
5446 "EVUENhCQAQ+RAQ6SAQ2TAQyTAQyUAQuVAQqWAQmXAQiYAQeZAQaZAQaaAQWbAQScAQOdAQKeAQGk"
5447 "FgAA");
5448 ok(match, "Figure does not match.\n");
5449 match = compare_figure(surface, 480, 160, 160, 160, 0xff652e89, 64,
5450 "wCsDmQEHlQELkQEPSwJAEkgLNhc8HCwcPCIgIj1iPmI+Yj4UATgBFD4UCiYKFD8UOBRAFDgUQBQ4"
5451 "FEAUOBRAFDgUQRQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDYUQxQ0FEQUNBREFDQURBQ0FEQUNBREFDQU"
5452 "RBQ0FEQUNBREFDQURBQ0FEUUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRG"
5453 "FDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEUU"
5454 "NBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBRDFDYUQhQ2FEIUNhRCFDYUQhQ2"
5455 "FEIUNhRBFDgUQBQ4FEAUOBRAFDgUQBQ4FD8UCiYKFD4UATgBFD5iPmI+Yj0iICI8HCwcPBc2FzwS"
5456 "QBI7D0gPOgtQCzoHWAc6A2AD3SoA");
5457 ok(match, "Figure does not match.\n");
5459 match = compare_figure(surface, 0, 320, 160, 160, 0xff652e89, 64,
5460 "3SkmcThiRFdOTVhEICAgPhwsHDwXNhc8FDwUOxQ+FDoUPhQ6FD4UOhQ+FDoUPhQ5FEAUOBRAFDgU"
5461 "QBQ4FEAUOBRAFDcUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDUURBQ0FEQUNBREFDQURBQ0FEQUNBRE"
5462 "FDQURBQ0FEQUNBREFDQURBQzFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYU"
5463 "MhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQz"
5464 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRCFDYUQhQ2FEIUNhRCFDYU"
5465 "QhQ2FEIUNxRAFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPhQ6FD4UOhQ+FDsUPBQ8FzYXPBws"
5466 "HD4gICBEWE1OV0RiOHEm3SkA");
5467 ok(match, "Figure does not match.\n");
5468 match = compare_figure(surface, 160, 320, 160, 160, 0xff652e89, 1024,
5469 "zykoczhkRVhQTlpEFx4tPRUrJDwUNRw7FDwVOxQ+FDoUPhQ5FEAUOBRAFDgUQBQ4FEAUOBRBFDcU"
5470 "QRQ3FEEUNhRCFDYUQhQ2FEIUNhRDFDUUQxQ1FEMUNRRDFDUUQxQ0FEQUNBREFDQURBQ0FEQUNBRE"
5471 "FDQURBQ0FEQUNBREFDQURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUU"
5472 "MxRFFDMURBQ0FEQUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURBQ0"
5473 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEMUNRRDFDUUQxQ1FEMUNRRDFDYU"
5474 "QhQ2FEIUNhRCFDYUQRQ3FEEUNxRBFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDsVPBQ7HDUUPCQr"
5475 "FT0tHhdEWk5QWEVkOHMozykA");
5476 ok(match, "Figure does not match.\n");
5477 match = compare_figure(surface, 320, 320, 160, 160, 0xff652e89, 1024,
5478 "6SkobThfRVNQSFpALR4XPSQrFTscNRQ7FTwUOhQ+FDoUPhQ5FEAUOBRAFDgUQBQ4FEAUNxRBFDcU"
5479 "QRQ3FEEUNxRCFDYUQhQ2FEIUNRRDFDUUQxQ1FEMUNRRDFDUUQxQ1FEQUNBREFDQURBQ0FEQUNBRE"
5480 "FDQURBQ0FEQUNBREFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUU"
5481 "MxRFFDQURBQ0FEQUNBRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDMURRQzFEUUMxRFFDQURBQ0"
5482 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ1FEMUNRRDFDUUQxQ1FEMUNRRDFDUU"
5483 "QhQ2FEIUNhRCFDcUQRQ3FEEUNxRBFDcUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPBU7FDUcOxUr"
5484 "JD0XHi1AWkhQU0VfOG0o6SkA");
5485 ok(match, "Figure does not match.\n");
5486 match = compare_figure(surface, 480, 320, 160, 160, 0xff652e89, 64,
5487 "3SkmcThiRFdOTVhGHiAgRhQsHDwXNhc8FDwUOxQ+FDoUPhQ6FD4UOhQ+FDoUPhQ5FEAUOBRAFDgU"
5488 "QBQ4FEAUOBRAFDcUQhQ2FEIUNhRCFDYUQhQ2FEIUNhRCFDUURBQ0FEQUNBREFDQURBQ0FEQUNBRE"
5489 "FDQURBQ0FEQUNBREFDQURBQzFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYU"
5490 "MhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQyFEYUMhRGFDIURhQz"
5491 "FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNBREFDQURBQ0FEQUNRRCFDYUQhQ2FEIUNhRCFDYU"
5492 "QhQ2FEIUNxRAFDgUQBQ4FEAUOBRAFDgUQBQ5FD4UOhQ+FDoUPhQ6FD4UOhQ+FDsUPBQ8FzYXPBws"
5493 "HD4gICBEWE1OV0RiOHEm3SkA");
5494 ok(match, "Figure does not match.\n");
5496 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
5497 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
5498 hr = ID2D1PathGeometry_Open(geometry, &sink);
5499 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
5501 set_point(&point, -0.402914f, 0.915514f);
5502 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
5503 quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
5504 quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f);
5505 quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f);
5506 quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f);
5507 quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f);
5508 quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f);
5509 quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f);
5510 quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f);
5511 quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f);
5512 quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f);
5513 quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f);
5514 quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f);
5515 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5517 hr = ID2D1GeometrySink_Close(sink);
5518 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
5519 ID2D1GeometrySink_Release(sink);
5521 set_matrix_identity(&matrix);
5522 translate_matrix(&matrix, 40.0f, 160.0f);
5523 scale_matrix(&matrix, 20.0f, 80.0f);
5524 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5525 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]);
5526 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5528 set_matrix_identity(&matrix);
5529 translate_matrix(&matrix, 160.0f, 640.0f);
5530 scale_matrix(&matrix, 40.0f, 160.0f);
5531 rotate_matrix(&matrix, M_PI / -5.0f);
5532 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5533 (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]);
5534 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5535 ID2D1PathGeometry_Release(geometry);
5537 set_matrix_identity(&matrix);
5538 scale_matrix(&matrix, 0.5f, 1.0f);
5539 translate_matrix(&matrix, -80.0f, 0.0f);
5540 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5541 (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
5542 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5544 set_matrix_identity(&matrix);
5545 rotate_matrix(&matrix, M_PI / 2.0f);
5546 translate_matrix(&matrix, 80.0f, -320.0f);
5547 scale_matrix(&matrix, 2.0f, 0.25f);
5548 hr = ID2D1Factory_CreateTransformedGeometry(factory,
5549 (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]);
5550 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
5552 ID2D1RenderTarget_BeginDraw(rt);
5553 ID2D1RenderTarget_Clear(rt, &color);
5554 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[0], (ID2D1Brush *)brush, 2.0f, NULL);
5555 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[1], (ID2D1Brush *)brush, 10.0f, NULL);
5556 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[2], (ID2D1Brush *)brush, 5.0f, NULL);
5557 ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)transformed_geometry[3], (ID2D1Brush *)brush, 15.0f, NULL);
5558 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5559 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5560 ID2D1TransformedGeometry_Release(transformed_geometry[3]);
5561 ID2D1TransformedGeometry_Release(transformed_geometry[2]);
5562 ID2D1TransformedGeometry_Release(transformed_geometry[1]);
5563 ID2D1TransformedGeometry_Release(transformed_geometry[0]);
5565 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 128,
5566 "yjIJkQEHBwaIAQUSBYMBBBYEggEEFgSCAQQWBIIBBBYEggEEFgSCAQQWBIIBBBYEggEEFgSCAQQW"
5567 "BIIBBBYEggEEFgSDAQQVBIMBBBUEgwEEFQSDAQQVBIMBBBUEgwEEFQSDAQQVBIMBBBUEgwEEFQSD"
5568 "AQQVBIQBBBQEhAEEFASEAQQTBIUBBBMEhQEEEwSFAQQTBIUBBBMEhQEEEwSGAQQSBIYBBBIEhgEE"
5569 "EgSGAQQSBIYBBBIEhgEEEgSGAQQRBIgBBBAEiAEEEASIAQQQBIkBBA4EigEEDgSLAQQMBIwBBAwE"
5570 "jQEECgSOAQQJBJABBAgEkAEFBgSSAQQGBJMBBAQElAEEBASVAQQDBJUBBAIElwEEAQSXAQiZAQeZ"
5571 "AQaaAQaaAQaaAQabAQWbAQWbAQWbAQWaAQeZAQeZAQeZAQiXAQQBBJYBBAMElQEEAwWRAQUGBY0B"
5572 "BQwFhwEFEgSCAQUXBYABBBoFfgUYBIIBBhEFiAEUpTEA");
5573 ok(match, "Figure does not match.\n");
5574 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 512,
5575 "yJIBArkCDa4CGKMCIZoCK5ECM4gCO4ECQ/gBS/EBUesBLAYl5QEsDiPeASwWIdkBLBwh0wEsISHO"
5576 "ASsgKMsBKR4vyAEnHDPIASUaNMsBIxg1mQEFMCIUN54BCygiDzijAREhIgY9qAEYGWGuAR4RXbMB"
5577 "JAhbuQGAAcABesYBc84Ba9YBTvQBP4MCOIoCNI4CM5ACMZICL5QCLZYCK5kCKJsCJ54CI6MCHq8C"
5578 "EraSAQAA");
5579 ok(match, "Figure does not match.\n");
5580 match = compare_figure(surface, 0, 160, 160, 320, 0xff652e89, 512,
5581 "xWkCmwEFmAEJlQELlAENkgEOkQEPjwESjQETjAEVigELAQqJAQsCCogBCwQKhwEKBQqGAQoGCoYB"
5582 "CgcKhAEKCAqEAQoIC4IBCgoKggEKCgqBAQoMCoABCgwKfwoNCn8KDgp9Cg8KfQoPCnwKEQp7ChEK"
5583 "egoSCnoKEwp4ChQKeAoUCncLFQp2ChYKdgoWCnYKFwp2ChYKdgoWCncKFgp2ChYKdgoWCncKFQt2"
5584 "ChYKdwoVCncKFQp4ChUKdwoVCncKFQp4ChUKdwoVCngKFAp4ChUKeAoUCngKFAp4CxMKeQoUCngK"
5585 "FAp5ChMKeQoUCnkKEwp5ChMKegoSC3kKEwp6ChIKegoSCnoLEgp6ChIKegoSCnsKEQp7ChEKfAoQ"
5586 "CnwKEAp9Cg8KfQoPCn4KDgp+Cg4KfwoOCn4KDgp/Cg0KfwoNCoABCgwKgAEKDAqBAQoLCoEBCgsK"
5587 "gQELCgqCAQoKCoIBCwkKgwEKCQqDAQoJCoQBCggKhAEKCQqEAQsHCoUBCwYKhgELBQqHAQsECogB"
5588 "CwMKiQELAgqLAQoBCowBFI0BE44BE44BEo8BEZABEJEBD5IBDpMBDpMBDZMBDZQBDJQBDZQBDJQB"
5589 "DBUCfgwSBH4MEQV/DA4GgAEMDAiAAQ0KCYEBDAgLgQENBQ2BAQ0EDoIBDQEPgwEdgwEdgwEdgwEc"
5590 "hAEKAgQCCoUBCgYKhgEKBgqGAQoFC4YBCgUKhwEKBAqIAQoECogBCgMKiQEKAwqIAQoDCokBCgMK"
5591 "iQEKAgqJAQoCCooBCgIKiQEKAgqKAQoBCosBCgEKigEKAQqLARSMARSLARSMAROMARONARKOARGO"
5592 "ARGPARCQAQ6RAQ2YAQTEZAAA");
5593 ok(match, "Figure does not match.\n");
5594 match = compare_figure(surface, 160, 160, 320, 320, 0xff652e89, 1024,
5595 "ytABA7gCCbICD60CFKkCF6cCGqMCHqACIZ0CJJoCJpgCKZUCFgIUkgIWBBWPAhYHFI4CFQoUjAIV"
5596 "DBSKAhUNFYgCFQ8UhwIVERSFAhUTFIMCFRQVgQIUFxSAAhQZFP4BFBoV/AEUHBT7ARQeFPkBFB8V"
5597 "9wEUIRT2ARQjFPQBFSMV8gEVJRTxARUnFPABFCgV7gEUKhTtARQsFOwBFCwV7AEULBTsARUsFOwB"
5598 "FSsV7AEULBTtARQsFO0BFCsU7QEVKxTtARUqFe0BFSoU7gEUKxTuARQqFe4BFCoU7wEUKhTuARUp"
5599 "FO8BFSkU7wEVKBXvARUoFPABFCkU8AEUKBTxARQoFPEBFCcV8QEUJxTxARUnFPEBFSYU8gEVJhTy"
5600 "ARUlFfIBFSUU8wEUJRXzARQlFPQBFCUU9AEUJBT1ARQkFPUBFCMU9gEUIhT2ARUhFPcBFSAU+AEV"
5601 "HxT5ARUeFPoBFR4U+gEVHRT7ARUcFPwBFRsU/QEVGhT+ARUZFP8BFBkUgAIUGBSBAhQXFIICFBcU"
5602 "ggIUFhSDAhQVFIQCFBQUhQIUExSGAhQSFIcCFBIUhwIUERSIAhUPFIkCFg0UigIXCxSNAhYJFI8C"
5603 "FggUkAIXBRSSAhcDFJQCFwEUlgIrlwIpmgImnAIkngIjnwIhoQIfowIepAIcpgIbpgIaqAIZqAIZ"
5604 "qAIYKwP7ARgnBf0BGCMI/QEZHgz+ARgbD/8BGBcSgAIYEhaAAhoNGIICGggcgwIaBB+DAjyEAjyF"
5605 "AjqGAjmIAjiIAiECFIkCFAIIBBSKAhQNFIsCFAwUjAIUCxSNAhQKFI4CFAkUjwIUBxWQAhQGFZEC"
5606 "FAUVkQIUBRWRAhQFFZECFQMVkwIUAxWTAhQDFZMCFAIVlAIVARWVAiqVAimWAimWAiiYAiaZAiaZ"
5607 "AiWaAiScAiKdAiGeAh+hAhyjAhmuAg3GxgEA");
5608 ok(match, "Figure does not match.\n");
5610 ID2D1SolidColorBrush_Release(brush);
5611 ID2D1RenderTarget_Release(rt);
5612 refcount = ID2D1Factory_Release(factory);
5613 ok(!refcount, "Factory has %u references left.\n", refcount);
5614 IDXGISurface_Release(surface);
5615 IDXGISwapChain_Release(swapchain);
5616 ID3D10Device1_Release(device);
5617 DestroyWindow(window);
5620 static void test_gdi_interop(void)
5622 ID2D1GdiInteropRenderTarget *interop;
5623 D2D1_RENDER_TARGET_PROPERTIES desc;
5624 IWICImagingFactory *wic_factory;
5625 IWICBitmapLock *wic_lock;
5626 IWICBitmap *wic_bitmap;
5627 ID2D1RenderTarget *rt;
5628 ID2D1Factory *factory;
5629 ID3D10Device1 *device;
5630 D2D1_COLOR_F color;
5631 HRESULT hr;
5632 BOOL match;
5633 RECT rect;
5634 HDC dc;
5636 if (!(device = create_device()))
5638 skip("Failed to create device, skipping tests.\n");
5639 return;
5642 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
5643 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
5645 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
5646 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
5647 &IID_IWICImagingFactory, (void **)&wic_factory);
5648 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
5649 hr = IWICImagingFactory_CreateBitmap(wic_factory, 16, 16,
5650 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap);
5651 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
5652 IWICImagingFactory_Release(wic_factory);
5654 /* WIC target, default usage */
5655 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
5656 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
5657 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
5658 desc.dpiX = 0.0f;
5659 desc.dpiY = 0.0f;
5660 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
5661 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
5663 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory, wic_bitmap, &desc, &rt);
5664 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5666 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5667 ok(SUCCEEDED(hr), "Failed to get gdi interop interface, hr %#x.\n", hr);
5669 ID2D1RenderTarget_BeginDraw(rt);
5670 dc = (void *)0xdeadbeef;
5671 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
5672 ok(FAILED(hr), "GetDC() was expected to fail, hr %#x.\n", hr);
5673 todo_wine
5674 ok(dc == NULL, "Expected NULL dc, got %p.\n", dc);
5675 ID2D1GdiInteropRenderTarget_Release(interop);
5676 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5678 ID2D1RenderTarget_Release(rt);
5680 /* WIC target, gdi compatible */
5681 desc.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
5683 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory, wic_bitmap, &desc, &rt);
5684 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5686 hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1GdiInteropRenderTarget, (void **)&interop);
5687 ok(SUCCEEDED(hr), "Failed to get gdi interop interface, hr %#x.\n", hr);
5689 ID2D1RenderTarget_BeginDraw(rt);
5690 dc = NULL;
5691 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
5692 ok(SUCCEEDED(hr), "GetDC() was expected to succeed, hr %#x.\n", hr);
5693 ok(dc != NULL, "Expected NULL dc, got %p.\n", dc);
5694 ID2D1GdiInteropRenderTarget_ReleaseDC(interop, NULL);
5695 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5697 ID2D1RenderTarget_BeginDraw(rt);
5698 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
5699 ID2D1RenderTarget_Clear(rt, &color);
5700 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5702 match = compare_wic_bitmap(wic_bitmap, "54034063dbc1c1bb61cb60ec57e4498678dc2b13");
5703 ok(match, "Bitmap does not match.\n");
5705 /* Do solid fill using GDI */
5706 ID2D1RenderTarget_BeginDraw(rt);
5708 hr = ID2D1GdiInteropRenderTarget_GetDC(interop, D2D1_DC_INITIALIZE_MODE_COPY, &dc);
5709 ok(SUCCEEDED(hr), "GetDC() was expected to succeed, hr %#x.\n", hr);
5711 SetRect(&rect, 0, 0, 16, 16);
5712 FillRect(dc, &rect, GetStockObject(BLACK_BRUSH));
5713 ID2D1GdiInteropRenderTarget_ReleaseDC(interop, NULL);
5715 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5717 match = compare_wic_bitmap(wic_bitmap, "60cacbf3d72e1e7834203da608037b1bf83b40e8");
5718 ok(match, "Bitmap does not match.\n");
5720 /* Bitmap is locked at BeginDraw(). */
5721 hr = IWICBitmap_Lock(wic_bitmap, NULL, WICBitmapLockRead, &wic_lock);
5722 ok(SUCCEEDED(hr), "Expected bitmap to be unlocked, hr %#x.\n", hr);
5723 IWICBitmapLock_Release(wic_lock);
5725 ID2D1RenderTarget_BeginDraw(rt);
5726 hr = IWICBitmap_Lock(wic_bitmap, NULL, WICBitmapLockRead, &wic_lock);
5727 todo_wine
5728 ok(hr == WINCODEC_ERR_ALREADYLOCKED, "Expected bitmap to be locked, hr %#x.\n", hr);
5729 if (SUCCEEDED(hr))
5730 IWICBitmapLock_Release(wic_lock);
5731 ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5733 ID2D1GdiInteropRenderTarget_Release(interop);
5734 ID2D1RenderTarget_Release(rt);
5736 IWICBitmap_Release(wic_bitmap);
5737 ID2D1Factory_Release(factory);
5740 static void test_layer(void)
5742 ID2D1Factory *factory, *layer_factory;
5743 IDXGISwapChain *swapchain;
5744 ID2D1RenderTarget *rt;
5745 ID3D10Device1 *device;
5746 IDXGISurface *surface;
5747 ID2D1Layer *layer;
5748 D2D1_SIZE_F size;
5749 ULONG refcount;
5750 HWND window;
5751 HRESULT hr;
5753 if (!(device = create_device()))
5755 skip("Failed to create device, skipping tests.\n");
5756 return;
5758 window = create_window();
5759 swapchain = create_swapchain(device, window, TRUE);
5760 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
5761 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
5762 rt = create_render_target(surface);
5763 ok(!!rt, "Failed to create render target.\n");
5764 ID2D1RenderTarget_GetFactory(rt, &factory);
5766 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
5767 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
5769 hr = ID2D1RenderTarget_CreateLayer(rt, NULL, &layer);
5770 ok(SUCCEEDED(hr), "Failed to create layer, hr %#x.\n", hr);
5771 ID2D1Layer_GetFactory(layer, &layer_factory);
5772 ok(layer_factory == factory, "Got unexpected layer factory %p, expected %p.\n", layer_factory, factory);
5773 ID2D1Factory_Release(layer_factory);
5774 size = ID2D1Layer_GetSize(layer);
5775 ok(size.width == 0.0f, "Got unexpected width %.8e.\n", size.width);
5776 ok(size.height == 0.0f, "Got unexpected height %.8e.\n", size.height);
5777 ID2D1Layer_Release(layer);
5779 set_size_f(&size, 800.0f, 600.0f);
5780 hr = ID2D1RenderTarget_CreateLayer(rt, &size, &layer);
5781 ok(SUCCEEDED(hr), "Failed to create layer, hr %#x.\n", hr);
5782 size = ID2D1Layer_GetSize(layer);
5783 ok(size.width == 800.0f, "Got unexpected width %.8e.\n", size.width);
5784 ok(size.height == 600.0f, "Got unexpected height %.8e.\n", size.height);
5785 ID2D1Layer_Release(layer);
5787 ID2D1RenderTarget_Release(rt);
5788 refcount = ID2D1Factory_Release(factory);
5789 ok(!refcount, "Factory has %u references left.\n", refcount);
5790 IDXGISurface_Release(surface);
5791 IDXGISwapChain_Release(swapchain);
5792 ID3D10Device1_Release(device);
5793 DestroyWindow(window);
5796 static void test_bezier_intersect(void)
5798 D2D1_POINT_2F point = {0.0f, 0.0f};
5799 ID2D1SolidColorBrush *brush;
5800 ID2D1PathGeometry *geometry;
5801 IDXGISwapChain *swapchain;
5802 ID2D1GeometrySink *sink;
5803 ID2D1RenderTarget *rt;
5804 ID3D10Device1 *device;
5805 IDXGISurface *surface;
5806 ID2D1Factory *factory;
5807 D2D1_COLOR_F color;
5808 ULONG refcount;
5809 HWND window;
5810 HRESULT hr;
5811 BOOL match;
5813 if (!(device = create_device()))
5815 skip("Failed to create device, skipping tests.\n");
5816 return;
5818 window = create_window();
5819 swapchain = create_swapchain(device, window, TRUE);
5820 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
5821 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
5822 rt = create_render_target(surface);
5823 ok(!!rt, "Failed to create render target.\n");
5824 ID2D1RenderTarget_GetFactory(rt, &factory);
5826 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
5827 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
5828 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
5829 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
5830 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
5832 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
5833 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
5834 hr = ID2D1PathGeometry_Open(geometry, &sink);
5835 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
5837 set_point(&point, 160.0f, 720.0f);
5838 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5839 cubic_to(sink, 119.0f, 720.0f, 83.0f, 600.0f, 80.0f, 474.0f);
5840 cubic_to(sink, 78.0f, 349.0f, 108.0f, 245.0f, 135.0f, 240.0f);
5841 cubic_to(sink, 163.0f, 235.0f, 180.0f, 318.0f, 176.0f, 370.0f);
5842 cubic_to(sink, 171.0f, 422.0f, 149.0f, 422.0f, 144.0f, 370.0f);
5843 cubic_to(sink, 140.0f, 318.0f, 157.0f, 235.0f, 185.0f, 240.0f);
5844 cubic_to(sink, 212.0f, 245.0f, 242.0f, 349.0f, 240.0f, 474.0f);
5845 cubic_to(sink, 238.0f, 600.0f, 201.0f, 720.0f, 160.0f, 720.0f);
5846 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5848 set_point(&point, 160.0f, 240.0f);
5849 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5850 line_to(sink, 240.0f, 240.0f);
5851 line_to(sink, 240.0f, 720.0f);
5852 line_to(sink, 160.0f, 720.0f);
5853 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5855 hr = ID2D1GeometrySink_Close(sink);
5856 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
5857 ID2D1GeometrySink_Release(sink);
5859 ID2D1RenderTarget_BeginDraw(rt);
5860 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
5861 ID2D1RenderTarget_Clear(rt, &color);
5862 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
5863 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5864 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5865 ID2D1PathGeometry_Release(geometry);
5867 match = compare_figure(surface, 160, 120, 320, 240, 0xff652e89, 2048,
5868 "aRQjIxRpYiIcHCJiXSwXFyxdWTQTEzRZVTsQEDtVUkIMDEJST0cKCkdPTUsICEtNSlEFBVFKSFUD"
5869 "A1VIRlkBAVlGRFsBAVtEQlwCAlxCQFwEBFxAPl0FBV0+PF0HB108Ol4ICF46OV0KCl05N14LC143"
5870 "Nl4MDF42NF8NDV80M14PD14zMV8QEF8xMF8REV8wL18SEl8vLWATE2AtLGAUFGAsK2EUFGErKWIV"
5871 "FWIpKGIWFmIoJ2IXF2InJmIYGGImJWMYGGMlJGMZGWMkI2MaGmMjImQaGmQiIWQbG2QhIGQcHGQg"
5872 "H2UcHGUfHmUdHWUeHWYdHWYdHGcdHWccG2ceHmcbGmgeHmgaGWgfH2gZGWgfH2gZGGkfH2kYF2kg"
5873 "IGkXFmogIGoWFmogIGoWFWsgIGsVFGshIWsUE2whIWwTE2whIWwTEm0hIW0SEW4hIW4REW4hIW4R"
5874 "EG8hIW8QD3AhIXAPD3AhIXAPDnEhIXEODnEhIXEODXIhIXINDHQgIHQMDHQgIHQMC3UgIHULC3Yf"
5875 "H3YLCncfH3cKCngeHngKCXkeHnkJCXodHXoJCXscHHsJCHwcHHwICH0bG30IB38aGn8HB4ABGRmA"
5876 "AQcHgQEYGIEBBwaEARYWhAEGBoUBFRWFAQYFiAETE4gBBQWKARERigEFBYwBDw+MAQUEkAEMDJAB"
5877 "BASTAQkJkwEEBJwBnAEEA50BnQEDA50BnQEDA50BnQEDA50BnQEDAp4BngECAp4BngECAp4BngEC"
5878 "Ap4BngECAp4BngECAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwEBAZ8BnwGhAaAB"
5879 "oAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGg"
5880 "AaABoAGgAaABoAGgAaABoAGhAZ8BoQGfAZ8BAQGfAZ8BAQGfAZ8BAQGfAZ8BAQGfAZ8BAQKeAZ8B"
5881 "AQKeAZ4BAgKeAZ4BAgKeAZ4BAgOdAZ4BAgOdAZ4BAgOdAZ0BAwScAZ0BAwScAZ0BAwScAZ0BAwSc"
5882 "AZwBBAWbAZwBBAWbAZwBBAWbAZsBBQaaAZsBBQaaAZoBBgeZAZoBBgeZAZoBBgeZAZkBBwiYAZkB"
5883 "BwiYAZgBCAmXAZgBCAmXAZgBCAmXAZcBCQqWAZcBCQqWAZYBCguVAZYBCguVAZUBCwyUAZUBCw2T"
5884 "AZQBDA2TAZQBDA6SAZMBDQ6SAZMBDQ+RAZIBDg+RAZIBDhCQAZEBDxCQAZABEBGPAZABEBKOAY8B"
5885 "ERONAY4BEhONAY4BEhSMAY0BExWLAYwBFBWLAYwBFBaKAYsBFReJAYoBFheJAYoBFhiIAYkBFxmH"
5886 "AYgBGBqGAYcBGRuFAYYBGhuFAYUBGxyEAYUBGx2DAYQBHB6CAYMBHR+BAYIBHiCAAYEBHyF/gAEg"
5887 "In5/ISJ+fiIjfX0jJHx8JCV7eyUmenomJ3l5Jyh4eCgpd3cpK3V2Kix0dSstc3QsLnJzLS9xci4w"
5888 "cHAwMm5vMTNtbjI0bG0zNWtrNTdpajY4aGk3OmZnOTtlZjo8ZGQ8PmJjPT9hYj5BX2BAQl5eQkRc"
5889 "XUNGWltFR1lZR0lXWEhLVVZKTVNUTE9RUk5RT1BQUk5OUlRMTFRWSkpWWUdIWFtFRVteQkNdYEBA"
5890 "YGI+PmJlOztlaDg4aGs1NWtuMjJuci4vcXUrK3V6JiZ6fiIifoMBHR2DAYsBFRWLAZUBCwuVAQAA");
5891 ok(match, "Figure does not match.\n");
5893 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
5894 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
5895 hr = ID2D1PathGeometry_Open(geometry, &sink);
5896 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
5898 set_point(&point, 240.0f, 720.0f);
5899 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
5900 cubic_to(sink, 152.0f, 720.0f, 80.0f, 613.0f, 80.0f, 480.0f);
5901 cubic_to(sink, 80.0f, 347.0f, 152.0f, 240.0f, 240.0f, 240.0f);
5902 cubic_to(sink, 152.0f, 339.0f, 134.0f, 528.0f, 200.0f, 660.0f);
5903 cubic_to(sink, 212.0f, 683.0f, 225.0f, 703.0f, 240.0f, 720.0f);
5904 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
5906 hr = ID2D1GeometrySink_Close(sink);
5907 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
5908 ID2D1GeometrySink_Release(sink);
5910 ID2D1RenderTarget_BeginDraw(rt);
5911 ID2D1RenderTarget_Clear(rt, &color);
5912 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
5913 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
5914 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
5915 ID2D1PathGeometry_Release(geometry);
5917 match = compare_figure(surface, 160, 120, 320, 240, 0xff652e89, 2048,
5918 "pQIZkgIrhAI5/QE/9gFH7wFO6wFS5wFW4gFb3gFf2wFi2AFl1gFn1AFp0gFszwFuzQFxywFyyQF1"
5919 "xwF2xgF4xAF5xAF6wgF8wAF+vwF+vwF/vQGBAbwBggG7AYMBugGEAbkBhQG4AYYBtwGHAbcBiAG1"
5920 "AYkBtAGKAbQBigGzAYsBswGMAbEBjQGxAY0BsQGOAa8BjwGvAZABrgGQAa4BkQGtAZEBrQGSAawB"
5921 "kgGsAZMBqwGTAasBlAGrAZQBqgGVAakBlQGqAZUBqQGWAagBlwGoAZYBqAGXAagBlwGnAZgBpwGY"
5922 "AaYBmQGmAZkBpgGZAaUBmgGlAZoBpQGaAaUBmgGkAZsBpAGbAaQBmwGkAZsBpAGcAaMBnAGjAZwB"
5923 "owGcAaMBnAGjAZ0BogGdAaIBnQGiAZ4BoQGeAaEBngGiAZ4BoQGeAaEBnwGgAZ8BoQGeAaEBnwGh"
5924 "AZ4BoQGfAaABnwGhAZ8BoAGgAaABnwGgAaABoAGfAaABoAGgAaABnwGgAaABoAGgAaABnwGgAaAB"
5925 "oAGgAaABnwGhAZ8BoQGfAaABoAGgAaABoAGfAaEBnwGhAZ8BoQGfAaEBnwGhAZ8BoQGfAaABoAGg"
5926 "AaABoAGgAaEBnwGhAZ8BoQGfAaEBnwGhAaABoAGgAaABoAGgAaABoAGgAaEBoAGgAaABoAGgAaAB"
5927 "oQGgAaABoAGgAaABoQGfAaEBoAGhAZ8BoQGfAaIBnwGhAZ8BogGfAaEBnwGiAZ8BogGeAaIBnwGi"
5928 "AZ4BogGfAaIBngGjAZ4BowGdAaMBngGjAZ4BowGdAaQBnQGkAZ0BpAGcAaUBnAGlAZwBpQGcAaUB"
5929 "mwGmAZsBpgGbAaYBmwGmAZsBpgGbAacBmgGnAZkBqAGZAagBmQGpAZgBqQGZAagBmQGpAZgBqQGY"
5930 "AaoBlwGqAZcBqwGWAasBlgGsAZUBrQGVAawBlQGtAZQBrgGUAa0BlAGuAZMBrwGTAa8BkgGwAZEB"
5931 "sQGRAbEBkAGyAZABsgGPAbMBjwG0AY4BtAGNAbUBjQG2AYwBtgGLAbgBigG4AYoBuQGJAboBhwG7"
5932 "AYcBvAGGAb0BhQG+AYQBvwGDAcABggHBAYIBwgGAAcMBf8QBfsYBfMgBe8gBesoBeMwBd80BddAB"
5933 "c9EBcdQBb9YBbNkBatsBaN0BZeEBYuQBX+gBW+0BVvEBUvUBTvwBR4QCQIoCOZgCK6oCGQIA");
5934 ok(match, "Figure does not match.\n");
5936 ID2D1SolidColorBrush_Release(brush);
5937 ID2D1RenderTarget_Release(rt);
5938 refcount = ID2D1Factory_Release(factory);
5939 ok(!refcount, "Factory has %u references left.\n", refcount);
5940 IDXGISurface_Release(surface);
5941 IDXGISwapChain_Release(swapchain);
5942 ID3D10Device1_Release(device);
5943 DestroyWindow(window);
5946 START_TEST(d2d1)
5948 test_clip();
5949 test_state_block();
5950 test_color_brush();
5951 test_bitmap_brush();
5952 test_path_geometry();
5953 test_rectangle_geometry();
5954 test_rounded_rectangle_geometry();
5955 test_bitmap_formats();
5956 test_alpha_mode();
5957 test_shared_bitmap();
5958 test_bitmap_updates();
5959 test_opacity_brush();
5960 test_create_target();
5961 test_draw_text_layout();
5962 test_dc_target();
5963 test_hwnd_target();
5964 test_bitmap_target();
5965 test_desktop_dpi();
5966 test_stroke_style();
5967 test_gradient();
5968 test_draw_geometry();
5969 test_gdi_interop();
5970 test_layer();
5971 test_bezier_intersect();