14b4f51a2c8b3ea8ce39766a867d62922af7f7ac
[reactos.git] / 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) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got))
34
35 static BOOL save_metafiles;
36
37 typedef struct emfplus_record
38 {
39 BOOL todo;
40 ULONG record_type;
41 BOOL playback_todo;
42 } emfplus_record;
43
44 typedef struct emfplus_check_state
45 {
46 const char *desc;
47 int count;
48 const struct emfplus_record *expected;
49 GpMetafile *metafile;
50 } emfplus_check_state;
51
52 static void check_record(int count, const char *desc, const struct emfplus_record *expected, const struct emfplus_record *actual)
53 {
54 if (expected->todo)
55 todo_wine ok(expected->record_type == actual->record_type,
56 "%s.%i: Expected record type 0x%x, got 0x%x\n", desc, count,
57 expected->record_type, actual->record_type);
58 else
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 static int CALLBACK enum_emf_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR,
73 int nObj, LPARAM lpData)
74 {
75 emfplus_check_state *state = (emfplus_check_state*)lpData;
76 emfplus_record actual;
77
78 if (lpEMFR->iType == EMR_GDICOMMENT)
79 {
80 const EMRGDICOMMENT *comment = (const EMRGDICOMMENT*)lpEMFR;
81
82 if (comment->cbData >= 4 && memcmp(comment->Data, "EMF+", 4) == 0)
83 {
84 int offset = 4;
85
86 while (offset + sizeof(EmfPlusRecordHeader) <= comment->cbData)
87 {
88 const EmfPlusRecordHeader *record = (const EmfPlusRecordHeader*)&comment->Data[offset];
89
90 ok(record->Size == record->DataSize + sizeof(EmfPlusRecordHeader),
91 "%s: EMF+ record datasize %u and size %u mismatch\n", state->desc, record->DataSize, record->Size);
92
93 ok(offset + record->DataSize <= comment->cbData,
94 "%s: EMF+ record truncated\n", state->desc);
95
96 if (offset + record->DataSize > comment->cbData)
97 return 0;
98
99 if (state->expected[state->count].record_type)
100 {
101 actual.todo = FALSE;
102 actual.record_type = record->Type;
103
104 check_record(state->count, state->desc, &state->expected[state->count], &actual);
105
106 state->count++;
107 }
108 else
109 {
110 ok(0, "%s: Unexpected EMF+ 0x%x record\n", state->desc, record->Type);
111 }
112
113 offset += record->Size;
114 }
115
116 ok(offset == comment->cbData, "%s: truncated EMF+ record data?\n", state->desc);
117
118 return 1;
119 }
120 }
121
122 if (state->expected[state->count].record_type)
123 {
124 actual.todo = FALSE;
125 actual.record_type = lpEMFR->iType;
126
127 check_record(state->count, state->desc, &state->expected[state->count], &actual);
128
129 state->count++;
130 }
131 else
132 {
133 ok(0, "%s: Unexpected EMF 0x%x record\n", state->desc, lpEMFR->iType);
134 }
135
136 return 1;
137 }
138
139 static void check_emfplus(HENHMETAFILE hemf, const emfplus_record *expected, const char *desc)
140 {
141 emfplus_check_state state;
142
143 state.desc = desc;
144 state.count = 0;
145 state.expected = expected;
146
147 EnumEnhMetaFile(0, hemf, enum_emf_proc, &state, NULL);
148
149 if (expected[state.count].todo)
150 todo_wine ok(expected[state.count].record_type == 0, "%s: Got %i records, expecting more\n", desc, state.count);
151 else
152 ok(expected[state.count].record_type == 0, "%s: Got %i records, expecting more\n", desc, state.count);
153 }
154
155 static BOOL CALLBACK enum_metafile_proc(EmfPlusRecordType record_type, unsigned int flags,
156 unsigned int dataSize, const unsigned char *pStr, void *userdata)
157 {
158 emfplus_check_state *state = (emfplus_check_state*)userdata;
159 emfplus_record actual;
160
161 actual.todo = FALSE;
162 actual.record_type = record_type;
163
164 if (dataSize == 0)
165 ok(pStr == NULL, "non-NULL pStr\n");
166
167 if (state->expected[state->count].record_type)
168 {
169 check_record(state->count, state->desc, &state->expected[state->count], &actual);
170
171 state->count++;
172 }
173 else
174 {
175 ok(0, "%s: Unexpected EMF 0x%x record\n", state->desc, record_type);
176 }
177
178 return TRUE;
179 }
180
181 static void check_metafile(GpMetafile *metafile, const emfplus_record *expected, const char *desc,
182 const GpPointF *dst_points, const GpRectF *src_rect, Unit src_unit)
183 {
184 GpStatus stat;
185 HDC hdc;
186 GpGraphics *graphics;
187 emfplus_check_state state;
188
189 state.desc = desc;
190 state.count = 0;
191 state.expected = expected;
192 state.metafile = metafile;
193
194 hdc = CreateCompatibleDC(0);
195
196 stat = GdipCreateFromHDC(hdc, &graphics);
197 expect(Ok, stat);
198
199 stat = GdipEnumerateMetafileSrcRectDestPoints(graphics, metafile, dst_points,
200 3, src_rect, src_unit, enum_metafile_proc, &state, NULL);
201 expect(Ok, stat);
202
203 if (expected[state.count].todo)
204 todo_wine ok(expected[state.count].record_type == 0, "%s: Got %i records, expecting more\n", desc, state.count);
205 else
206 ok(expected[state.count].record_type == 0, "%s: Got %i records, expecting more\n", desc, state.count);
207
208 GdipDeleteGraphics(graphics);
209
210 DeleteDC(hdc);
211 }
212
213 static BOOL CALLBACK play_metafile_proc(EmfPlusRecordType record_type, unsigned int flags,
214 unsigned int dataSize, const unsigned char *pStr, void *userdata)
215 {
216 emfplus_check_state *state = (emfplus_check_state*)userdata;
217 GpStatus stat;
218
219 stat = GdipPlayMetafileRecord(state->metafile, record_type, flags, dataSize, pStr);
220
221 if (state->expected[state->count].record_type)
222 {
223 if (state->expected[state->count].playback_todo)
224 todo_wine ok(stat == Ok, "%s.%i: GdipPlayMetafileRecord failed with stat %i\n", state->desc, state->count, stat);
225 else
226 ok(stat == Ok, "%s.%i: GdipPlayMetafileRecord failed with stat %i\n", state->desc, state->count, stat);
227 state->count++;
228 }
229 else
230 {
231 if (state->expected[state->count].playback_todo)
232 todo_wine ok(0, "%s: too many records\n", state->desc);
233 else
234 ok(0, "%s: too many records\n", state->desc);
235
236 return FALSE;
237 }
238
239 return TRUE;
240 }
241
242 static void play_metafile(GpMetafile *metafile, GpGraphics *graphics, const emfplus_record *expected,
243 const char *desc, const GpPointF *dst_points, const GpRectF *src_rect, Unit src_unit)
244 {
245 GpStatus stat;
246 emfplus_check_state state;
247
248 state.desc = desc;
249 state.count = 0;
250 state.expected = expected;
251 state.metafile = metafile;
252
253 stat = GdipEnumerateMetafileSrcRectDestPoints(graphics, metafile, dst_points,
254 3, src_rect, src_unit, play_metafile_proc, &state, NULL);
255 expect(Ok, stat);
256 }
257
258 static void save_metafile(GpMetafile *metafile, const char *filename)
259 {
260 if (save_metafiles)
261 {
262 GpMetafile *clone;
263 HENHMETAFILE hemf;
264 GpStatus stat;
265
266 stat = GdipCloneImage((GpImage*)metafile, (GpImage**)&clone);
267 expect(Ok, stat);
268
269 stat = GdipGetHemfFromMetafile(clone, &hemf);
270 expect(Ok, stat);
271
272 DeleteEnhMetaFile(CopyEnhMetaFileA(hemf, filename));
273
274 DeleteEnhMetaFile(hemf);
275
276 stat = GdipDisposeImage((GpImage*)clone);
277 expect(Ok, stat);
278 }
279 }
280
281 static const emfplus_record empty_records[] = {
282 {0, EMR_HEADER},
283 {0, EmfPlusRecordTypeHeader},
284 {0, EmfPlusRecordTypeEndOfFile},
285 {0, EMR_EOF},
286 {0}
287 };
288
289 static void test_empty(void)
290 {
291 GpStatus stat;
292 GpMetafile *metafile;
293 GpGraphics *graphics;
294 HDC hdc;
295 HENHMETAFILE hemf, dummy;
296 BOOL ret;
297 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
298 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
299 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
300
301 hdc = CreateCompatibleDC(0);
302
303 stat = GdipRecordMetafile(NULL, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
304 expect(InvalidParameter, stat);
305
306 stat = GdipRecordMetafile(hdc, MetafileTypeInvalid, &frame, MetafileFrameUnitPixel, description, &metafile);
307 expect(InvalidParameter, stat);
308
309 stat = GdipRecordMetafile(hdc, MetafileTypeWmf, &frame, MetafileFrameUnitPixel, description, &metafile);
310 expect(InvalidParameter, stat);
311
312 stat = GdipRecordMetafile(hdc, MetafileTypeWmfPlaceable, &frame, MetafileFrameUnitPixel, description, &metafile);
313 expect(InvalidParameter, stat);
314
315 stat = GdipRecordMetafile(hdc, MetafileTypeEmfPlusDual+1, &frame, MetafileFrameUnitPixel, description, &metafile);
316 expect(InvalidParameter, stat);
317
318 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, NULL);
319 expect(InvalidParameter, stat);
320
321 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
322 expect(Ok, stat);
323
324 DeleteDC(hdc);
325
326 if (stat != Ok)
327 return;
328
329 stat = GdipGetHemfFromMetafile(metafile, &hemf);
330 expect(InvalidParameter, stat);
331
332 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
333 expect(Ok, stat);
334
335 stat = GdipGetHemfFromMetafile(metafile, &hemf);
336 expect(InvalidParameter, stat);
337
338 stat = GdipDeleteGraphics(graphics);
339 expect(Ok, stat);
340
341 check_metafile(metafile, empty_records, "empty metafile", dst_points, &frame, UnitPixel);
342
343 save_metafile(metafile, "empty.emf");
344
345 stat = GdipGetHemfFromMetafile(metafile, &hemf);
346 expect(Ok, stat);
347
348 stat = GdipGetHemfFromMetafile(metafile, &dummy);
349 expect(InvalidParameter, stat);
350
351 stat = GdipDisposeImage((GpImage*)metafile);
352 expect(Ok, stat);
353
354 check_emfplus(hemf, empty_records, "empty emf");
355
356 ret = DeleteEnhMetaFile(hemf);
357 ok(ret != 0, "Failed to delete enhmetafile %p\n", hemf);
358 }
359
360 static const emfplus_record getdc_records[] = {
361 {0, EMR_HEADER},
362 {0, EmfPlusRecordTypeHeader},
363 {0, EmfPlusRecordTypeGetDC},
364 {0, EMR_CREATEBRUSHINDIRECT},
365 {0, EMR_SELECTOBJECT},
366 {0, EMR_RECTANGLE},
367 {0, EMR_SELECTOBJECT},
368 {0, EMR_DELETEOBJECT},
369 {0, EmfPlusRecordTypeEndOfFile},
370 {0, EMR_EOF},
371 {0}
372 };
373
374 static void test_getdc(void)
375 {
376 GpStatus stat;
377 GpMetafile *metafile;
378 GpGraphics *graphics;
379 HDC hdc, metafile_dc;
380 HENHMETAFILE hemf;
381 BOOL ret;
382 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
383 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
384 static const GpPointF dst_points_half[3] = {{0.0,0.0},{50.0,0.0},{0.0,50.0}};
385 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
386 HBRUSH hbrush, holdbrush;
387 GpBitmap *bitmap;
388 ARGB color;
389
390 hdc = CreateCompatibleDC(0);
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 = GdipGetDC(graphics, &metafile_dc);
407 expect(Ok, stat);
408
409 if (stat != Ok)
410 {
411 GdipDeleteGraphics(graphics);
412 GdipDisposeImage((GpImage*)metafile);
413 return;
414 }
415
416 hbrush = CreateSolidBrush(0xff0000);
417
418 holdbrush = SelectObject(metafile_dc, hbrush);
419
420 Rectangle(metafile_dc, 25, 25, 75, 75);
421
422 SelectObject(metafile_dc, holdbrush);
423
424 DeleteObject(hbrush);
425
426 stat = GdipReleaseDC(graphics, metafile_dc);
427 expect(Ok, stat);
428
429 stat = GdipDeleteGraphics(graphics);
430 expect(Ok, stat);
431
432 check_metafile(metafile, getdc_records, "getdc metafile", dst_points, &frame, UnitPixel);
433
434 save_metafile(metafile, "getdc.emf");
435
436 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
437 expect(Ok, stat);
438
439 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
440 expect(Ok, stat);
441
442 play_metafile(metafile, graphics, getdc_records, "getdc playback", dst_points, &frame, UnitPixel);
443
444 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
445 expect(Ok, stat);
446 expect(0, color);
447
448 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
449 expect(Ok, stat);
450 expect(0xff0000ff, color);
451
452 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
453 expect(Ok, stat);
454
455 play_metafile(metafile, graphics, getdc_records, "getdc playback", dst_points_half, &frame, UnitPixel);
456
457 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
458 expect(Ok, stat);
459 expect(0xff0000ff, color);
460
461 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
462 expect(Ok, stat);
463 expect(0, color);
464
465 stat = GdipBitmapSetPixel(bitmap, 15, 15, 0);
466 expect(Ok, stat);
467
468 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
469 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
470 expect(Ok, stat);
471
472 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
473 expect(Ok, stat);
474 expect(0, color);
475
476 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
477 expect(Ok, stat);
478 expect(0xff0000ff, color);
479
480 stat = GdipDeleteGraphics(graphics);
481 expect(Ok, stat);
482
483 stat = GdipDisposeImage((GpImage*)bitmap);
484 expect(Ok, stat);
485
486 stat = GdipGetHemfFromMetafile(metafile, &hemf);
487 expect(Ok, stat);
488
489 stat = GdipDisposeImage((GpImage*)metafile);
490 expect(Ok, stat);
491
492 check_emfplus(hemf, getdc_records, "getdc emf");
493
494 ret = DeleteEnhMetaFile(hemf);
495 ok(ret != 0, "Failed to delete enhmetafile %p\n", hemf);
496 }
497
498 static const emfplus_record emfonly_records[] = {
499 {0, EMR_HEADER},
500 {0, EMR_CREATEBRUSHINDIRECT},
501 {0, EMR_SELECTOBJECT},
502 {0, EMR_RECTANGLE},
503 {0, EMR_SELECTOBJECT},
504 {0, EMR_DELETEOBJECT},
505 {0, EMR_EOF},
506 {0}
507 };
508
509 static void test_emfonly(void)
510 {
511 GpStatus stat;
512 GpMetafile *metafile;
513 GpImage *clone;
514 GpGraphics *graphics;
515 HDC hdc, metafile_dc;
516 HENHMETAFILE hemf;
517 BOOL ret;
518 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
519 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
520 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
521 HBRUSH hbrush, holdbrush;
522 GpBitmap *bitmap;
523 ARGB color;
524
525 hdc = CreateCompatibleDC(0);
526
527 stat = GdipRecordMetafile(hdc, EmfTypeEmfOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
528 expect(Ok, stat);
529
530 DeleteDC(hdc);
531
532 if (stat != Ok)
533 return;
534
535 stat = GdipGetHemfFromMetafile(metafile, &hemf);
536 expect(InvalidParameter, stat);
537
538 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
539 expect(Ok, stat);
540
541 stat = GdipGetDC(graphics, &metafile_dc);
542 expect(Ok, stat);
543
544 if (stat != Ok)
545 {
546 GdipDeleteGraphics(graphics);
547 GdipDisposeImage((GpImage*)metafile);
548 return;
549 }
550
551 hbrush = CreateSolidBrush(0xff0000);
552
553 holdbrush = SelectObject(metafile_dc, hbrush);
554
555 Rectangle(metafile_dc, 25, 25, 75, 75);
556
557 SelectObject(metafile_dc, holdbrush);
558
559 DeleteObject(hbrush);
560
561 stat = GdipReleaseDC(graphics, metafile_dc);
562 expect(Ok, stat);
563
564 stat = GdipDeleteGraphics(graphics);
565 expect(Ok, stat);
566
567 check_metafile(metafile, emfonly_records, "emfonly metafile", dst_points, &frame, UnitPixel);
568
569 save_metafile(metafile, "emfonly.emf");
570
571 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
572 expect(Ok, stat);
573
574 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
575 expect(Ok, stat);
576
577 play_metafile(metafile, graphics, emfonly_records, "emfonly playback", dst_points, &frame, UnitPixel);
578
579 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
580 expect(Ok, stat);
581 expect(0, color);
582
583 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
584 expect(Ok, stat);
585 expect(0xff0000ff, color);
586
587 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
588 expect(Ok, stat);
589
590 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
591 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
592 expect(Ok, stat);
593
594 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
595 expect(Ok, stat);
596 expect(0, color);
597
598 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
599 expect(Ok, stat);
600 expect(0xff0000ff, color);
601
602 stat = GdipCloneImage((GpImage*)metafile, &clone);
603 expect(Ok, stat);
604
605 if (stat == Ok)
606 {
607 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
608 expect(Ok, stat);
609
610 stat = GdipDrawImagePointsRect(graphics, clone, dst_points, 3,
611 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
612 expect(Ok, stat);
613
614 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
615 expect(Ok, stat);
616 expect(0, color);
617
618 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
619 expect(Ok, stat);
620 expect(0xff0000ff, color);
621
622 GdipDisposeImage(clone);
623 }
624
625 stat = GdipDeleteGraphics(graphics);
626 expect(Ok, stat);
627
628 stat = GdipDisposeImage((GpImage*)bitmap);
629 expect(Ok, stat);
630
631 stat = GdipGetHemfFromMetafile(metafile, &hemf);
632 expect(Ok, stat);
633
634 stat = GdipDisposeImage((GpImage*)metafile);
635 expect(Ok, stat);
636
637 check_emfplus(hemf, emfonly_records, "emfonly emf");
638
639 ret = DeleteEnhMetaFile(hemf);
640 ok(ret != 0, "Failed to delete enhmetafile %p\n", hemf);
641 }
642
643 static const emfplus_record fillrect_records[] = {
644 {0, EMR_HEADER},
645 {0, EmfPlusRecordTypeHeader},
646 {0, EmfPlusRecordTypeFillRects},
647 {0, EmfPlusRecordTypeEndOfFile},
648 {0, EMR_EOF},
649 {0}
650 };
651
652 static void test_fillrect(void)
653 {
654 GpStatus stat;
655 GpMetafile *metafile;
656 GpGraphics *graphics;
657 HDC hdc;
658 HENHMETAFILE hemf;
659 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
660 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
661 static const GpPointF dst_points_half[3] = {{0.0,0.0},{50.0,0.0},{0.0,50.0}};
662 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
663 GpBitmap *bitmap;
664 ARGB color;
665 GpBrush *brush;
666
667 hdc = CreateCompatibleDC(0);
668
669 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
670 expect(Ok, stat);
671
672 DeleteDC(hdc);
673
674 if (stat != Ok)
675 return;
676
677 stat = GdipGetHemfFromMetafile(metafile, &hemf);
678 expect(InvalidParameter, stat);
679
680 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
681 expect(Ok, stat);
682
683 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
684 expect(Ok, stat);
685
686 stat = GdipFillRectangleI(graphics, brush, 25, 25, 75, 75);
687 expect(Ok, stat);
688
689 stat = GdipDeleteBrush(brush);
690 expect(Ok, stat);
691
692 stat = GdipDeleteGraphics(graphics);
693 expect(Ok, stat);
694
695 check_metafile(metafile, fillrect_records, "fillrect metafile", dst_points, &frame, UnitPixel);
696
697 save_metafile(metafile, "fillrect.emf");
698
699 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
700 expect(Ok, stat);
701
702 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
703 expect(Ok, stat);
704
705 play_metafile(metafile, graphics, fillrect_records, "fillrect playback", dst_points, &frame, UnitPixel);
706
707 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
708 expect(Ok, stat);
709 expect(0, color);
710
711 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
712 expect(Ok, stat);
713 expect(0xff0000ff, color);
714
715 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
716 expect(Ok, stat);
717
718 play_metafile(metafile, graphics, fillrect_records, "fillrect playback", dst_points_half, &frame, UnitPixel);
719
720 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
721 expect(Ok, stat);
722 expect(0xff0000ff, color);
723
724 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
725 expect(Ok, stat);
726 expect(0, color);
727
728 stat = GdipBitmapSetPixel(bitmap, 15, 15, 0);
729 expect(Ok, stat);
730
731 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
732 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
733 expect(Ok, stat);
734
735 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
736 expect(Ok, stat);
737 expect(0, color);
738
739 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
740 expect(Ok, stat);
741 expect(0xff0000ff, color);
742
743 stat = GdipDeleteGraphics(graphics);
744 expect(Ok, stat);
745
746 stat = GdipDisposeImage((GpImage*)bitmap);
747 expect(Ok, stat);
748
749 stat = GdipDisposeImage((GpImage*)metafile);
750 expect(Ok, stat);
751 }
752
753 static const emfplus_record pagetransform_records[] = {
754 {0, EMR_HEADER},
755 {0, EmfPlusRecordTypeHeader},
756 {0, EmfPlusRecordTypeFillRects},
757 {0, EmfPlusRecordTypeSetPageTransform},
758 {0, EmfPlusRecordTypeFillRects},
759 {0, EmfPlusRecordTypeSetPageTransform},
760 {0, EmfPlusRecordTypeFillRects},
761 {0, EmfPlusRecordTypeSetPageTransform},
762 {0, EmfPlusRecordTypeFillRects},
763 {0, EmfPlusRecordTypeSetPageTransform},
764 {0, EmfPlusRecordTypeFillRects},
765 {0, EmfPlusRecordTypeEndOfFile},
766 {0, EMR_EOF},
767 {0}
768 };
769
770 static void test_pagetransform(void)
771 {
772 GpStatus stat;
773 GpMetafile *metafile;
774 GpGraphics *graphics;
775 HDC hdc;
776 static const GpRectF frame = {0.0, 0.0, 5.0, 5.0};
777 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
778 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
779 GpBitmap *bitmap;
780 ARGB color;
781 GpBrush *brush;
782 GpUnit unit;
783 REAL scale, dpix, dpiy;
784 UINT width, height;
785
786 hdc = CreateCompatibleDC(0);
787
788 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitInch, description, &metafile);
789 expect(Ok, stat);
790
791 DeleteDC(hdc);
792
793 if (stat != Ok)
794 return;
795
796 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &dpix);
797 todo_wine expect(InvalidParameter, stat);
798
799 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &dpiy);
800 todo_wine expect(InvalidParameter, stat);
801
802 stat = GdipGetImageWidth((GpImage*)metafile, &width);
803 todo_wine expect(InvalidParameter, stat);
804
805 stat = GdipGetImageHeight((GpImage*)metafile, &height);
806 todo_wine expect(InvalidParameter, stat);
807
808 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
809 expect(Ok, stat);
810
811 /* initial scale */
812 stat = GdipGetPageUnit(graphics, &unit);
813 expect(Ok, stat);
814 expect(UnitDisplay, unit);
815
816 stat = GdipGetPageScale(graphics, &scale);
817 expect(Ok, stat);
818 expectf(1.0, scale);
819
820 stat = GdipGetDpiX(graphics, &dpix);
821 expect(Ok, stat);
822 expectf(96.0, dpix);
823
824 stat = GdipGetDpiY(graphics, &dpiy);
825 expect(Ok, stat);
826 expectf(96.0, dpiy);
827
828 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
829 expect(Ok, stat);
830
831 stat = GdipFillRectangleI(graphics, brush, 1, 2, 1, 1);
832 expect(Ok, stat);
833
834 stat = GdipDeleteBrush(brush);
835 expect(Ok, stat);
836
837 /* page unit = pixels */
838 stat = GdipSetPageUnit(graphics, UnitPixel);
839 expect(Ok, stat);
840
841 stat = GdipGetPageUnit(graphics, &unit);
842 expect(Ok, stat);
843 expect(UnitPixel, unit);
844
845 stat = GdipCreateSolidFill((ARGB)0xff00ff00, (GpSolidFill**)&brush);
846 expect(Ok, stat);
847
848 stat = GdipFillRectangleI(graphics, brush, 0, 1, 1, 1);
849 expect(Ok, stat);
850
851 stat = GdipDeleteBrush(brush);
852 expect(Ok, stat);
853
854 /* page scale = 3, unit = pixels */
855 stat = GdipSetPageScale(graphics, 3.0);
856 expect(Ok, stat);
857
858 stat = GdipGetPageScale(graphics, &scale);
859 expect(Ok, stat);
860 expectf(3.0, scale);
861
862 stat = GdipCreateSolidFill((ARGB)0xff00ffff, (GpSolidFill**)&brush);
863 expect(Ok, stat);
864
865 stat = GdipFillRectangleI(graphics, brush, 0, 1, 2, 2);
866 expect(Ok, stat);
867
868 stat = GdipDeleteBrush(brush);
869 expect(Ok, stat);
870
871 /* page scale = 3, unit = inches */
872 stat = GdipSetPageUnit(graphics, UnitInch);
873 expect(Ok, stat);
874
875 stat = GdipGetPageUnit(graphics, &unit);
876 expect(Ok, stat);
877 expect(UnitInch, unit);
878
879 stat = GdipCreateSolidFill((ARGB)0xffff0000, (GpSolidFill**)&brush);
880 expect(Ok, stat);
881
882 stat = GdipFillRectangle(graphics, brush, 1.0/96.0, 0, 1, 1);
883 expect(Ok, stat);
884
885 stat = GdipDeleteBrush(brush);
886 expect(Ok, stat);
887
888 /* page scale = 3, unit = display */
889 stat = GdipSetPageUnit(graphics, UnitDisplay);
890 expect(Ok, stat);
891
892 stat = GdipGetPageUnit(graphics, &unit);
893 expect(Ok, stat);
894 expect(UnitDisplay, unit);
895
896 stat = GdipCreateSolidFill((ARGB)0xffff00ff, (GpSolidFill**)&brush);
897 expect(Ok, stat);
898
899 stat = GdipFillRectangle(graphics, brush, 3, 3, 2, 2);
900 expect(Ok, stat);
901
902 stat = GdipDeleteBrush(brush);
903 expect(Ok, stat);
904
905 stat = GdipDeleteGraphics(graphics);
906 expect(Ok, stat);
907
908 check_metafile(metafile, pagetransform_records, "pagetransform metafile", dst_points, &frame, UnitPixel);
909
910 save_metafile(metafile, "pagetransform.emf");
911
912 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
913 expect(Ok, stat);
914
915 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
916 expect(Ok, stat);
917
918 play_metafile(metafile, graphics, pagetransform_records, "pagetransform playback", dst_points, &frame, UnitPixel);
919
920 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
921 expect(Ok, stat);
922 expect(0, color);
923
924 stat = GdipBitmapGetPixel(bitmap, 30, 50, &color);
925 expect(Ok, stat);
926 expect(0xff0000ff, color);
927
928 stat = GdipBitmapGetPixel(bitmap, 10, 30, &color);
929 expect(Ok, stat);
930 expect(0xff00ff00, color);
931
932 stat = GdipBitmapGetPixel(bitmap, 20, 80, &color);
933 expect(Ok, stat);
934 expect(0xff00ffff, color);
935
936 stat = GdipBitmapGetPixel(bitmap, 80, 20, &color);
937 expect(Ok, stat);
938 expect(0xffff0000, color);
939
940 stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
941 expect(Ok, stat);
942 expect(0xffff00ff, color);
943
944 stat = GdipDeleteGraphics(graphics);
945 expect(Ok, stat);
946
947 stat = GdipDisposeImage((GpImage*)bitmap);
948 expect(Ok, stat);
949
950 stat = GdipDisposeImage((GpImage*)metafile);
951 expect(Ok, stat);
952 }
953
954 START_TEST(metafile)
955 {
956 struct GdiplusStartupInput gdiplusStartupInput;
957 ULONG_PTR gdiplusToken;
958 int myARGC;
959 char **myARGV;
960
961 gdiplusStartupInput.GdiplusVersion = 1;
962 gdiplusStartupInput.DebugEventCallback = NULL;
963 gdiplusStartupInput.SuppressBackgroundThread = 0;
964 gdiplusStartupInput.SuppressExternalCodecs = 0;
965
966 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
967
968 myARGC = winetest_get_mainargs( &myARGV );
969
970 if (myARGC >= 3 && !strcmp(myARGV[2], "save"))
971 save_metafiles = TRUE;
972
973 test_empty();
974 test_getdc();
975 test_emfonly();
976 test_fillrect();
977 test_pagetransform();
978
979 GdiplusShutdown(gdiplusToken);
980 }