Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / modules / rostests / winetests / gdiplus / metafile.c
1 /*
2 * Unit test suite for metafiles
3 *
4 * Copyright (C) 2011 Vincent Povirk for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #include <math.h>
26
27 #include <wine/test.h>
28 #include <wingdi.h>
29 #include <objbase.h>
30 #include <gdiplus.h>
31
32 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
33 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
34 #define expectf(expected, got) expectf_((expected), (got), 0.001)
35
36 static BOOL save_metafiles;
37 static BOOL load_metafiles;
38
39 typedef struct emfplus_record
40 {
41 BOOL todo;
42 ULONG record_type;
43 BOOL playback_todo;
44 void (*playback_fn)(GpMetafile* metafile, EmfPlusRecordType record_type,
45 unsigned int flags, unsigned int dataSize, const unsigned char *pStr);
46 } emfplus_record;
47
48 typedef struct emfplus_check_state
49 {
50 const char *desc;
51 int count;
52 const struct emfplus_record *expected;
53 GpMetafile *metafile;
54 } emfplus_check_state;
55
56 static void check_record(int count, const char *desc, const struct emfplus_record *expected, const struct emfplus_record *actual)
57 {
58 todo_wine_if (expected->todo)
59 ok(expected->record_type == actual->record_type,
60 "%s.%i: Expected record type 0x%x, got 0x%x\n", desc, count,
61 expected->record_type, actual->record_type);
62 }
63
64 typedef struct EmfPlusRecordHeader
65 {
66 WORD Type;
67 WORD Flags;
68 DWORD Size;
69 DWORD DataSize;
70 } EmfPlusRecordHeader;
71
72 typedef enum
73 {
74 ObjectTypeInvalid,
75 ObjectTypeBrush,
76 ObjectTypePen,
77 ObjectTypePath,
78 ObjectTypeRegion,
79 ObjectTypeImage,
80 ObjectTypeFont,
81 ObjectTypeStringFormat,
82 ObjectTypeImageAttributes,
83 ObjectTypeCustomLineCap,
84 } ObjectType;
85
86 typedef enum
87 {
88 ImageDataTypeUnknown,
89 ImageDataTypeBitmap,
90 ImageDataTypeMetafile,
91 } ImageDataType;
92
93 typedef struct
94 {
95 EmfPlusRecordHeader Header;
96 /* EmfPlusImage */
97 DWORD Version;
98 ImageDataType Type;
99 /* EmfPlusMetafile */
100 DWORD MetafileType;
101 DWORD MetafileDataSize;
102 BYTE MetafileData[1];
103 } MetafileImageObject;
104
105 static int CALLBACK enum_emf_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR,
106 int nObj, LPARAM lpData)
107 {
108 emfplus_check_state *state = (emfplus_check_state*)lpData;
109 emfplus_record actual;
110
111 if (lpEMFR->iType == EMR_GDICOMMENT)
112 {
113 const EMRGDICOMMENT *comment = (const EMRGDICOMMENT*)lpEMFR;
114
115 if (comment->cbData >= 4 && memcmp(comment->Data, "EMF+", 4) == 0)
116 {
117 int offset = 4;
118
119 while (offset + sizeof(EmfPlusRecordHeader) <= comment->cbData)
120 {
121 const EmfPlusRecordHeader *record = (const EmfPlusRecordHeader*)&comment->Data[offset];
122
123 ok(record->Size == record->DataSize + sizeof(EmfPlusRecordHeader),
124 "%s: EMF+ record datasize %u and size %u mismatch\n", state->desc, record->DataSize, record->Size);
125
126 ok(offset + record->DataSize <= comment->cbData,
127 "%s: EMF+ record truncated\n", state->desc);
128
129 if (offset + record->DataSize > comment->cbData)
130 return 0;
131
132 if (state->expected[state->count].record_type)
133 {
134 actual.todo = FALSE;
135 actual.record_type = record->Type;
136
137 check_record(state->count, state->desc, &state->expected[state->count], &actual);
138 state->count++;
139
140 if (state->expected[state->count-1].todo && state->expected[state->count-1].record_type != actual.record_type)
141 continue;
142 }
143 else
144 {
145 ok(0, "%s: Unexpected EMF+ 0x%x record\n", state->desc, record->Type);
146 }
147
148 if ((record->Flags >> 8) == ObjectTypeImage && record->Type == EmfPlusRecordTypeObject)
149 {
150 const MetafileImageObject *image = (const MetafileImageObject*)record;
151
152 if (image->Type == ImageDataTypeMetafile)
153 {
154 HENHMETAFILE hemf = SetEnhMetaFileBits(image->MetafileDataSize, image->MetafileData);
155 ok(hemf != NULL, "%s: SetEnhMetaFileBits failed\n", state->desc);
156
157 EnumEnhMetaFile(0, hemf, enum_emf_proc, state, NULL);
158 DeleteEnhMetaFile(hemf);
159 }
160 }
161
162 offset += record->Size;
163 }
164
165 ok(offset == comment->cbData, "%s: truncated EMF+ record data?\n", state->desc);
166
167 return 1;
168 }
169 }
170
171 if (state->expected[state->count].record_type)
172 {
173 actual.todo = FALSE;
174 actual.record_type = lpEMFR->iType;
175
176 check_record(state->count, state->desc, &state->expected[state->count], &actual);
177
178 state->count++;
179 }
180 else
181 {
182 ok(0, "%s: Unexpected EMF 0x%x record\n", state->desc, lpEMFR->iType);
183 }
184
185 return 1;
186 }
187
188 static void check_emfplus(HENHMETAFILE hemf, const emfplus_record *expected, const char *desc)
189 {
190 emfplus_check_state state;
191
192 state.desc = desc;
193 state.count = 0;
194 state.expected = expected;
195
196 EnumEnhMetaFile(0, hemf, enum_emf_proc, &state, NULL);
197
198 todo_wine_if (expected[state.count].todo)
199 ok(expected[state.count].record_type == 0, "%s: Got %i records, expecting more\n", desc, state.count);
200 }
201
202 static BOOL CALLBACK enum_metafile_proc(EmfPlusRecordType record_type, unsigned int flags,
203 unsigned int dataSize, const unsigned char *pStr, void *userdata)
204 {
205 emfplus_check_state *state = (emfplus_check_state*)userdata;
206 emfplus_record actual;
207
208 actual.todo = FALSE;
209 actual.record_type = record_type;
210
211 if (dataSize == 0)
212 ok(pStr == NULL, "non-NULL pStr\n");
213
214 if (state->expected[state->count].record_type)
215 {
216 check_record(state->count, state->desc, &state->expected[state->count], &actual);
217
218 state->count++;
219 }
220 else
221 {
222 ok(0, "%s: Unexpected EMF 0x%x record\n", state->desc, record_type);
223 }
224
225 return TRUE;
226 }
227
228 static void check_metafile(GpMetafile *metafile, const emfplus_record *expected, const char *desc,
229 const GpPointF *dst_points, const GpRectF *src_rect, Unit src_unit)
230 {
231 GpStatus stat;
232 HDC hdc;
233 GpGraphics *graphics;
234 emfplus_check_state state;
235
236 state.desc = desc;
237 state.count = 0;
238 state.expected = expected;
239 state.metafile = metafile;
240
241 hdc = CreateCompatibleDC(0);
242
243 stat = GdipCreateFromHDC(hdc, &graphics);
244 expect(Ok, stat);
245
246 stat = GdipEnumerateMetafileSrcRectDestPoints(graphics, metafile, dst_points,
247 3, src_rect, src_unit, enum_metafile_proc, &state, NULL);
248 expect(Ok, stat);
249
250 todo_wine_if (expected[state.count].todo)
251 ok(expected[state.count].record_type == 0, "%s: Got %i records, expecting more\n", desc, state.count);
252
253 GdipDeleteGraphics(graphics);
254
255 DeleteDC(hdc);
256 }
257
258 static BOOL CALLBACK play_metafile_proc(EmfPlusRecordType record_type, unsigned int flags,
259 unsigned int dataSize, const unsigned char *pStr, void *userdata)
260 {
261 emfplus_check_state *state = (emfplus_check_state*)userdata;
262 GpStatus stat;
263
264 if (state->expected[state->count].record_type)
265 {
266 BOOL match = (state->expected[state->count].record_type == record_type);
267
268 if (match && state->expected[state->count].playback_fn)
269 state->expected[state->count].playback_fn(state->metafile, record_type, flags, dataSize, pStr);
270 else
271 {
272 stat = GdipPlayMetafileRecord(state->metafile, record_type, flags, dataSize, pStr);
273 todo_wine_if (state->expected[state->count].playback_todo)
274 ok(stat == Ok, "%s.%i: GdipPlayMetafileRecord failed with stat %i\n", state->desc, state->count, stat);
275 }
276
277 todo_wine_if (state->expected[state->count].todo)
278 ok(state->expected[state->count].record_type == record_type,
279 "%s.%i: expected record type 0x%x, got 0x%x\n", state->desc, state->count,
280 state->expected[state->count].record_type, record_type);
281 state->count++;
282 }
283 else
284 {
285 todo_wine_if (state->expected[state->count].playback_todo)
286 ok(0, "%s: unexpected record 0x%x\n", state->desc, record_type);
287
288 return FALSE;
289 }
290
291 return TRUE;
292 }
293
294 static void play_metafile(GpMetafile *metafile, GpGraphics *graphics, const emfplus_record *expected,
295 const char *desc, const GpPointF *dst_points, const GpRectF *src_rect, Unit src_unit)
296 {
297 GpStatus stat;
298 emfplus_check_state state;
299
300 state.desc = desc;
301 state.count = 0;
302 state.expected = expected;
303 state.metafile = metafile;
304
305 stat = GdipEnumerateMetafileSrcRectDestPoints(graphics, metafile, dst_points,
306 3, src_rect, src_unit, play_metafile_proc, &state, NULL);
307 expect(Ok, stat);
308 }
309
310 /* When 'save' or 'load' is specified on the command line, save or
311 * load the specified filename. */
312 static void sync_metafile(GpMetafile **metafile, const char *filename)
313 {
314 GpStatus stat;
315 if (save_metafiles)
316 {
317 GpMetafile *clone;
318 HENHMETAFILE hemf;
319
320 stat = GdipCloneImage((GpImage*)*metafile, (GpImage**)&clone);
321 expect(Ok, stat);
322
323 stat = GdipGetHemfFromMetafile(clone, &hemf);
324 expect(Ok, stat);
325
326 DeleteEnhMetaFile(CopyEnhMetaFileA(hemf, filename));
327
328 DeleteEnhMetaFile(hemf);
329
330 stat = GdipDisposeImage((GpImage*)clone);
331 expect(Ok, stat);
332 }
333 else if (load_metafiles)
334 {
335 HENHMETAFILE hemf;
336
337 stat = GdipDisposeImage((GpImage*)*metafile);
338 expect(Ok, stat);
339 *metafile = NULL;
340
341 hemf = GetEnhMetaFileA(filename);
342 ok(hemf != NULL, "%s could not be opened\n", filename);
343
344 stat = GdipCreateMetafileFromEmf(hemf, TRUE, metafile);
345 expect(Ok, stat);
346 }
347 }
348
349 static const emfplus_record empty_records[] = {
350 {0, EMR_HEADER},
351 {0, EmfPlusRecordTypeHeader},
352 {0, EmfPlusRecordTypeEndOfFile},
353 {0, EMR_EOF},
354 {0}
355 };
356
357 static void test_empty(void)
358 {
359 GpStatus stat;
360 GpMetafile *metafile;
361 GpGraphics *graphics;
362 HDC hdc;
363 GpRectF bounds;
364 GpUnit unit;
365 REAL xres, yres;
366 HENHMETAFILE hemf, dummy;
367 MetafileHeader header;
368 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
369 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
370 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
371
372 hdc = CreateCompatibleDC(0);
373
374 stat = GdipRecordMetafile(NULL, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
375 expect(InvalidParameter, stat);
376
377 stat = GdipRecordMetafile(hdc, MetafileTypeInvalid, &frame, MetafileFrameUnitPixel, description, &metafile);
378 expect(InvalidParameter, stat);
379
380 stat = GdipRecordMetafile(hdc, MetafileTypeWmf, &frame, MetafileFrameUnitPixel, description, &metafile);
381 expect(InvalidParameter, stat);
382
383 stat = GdipRecordMetafile(hdc, MetafileTypeWmfPlaceable, &frame, MetafileFrameUnitPixel, description, &metafile);
384 expect(InvalidParameter, stat);
385
386 stat = GdipRecordMetafile(hdc, MetafileTypeEmfPlusDual+1, &frame, MetafileFrameUnitPixel, description, &metafile);
387 expect(InvalidParameter, stat);
388
389 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, NULL);
390 expect(InvalidParameter, stat);
391
392 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
393 expect(Ok, stat);
394
395 DeleteDC(hdc);
396
397 if (stat != Ok)
398 return;
399
400 stat = GdipGetHemfFromMetafile(metafile, &hemf);
401 expect(InvalidParameter, stat);
402
403 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
404 expect(Ok, stat);
405
406 stat = GdipGetHemfFromMetafile(metafile, &hemf);
407 expect(InvalidParameter, stat);
408
409 stat = GdipDeleteGraphics(graphics);
410 expect(Ok, stat);
411
412 check_metafile(metafile, empty_records, "empty metafile", dst_points, &frame, UnitPixel);
413
414 sync_metafile(&metafile, "empty.emf");
415
416 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
417 expect(Ok, stat);
418 expectf(0.0, bounds.X);
419 expectf(0.0, bounds.Y);
420 expectf_(100.0, bounds.Width, 0.05);
421 expectf_(100.0, bounds.Height, 0.05);
422 expect(UnitPixel, unit);
423
424 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &xres);
425 expect(Ok, stat);
426
427 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &yres);
428 expect(Ok, stat);
429
430 memset(&header, 0xaa, sizeof(header));
431 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
432 expect(Ok, stat);
433 expect(MetafileTypeEmfPlusOnly, header.Type);
434 expect(U(header).EmfHeader.nBytes, header.Size);
435 ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
436 expect(1, header.EmfPlusFlags); /* reference device was display, not printer */
437 expectf(xres, header.DpiX);
438 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
439 expectf(yres, header.DpiY);
440 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
441 expect(0, header.X);
442 expect(0, header.Y);
443 expect(100, header.Width);
444 expect(100, header.Height);
445 expect(28, header.EmfPlusHeaderSize);
446 expect(96, header.LogicalDpiX);
447 expect(96, header.LogicalDpiX);
448 expect(EMR_HEADER, U(header).EmfHeader.iType);
449 expect(0, U(header).EmfHeader.rclBounds.left);
450 expect(0, U(header).EmfHeader.rclBounds.top);
451 expect(-1, U(header).EmfHeader.rclBounds.right);
452 expect(-1, U(header).EmfHeader.rclBounds.bottom);
453 expect(0, U(header).EmfHeader.rclFrame.left);
454 expect(0, U(header).EmfHeader.rclFrame.top);
455 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
456 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
457
458 stat = GdipGetHemfFromMetafile(metafile, &hemf);
459 expect(Ok, stat);
460
461 stat = GdipGetHemfFromMetafile(metafile, &dummy);
462 expect(InvalidParameter, stat);
463
464 stat = GdipDisposeImage((GpImage*)metafile);
465 expect(Ok, stat);
466
467 check_emfplus(hemf, empty_records, "empty emf");
468
469 memset(&header, 0xaa, sizeof(header));
470 stat = GdipGetMetafileHeaderFromEmf(hemf, &header);
471 expect(Ok, stat);
472 expect(MetafileTypeEmfPlusOnly, header.Type);
473 expect(U(header).EmfHeader.nBytes, header.Size);
474 ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
475 expect(1, header.EmfPlusFlags); /* reference device was display, not printer */
476 expectf(xres, header.DpiX);
477 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
478 expectf(yres, header.DpiY);
479 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
480 expect(0, header.X);
481 expect(0, header.Y);
482 expect(100, header.Width);
483 expect(100, header.Height);
484 expect(28, header.EmfPlusHeaderSize);
485 expect(96, header.LogicalDpiX);
486 expect(96, header.LogicalDpiX);
487 expect(EMR_HEADER, U(header).EmfHeader.iType);
488 expect(0, U(header).EmfHeader.rclBounds.left);
489 expect(0, U(header).EmfHeader.rclBounds.top);
490 expect(-1, U(header).EmfHeader.rclBounds.right);
491 expect(-1, U(header).EmfHeader.rclBounds.bottom);
492 expect(0, U(header).EmfHeader.rclFrame.left);
493 expect(0, U(header).EmfHeader.rclFrame.top);
494 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
495 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
496
497 stat = GdipCreateMetafileFromEmf(hemf, TRUE, &metafile);
498 expect(Ok, stat);
499
500 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
501 expect(Ok, stat);
502 expectf(0.0, bounds.X);
503 expectf(0.0, bounds.Y);
504 expectf_(100.0, bounds.Width, 0.05);
505 expectf_(100.0, bounds.Height, 0.05);
506 expect(UnitPixel, unit);
507
508 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &xres);
509 expect(Ok, stat);
510 expectf(header.DpiX, xres);
511
512 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &yres);
513 expect(Ok, stat);
514 expectf(header.DpiY, yres);
515
516 memset(&header, 0xaa, sizeof(header));
517 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
518 expect(Ok, stat);
519 expect(MetafileTypeEmfPlusOnly, header.Type);
520 expect(U(header).EmfHeader.nBytes, header.Size);
521 ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
522 expect(1, header.EmfPlusFlags); /* reference device was display, not printer */
523 expectf(xres, header.DpiX);
524 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
525 expectf(yres, header.DpiY);
526 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
527 expect(0, header.X);
528 expect(0, header.Y);
529 expect(100, header.Width);
530 expect(100, header.Height);
531 expect(28, header.EmfPlusHeaderSize);
532 expect(96, header.LogicalDpiX);
533 expect(96, header.LogicalDpiX);
534 expect(EMR_HEADER, U(header).EmfHeader.iType);
535 expect(0, U(header).EmfHeader.rclBounds.left);
536 expect(0, U(header).EmfHeader.rclBounds.top);
537 expect(-1, U(header).EmfHeader.rclBounds.right);
538 expect(-1, U(header).EmfHeader.rclBounds.bottom);
539 expect(0, U(header).EmfHeader.rclFrame.left);
540 expect(0, U(header).EmfHeader.rclFrame.top);
541 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
542 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
543
544 stat = GdipDisposeImage((GpImage*)metafile);
545 expect(Ok, stat);
546 }
547
548 static const emfplus_record getdc_records[] = {
549 {0, EMR_HEADER},
550 {0, EmfPlusRecordTypeHeader},
551 {0, EmfPlusRecordTypeGetDC},
552 {0, EMR_CREATEBRUSHINDIRECT},
553 {0, EMR_SELECTOBJECT},
554 {0, EMR_RECTANGLE},
555 {0, EMR_SELECTOBJECT},
556 {0, EMR_DELETEOBJECT},
557 {0, EmfPlusRecordTypeEndOfFile},
558 {0, EMR_EOF},
559 {0}
560 };
561
562 static void test_getdc(void)
563 {
564 GpStatus stat;
565 GpMetafile *metafile;
566 GpGraphics *graphics;
567 HDC hdc, metafile_dc;
568 HENHMETAFILE hemf;
569 BOOL ret;
570 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
571 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
572 static const GpPointF dst_points_half[3] = {{0.0,0.0},{50.0,0.0},{0.0,50.0}};
573 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
574 HBRUSH hbrush, holdbrush;
575 GpBitmap *bitmap;
576 ARGB color;
577
578 hdc = CreateCompatibleDC(0);
579
580 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
581 expect(Ok, stat);
582
583 DeleteDC(hdc);
584
585 if (stat != Ok)
586 return;
587
588 stat = GdipGetHemfFromMetafile(metafile, &hemf);
589 expect(InvalidParameter, stat);
590
591 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
592 expect(Ok, stat);
593
594 stat = GdipGetDC(graphics, &metafile_dc);
595 expect(Ok, stat);
596
597 if (stat != Ok)
598 {
599 GdipDeleteGraphics(graphics);
600 GdipDisposeImage((GpImage*)metafile);
601 return;
602 }
603
604 hbrush = CreateSolidBrush(0xff0000);
605
606 holdbrush = SelectObject(metafile_dc, hbrush);
607
608 Rectangle(metafile_dc, 25, 25, 75, 75);
609
610 SelectObject(metafile_dc, holdbrush);
611
612 DeleteObject(hbrush);
613
614 stat = GdipReleaseDC(graphics, metafile_dc);
615 expect(Ok, stat);
616
617 stat = GdipDeleteGraphics(graphics);
618 expect(Ok, stat);
619
620 check_metafile(metafile, getdc_records, "getdc metafile", dst_points, &frame, UnitPixel);
621
622 sync_metafile(&metafile, "getdc.emf");
623
624 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
625 expect(Ok, stat);
626
627 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
628 expect(Ok, stat);
629
630 play_metafile(metafile, graphics, getdc_records, "getdc playback", dst_points, &frame, UnitPixel);
631
632 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
633 expect(Ok, stat);
634 expect(0, color);
635
636 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
637 expect(Ok, stat);
638 expect(0xff0000ff, color);
639
640 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
641 expect(Ok, stat);
642
643 play_metafile(metafile, graphics, getdc_records, "getdc playback", dst_points_half, &frame, UnitPixel);
644
645 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
646 expect(Ok, stat);
647 expect(0xff0000ff, color);
648
649 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
650 expect(Ok, stat);
651 expect(0, color);
652
653 stat = GdipBitmapSetPixel(bitmap, 15, 15, 0);
654 expect(Ok, stat);
655
656 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
657 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
658 expect(Ok, stat);
659
660 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
661 expect(Ok, stat);
662 expect(0, color);
663
664 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
665 expect(Ok, stat);
666 expect(0xff0000ff, color);
667
668 stat = GdipDeleteGraphics(graphics);
669 expect(Ok, stat);
670
671 stat = GdipDisposeImage((GpImage*)bitmap);
672 expect(Ok, stat);
673
674 stat = GdipGetHemfFromMetafile(metafile, &hemf);
675 expect(Ok, stat);
676
677 stat = GdipDisposeImage((GpImage*)metafile);
678 expect(Ok, stat);
679
680 check_emfplus(hemf, getdc_records, "getdc emf");
681
682 ret = DeleteEnhMetaFile(hemf);
683 ok(ret != 0, "Failed to delete enhmetafile %p\n", hemf);
684 }
685
686 static const emfplus_record emfonly_records[] = {
687 {0, EMR_HEADER},
688 {0, EMR_CREATEBRUSHINDIRECT},
689 {0, EMR_SELECTOBJECT},
690 {0, EMR_RECTANGLE},
691 {0, EMR_SELECTOBJECT},
692 {0, EMR_DELETEOBJECT},
693 {0, EMR_EOF},
694 {0}
695 };
696
697 static const emfplus_record emfonly_draw_records[] = {
698 {0, EMR_HEADER},
699 {1, EMR_SAVEDC},
700 {1, EMR_SETICMMODE},
701 {1, EMR_SETMITERLIMIT},
702 {1, EMR_MODIFYWORLDTRANSFORM},
703 {1, EMR_EXTCREATEPEN},
704 {1, EMR_SELECTOBJECT},
705 {1, EMR_SELECTOBJECT},
706 {1, EMR_POLYLINE16},
707 {1, EMR_SELECTOBJECT},
708 {1, EMR_SELECTOBJECT},
709 {1, EMR_MODIFYWORLDTRANSFORM},
710 {1, EMR_DELETEOBJECT},
711 {1, EMR_SETMITERLIMIT},
712 {1, EMR_RESTOREDC},
713 {0, EMR_EOF},
714 {1}
715 };
716
717 static void test_emfonly(void)
718 {
719 GpStatus stat;
720 GpMetafile *metafile;
721 GpImage *clone;
722 GpGraphics *graphics;
723 HDC hdc, metafile_dc;
724 GpRectF bounds;
725 GpUnit unit;
726 REAL xres, yres;
727 HENHMETAFILE hemf;
728 MetafileHeader header;
729 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
730 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
731 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
732 HBRUSH hbrush, holdbrush;
733 GpBitmap *bitmap;
734 ARGB color;
735 GpPen *pen;
736
737 hdc = CreateCompatibleDC(0);
738
739 stat = GdipRecordMetafile(hdc, EmfTypeEmfOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
740 expect(Ok, stat);
741
742 DeleteDC(hdc);
743
744 if (stat != Ok)
745 return;
746
747 stat = GdipGetHemfFromMetafile(metafile, &hemf);
748 expect(InvalidParameter, stat);
749
750 memset(&header, 0xaa, sizeof(header));
751 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
752 expect(Ok, stat);
753 expect(MetafileTypeEmf, header.Type);
754 ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
755 /* The rest is zeroed or seemingly random/uninitialized garbage. */
756
757 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
758 expect(Ok, stat);
759
760 stat = GdipGetDC(graphics, &metafile_dc);
761 expect(Ok, stat);
762
763 if (stat != Ok)
764 {
765 GdipDeleteGraphics(graphics);
766 GdipDisposeImage((GpImage*)metafile);
767 return;
768 }
769
770 hbrush = CreateSolidBrush(0xff0000);
771
772 holdbrush = SelectObject(metafile_dc, hbrush);
773
774 Rectangle(metafile_dc, 25, 25, 75, 75);
775
776 SelectObject(metafile_dc, holdbrush);
777
778 DeleteObject(hbrush);
779
780 stat = GdipReleaseDC(graphics, metafile_dc);
781 expect(Ok, stat);
782
783 stat = GdipDeleteGraphics(graphics);
784 expect(Ok, stat);
785
786 check_metafile(metafile, emfonly_records, "emfonly metafile", dst_points, &frame, UnitPixel);
787
788 sync_metafile(&metafile, "emfonly.emf");
789
790 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
791 expect(Ok, stat);
792 expectf(0.0, bounds.X);
793 expectf(0.0, bounds.Y);
794 expectf_(100.0, bounds.Width, 0.05);
795 expectf_(100.0, bounds.Height, 0.05);
796 expect(UnitPixel, unit);
797
798 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &xres);
799 expect(Ok, stat);
800
801 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &yres);
802 expect(Ok, stat);
803
804 memset(&header, 0xaa, sizeof(header));
805 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
806 expect(Ok, stat);
807 expect(MetafileTypeEmf, header.Type);
808 expect(U(header).EmfHeader.nBytes, header.Size);
809 /* For some reason a recoreded EMF Metafile has an EMF+ version. */
810 todo_wine ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
811 expect(0, header.EmfPlusFlags);
812 expectf(xres, header.DpiX);
813 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
814 expectf(yres, header.DpiY);
815 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
816 expect(0, header.X);
817 expect(0, header.Y);
818 expect(100, header.Width);
819 expect(100, header.Height);
820 expect(0, header.EmfPlusHeaderSize);
821 expect(0, header.LogicalDpiX);
822 expect(0, header.LogicalDpiX);
823 expect(EMR_HEADER, U(header).EmfHeader.iType);
824 expect(25, U(header).EmfHeader.rclBounds.left);
825 expect(25, U(header).EmfHeader.rclBounds.top);
826 expect(74, U(header).EmfHeader.rclBounds.right);
827 expect(74, U(header).EmfHeader.rclBounds.bottom);
828 expect(0, U(header).EmfHeader.rclFrame.left);
829 expect(0, U(header).EmfHeader.rclFrame.top);
830 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
831 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
832
833 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
834 expect(Ok, stat);
835
836 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
837 expect(Ok, stat);
838
839 play_metafile(metafile, graphics, emfonly_records, "emfonly playback", dst_points, &frame, UnitPixel);
840
841 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
842 expect(Ok, stat);
843 expect(0, color);
844
845 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
846 expect(Ok, stat);
847 expect(0xff0000ff, color);
848
849 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
850 expect(Ok, stat);
851
852 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
853 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
854 expect(Ok, stat);
855
856 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
857 expect(Ok, stat);
858 expect(0, color);
859
860 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
861 expect(Ok, stat);
862 expect(0xff0000ff, color);
863
864 stat = GdipCloneImage((GpImage*)metafile, &clone);
865 expect(Ok, stat);
866
867 if (stat == Ok)
868 {
869 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
870 expect(Ok, stat);
871
872 stat = GdipDrawImagePointsRect(graphics, clone, dst_points, 3,
873 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
874 expect(Ok, stat);
875
876 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
877 expect(Ok, stat);
878 expect(0, color);
879
880 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
881 expect(Ok, stat);
882 expect(0xff0000ff, color);
883
884 GdipDisposeImage(clone);
885 }
886
887 stat = GdipDeleteGraphics(graphics);
888 expect(Ok, stat);
889
890 stat = GdipDisposeImage((GpImage*)bitmap);
891 expect(Ok, stat);
892
893 stat = GdipGetHemfFromMetafile(metafile, &hemf);
894 expect(Ok, stat);
895
896 stat = GdipDisposeImage((GpImage*)metafile);
897 expect(Ok, stat);
898
899 check_emfplus(hemf, emfonly_records, "emfonly emf");
900
901 memset(&header, 0xaa, sizeof(header));
902 stat = GdipGetMetafileHeaderFromEmf(hemf, &header);
903 expect(Ok, stat);
904 expect(MetafileTypeEmf, header.Type);
905 expect(U(header).EmfHeader.nBytes, header.Size);
906 expect(0x10000, header.Version);
907 expect(0, header.EmfPlusFlags);
908 expectf(xres, header.DpiX);
909 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
910 expectf(yres, header.DpiY);
911 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
912 expect(0, header.X);
913 expect(0, header.Y);
914 expect(100, header.Width);
915 expect(100, header.Height);
916 expect(0, header.EmfPlusHeaderSize);
917 expect(0, header.LogicalDpiX);
918 expect(0, header.LogicalDpiX);
919 expect(EMR_HEADER, U(header).EmfHeader.iType);
920 expect(25, U(header).EmfHeader.rclBounds.left);
921 expect(25, U(header).EmfHeader.rclBounds.top);
922 expect(74, U(header).EmfHeader.rclBounds.right);
923 expect(74, U(header).EmfHeader.rclBounds.bottom);
924 expect(0, U(header).EmfHeader.rclFrame.left);
925 expect(0, U(header).EmfHeader.rclFrame.top);
926 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
927 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
928
929 stat = GdipCreateMetafileFromEmf(hemf, TRUE, &metafile);
930 expect(Ok, stat);
931
932 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
933 expect(Ok, stat);
934 expectf(0.0, bounds.X);
935 expectf(0.0, bounds.Y);
936 expectf_(100.0, bounds.Width, 0.05);
937 expectf_(100.0, bounds.Height, 0.05);
938 expect(UnitPixel, unit);
939
940 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &xres);
941 expect(Ok, stat);
942 expectf(header.DpiX, xres);
943
944 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &yres);
945 expect(Ok, stat);
946 expectf(header.DpiY, yres);
947
948 memset(&header, 0xaa, sizeof(header));
949 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
950 expect(Ok, stat);
951 expect(MetafileTypeEmf, header.Type);
952 expect(U(header).EmfHeader.nBytes, header.Size);
953 expect(0x10000, header.Version);
954 expect(0, header.EmfPlusFlags);
955 expectf(xres, header.DpiX);
956 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
957 expectf(yres, header.DpiY);
958 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
959 expect(0, header.X);
960 expect(0, header.Y);
961 expect(100, header.Width);
962 expect(100, header.Height);
963 expect(0, header.EmfPlusHeaderSize);
964 expect(0, header.LogicalDpiX);
965 expect(0, header.LogicalDpiX);
966 expect(EMR_HEADER, U(header).EmfHeader.iType);
967 expect(25, U(header).EmfHeader.rclBounds.left);
968 expect(25, U(header).EmfHeader.rclBounds.top);
969 expect(74, U(header).EmfHeader.rclBounds.right);
970 expect(74, U(header).EmfHeader.rclBounds.bottom);
971 expect(0, U(header).EmfHeader.rclFrame.left);
972 expect(0, U(header).EmfHeader.rclFrame.top);
973 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
974 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
975
976 stat = GdipDisposeImage((GpImage*)metafile);
977 expect(Ok, stat);
978
979 /* test drawing to metafile with gdi+ functions */
980 hdc = CreateCompatibleDC(0);
981
982 stat = GdipRecordMetafile(hdc, EmfTypeEmfOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
983 expect(Ok, stat);
984
985 DeleteDC(hdc);
986
987 if (stat != Ok)
988 return;
989
990 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
991 expect(Ok, stat);
992
993 stat = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
994 expect(Ok, stat);
995 stat = GdipDrawLineI(graphics, pen, 0, 0, 10, 10);
996 todo_wine expect(Ok, stat);
997 GdipDeletePen(pen);
998
999 stat = GdipDeleteGraphics(graphics);
1000 expect(Ok, stat);
1001
1002 check_metafile(metafile, emfonly_draw_records, "emfonly draw metafile", dst_points, &frame, UnitPixel);
1003 sync_metafile(&metafile, "emfonly_draw.emf");
1004
1005 stat = GdipDisposeImage((GpImage*)metafile);
1006 expect(Ok, stat);
1007 }
1008
1009 static const emfplus_record fillrect_records[] = {
1010 {0, EMR_HEADER},
1011 {0, EmfPlusRecordTypeHeader},
1012 {0, EmfPlusRecordTypeFillRects},
1013 {0, EmfPlusRecordTypeEndOfFile},
1014 {0, EMR_EOF},
1015 {0}
1016 };
1017
1018 static void test_fillrect(void)
1019 {
1020 GpStatus stat;
1021 GpMetafile *metafile;
1022 GpGraphics *graphics;
1023 HDC hdc;
1024 HENHMETAFILE hemf;
1025 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
1026 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
1027 static const GpPointF dst_points_half[3] = {{0.0,0.0},{50.0,0.0},{0.0,50.0}};
1028 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1029 GpBitmap *bitmap;
1030 ARGB color;
1031 GpBrush *brush;
1032
1033 hdc = CreateCompatibleDC(0);
1034
1035 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
1036 expect(Ok, stat);
1037
1038 DeleteDC(hdc);
1039
1040 if (stat != Ok)
1041 return;
1042
1043 stat = GdipGetHemfFromMetafile(metafile, &hemf);
1044 expect(InvalidParameter, stat);
1045
1046 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1047 expect(Ok, stat);
1048
1049 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
1050 expect(Ok, stat);
1051
1052 stat = GdipFillRectangleI(graphics, brush, 25, 25, 75, 75);
1053 expect(Ok, stat);
1054
1055 stat = GdipDeleteBrush(brush);
1056 expect(Ok, stat);
1057
1058 stat = GdipDeleteGraphics(graphics);
1059 expect(Ok, stat);
1060
1061 check_metafile(metafile, fillrect_records, "fillrect metafile", dst_points, &frame, UnitPixel);
1062
1063 sync_metafile(&metafile, "fillrect.emf");
1064
1065 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
1066 expect(Ok, stat);
1067
1068 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1069 expect(Ok, stat);
1070
1071 play_metafile(metafile, graphics, fillrect_records, "fillrect playback", dst_points, &frame, UnitPixel);
1072
1073 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
1074 expect(Ok, stat);
1075 expect(0, color);
1076
1077 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
1078 expect(Ok, stat);
1079 expect(0xff0000ff, color);
1080
1081 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
1082 expect(Ok, stat);
1083
1084 play_metafile(metafile, graphics, fillrect_records, "fillrect playback", dst_points_half, &frame, UnitPixel);
1085
1086 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
1087 expect(Ok, stat);
1088 expect(0xff0000ff, color);
1089
1090 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
1091 expect(Ok, stat);
1092 expect(0, color);
1093
1094 stat = GdipBitmapSetPixel(bitmap, 15, 15, 0);
1095 expect(Ok, stat);
1096
1097 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
1098 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
1099 expect(Ok, stat);
1100
1101 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
1102 expect(Ok, stat);
1103 expect(0, color);
1104
1105 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
1106 expect(Ok, stat);
1107 expect(0xff0000ff, color);
1108
1109 stat = GdipDeleteGraphics(graphics);
1110 expect(Ok, stat);
1111
1112 stat = GdipDisposeImage((GpImage*)bitmap);
1113 expect(Ok, stat);
1114
1115 stat = GdipDisposeImage((GpImage*)metafile);
1116 expect(Ok, stat);
1117 }
1118
1119 static const emfplus_record clear_emf_records[] = {
1120 {0, EMR_HEADER},
1121 {0, EmfPlusRecordTypeHeader},
1122 {0, EmfPlusRecordTypeClear},
1123 {1, EMR_SAVEDC},
1124 {1, EMR_SETICMMODE},
1125 {1, EMR_BITBLT},
1126 {1, EMR_RESTOREDC},
1127 {0, EmfPlusRecordTypeEndOfFile},
1128 {0, EMR_EOF},
1129 {0}
1130 };
1131
1132 static void test_clear(void)
1133 {
1134 GpStatus stat;
1135 GpMetafile *metafile;
1136 GpGraphics *graphics;
1137 HDC hdc;
1138 HENHMETAFILE hemf;
1139 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
1140 static const GpPointF dst_points[3] = {{10.0,10.0},{20.0,10.0},{10.0,20.0}};
1141 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1142 GpBitmap *bitmap;
1143 ARGB color;
1144
1145 hdc = CreateCompatibleDC(0);
1146
1147 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
1148 expect(Ok, stat);
1149
1150 DeleteDC(hdc);
1151
1152 if (stat != Ok)
1153 return;
1154
1155 stat = GdipGetHemfFromMetafile(metafile, &hemf);
1156 expect(InvalidParameter, stat);
1157
1158 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1159 expect(Ok, stat);
1160
1161 stat = GdipGraphicsClear(graphics, 0xffffff00);
1162 expect(Ok, stat);
1163
1164 stat = GdipDeleteGraphics(graphics);
1165 expect(Ok, stat);
1166
1167 sync_metafile(&metafile, "clear.emf");
1168
1169 stat = GdipCreateBitmapFromScan0(30, 30, 0, PixelFormat32bppRGB, NULL, &bitmap);
1170 expect(Ok, stat);
1171
1172 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1173 expect(Ok, stat);
1174
1175 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
1176 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
1177 expect(Ok, stat);
1178
1179 stat = GdipBitmapGetPixel(bitmap, 5, 5, &color);
1180 expect(Ok, stat);
1181 expect(0xff000000, color);
1182
1183 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
1184 expect(Ok, stat);
1185 expect(0xffffff00, color);
1186
1187 stat = GdipBitmapGetPixel(bitmap, 25, 25, &color);
1188 expect(Ok, stat);
1189 expect(0xff000000, color);
1190
1191 stat = GdipDeleteGraphics(graphics);
1192 expect(Ok, stat);
1193
1194 stat = GdipDisposeImage((GpImage*)bitmap);
1195 expect(Ok, stat);
1196
1197 stat = GdipGetHemfFromMetafile(metafile, &hemf);
1198 expect(Ok, stat);
1199
1200 stat = GdipDisposeImage((GpImage*)metafile);
1201 expect(Ok, stat);
1202
1203 check_emfplus(hemf, clear_emf_records, "clear emf");
1204
1205 DeleteEnhMetaFile(hemf);
1206 }
1207
1208 static void test_nullframerect(void) {
1209 GpStatus stat;
1210 GpMetafile *metafile;
1211 GpGraphics *graphics;
1212 HDC hdc, metafile_dc;
1213 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1214 GpBrush *brush;
1215 HBRUSH hbrush, holdbrush;
1216 GpRectF bounds;
1217 GpUnit unit;
1218
1219 hdc = CreateCompatibleDC(0);
1220
1221 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, NULL, MetafileFrameUnitPixel, description, &metafile);
1222 expect(Ok, stat);
1223
1224 DeleteDC(hdc);
1225
1226 if (stat != Ok)
1227 return;
1228
1229 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1230 expect(Ok, stat);
1231 expect(UnitPixel, unit);
1232 expectf(0.0, bounds.X);
1233 expectf(0.0, bounds.Y);
1234 ok(bounds.Width == 1.0 || broken(bounds.Width == 0.0) /* xp sp1 */,
1235 "expected 1.0, got %f\n", bounds.Width);
1236 ok(bounds.Height == 1.0 || broken(bounds.Height == 0.0) /* xp sp1 */,
1237 "expected 1.0, got %f\n", bounds.Height);
1238
1239 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1240 expect(Ok, stat);
1241
1242 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
1243 expect(Ok, stat);
1244
1245 stat = GdipFillRectangleI(graphics, brush, 25, 25, 75, 75);
1246 expect(Ok, stat);
1247
1248 stat = GdipDeleteBrush(brush);
1249 expect(Ok, stat);
1250
1251 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1252 expect(Ok, stat);
1253 expect(UnitPixel, unit);
1254 expectf(0.0, bounds.X);
1255 expectf(0.0, bounds.Y);
1256 ok(bounds.Width == 1.0 || broken(bounds.Width == 0.0) /* xp sp1 */,
1257 "expected 1.0, got %f\n", bounds.Width);
1258 ok(bounds.Height == 1.0 || broken(bounds.Height == 0.0) /* xp sp1 */,
1259 "expected 1.0, got %f\n", bounds.Height);
1260
1261 stat = GdipDeleteGraphics(graphics);
1262 expect(Ok, stat);
1263
1264 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1265 expect(Ok, stat);
1266 expect(UnitPixel, unit);
1267 expectf_(25.0, bounds.X, 0.05);
1268 expectf_(25.0, bounds.Y, 0.05);
1269 expectf_(75.0, bounds.Width, 0.05);
1270 expectf_(75.0, bounds.Height, 0.05);
1271
1272 stat = GdipDisposeImage((GpImage*)metafile);
1273 expect(Ok, stat);
1274
1275 hdc = CreateCompatibleDC(0);
1276
1277 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, NULL, MetafileFrameUnitMillimeter, description, &metafile);
1278 expect(Ok, stat);
1279
1280 DeleteDC(hdc);
1281
1282 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1283 expect(Ok, stat);
1284
1285 stat = GdipGetDC(graphics, &metafile_dc);
1286 expect(Ok, stat);
1287
1288 if (stat != Ok)
1289 {
1290 GdipDeleteGraphics(graphics);
1291 GdipDisposeImage((GpImage*)metafile);
1292 return;
1293 }
1294
1295 hbrush = CreateSolidBrush(0xff0000);
1296
1297 holdbrush = SelectObject(metafile_dc, hbrush);
1298
1299 Rectangle(metafile_dc, 25, 25, 75, 75);
1300
1301 SelectObject(metafile_dc, holdbrush);
1302
1303 DeleteObject(hbrush);
1304
1305 stat = GdipReleaseDC(graphics, metafile_dc);
1306 expect(Ok, stat);
1307
1308 stat = GdipDeleteGraphics(graphics);
1309 expect(Ok, stat);
1310
1311 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1312 expect(Ok, stat);
1313 expect(UnitPixel, unit);
1314 expectf_(25.0, bounds.X, 0.05);
1315 expectf_(25.0, bounds.Y, 0.05);
1316 todo_wine expectf_(50.0, bounds.Width, 0.05);
1317 todo_wine expectf_(50.0, bounds.Height, 0.05);
1318
1319 stat = GdipDisposeImage((GpImage*)metafile);
1320 expect(Ok, stat);
1321 }
1322
1323 static const emfplus_record pagetransform_records[] = {
1324 {0, EMR_HEADER},
1325 {0, EmfPlusRecordTypeHeader},
1326 {0, EmfPlusRecordTypeFillRects},
1327 {0, EmfPlusRecordTypeSetPageTransform},
1328 {0, EmfPlusRecordTypeFillRects},
1329 {0, EmfPlusRecordTypeSetPageTransform},
1330 {0, EmfPlusRecordTypeFillRects},
1331 {0, EmfPlusRecordTypeSetPageTransform},
1332 {0, EmfPlusRecordTypeFillRects},
1333 {0, EmfPlusRecordTypeSetPageTransform},
1334 {0, EmfPlusRecordTypeFillRects},
1335 {0, EmfPlusRecordTypeEndOfFile},
1336 {0, EMR_EOF},
1337 {0}
1338 };
1339
1340 static void test_pagetransform(void)
1341 {
1342 GpStatus stat;
1343 GpMetafile *metafile;
1344 GpGraphics *graphics;
1345 HDC hdc;
1346 static const GpRectF frame = {0.0, 0.0, 5.0, 5.0};
1347 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
1348 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1349 GpBitmap *bitmap;
1350 ARGB color;
1351 GpBrush *brush;
1352 GpUnit unit;
1353 REAL scale, dpix, dpiy;
1354 UINT width, height;
1355
1356 hdc = CreateCompatibleDC(0);
1357
1358 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitInch, description, &metafile);
1359 expect(Ok, stat);
1360
1361 DeleteDC(hdc);
1362
1363 if (stat != Ok)
1364 return;
1365
1366 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &dpix);
1367 todo_wine expect(InvalidParameter, stat);
1368
1369 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &dpiy);
1370 todo_wine expect(InvalidParameter, stat);
1371
1372 stat = GdipGetImageWidth((GpImage*)metafile, &width);
1373 todo_wine expect(InvalidParameter, stat);
1374
1375 stat = GdipGetImageHeight((GpImage*)metafile, &height);
1376 todo_wine expect(InvalidParameter, stat);
1377
1378 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1379 expect(Ok, stat);
1380
1381 /* initial scale */
1382 stat = GdipGetPageUnit(graphics, &unit);
1383 expect(Ok, stat);
1384 expect(UnitDisplay, unit);
1385
1386 stat = GdipGetPageScale(graphics, &scale);
1387 expect(Ok, stat);
1388 expectf(1.0, scale);
1389
1390 stat = GdipGetDpiX(graphics, &dpix);
1391 expect(Ok, stat);
1392 expectf(96.0, dpix);
1393
1394 stat = GdipGetDpiY(graphics, &dpiy);
1395 expect(Ok, stat);
1396 expectf(96.0, dpiy);
1397
1398 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
1399 expect(Ok, stat);
1400
1401 stat = GdipFillRectangleI(graphics, brush, 1, 2, 1, 1);
1402 expect(Ok, stat);
1403
1404 stat = GdipDeleteBrush(brush);
1405 expect(Ok, stat);
1406
1407 /* page unit = pixels */
1408 stat = GdipSetPageUnit(graphics, UnitPixel);
1409 expect(Ok, stat);
1410
1411 stat = GdipGetPageUnit(graphics, &unit);
1412 expect(Ok, stat);
1413 expect(UnitPixel, unit);
1414
1415 stat = GdipCreateSolidFill((ARGB)0xff00ff00, (GpSolidFill**)&brush);
1416 expect(Ok, stat);
1417
1418 stat = GdipFillRectangleI(graphics, brush, 0, 1, 1, 1);
1419 expect(Ok, stat);
1420
1421 stat = GdipDeleteBrush(brush);
1422 expect(Ok, stat);
1423
1424 /* page scale = 3, unit = pixels */
1425 stat = GdipSetPageScale(graphics, 3.0);
1426 expect(Ok, stat);
1427
1428 stat = GdipGetPageScale(graphics, &scale);
1429 expect(Ok, stat);
1430 expectf(3.0, scale);
1431
1432 stat = GdipCreateSolidFill((ARGB)0xff00ffff, (GpSolidFill**)&brush);
1433 expect(Ok, stat);
1434
1435 stat = GdipFillRectangleI(graphics, brush, 0, 1, 2, 2);
1436 expect(Ok, stat);
1437
1438 stat = GdipDeleteBrush(brush);
1439 expect(Ok, stat);
1440
1441 /* page scale = 3, unit = inches */
1442 stat = GdipSetPageUnit(graphics, UnitInch);
1443 expect(Ok, stat);
1444
1445 stat = GdipGetPageUnit(graphics, &unit);
1446 expect(Ok, stat);
1447 expect(UnitInch, unit);
1448
1449 stat = GdipCreateSolidFill((ARGB)0xffff0000, (GpSolidFill**)&brush);
1450 expect(Ok, stat);
1451
1452 stat = GdipFillRectangle(graphics, brush, 1.0/96.0, 0, 1, 1);
1453 expect(Ok, stat);
1454
1455 stat = GdipDeleteBrush(brush);
1456 expect(Ok, stat);
1457
1458 /* page scale = 3, unit = display */
1459 stat = GdipSetPageUnit(graphics, UnitDisplay);
1460 expect(Ok, stat);
1461
1462 stat = GdipGetPageUnit(graphics, &unit);
1463 expect(Ok, stat);
1464 expect(UnitDisplay, unit);
1465
1466 stat = GdipCreateSolidFill((ARGB)0xffff00ff, (GpSolidFill**)&brush);
1467 expect(Ok, stat);
1468
1469 stat = GdipFillRectangle(graphics, brush, 3, 3, 2, 2);
1470 expect(Ok, stat);
1471
1472 stat = GdipDeleteBrush(brush);
1473 expect(Ok, stat);
1474
1475 stat = GdipDeleteGraphics(graphics);
1476 expect(Ok, stat);
1477
1478 check_metafile(metafile, pagetransform_records, "pagetransform metafile", dst_points, &frame, UnitPixel);
1479
1480 sync_metafile(&metafile, "pagetransform.emf");
1481
1482 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
1483 expect(Ok, stat);
1484
1485 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1486 expect(Ok, stat);
1487
1488 play_metafile(metafile, graphics, pagetransform_records, "pagetransform playback", dst_points, &frame, UnitPixel);
1489
1490 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
1491 expect(Ok, stat);
1492 expect(0, color);
1493
1494 stat = GdipBitmapGetPixel(bitmap, 30, 50, &color);
1495 expect(Ok, stat);
1496 expect(0xff0000ff, color);
1497
1498 stat = GdipBitmapGetPixel(bitmap, 10, 30, &color);
1499 expect(Ok, stat);
1500 expect(0xff00ff00, color);
1501
1502 stat = GdipBitmapGetPixel(bitmap, 20, 80, &color);
1503 expect(Ok, stat);
1504 expect(0xff00ffff, color);
1505
1506 stat = GdipBitmapGetPixel(bitmap, 80, 20, &color);
1507 expect(Ok, stat);
1508 expect(0xffff0000, color);
1509
1510 stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
1511 expect(Ok, stat);
1512 expect(0xffff00ff, color);
1513
1514 stat = GdipDeleteGraphics(graphics);
1515 expect(Ok, stat);
1516
1517 stat = GdipDisposeImage((GpImage*)bitmap);
1518 expect(Ok, stat);
1519
1520 stat = GdipDisposeImage((GpImage*)metafile);
1521 expect(Ok, stat);
1522 }
1523
1524 static const emfplus_record worldtransform_records[] = {
1525 {0, EMR_HEADER},
1526 {0, EmfPlusRecordTypeHeader},
1527 {0, EmfPlusRecordTypeFillRects},
1528 {0, EmfPlusRecordTypeScaleWorldTransform},
1529 {0, EmfPlusRecordTypeFillRects},
1530 {0, EmfPlusRecordTypeResetWorldTransform},
1531 {0, EmfPlusRecordTypeFillRects},
1532 {0, EmfPlusRecordTypeMultiplyWorldTransform},
1533 {0, EmfPlusRecordTypeFillRects},
1534 {0, EmfPlusRecordTypeRotateWorldTransform},
1535 {0, EmfPlusRecordTypeFillRects},
1536 {0, EmfPlusRecordTypeSetWorldTransform},
1537 {0, EmfPlusRecordTypeFillRects},
1538 {0, EmfPlusRecordTypeTranslateWorldTransform},
1539 {0, EmfPlusRecordTypeFillRects},
1540 {0, EmfPlusRecordTypeEndOfFile},
1541 {0, EMR_EOF},
1542 {0}
1543 };
1544
1545 static void test_worldtransform(void)
1546 {
1547 GpStatus stat;
1548 GpMetafile *metafile;
1549 GpGraphics *graphics;
1550 HDC hdc;
1551 static const GpRectF frame = {0.0, 0.0, 5.0, 5.0};
1552 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
1553 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1554 GpBitmap *bitmap;
1555 ARGB color;
1556 GpBrush *brush;
1557 GpMatrix *transform;
1558 BOOL identity;
1559 REAL elements[6];
1560
1561 hdc = CreateCompatibleDC(0);
1562
1563 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
1564 expect(Ok, stat);
1565
1566 DeleteDC(hdc);
1567
1568 if (stat != Ok)
1569 return;
1570
1571 stat = GdipCreateMatrix(&transform);
1572 expect(Ok, stat);
1573
1574 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1575 expect(Ok, stat);
1576
1577 /* initial transform */
1578 stat = GdipGetWorldTransform(graphics, transform);
1579 expect(Ok, stat);
1580
1581 stat = GdipIsMatrixIdentity(transform, &identity);
1582 expect(Ok, stat);
1583 expect(TRUE, identity);
1584
1585 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
1586 expect(Ok, stat);
1587
1588 stat = GdipFillRectangleI(graphics, brush, 0, 0, 1, 1);
1589 expect(Ok, stat);
1590
1591 stat = GdipDeleteBrush(brush);
1592 expect(Ok, stat);
1593
1594 /* scale transform */
1595 stat = GdipScaleWorldTransform(graphics, 2.0, 4.0, MatrixOrderPrepend);
1596 expect(Ok, stat);
1597
1598 stat = GdipGetWorldTransform(graphics, transform);
1599 expect(Ok, stat);
1600
1601 stat = GdipGetMatrixElements(transform, elements);
1602 expect(Ok, stat);
1603 expectf(2.0, elements[0]);
1604 expectf(0.0, elements[1]);
1605 expectf(0.0, elements[2]);
1606 expectf(4.0, elements[3]);
1607 expectf(0.0, elements[4]);
1608 expectf(0.0, elements[5]);
1609
1610 stat = GdipCreateSolidFill((ARGB)0xff00ff00, (GpSolidFill**)&brush);
1611 expect(Ok, stat);
1612
1613 stat = GdipFillRectangle(graphics, brush, 0.5, 0.5, 0.5, 0.25);
1614 expect(Ok, stat);
1615
1616 stat = GdipDeleteBrush(brush);
1617 expect(Ok, stat);
1618
1619 /* reset transform */
1620 stat = GdipResetWorldTransform(graphics);
1621 expect(Ok, stat);
1622
1623 stat = GdipGetWorldTransform(graphics, transform);
1624 expect(Ok, stat);
1625
1626 stat = GdipIsMatrixIdentity(transform, &identity);
1627 expect(Ok, stat);
1628 expect(TRUE, identity);
1629
1630 stat = GdipCreateSolidFill((ARGB)0xff00ffff, (GpSolidFill**)&brush);
1631 expect(Ok, stat);
1632
1633 stat = GdipFillRectangle(graphics, brush, 1.0, 0.0, 1.0, 1.0);
1634 expect(Ok, stat);
1635
1636 stat = GdipDeleteBrush(brush);
1637 expect(Ok, stat);
1638
1639 /* multiply transform */
1640 stat = GdipSetMatrixElements(transform, 2.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1641 expect(Ok, stat);
1642
1643 stat = GdipMultiplyWorldTransform(graphics, transform, MatrixOrderPrepend);
1644 expect(Ok, stat);
1645
1646 stat = GdipGetWorldTransform(graphics, transform);
1647 expect(Ok, stat);
1648
1649 stat = GdipGetMatrixElements(transform, elements);
1650 expect(Ok, stat);
1651 expectf(2.0, elements[0]);
1652 expectf(0.0, elements[1]);
1653 expectf(0.0, elements[2]);
1654 expectf(1.0, elements[3]);
1655 expectf(0.0, elements[4]);
1656 expectf(0.0, elements[5]);
1657
1658 stat = GdipCreateSolidFill((ARGB)0xffff0000, (GpSolidFill**)&brush);
1659 expect(Ok, stat);
1660
1661 stat = GdipFillRectangle(graphics, brush, 1.0, 1.0, 0.5, 1.0);
1662 expect(Ok, stat);
1663
1664 stat = GdipDeleteBrush(brush);
1665 expect(Ok, stat);
1666
1667 /* rotate transform */
1668 stat = GdipRotateWorldTransform(graphics, 90.0, MatrixOrderAppend);
1669 expect(Ok, stat);
1670
1671 stat = GdipGetWorldTransform(graphics, transform);
1672 expect(Ok, stat);
1673
1674 stat = GdipGetMatrixElements(transform, elements);
1675 expect(Ok, stat);
1676 expectf(0.0, elements[0]);
1677 expectf(2.0, elements[1]);
1678 expectf(-1.0, elements[2]);
1679 expectf(0.0, elements[3]);
1680 expectf(0.0, elements[4]);
1681 expectf(0.0, elements[5]);
1682
1683 stat = GdipCreateSolidFill((ARGB)0xffff00ff, (GpSolidFill**)&brush);
1684 expect(Ok, stat);
1685
1686 stat = GdipFillRectangle(graphics, brush, 1.0, -1.0, 0.5, 1.0);
1687 expect(Ok, stat);
1688
1689 stat = GdipDeleteBrush(brush);
1690 expect(Ok, stat);
1691
1692 /* set transform */
1693 stat = GdipSetMatrixElements(transform, 1.0, 0.0, 0.0, 3.0, 0.0, 0.0);
1694 expect(Ok, stat);
1695
1696 stat = GdipSetWorldTransform(graphics, transform);
1697 expect(Ok, stat);
1698
1699 stat = GdipGetWorldTransform(graphics, transform);
1700 expect(Ok, stat);
1701
1702 stat = GdipGetMatrixElements(transform, elements);
1703 expect(Ok, stat);
1704 expectf(1.0, elements[0]);
1705 expectf(0.0, elements[1]);
1706 expectf(0.0, elements[2]);
1707 expectf(3.0, elements[3]);
1708 expectf(0.0, elements[4]);
1709 expectf(0.0, elements[5]);
1710
1711 stat = GdipCreateSolidFill((ARGB)0xffffff00, (GpSolidFill**)&brush);
1712 expect(Ok, stat);
1713
1714 stat = GdipFillRectangle(graphics, brush, 1.0, 1.0, 1.0, 1.0);
1715 expect(Ok, stat);
1716
1717 stat = GdipDeleteBrush(brush);
1718 expect(Ok, stat);
1719
1720 /* translate transform */
1721 stat = GdipTranslateWorldTransform(graphics, -1.0, 0.0, MatrixOrderAppend);
1722 expect(Ok, stat);
1723
1724 stat = GdipGetWorldTransform(graphics, transform);
1725 expect(Ok, stat);
1726
1727 stat = GdipGetMatrixElements(transform, elements);
1728 expect(Ok, stat);
1729 expectf(1.0, elements[0]);
1730 expectf(0.0, elements[1]);
1731 expectf(0.0, elements[2]);
1732 expectf(3.0, elements[3]);
1733 expectf(-1.0, elements[4]);
1734 expectf(0.0, elements[5]);
1735
1736 stat = GdipCreateSolidFill((ARGB)0xffffffff, (GpSolidFill**)&brush);
1737 expect(Ok, stat);
1738
1739 stat = GdipFillRectangle(graphics, brush, 1.0, 1.0, 1.0, 1.0);
1740 expect(Ok, stat);
1741
1742 stat = GdipDeleteBrush(brush);
1743 expect(Ok, stat);
1744
1745 stat = GdipDeleteMatrix(transform);
1746 expect(Ok, stat);
1747
1748 stat = GdipDeleteGraphics(graphics);
1749 expect(Ok, stat);
1750
1751 check_metafile(metafile, worldtransform_records, "worldtransform metafile", dst_points, &frame, UnitPixel);
1752
1753 sync_metafile(&metafile, "worldtransform.emf");
1754
1755 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
1756 expect(Ok, stat);
1757
1758 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1759 expect(Ok, stat);
1760
1761 play_metafile(metafile, graphics, worldtransform_records, "worldtransform playback", dst_points, &frame, UnitPixel);
1762
1763 stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
1764 expect(Ok, stat);
1765 expect(0, color);
1766
1767 stat = GdipBitmapGetPixel(bitmap, 10, 10, &color);
1768 expect(Ok, stat);
1769 expect(0xff0000ff, color);
1770
1771 stat = GdipBitmapGetPixel(bitmap, 30, 50, &color);
1772 expect(Ok, stat);
1773 expect(0xff00ff00, color);
1774
1775 stat = GdipBitmapGetPixel(bitmap, 30, 10, &color);
1776 expect(Ok, stat);
1777 expect(0xff00ffff, color);
1778
1779 stat = GdipBitmapGetPixel(bitmap, 50, 30, &color);
1780 expect(Ok, stat);
1781 expect(0xffff0000, color);
1782
1783 stat = GdipBitmapGetPixel(bitmap, 10, 50, &color);
1784 expect(Ok, stat);
1785 expect(0xffff00ff, color);
1786
1787 stat = GdipBitmapGetPixel(bitmap, 30, 90, &color);
1788 expect(Ok, stat);
1789 expect(0xffffff00, color);
1790
1791 stat = GdipBitmapGetPixel(bitmap, 10, 90, &color);
1792 expect(Ok, stat);
1793 expect(0xffffffff, color);
1794
1795 stat = GdipDeleteGraphics(graphics);
1796 expect(Ok, stat);
1797
1798 stat = GdipDisposeImage((GpImage*)bitmap);
1799 expect(Ok, stat);
1800
1801 stat = GdipDisposeImage((GpImage*)metafile);
1802 expect(Ok, stat);
1803 }
1804
1805 static void test_converttoemfplus(void)
1806 {
1807 GpStatus (WINAPI *pGdipConvertToEmfPlus)( const GpGraphics *graphics, GpMetafile *metafile, BOOL *succ,
1808 EmfType emfType, const WCHAR *description, GpMetafile **outmetafile);
1809 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
1810 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1811 GpStatus stat;
1812 GpMetafile *metafile, *metafile2 = NULL, *emhmeta;
1813 GpGraphics *graphics;
1814 HDC hdc;
1815 BOOL succ;
1816 HMODULE mod = GetModuleHandleA("gdiplus.dll");
1817
1818 pGdipConvertToEmfPlus = (void*)GetProcAddress( mod, "GdipConvertToEmfPlus");
1819 if(!pGdipConvertToEmfPlus)
1820 {
1821 /* GdipConvertToEmfPlus was introduced in Windows Vista. */
1822 win_skip("GDIPlus version 1.1 not available\n");
1823 return;
1824 }
1825
1826 hdc = CreateCompatibleDC(0);
1827
1828 stat = GdipRecordMetafile(hdc, MetafileTypeEmf, &frame, MetafileFrameUnitPixel, description, &metafile);
1829 expect(Ok, stat);
1830
1831 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &emhmeta);
1832 expect(Ok, stat);
1833
1834 DeleteDC(hdc);
1835
1836 if (stat != Ok)
1837 return;
1838
1839 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1840 expect(Ok, stat);
1841
1842 /* Invalid Parameters */
1843 stat = pGdipConvertToEmfPlus(NULL, metafile, &succ, EmfTypeEmfPlusOnly, description, &metafile2);
1844 expect(InvalidParameter, stat);
1845
1846 stat = pGdipConvertToEmfPlus(graphics, NULL, &succ, EmfTypeEmfPlusOnly, description, &metafile2);
1847 expect(InvalidParameter, stat);
1848
1849 stat = pGdipConvertToEmfPlus(graphics, metafile, &succ, EmfTypeEmfPlusOnly, description, NULL);
1850 expect(InvalidParameter, stat);
1851
1852 stat = pGdipConvertToEmfPlus(graphics, metafile, NULL, MetafileTypeInvalid, NULL, &metafile2);
1853 expect(InvalidParameter, stat);
1854
1855 stat = pGdipConvertToEmfPlus(graphics, metafile, NULL, MetafileTypeEmfPlusDual+1, NULL, &metafile2);
1856 expect(InvalidParameter, stat);
1857
1858 /* If we are already an Enhanced Metafile then the conversion fails. */
1859 stat = pGdipConvertToEmfPlus(graphics, emhmeta, NULL, EmfTypeEmfPlusOnly, NULL, &metafile2);
1860 todo_wine expect(InvalidParameter, stat);
1861
1862 stat = pGdipConvertToEmfPlus(graphics, metafile, NULL, EmfTypeEmfPlusOnly, NULL, &metafile2);
1863 todo_wine expect(Ok, stat);
1864 if(metafile2)
1865 GdipDisposeImage((GpImage*)metafile2);
1866
1867 succ = FALSE;
1868 stat = pGdipConvertToEmfPlus(graphics, metafile, &succ, EmfTypeEmfPlusOnly, NULL, &metafile2);
1869 todo_wine expect(Ok, stat);
1870 if(metafile2)
1871 GdipDisposeImage((GpImage*)metafile2);
1872
1873 stat = GdipDeleteGraphics(graphics);
1874 expect(Ok, stat);
1875
1876 stat = GdipDisposeImage((GpImage*)metafile);
1877 expect(Ok, stat);
1878
1879 stat = GdipDisposeImage((GpImage*)emhmeta);
1880 expect(Ok, stat);
1881 }
1882
1883 static void test_frameunit(void)
1884 {
1885 GpStatus stat;
1886 GpMetafile *metafile;
1887 GpGraphics *graphics;
1888 HDC hdc;
1889 static const GpRectF frame = {0.0, 0.0, 5.0, 5.0};
1890 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1891 GpUnit unit;
1892 REAL dpix, dpiy;
1893 GpRectF bounds;
1894
1895 hdc = CreateCompatibleDC(0);
1896
1897 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitInch, description, &metafile);
1898 expect(Ok, stat);
1899
1900 DeleteDC(hdc);
1901
1902 if (stat != Ok)
1903 return;
1904
1905 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1906 expect(Ok, stat);
1907 expect(UnitPixel, unit);
1908 expectf(0.0, bounds.X);
1909 expectf(0.0, bounds.Y);
1910 ok(bounds.Width == 1.0 || broken(bounds.Width == 0.0) /* xp sp1 */,
1911 "expected 1.0, got %f\n", bounds.Width);
1912 ok(bounds.Height == 1.0 || broken(bounds.Height == 0.0) /* xp sp1 */,
1913 "expected 1.0, got %f\n", bounds.Height);
1914
1915 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1916 expect(Ok, stat);
1917
1918 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1919 expect(Ok, stat);
1920 expect(UnitPixel, unit);
1921 expectf(0.0, bounds.X);
1922 expectf(0.0, bounds.Y);
1923 ok(bounds.Width == 1.0 || broken(bounds.Width == 0.0) /* xp sp1 */,
1924 "expected 1.0, got %f\n", bounds.Width);
1925 ok(bounds.Height == 1.0 || broken(bounds.Height == 0.0) /* xp sp1 */,
1926 "expected 1.0, got %f\n", bounds.Height);
1927
1928 stat = GdipDeleteGraphics(graphics);
1929 expect(Ok, stat);
1930
1931 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &dpix);
1932 expect(Ok, stat);
1933
1934 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &dpiy);
1935 expect(Ok, stat);
1936
1937 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1938 expect(Ok, stat);
1939 expect(UnitPixel, unit);
1940 expectf(0.0, bounds.X);
1941 expectf(0.0, bounds.Y);
1942 expectf_(5.0 * dpix, bounds.Width, 1.0);
1943 expectf_(5.0 * dpiy, bounds.Height, 1.0);
1944
1945 stat = GdipDisposeImage((GpImage*)metafile);
1946 expect(Ok, stat);
1947 }
1948
1949 static const emfplus_record container_records[] = {
1950 {0, EMR_HEADER},
1951 {0, EmfPlusRecordTypeHeader},
1952 {0, EmfPlusRecordTypeBeginContainerNoParams},
1953 {0, EmfPlusRecordTypeScaleWorldTransform},
1954 {0, EmfPlusRecordTypeFillRects},
1955 {0, EmfPlusRecordTypeEndContainer},
1956 {0, EmfPlusRecordTypeScaleWorldTransform},
1957 {0, EmfPlusRecordTypeFillRects},
1958 {0, EmfPlusRecordTypeSave},
1959 {0, EmfPlusRecordTypeRestore},
1960 {0, EmfPlusRecordTypeScaleWorldTransform},
1961 {0, EmfPlusRecordTypeBeginContainerNoParams},
1962 {0, EmfPlusRecordTypeScaleWorldTransform},
1963 {0, EmfPlusRecordTypeBeginContainerNoParams},
1964 {0, EmfPlusRecordTypeEndContainer},
1965 {0, EmfPlusRecordTypeFillRects},
1966 {0, EmfPlusRecordTypeBeginContainer},
1967 {0, EmfPlusRecordTypeFillRects},
1968 {0, EmfPlusRecordTypeEndContainer},
1969 {0, EmfPlusRecordTypeBeginContainerNoParams},
1970 {0, EmfPlusRecordTypeEndOfFile},
1971 {0, EMR_EOF},
1972 {0}
1973 };
1974
1975 static void test_containers(void)
1976 {
1977 GpStatus stat;
1978 GpMetafile *metafile;
1979 GpGraphics *graphics;
1980 GpBitmap *bitmap;
1981 GpBrush *brush;
1982 ARGB color;
1983 HDC hdc;
1984 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
1985 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
1986 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1987 GraphicsContainer state1, state2;
1988 GpRectF srcrect, dstrect;
1989 REAL dpix, dpiy;
1990
1991 hdc = CreateCompatibleDC(0);
1992
1993 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
1994 expect(Ok, stat);
1995
1996 DeleteDC(hdc);
1997
1998 if (stat != Ok)
1999 return;
2000
2001 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2002 expect(Ok, stat);
2003
2004 /* Normal usage */
2005 stat = GdipBeginContainer2(graphics, &state1);
2006 expect(Ok, stat);
2007
2008 stat = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
2009 expect(Ok, stat);
2010
2011 stat = GdipCreateSolidFill((ARGB)0xff000000, (GpSolidFill**)&brush);
2012 expect(Ok, stat);
2013
2014 stat = GdipFillRectangle(graphics, brush, 5.0, 5.0, 5.0, 5.0);
2015 expect(Ok, stat);
2016
2017 stat = GdipDeleteBrush(brush);
2018 expect(Ok, stat);
2019
2020 stat = GdipEndContainer(graphics, state1);
2021 expect(Ok, stat);
2022
2023 stat = GdipScaleWorldTransform(graphics, 1.0, 1.0, MatrixOrderPrepend);
2024 expect(Ok, stat);
2025
2026 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
2027 expect(Ok, stat);
2028
2029 stat = GdipFillRectangle(graphics, brush, 5.0, 5.0, 5.0, 5.0);
2030 expect(Ok, stat);
2031
2032 stat = GdipDeleteBrush(brush);
2033 expect(Ok, stat);
2034
2035 stat = GdipSaveGraphics(graphics, &state1);
2036 expect(Ok, stat);
2037
2038 stat = GdipRestoreGraphics(graphics, state1);
2039 expect(Ok, stat);
2040
2041 /* Popping two states at once */
2042 stat = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
2043 expect(Ok, stat);
2044
2045 stat = GdipBeginContainer2(graphics, &state1);
2046 expect(Ok, stat);
2047
2048 stat = GdipScaleWorldTransform(graphics, 4.0, 4.0, MatrixOrderPrepend);
2049 expect(Ok, stat);
2050
2051 stat = GdipBeginContainer2(graphics, &state2);
2052 expect(Ok, stat);
2053
2054 stat = GdipEndContainer(graphics, state1);
2055 expect(Ok, stat);
2056
2057 stat = GdipCreateSolidFill((ARGB)0xff00ff00, (GpSolidFill**)&brush);
2058 expect(Ok, stat);
2059
2060 stat = GdipFillRectangle(graphics, brush, 20.0, 20.0, 5.0, 5.0);
2061 expect(Ok, stat);
2062
2063 stat = GdipDeleteBrush(brush);
2064 expect(Ok, stat);
2065
2066 /* With transform applied */
2067 stat = GdipGetDpiX(graphics, &dpix);
2068 expect(Ok, stat);
2069
2070 stat = GdipGetDpiY(graphics, &dpiy);
2071 expect(Ok, stat);
2072
2073 srcrect.X = 0.0;
2074 srcrect.Y = 0.0;
2075 srcrect.Width = 1.0;
2076 srcrect.Height = 1.0;
2077
2078 dstrect.X = 25.0;
2079 dstrect.Y = 0.0;
2080 dstrect.Width = 5.0;
2081 dstrect.Height = 5.0;
2082
2083 stat = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state1);
2084 expect(Ok, stat);
2085
2086 stat = GdipCreateSolidFill((ARGB)0xff00ffff, (GpSolidFill**)&brush);
2087 expect(Ok, stat);
2088
2089 stat = GdipFillRectangle(graphics, brush, 0.0, 0.0, dpix, dpiy);
2090 expect(Ok, stat);
2091
2092 stat = GdipDeleteBrush(brush);
2093 expect(Ok, stat);
2094
2095 stat = GdipEndContainer(graphics, state1);
2096 expect(Ok, stat);
2097
2098 /* Restoring an invalid state seems to break the graphics object? */
2099 if (0) {
2100 stat = GdipEndContainer(graphics, state1);
2101 expect(Ok, stat);
2102 }
2103
2104 /* Ending metafile with a state open */
2105 stat = GdipBeginContainer2(graphics, &state1);
2106 expect(Ok, stat);
2107
2108 stat = GdipDeleteGraphics(graphics);
2109 expect(Ok, stat);
2110
2111 check_metafile(metafile, container_records, "container metafile", dst_points, &frame, UnitPixel);
2112
2113 sync_metafile(&metafile, "container.emf");
2114
2115 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
2116 expect(Ok, stat);
2117
2118 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2119 expect(Ok, stat);
2120
2121 play_metafile(metafile, graphics, container_records, "container playback", dst_points, &frame, UnitPixel);
2122
2123 stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
2124 expect(Ok, stat);
2125 expect(0, color);
2126
2127 stat = GdipBitmapGetPixel(bitmap, 12, 12, &color);
2128 expect(Ok, stat);
2129 expect(0xff000000, color);
2130
2131 stat = GdipBitmapGetPixel(bitmap, 8, 8, &color);
2132 expect(Ok, stat);
2133 expect(0xff0000ff, color);
2134
2135 stat = GdipBitmapGetPixel(bitmap, 42, 42, &color);
2136 expect(Ok, stat);
2137 expect(0xff00ff00, color);
2138
2139 stat = GdipBitmapGetPixel(bitmap, 55, 5, &color);
2140 expect(Ok, stat);
2141 expect(0xff00ffff, color);
2142
2143 stat = GdipDeleteGraphics(graphics);
2144 expect(Ok, stat);
2145
2146 stat = GdipDisposeImage((GpImage*)bitmap);
2147 expect(Ok, stat);
2148
2149 stat = GdipDisposeImage((GpImage*)metafile);
2150 expect(Ok, stat);
2151 }
2152
2153 static const emfplus_record clipping_records[] = {
2154 {0, EMR_HEADER},
2155 {0, EmfPlusRecordTypeHeader},
2156 {0, EmfPlusRecordTypeSave},
2157 {0, EmfPlusRecordTypeSetClipRect},
2158 {0, EmfPlusRecordTypeFillRects},
2159 {0, EmfPlusRecordTypeRestore},
2160 {0, EmfPlusRecordTypeSetClipRect},
2161 {0, EmfPlusRecordTypeFillRects},
2162 {0, EmfPlusRecordTypeObject, 1},
2163 {0, EmfPlusRecordTypeSetClipRegion, 1},
2164 {0, EmfPlusRecordTypeEndOfFile},
2165 {0, EMR_EOF},
2166 {0}
2167 };
2168
2169 static void test_clipping(void)
2170 {
2171 GpStatus stat;
2172 GpMetafile *metafile;
2173 GpGraphics *graphics;
2174 GpBitmap *bitmap;
2175 GpRegion *region;
2176 GpBrush *brush;
2177 GpRectF rect;
2178 ARGB color;
2179 HDC hdc;
2180 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2181 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
2182 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2183 GraphicsState state;
2184
2185 hdc = CreateCompatibleDC(0);
2186
2187 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2188 expect(Ok, stat);
2189
2190 DeleteDC(hdc);
2191
2192 if (stat != Ok)
2193 return;
2194
2195 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2196 expect(Ok, stat);
2197
2198 stat = GdipSaveGraphics(graphics, &state);
2199 expect(Ok, stat);
2200
2201 stat = GdipGetVisibleClipBounds(graphics, &rect);
2202 expect(Ok, stat);
2203 ok(rect.X == -0x400000, "rect.X = %f\n", rect.X);
2204 ok(rect.Y == -0x400000, "rect.Y = %f\n", rect.Y);
2205 ok(rect.Width == 0x800000, "rect.Width = %f\n", rect.Width);
2206 ok(rect.Height == 0x800000, "rect.Height = %f\n", rect.Height);
2207
2208 stat = GdipSetClipRect(graphics, 30, 30, 10, 10, CombineModeReplace);
2209 expect(Ok, stat);
2210
2211 stat = GdipGetVisibleClipBounds(graphics, &rect);
2212 expect(Ok, stat);
2213 ok(rect.X == 30, "rect.X = %f\n", rect.X);
2214 ok(rect.Y == 30, "rect.Y = %f\n", rect.Y);
2215 ok(rect.Width == 10, "rect.Width = %f\n", rect.Width);
2216 ok(rect.Height == 10, "rect.Height = %f\n", rect.Height);
2217
2218 stat = GdipCreateSolidFill((ARGB)0xff000000, (GpSolidFill**)&brush);
2219 expect(Ok, stat);
2220
2221 stat = GdipFillRectangle(graphics, brush, 0, 0, 100, 100);
2222 expect(Ok, stat);
2223
2224 stat = GdipDeleteBrush(brush);
2225 expect(Ok, stat);
2226
2227 stat = GdipRestoreGraphics(graphics, state);
2228 expect(Ok, stat);
2229
2230 stat = GdipSetClipRect(graphics, 30, 30, 10, 10, CombineModeXor);
2231 expect(Ok, stat);
2232
2233 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
2234 expect(Ok, stat);
2235
2236 stat = GdipFillRectangle(graphics, brush, 30, 30, 20, 10);
2237 expect(Ok, stat);
2238
2239 stat = GdipDeleteBrush(brush);
2240 expect(Ok, stat);
2241
2242 stat = GdipCreateRegionRect(&rect, &region);
2243 expect(Ok, stat);
2244
2245 stat = GdipSetClipRegion(graphics, region, CombineModeIntersect);
2246 expect(Ok, stat);
2247
2248 stat = GdipDeleteRegion(region);
2249 expect(Ok, stat);
2250
2251 stat = GdipDeleteGraphics(graphics);
2252 expect(Ok, stat);
2253
2254 check_metafile(metafile, clipping_records, "clipping metafile", dst_points, &frame, UnitPixel);
2255
2256 sync_metafile(&metafile, "clipping.emf");
2257
2258 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
2259 expect(Ok, stat);
2260
2261 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2262 expect(Ok, stat);
2263
2264 play_metafile(metafile, graphics, clipping_records, "clipping playback", dst_points, &frame, UnitPixel);
2265
2266 stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
2267 expect(Ok, stat);
2268 expect(0, color);
2269
2270 stat = GdipBitmapGetPixel(bitmap, 35, 35, &color);
2271 expect(Ok, stat);
2272 expect(0xff000000, color);
2273
2274 stat = GdipBitmapGetPixel(bitmap, 45, 35, &color);
2275 expect(Ok, stat);
2276 expect(0xff0000ff, color);
2277
2278 stat = GdipDeleteGraphics(graphics);
2279 expect(Ok, stat);
2280
2281 stat = GdipDisposeImage((GpImage*)bitmap);
2282 expect(Ok, stat);
2283
2284 stat = GdipDisposeImage((GpImage*)metafile);
2285 expect(Ok, stat);
2286 }
2287
2288 static void test_gditransform_cb(GpMetafile* metafile, EmfPlusRecordType record_type,
2289 unsigned int flags, unsigned int dataSize, const unsigned char *pStr)
2290 {
2291 static const XFORM xform = {0.5, 0, 0, 0.5, 0, 0};
2292 static const RECTL rectangle = {0,0,100,100};
2293 GpStatus stat;
2294
2295 stat = GdipPlayMetafileRecord(metafile, EMR_SETWORLDTRANSFORM, 0, sizeof(xform), (void*)&xform);
2296 expect(Ok, stat);
2297
2298 stat = GdipPlayMetafileRecord(metafile, EMR_RECTANGLE, 0, sizeof(rectangle), (void*)&rectangle);
2299 expect(Ok, stat);
2300 }
2301
2302 static const emfplus_record gditransform_records[] = {
2303 {0, EMR_HEADER},
2304 {0, EMR_CREATEBRUSHINDIRECT},
2305 {0, EMR_SELECTOBJECT},
2306 {0, EMR_GDICOMMENT, 0, test_gditransform_cb},
2307 {0, EMR_SELECTOBJECT},
2308 {0, EMR_DELETEOBJECT},
2309 {0, EMR_EOF},
2310 {0}
2311 };
2312
2313 static void test_gditransform(void)
2314 {
2315 GpStatus stat;
2316 GpMetafile *metafile;
2317 GpGraphics *graphics;
2318 HDC hdc, metafile_dc;
2319 HENHMETAFILE hemf;
2320 MetafileHeader header;
2321 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2322 static const GpPointF dst_points[3] = {{0.0,0.0},{40.0,0.0},{0.0,40.0}};
2323 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2324 HBRUSH hbrush, holdbrush;
2325 GpBitmap *bitmap;
2326 ARGB color;
2327
2328 hdc = CreateCompatibleDC(0);
2329
2330 stat = GdipRecordMetafile(hdc, EmfTypeEmfOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2331 expect(Ok, stat);
2332
2333 DeleteDC(hdc);
2334
2335 if (stat != Ok)
2336 return;
2337
2338 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2339 expect(InvalidParameter, stat);
2340
2341 memset(&header, 0xaa, sizeof(header));
2342 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
2343 expect(Ok, stat);
2344 expect(MetafileTypeEmf, header.Type);
2345 ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
2346
2347 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2348 expect(Ok, stat);
2349
2350 stat = GdipGetDC(graphics, &metafile_dc);
2351 expect(Ok, stat);
2352
2353 if (stat != Ok)
2354 {
2355 GdipDeleteGraphics(graphics);
2356 GdipDisposeImage((GpImage*)metafile);
2357 return;
2358 }
2359
2360 hbrush = CreateSolidBrush(0xff);
2361
2362 holdbrush = SelectObject(metafile_dc, hbrush);
2363
2364 GdiComment(metafile_dc, 8, (const BYTE*)"winetest");
2365
2366 SelectObject(metafile_dc, holdbrush);
2367
2368 DeleteObject(hbrush);
2369
2370 stat = GdipReleaseDC(graphics, metafile_dc);
2371 expect(Ok, stat);
2372
2373 stat = GdipDeleteGraphics(graphics);
2374 expect(Ok, stat);
2375
2376 check_metafile(metafile, gditransform_records, "gditransform metafile", dst_points, &frame, UnitPixel);
2377
2378 sync_metafile(&metafile, "gditransform.emf");
2379
2380 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
2381 expect(Ok, stat);
2382
2383 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2384 expect(Ok, stat);
2385
2386 play_metafile(metafile, graphics, gditransform_records, "gditransform playback", dst_points, &frame, UnitPixel);
2387
2388 stat = GdipBitmapGetPixel(bitmap, 10, 10, &color);
2389 expect(Ok, stat);
2390 expect(0xffff0000, color);
2391
2392 stat = GdipBitmapGetPixel(bitmap, 30, 30, &color);
2393 expect(Ok, stat);
2394 expect(0x00000000, color);
2395
2396 stat = GdipDeleteGraphics(graphics);
2397 expect(Ok, stat);
2398
2399 stat = GdipDisposeImage((GpImage*)bitmap);
2400 expect(Ok, stat);
2401
2402 stat = GdipDisposeImage((GpImage*)metafile);
2403 expect(Ok, stat);
2404 }
2405
2406 static const emfplus_record draw_image_bitmap_records[] = {
2407 {0, EMR_HEADER},
2408 {0, EmfPlusRecordTypeHeader},
2409 {0, EmfPlusRecordTypeObject},
2410 {0, EmfPlusRecordTypeObject},
2411 {0, EmfPlusRecordTypeDrawImagePoints},
2412 {1, EMR_SAVEDC},
2413 {1, EMR_SETICMMODE},
2414 {1, EMR_BITBLT},
2415 {1, EMR_RESTOREDC},
2416 {0, EmfPlusRecordTypeEndOfFile},
2417 {0, EMR_EOF},
2418 {0}
2419 };
2420
2421 static const emfplus_record draw_image_metafile_records[] = {
2422 {0, EMR_HEADER},
2423 {0, EmfPlusRecordTypeHeader},
2424 {0, EmfPlusRecordTypeObject},
2425 /* metafile object */
2426 {0, EMR_HEADER},
2427 {0, EmfPlusRecordTypeHeader},
2428 {0, EmfPlusRecordTypeObject},
2429 {0, EmfPlusRecordTypeObject},
2430 {0, EmfPlusRecordTypeDrawImagePoints},
2431 {1, EMR_SAVEDC},
2432 {1, EMR_SETICMMODE},
2433 {1, EMR_BITBLT},
2434 {1, EMR_RESTOREDC},
2435 {0, EmfPlusRecordTypeEndOfFile},
2436 {0, EMR_EOF},
2437 /* end of metafile object */
2438 {0, EmfPlusRecordTypeDrawImagePoints},
2439 {1, EMR_SAVEDC},
2440 {1, EMR_SETICMMODE},
2441 {1, EMR_BITBLT},
2442 {1, EMR_RESTOREDC},
2443 {0, EmfPlusRecordTypeEndOfFile},
2444 {0, EMR_EOF},
2445 {0}
2446 };
2447
2448 static void test_drawimage(void)
2449 {
2450 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2451 static const GpPointF dst_points[3] = {{10.0,10.0},{85.0,15.0},{10.0,80.0}};
2452 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2453 const ColorMatrix double_red = {{
2454 {2.0,0.0,0.0,0.0,0.0},
2455 {0.0,1.0,0.0,0.0,0.0},
2456 {0.0,0.0,1.0,0.0,0.0},
2457 {0.0,0.0,0.0,1.0,0.0},
2458 {0.0,0.0,0.0,0.0,1.0}}};
2459
2460 GpImageAttributes *imageattr;
2461 GpMetafile *metafile;
2462 GpGraphics *graphics;
2463 HENHMETAFILE hemf;
2464 GpStatus stat;
2465 BITMAPINFO info;
2466 BYTE buff[400];
2467 GpImage *image;
2468 HDC hdc;
2469
2470 hdc = CreateCompatibleDC(0);
2471 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2472 expect(Ok, stat);
2473
2474 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2475 expect(Ok, stat);
2476
2477 memset(&info, 0, sizeof(info));
2478 info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2479 info.bmiHeader.biWidth = 10;
2480 info.bmiHeader.biHeight = 10;
2481 info.bmiHeader.biPlanes = 1;
2482 info.bmiHeader.biBitCount = 32;
2483 info.bmiHeader.biCompression = BI_RGB;
2484 memset(buff, 0x80, sizeof(buff));
2485 stat = GdipCreateBitmapFromGdiDib(&info, buff, (GpBitmap**)&image);
2486 expect(Ok, stat);
2487
2488 stat = GdipCreateImageAttributes(&imageattr);
2489 expect(Ok, stat);
2490
2491 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2492 TRUE, &double_red, NULL, ColorMatrixFlagsDefault);
2493 expect(Ok, stat);
2494
2495 stat = GdipDrawImagePointsRect(graphics, image, dst_points, 3,
2496 0.0, 0.0, 10.0, 10.0, UnitPixel, imageattr, NULL, NULL);
2497 GdipDisposeImageAttributes(imageattr);
2498 expect(Ok, stat);
2499
2500 GdipDisposeImage(image);
2501
2502 stat = GdipDeleteGraphics(graphics);
2503 expect(Ok, stat);
2504 sync_metafile(&metafile, "draw_image_bitmap.emf");
2505
2506 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2507 expect(Ok, stat);
2508
2509 check_emfplus(hemf, draw_image_bitmap_records, "draw image bitmap");
2510
2511 /* test drawing metafile */
2512 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2513 expect(Ok, stat);
2514
2515 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2516 expect(Ok, stat);
2517
2518 stat = GdipCreateMetafileFromEmf(hemf, TRUE, (GpMetafile**)&image);
2519 expect(Ok, stat);
2520
2521 stat = GdipDrawImagePointsRect(graphics, image, dst_points, 3,
2522 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
2523 expect(Ok, stat);
2524
2525 GdipDisposeImage(image);
2526
2527 stat = GdipDeleteGraphics(graphics);
2528 expect(Ok, stat);
2529 sync_metafile(&metafile, "draw_image_metafile.emf");
2530
2531 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2532 expect(Ok, stat);
2533
2534 if (GetProcAddress(GetModuleHandleA("gdiplus.dll"), "GdipConvertToEmfPlus"))
2535 {
2536 check_emfplus(hemf, draw_image_metafile_records, "draw image metafile");
2537 }
2538 else
2539 {
2540 win_skip("draw image metafile records tests skipped\n");
2541 }
2542 DeleteEnhMetaFile(hemf);
2543
2544 DeleteDC(hdc);
2545 stat = GdipDisposeImage((GpImage*)metafile);
2546 expect(Ok, stat);
2547 }
2548
2549 static const emfplus_record properties_records[] = {
2550 {0, EMR_HEADER},
2551 {0, EmfPlusRecordTypeHeader},
2552 {0, EmfPlusRecordTypeSetTextRenderingHint},
2553 {0, EmfPlusRecordTypeSetPixelOffsetMode},
2554 {0, EmfPlusRecordTypeSetAntiAliasMode},
2555 {0, EmfPlusRecordTypeSetCompositingMode},
2556 {0, EmfPlusRecordTypeSetCompositingQuality},
2557 {0, EmfPlusRecordTypeSetInterpolationMode},
2558 {0, EmfPlusRecordTypeEndOfFile},
2559 {0, EMR_EOF},
2560 {0}
2561 };
2562
2563 static void test_properties(void)
2564 {
2565 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2566 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2567
2568 GpMetafile *metafile;
2569 GpGraphics *graphics;
2570 HENHMETAFILE hemf;
2571 GpStatus stat;
2572 HDC hdc;
2573
2574 hdc = CreateCompatibleDC(0);
2575 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2576 expect(Ok, stat);
2577 DeleteDC(hdc);
2578
2579 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2580 expect(Ok, stat);
2581
2582 stat = GdipSetTextRenderingHint(graphics, TextRenderingHintSystemDefault);
2583 expect(Ok, stat);
2584 stat = GdipSetTextRenderingHint(graphics, TextRenderingHintAntiAlias);
2585 expect(Ok, stat);
2586
2587 stat = GdipSetPixelOffsetMode(graphics, PixelOffsetModeHighQuality);
2588 expect(Ok, stat);
2589 stat = GdipSetPixelOffsetMode(graphics, PixelOffsetModeHighQuality);
2590 expect(Ok, stat);
2591
2592 stat = GdipSetSmoothingMode(graphics, SmoothingModeAntiAlias);
2593 expect(Ok, stat);
2594 stat = GdipSetSmoothingMode(graphics, SmoothingModeAntiAlias);
2595 expect(Ok, stat);
2596
2597 stat = GdipSetCompositingMode(graphics, CompositingModeSourceOver);
2598 expect(Ok, stat);
2599 stat = GdipSetCompositingMode(graphics, CompositingModeSourceCopy);
2600 expect(Ok, stat);
2601
2602 stat = GdipSetCompositingQuality(graphics, CompositingQualityHighQuality);
2603 expect(Ok, stat);
2604 stat = GdipSetCompositingQuality(graphics, CompositingQualityHighQuality);
2605 expect(Ok, stat);
2606
2607 stat = GdipSetInterpolationMode(graphics, InterpolationModeDefault);
2608 expect(Ok, stat);
2609 stat = GdipSetInterpolationMode(graphics, InterpolationModeHighQuality);
2610 expect(Ok, stat);
2611
2612 stat = GdipDeleteGraphics(graphics);
2613 expect(Ok, stat);
2614 sync_metafile(&metafile, "properties.emf");
2615
2616 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2617 expect(Ok, stat);
2618
2619 check_emfplus(hemf, properties_records, "properties");
2620 DeleteEnhMetaFile(hemf);
2621
2622 stat = GdipDisposeImage((GpImage*)metafile);
2623 expect(Ok, stat);
2624 }
2625
2626 static const emfplus_record draw_path_records[] = {
2627 {0, EMR_HEADER},
2628 {0, EmfPlusRecordTypeHeader},
2629 {0, EmfPlusRecordTypeObject},
2630 {0, EmfPlusRecordTypeObject},
2631 {0, EmfPlusRecordTypeDrawPath},
2632 {1, EMR_SAVEDC},
2633 {1, EMR_SETICMMODE},
2634 {1, EMR_BITBLT},
2635 {1, EMR_RESTOREDC},
2636 {0, EmfPlusRecordTypeEndOfFile},
2637 {0, EMR_EOF},
2638 {0}
2639 };
2640
2641 static void test_drawpath(void)
2642 {
2643 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2644 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2645
2646 GpMetafile *metafile;
2647 GpGraphics *graphics;
2648 HENHMETAFILE hemf;
2649 GpStatus stat;
2650 GpPath *path;
2651 GpPen *pen;
2652 HDC hdc;
2653
2654 hdc = CreateCompatibleDC(0);
2655 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2656 expect(Ok, stat);
2657 DeleteDC(hdc);
2658
2659 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2660 expect(Ok, stat);
2661
2662 stat = GdipCreatePath(FillModeAlternate, &path);
2663 expect(Ok, stat);
2664 stat = GdipAddPathLine(path, 5, 5, 30, 30);
2665 expect(Ok, stat);
2666
2667 stat = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
2668 expect(Ok, stat);
2669
2670 stat = GdipDrawPath(graphics, pen, path);
2671 expect(Ok, stat);
2672
2673 stat = GdipDeletePen(pen);
2674 expect(Ok, stat);
2675 stat = GdipDeletePath(path);
2676 expect(Ok, stat);
2677
2678 stat = GdipDeleteGraphics(graphics);
2679 expect(Ok, stat);
2680 sync_metafile(&metafile, "draw_path.emf");
2681
2682 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2683 expect(Ok, stat);
2684
2685 check_emfplus(hemf, draw_path_records, "draw path");
2686 DeleteEnhMetaFile(hemf);
2687
2688 stat = GdipDisposeImage((GpImage*)metafile);
2689 expect(Ok, stat);
2690 }
2691
2692 static const emfplus_record fill_path_records[] = {
2693 {0, EMR_HEADER},
2694 {0, EmfPlusRecordTypeHeader},
2695 {0, EmfPlusRecordTypeObject},
2696 {0, EmfPlusRecordTypeFillPath},
2697 {1, EMR_SAVEDC},
2698 {1, EMR_SETICMMODE},
2699 {1, EMR_BITBLT},
2700 {1, EMR_RESTOREDC},
2701 {0, EmfPlusRecordTypeEndOfFile},
2702 {0, EMR_EOF},
2703 {0}
2704 };
2705
2706 static void test_fillpath(void)
2707 {
2708 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2709 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2710 static const WCHAR winetestemfW[] = {'w','i','n','e','t','e','s','t','.','e','m','f',0};
2711
2712 GpMetafile *metafile;
2713 GpGraphics *graphics;
2714 GpSolidFill *brush;
2715 HENHMETAFILE hemf;
2716 GpStatus stat;
2717 GpPath *path;
2718 HDC hdc;
2719
2720 hdc = CreateCompatibleDC(0);
2721 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2722 expect(Ok, stat);
2723 DeleteDC(hdc);
2724
2725 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2726 expect(Ok, stat);
2727
2728 stat = GdipCreatePath(FillModeAlternate, &path);
2729 expect(Ok, stat);
2730 stat = GdipAddPathLine(path, 5, 5, 30, 30);
2731 expect(Ok, stat);
2732 stat = GdipAddPathLine(path, 30, 30, 5, 30);
2733 expect(Ok, stat);
2734
2735 stat = GdipCreateSolidFill(0xffaabbcc, &brush);
2736 expect(Ok, stat);
2737
2738 stat = GdipFillPath(graphics, (GpBrush*)brush, path);
2739 expect(Ok, stat);
2740
2741 stat = GdipDeleteBrush((GpBrush*)brush);
2742 expect(Ok, stat);
2743 stat = GdipDeletePath(path);
2744 expect(Ok, stat);
2745
2746 stat = GdipDeleteGraphics(graphics);
2747 expect(Ok, stat);
2748 sync_metafile(&metafile, "fill_path.emf");
2749
2750 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2751 expect(Ok, stat);
2752
2753 check_emfplus(hemf, fill_path_records, "fill path");
2754
2755 /* write to disk */
2756 DeleteEnhMetaFile(CopyEnhMetaFileW(hemf, winetestemfW));
2757
2758 DeleteEnhMetaFile(hemf);
2759
2760 stat = GdipDisposeImage((GpImage*)metafile);
2761 expect(Ok, stat);
2762
2763 /* should succeed when given path to an EMF */
2764 stat = GdipCreateMetafileFromWmfFile(winetestemfW, NULL, &metafile);
2765 expect(Ok, stat);
2766
2767 stat = GdipDisposeImage((GpImage*)metafile);
2768 expect(Ok, stat);
2769
2770 DeleteFileW(winetestemfW);
2771
2772 stat = GdipCreateMetafileFromWmfFile(winetestemfW, NULL, &metafile);
2773 expect(GenericError, stat);
2774 }
2775
2776 START_TEST(metafile)
2777 {
2778 struct GdiplusStartupInput gdiplusStartupInput;
2779 ULONG_PTR gdiplusToken;
2780 int myARGC;
2781 char **myARGV;
2782 HMODULE hmsvcrt;
2783 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
2784
2785 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
2786 hmsvcrt = LoadLibraryA("msvcrt");
2787 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
2788 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
2789
2790 gdiplusStartupInput.GdiplusVersion = 1;
2791 gdiplusStartupInput.DebugEventCallback = NULL;
2792 gdiplusStartupInput.SuppressBackgroundThread = 0;
2793 gdiplusStartupInput.SuppressExternalCodecs = 0;
2794
2795 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
2796
2797 myARGC = winetest_get_mainargs( &myARGV );
2798
2799 if (myARGC >= 3)
2800 {
2801 if (!strcmp(myARGV[2], "save"))
2802 save_metafiles = TRUE;
2803 else if (!strcmp(myARGV[2], "load"))
2804 load_metafiles = TRUE;
2805 }
2806
2807 test_empty();
2808 test_getdc();
2809 test_emfonly();
2810 test_fillrect();
2811 test_clear();
2812 test_nullframerect();
2813 test_pagetransform();
2814 test_worldtransform();
2815 test_converttoemfplus();
2816 test_frameunit();
2817 test_containers();
2818 test_clipping();
2819 test_gditransform();
2820 test_drawimage();
2821 test_properties();
2822 test_drawpath();
2823 test_fillpath();
2824
2825 GdiplusShutdown(gdiplusToken);
2826 }