gdi32: Fix East-Asian font parameters.
[wine] / dlls / gdi32 / tests / mapping.c
1 /*
2  * Unit tests for mapping functions
3  *
4  * Copyright (c) 2005 Huw Davies
5  * Copyright (c) 2008 Dmitry  Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdio.h>
23 #include <math.h>
24
25 #include "wine/test.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
30
31 static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
32 static DWORD (WINAPI *pGetLayout)(HDC hdc);
33 static INT (WINAPI *pGetRandomRgn)(HDC hDC, HRGN hRgn, INT iCode);
34 static BOOL (WINAPI *pGetTransform)(HDC, DWORD, XFORM *);
35 static DWORD (WINAPI *pSetVirtualResolution)(HDC, DWORD, DWORD, DWORD, DWORD);
36
37 #define rough_match(got, expected) (abs( MulDiv( (got) - (expected), 1000, (expected) )) <= 5)
38
39 #define expect_LPtoDP(_hdc, _x, _y) \
40 { \
41     POINT _pt = { 1000, 1000 }; \
42     LPtoDP(_hdc, &_pt, 1); \
43     ok(rough_match(_pt.x, _x), "expected x %d, got %d\n", (_x), _pt.x); \
44     ok(rough_match(_pt.y, _y), "expected y %d, got %d\n", (_y), _pt.y); \
45 }
46
47 #define expect_world_transform(_hdc, _em11, _em22) \
48 { \
49     BOOL _ret; \
50     XFORM _xform; \
51     SetLastError(0xdeadbeef); \
52     _ret = GetWorldTransform(_hdc, &_xform); \
53     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) \
54     { \
55         ok(_ret, "GetWorldTransform error %u\n", GetLastError()); \
56         ok(_xform.eM11 == (_em11), "expected %f, got %f\n", (_em11), _xform.eM11); \
57         ok(_xform.eM12 == 0.0, "expected 0.0, got %f\n", _xform.eM12); \
58         ok(_xform.eM21 == 0.0, "expected 0.0, got %f\n", _xform.eM21); \
59         ok(_xform.eM22 == (_em22), "expected %f, got %f\n", (_em22), _xform.eM22); \
60         ok(_xform.eDx == 0.0, "expected 0.0, got %f\n", _xform.eDx); \
61         ok(_xform.eDy == 0.0, "expected 0.0, got %f\n", _xform.eDy); \
62     } \
63 }
64
65 #define expect_dc_ext(_func, _hdc, _cx, _cy) \
66 { \
67     BOOL _ret; \
68     SIZE _size; \
69     SetLastError(0xdeadbeef); \
70     _ret = _func(_hdc, &_size); \
71     ok(_ret, #_func " error %u\n", GetLastError()); \
72     ok(_size.cx == (_cx), "expected cx %d, got %d\n", (_cx), _size.cx); \
73     ok(_size.cy == (_cy), "expected cy %d, got %d\n", (_cy), _size.cy); \
74 }
75
76 #define expect_viewport_ext(_hdc, _cx, _cy) expect_dc_ext(GetViewportExtEx, _hdc, _cx, _cy)
77 #define expect_window_ext(_hdc, _cx, _cy)  expect_dc_ext(GetWindowExtEx, _hdc, _cx, _cy)
78
79 static void test_world_transform(void)
80 {
81     HDC hdc;
82     INT ret, size_cx, size_cy, res_x, res_y, dpi_x, dpi_y;
83     XFORM xform;
84     SIZE size;
85
86     hdc = CreateCompatibleDC(0);
87
88     xform.eM11 = 1.0f;
89     xform.eM12 = 0.0f;
90     xform.eM21 = 0.0f;
91     xform.eM22 = 1.0f;
92     xform.eDx = 0.0f;
93     xform.eDy = 0.0f;
94     ret = SetWorldTransform(hdc, &xform);
95     ok(!ret, "SetWorldTransform should fail in GM_COMPATIBLE mode\n");
96
97     size_cx = GetDeviceCaps(hdc, HORZSIZE);
98     size_cy = GetDeviceCaps(hdc, VERTSIZE);
99     res_x = GetDeviceCaps(hdc, HORZRES);
100     res_y = GetDeviceCaps(hdc, VERTRES);
101     dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
102     dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
103     trace("dc size %d x %d, resolution %d x %d dpi %d x %d\n",
104           size_cx, size_cy, res_x, res_y, dpi_x, dpi_y );
105
106     expect_viewport_ext(hdc, 1, 1);
107     expect_window_ext(hdc, 1, 1);
108     expect_world_transform(hdc, 1.0, 1.0);
109     expect_LPtoDP(hdc, 1000, 1000);
110
111     SetLastError(0xdeadbeef);
112     ret = SetMapMode(hdc, MM_LOMETRIC);
113     ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret);
114
115     expect_viewport_ext(hdc, res_x, -res_y);
116     ok( GetWindowExtEx( hdc, &size ), "GetWindowExtEx failed\n" );
117     ok( rough_match( size.cx, size_cx * 10 ) ||
118         rough_match( size.cx, MulDiv( res_x, 254, dpi_x )),  /* Vista uses a more precise method */
119         "expected cx %d or %d, got %d\n", size_cx * 10, MulDiv( res_x, 254, dpi_x ), size.cx );
120     ok( rough_match( size.cy, size_cy * 10 ) ||
121         rough_match( size.cy, MulDiv( res_y, 254, dpi_y )),  /* Vista uses a more precise method */
122         "expected cy %d or %d, got %d\n", size_cy * 10, MulDiv( res_y, 254, dpi_y ), size.cy );
123     expect_world_transform(hdc, 1.0, 1.0);
124     expect_LPtoDP(hdc, MulDiv(1000 / 10, res_x, size_cx), -MulDiv(1000 / 10, res_y, size_cy));
125
126     SetLastError(0xdeadbeef);
127     ret = SetMapMode(hdc, MM_TEXT);
128     ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d\n", ret);
129
130     expect_viewport_ext(hdc, 1, 1);
131     expect_window_ext(hdc, 1, 1);
132     expect_world_transform(hdc, 1.0, 1.0);
133     expect_LPtoDP(hdc, 1000, 1000);
134
135     ret = SetGraphicsMode(hdc, GM_ADVANCED);
136     if (!ret)
137     {
138         DeleteDC(hdc);
139         skip("GM_ADVANCED is not supported on this platform\n");
140         return;
141     }
142
143     expect_viewport_ext(hdc, 1, 1);
144     expect_window_ext(hdc, 1, 1);
145     expect_world_transform(hdc, 1.0, 1.0);
146     expect_LPtoDP(hdc, 1000, 1000);
147
148     /* The transform must conform to (eM11 * eM22 != eM12 * eM21) requirement */
149     xform.eM11 = 1.0f;
150     xform.eM12 = 2.0f;
151     xform.eM21 = 1.0f;
152     xform.eM22 = 2.0f;
153     xform.eDx = 0.0f;
154     xform.eDy = 0.0f;
155     ret = SetWorldTransform(hdc, &xform);
156     ok(!ret ||
157        broken(ret), /* NT4 */
158        "SetWorldTransform should fail with an invalid xform\n");
159
160     xform.eM11 = 20.0f;
161     xform.eM12 = 0.0f;
162     xform.eM21 = 0.0f;
163     xform.eM22 = 20.0f;
164     xform.eDx = 0.0f;
165     xform.eDy = 0.0f;
166     SetLastError(0xdeadbeef);
167     ret = SetWorldTransform(hdc, &xform);
168     ok(ret, "SetWorldTransform error %u\n", GetLastError());
169
170     expect_viewport_ext(hdc, 1, 1);
171     expect_window_ext(hdc, 1, 1);
172     expect_world_transform(hdc, 20.0, 20.0);
173     expect_LPtoDP(hdc, 20000, 20000);
174
175     SetLastError(0xdeadbeef);
176     ret = SetMapMode(hdc, MM_LOMETRIC);
177     ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret);
178
179     expect_viewport_ext(hdc, res_x, -res_y);
180     ok( GetWindowExtEx( hdc, &size ), "GetWindowExtEx failed\n" );
181     ok( rough_match( size.cx, size_cx * 10 ) ||
182         rough_match( size.cx, MulDiv( res_x, 254, dpi_x )),  /* Vista uses a more precise method */
183         "expected cx %d or %d, got %d\n", size_cx * 10, MulDiv( res_x, 254, dpi_x ), size.cx );
184     ok( rough_match( size.cy, size_cy * 10 ) ||
185         rough_match( size.cy, MulDiv( res_y, 254, dpi_y )),  /* Vista uses a more precise method */
186         "expected cy %d or %d, got %d\n", size_cy * 10, MulDiv( res_y, 254, dpi_y ), size.cy );
187     expect_world_transform(hdc, 20.0, 20.0);
188     expect_LPtoDP(hdc, MulDiv(20000, res_x, size.cx), -MulDiv(20000, res_y, size.cy));
189
190     SetLastError(0xdeadbeef);
191     ret = SetMapMode(hdc, MM_TEXT);
192     ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d\n", ret);
193
194     expect_viewport_ext(hdc, 1, 1);
195     expect_window_ext(hdc, 1, 1);
196     expect_world_transform(hdc, 20.0, 20.0);
197     expect_LPtoDP(hdc, 20000, 20000);
198
199     size.cx = 0xdeadbeef;
200     size.cy = 0xdeadbeef;
201     ret = SetViewportExtEx(hdc, -1, -1, &size);
202     ok(ret, "SetViewportExtEx(-1, -1) failed\n");
203     ok(size.cx == 1 && size.cy == 1, "expected 1,1 got %d,%d\n", size.cx, size.cy);
204     expect_viewport_ext(hdc, 1, 1);
205     expect_window_ext(hdc, 1, 1);
206     expect_world_transform(hdc, 20.0, 20.0);
207     expect_LPtoDP(hdc, 20000, 20000);
208
209     ret = SetMapMode(hdc, MM_ANISOTROPIC);
210     ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret);
211
212     expect_viewport_ext(hdc, 1, 1);
213     expect_window_ext(hdc, 1, 1);
214     expect_world_transform(hdc, 20.0, 20.0);
215     expect_LPtoDP(hdc, 20000, 20000);
216
217     size.cx = 0xdeadbeef;
218     size.cy = 0xdeadbeef;
219     ret = SetViewportExtEx(hdc, -1, -1, &size);
220     ok(ret, "SetViewportExtEx(-1, -1) failed\n");
221     ok(size.cx == 1 && size.cy == 1, "expected 1,1 got %d,%d\n", size.cx, size.cy);
222     expect_viewport_ext(hdc, -1, -1);
223     expect_window_ext(hdc, 1, 1);
224     expect_world_transform(hdc, 20.0, 20.0);
225     expect_LPtoDP(hdc, -20000, -20000);
226
227     ret = SetGraphicsMode(hdc, GM_COMPATIBLE);
228     ok(ret, "SetGraphicsMode(GM_COMPATIBLE) should not fail if DC has't an identity transform\n");
229     ret = GetGraphicsMode(hdc);
230     ok(ret == GM_COMPATIBLE, "expected GM_COMPATIBLE, got %d\n", ret);
231
232     expect_viewport_ext(hdc, -1, -1);
233     expect_window_ext(hdc, 1, 1);
234     expect_world_transform(hdc, 20.0, 20.0);
235     expect_LPtoDP(hdc, -20000, -20000);
236
237     DeleteDC(hdc);
238 }
239
240 static void test_dc_layout(void)
241 {
242     INT ret, size_cx, size_cy, res_x, res_y, dpi_x, dpi_y;
243     SIZE size;
244     POINT pt;
245     HBITMAP bitmap;
246     RECT rc, ret_rc;
247     HDC hdc;
248     HRGN hrgn;
249
250     if (!pGetLayout || !pSetLayout)
251     {
252         win_skip( "Don't have SetLayout\n" );
253         return;
254     }
255
256     hdc = CreateCompatibleDC(0);
257     bitmap = CreateCompatibleBitmap( hdc, 100, 100 );
258     SelectObject( hdc, bitmap );
259
260     size_cx = GetDeviceCaps(hdc, HORZSIZE);
261     size_cy = GetDeviceCaps(hdc, VERTSIZE);
262     res_x = GetDeviceCaps(hdc, HORZRES);
263     res_y = GetDeviceCaps(hdc, VERTRES);
264     dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
265     dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
266
267     ret = GetMapMode( hdc );
268     ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret);
269     expect_viewport_ext(hdc, 1, 1);
270     expect_window_ext(hdc, 1, 1);
271     expect_world_transform(hdc, 1.0, 1.0);
272     expect_LPtoDP(hdc, 1000, 1000);
273
274     pSetLayout( hdc, LAYOUT_RTL );
275     if (!pGetLayout( hdc ))
276     {
277         win_skip( "SetLayout not supported\n" );
278         DeleteDC(hdc);
279         return;
280     }
281
282     ret = GetMapMode( hdc );
283     ok(ret == MM_ANISOTROPIC, "expected MM_ANISOTROPIC, got %d\n", ret);
284     expect_viewport_ext(hdc, 1, 1);
285     expect_window_ext(hdc, 1, 1);
286     expect_world_transform(hdc, 1.0, 1.0);
287     expect_LPtoDP(hdc, -1000 + 99, 1000);
288     GetViewportOrgEx( hdc, &pt );
289     ok( pt.x == 0 && pt.y == 0, "wrong origin %d,%d\n", pt.x, pt.y );
290     GetWindowOrgEx( hdc, &pt );
291     ok( pt.x == 0 && pt.y == 0, "wrong origin %d,%d\n", pt.x, pt.y );
292     GetDCOrgEx( hdc, &pt );
293     ok( pt.x == 0 && pt.y == 0, "wrong origin %d,%d\n", pt.x, pt.y );
294     if (pGetTransform)
295     {
296         XFORM xform;
297         BOOL ret = pGetTransform( hdc, 0x204, &xform ); /* World -> Device */
298         ok( ret, "got %d\n", ret );
299         ok( xform.eM11 == -1.0, "got %f\n", xform.eM11 );
300         ok( xform.eM12 == 0.0, "got %f\n", xform.eM12 );
301         ok( xform.eM21 == 0.0, "got %f\n", xform.eM21 );
302         ok( xform.eM22 == 1.0, "got %f\n", xform.eM22 );
303         ok( xform.eDx == 99.0, "got %f\n", xform.eDx );
304         ok( xform.eDy == 0.0, "got %f\n", xform.eDy );
305     }
306
307     SetRect( &rc, 10, 10, 20, 20 );
308     IntersectClipRect( hdc, 10, 10, 20, 20 );
309     hrgn = CreateRectRgn( 0, 0, 0, 0 );
310     GetClipRgn( hdc, hrgn );
311     GetRgnBox( hrgn, &ret_rc );
312     ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
313         ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
314     pSetLayout( hdc, LAYOUT_LTR );
315     SetRect( &rc, 80, 10, 90, 20 );
316     GetClipRgn( hdc, hrgn );
317     GetRgnBox( hrgn, &ret_rc );
318     ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
319         ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
320     GetClipBox( hdc, &ret_rc );
321     ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
322         ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
323     IntersectClipRect( hdc, 80, 10, 85, 20 );
324     pSetLayout( hdc, LAYOUT_RTL );
325     SetRect( &rc, 15, 10, 20, 20 );
326     GetClipRgn( hdc, hrgn );
327     GetRgnBox( hrgn, &ret_rc );
328     ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
329         ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
330     GetClipBox( hdc, &ret_rc );
331     ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
332         ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
333     SetRectRgn( hrgn, 60, 10, 80, 20 );
334     pSetLayout( hdc, LAYOUT_LTR );
335     ExtSelectClipRgn( hdc, hrgn, RGN_OR );
336     pSetLayout( hdc, LAYOUT_RTL );
337     SetRect( &rc, 15, 10, 40, 20 );
338     GetClipRgn( hdc, hrgn );
339     GetRgnBox( hrgn, &ret_rc );
340     ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
341         ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
342     GetClipBox( hdc, &ret_rc );
343     ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
344         ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
345
346     /* OffsetClipRgn mirrors too */
347     OffsetClipRgn( hdc, 5, 5 );
348     OffsetRect( &rc, 5, 5 );
349     GetClipRgn( hdc, hrgn );
350     GetRgnBox( hrgn, &ret_rc );
351     ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
352         ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
353
354     /* GetRandomRgn returns the raw region */
355     if (pGetRandomRgn)
356     {
357         SetRect( &rc, 55, 15, 80, 25 );
358         pGetRandomRgn( hdc, hrgn, 1 );
359         GetRgnBox( hrgn, &ret_rc );
360         ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
361             ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
362     }
363
364     SetMapMode(hdc, MM_LOMETRIC);
365     ret = GetMapMode( hdc );
366     ok(ret == MM_ANISOTROPIC, "expected MM_ANISOTROPIC, got %d\n", ret);
367
368     expect_viewport_ext(hdc, res_x, -res_y);
369     ok( GetWindowExtEx( hdc, &size ), "GetWindowExtEx failed\n" );
370     ok( rough_match( size.cx, size_cx * 10 ) ||
371         rough_match( size.cx, MulDiv( res_x, 254, dpi_x )),  /* Vista uses a more precise method */
372         "expected cx %d or %d, got %d\n", size_cx * 10, MulDiv( res_x, 254, dpi_x ), size.cx );
373     ok( rough_match( size.cy, size_cy * 10 ) ||
374         rough_match( size.cy, MulDiv( res_y, 254, dpi_y )),  /* Vista uses a more precise method */
375         "expected cy %d or %d, got %d\n", size_cy * 10, MulDiv( res_y, 254, dpi_y ), size.cy );
376     expect_world_transform(hdc, 1.0, 1.0);
377     expect_LPtoDP(hdc, -MulDiv(1000 / 10, res_x, size_cx) + 99, -MulDiv(1000 / 10, res_y, size_cy));
378
379     SetMapMode(hdc, MM_TEXT);
380     ret = GetMapMode( hdc );
381     ok(ret == MM_ANISOTROPIC, "expected MM_ANISOTROPIC, got %d\n", ret);
382     pSetLayout( hdc, LAYOUT_LTR );
383     ret = GetMapMode( hdc );
384     ok(ret == MM_ANISOTROPIC, "expected MM_ANISOTROPIC, got %d\n", ret);
385     SetMapMode(hdc, MM_TEXT);
386     ret = GetMapMode( hdc );
387     ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret);
388
389     DeleteDC(hdc);
390     DeleteObject( bitmap );
391 }
392
393 static void test_modify_world_transform(void)
394 {
395     HDC hdc = GetDC(0);
396     int ret;
397
398     ret = SetGraphicsMode(hdc, GM_ADVANCED);
399     ok(ret, "ret = %d\n", ret);
400
401     ret = ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
402     ok(ret, "ret = %d\n", ret);
403
404     ret = ModifyWorldTransform(hdc, NULL, MWT_LEFTMULTIPLY);
405     ok(!ret, "ret = %d\n", ret);
406
407     ret = ModifyWorldTransform(hdc, NULL, MWT_RIGHTMULTIPLY);
408     ok(!ret, "ret = %d\n", ret);
409
410     ReleaseDC(0, hdc);
411 }
412
413 static void test_SetWindowExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy)
414 {
415     SIZE windowExt, viewportExt;
416     POINT windowOrg, windowOrgAfter, viewportOrg, viewportOrgAfter;
417
418     GetWindowOrgEx(hdc, &windowOrg);
419     GetViewportOrgEx(hdc, &viewportOrg);
420
421     SetWindowExtEx(hdc, cx, cy, NULL);
422     GetWindowExtEx(hdc, &windowExt);
423     ok(windowExt.cx == cx && windowExt.cy == cy,
424        "Window extension: Expected %dx%d, got %dx%d\n",
425        cx, cy, windowExt.cx, windowExt.cy);
426
427     GetViewportExtEx(hdc, &viewportExt);
428     ok(rough_match(viewportExt.cx, expected_vp_cx) && rough_match(viewportExt.cy, expected_vp_cy),
429         "Viewport extents have not been properly adjusted: Expected %dx%d, got %dx%d\n",
430         expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy);
431
432     GetWindowOrgEx(hdc, &windowOrgAfter);
433     ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y,
434         "Window origin changed from (%d,%d) to (%d,%d)\n",
435         windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y);
436
437     GetViewportOrgEx(hdc, &viewportOrgAfter);
438     ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y,
439         "Viewport origin changed from (%d,%d) to (%d,%d)\n",
440         viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y);
441 }
442
443 static void test_SetViewportExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy)
444 {
445     SIZE windowExt, windowExtAfter, viewportExt;
446     POINT windowOrg, windowOrgAfter, viewportOrg, viewportOrgAfter;
447
448     GetWindowOrgEx(hdc, &windowOrg);
449     GetViewportOrgEx(hdc, &viewportOrg);
450     GetWindowExtEx(hdc, &windowExt);
451
452     SetViewportExtEx(hdc, cx, cy, NULL);
453     GetViewportExtEx(hdc, &viewportExt);
454     ok(rough_match(viewportExt.cx, expected_vp_cx) && rough_match(viewportExt.cy, expected_vp_cy),
455         "Viewport extents have not been properly adjusted: Expected %dx%d, got %dx%d\n",
456         expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy);
457
458     GetWindowExtEx(hdc, &windowExtAfter);
459     ok(windowExt.cx == windowExtAfter.cx && windowExt.cy == windowExtAfter.cy,
460        "Window extension changed from %dx%d to %dx%d\n",
461        windowExt.cx, windowExt.cy, windowExtAfter.cx, windowExtAfter.cy);
462
463     GetWindowOrgEx(hdc, &windowOrgAfter);
464     ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y,
465         "Window origin changed from (%d,%d) to (%d,%d)\n",
466         windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y);
467
468     GetViewportOrgEx(hdc, &viewportOrgAfter);
469     ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y,
470         "Viewport origin changed from (%d,%d) to (%d,%d)\n",
471         viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y);
472 }
473
474 static void test_isotropic_mapping(void)
475 {
476     SIZE win, vp;
477     HDC hdc = GetDC(0);
478     
479     SetMapMode(hdc, MM_ISOTROPIC);
480     
481     /* MM_ISOTROPIC is set up like MM_LOMETRIC.
482        Initial values after SetMapMode():
483        (1 inch = 25.4 mm)
484        
485                        Windows 9x:               Windows NT:
486        Window Ext:     254 x -254                HORZSIZE*10 x VERTSIZE*10
487        Viewport Ext:   LOGPIXELSX x LOGPIXELSY   HORZRES x -VERTRES
488        
489        To test without rounding errors, we have to use multiples of
490        these values!
491      */
492     
493     GetWindowExtEx(hdc, &win);
494     GetViewportExtEx(hdc, &vp);
495     
496     test_SetViewportExt(hdc, 10 * vp.cx, 10 * vp.cy, 10 * vp.cx, 10 * vp.cy);
497     test_SetWindowExt(hdc, win.cx, win.cy, 10 * vp.cx, 10 * vp.cy);
498     test_SetWindowExt(hdc, 2 * win.cx, win.cy, 10 * vp.cx, 5 * vp.cy);
499     test_SetWindowExt(hdc, win.cx, win.cy, 5 * vp.cx, 5 * vp.cy);
500     test_SetViewportExt(hdc, 4 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
501     test_SetViewportExt(hdc, vp.cx, 2 * vp.cy, vp.cx, vp.cy);
502     test_SetViewportExt(hdc, 2 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
503     test_SetViewportExt(hdc, 4 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
504     test_SetWindowExt(hdc, 4 * win.cx, 2 * win.cy, 2 * vp.cx, vp.cy);
505     test_SetViewportExt(hdc, -2 * vp.cx, -4 * vp.cy, -2 * vp.cx, -vp.cy);
506     test_SetViewportExt(hdc, -2 * vp.cx, -1 * vp.cy, -2 * vp.cx, -vp.cy);    
507     test_SetWindowExt(hdc, -4 * win.cx, -2 * win.cy, -2 * vp.cx, -vp.cy);
508     test_SetWindowExt(hdc, 4 * win.cx, -4 * win.cy, -vp.cx, -vp.cy);
509     
510     ReleaseDC(0, hdc);
511 }
512
513 static void test_setvirtualresolution(void)
514 {
515     HDC hdc = CreateICA("DISPLAY", NULL, NULL, NULL);
516     DWORD r;
517     INT horz_res = GetDeviceCaps(hdc, HORZRES);
518     INT horz_size = GetDeviceCaps(hdc, HORZSIZE);
519     INT log_pixels_x = GetDeviceCaps(hdc, LOGPIXELSX);
520     SIZE orig_lometric_vp, orig_lometric_wnd;
521
522     if(!pSetVirtualResolution)
523     {
524         win_skip("Don't have SetVirtualResolution\n");
525         return;
526     }
527
528     /* Get the true resolution limits */
529     SetMapMode(hdc, MM_LOMETRIC);
530     GetViewportExtEx(hdc, &orig_lometric_vp);
531     GetWindowExtEx(hdc, &orig_lometric_wnd);
532     SetMapMode(hdc, MM_TEXT);
533
534     r = pSetVirtualResolution(hdc, 4000, 1000, 400, 200); /* 10 pix/mm x 5 pix/mm */
535     ok(r == TRUE, "got %d\n", r);
536     expect_LPtoDP(hdc, 1000, 1000);
537     expect_viewport_ext(hdc, 1, 1);
538     expect_window_ext(hdc, 1, 1);
539
540     SetMapMode(hdc, MM_LOMETRIC);
541     expect_LPtoDP(hdc, 1000, -500);
542     expect_viewport_ext(hdc, 4000, -1000);
543     expect_window_ext(hdc, 4000, 2000);
544
545     /* Doesn't change the device caps */
546     ok(horz_res == GetDeviceCaps(hdc, HORZRES), "horz_res changed\n");
547     ok(horz_size == GetDeviceCaps(hdc, HORZSIZE), "horz_size changed\n");
548     ok(log_pixels_x == GetDeviceCaps(hdc, LOGPIXELSX), "log_pixels_x changed\n");
549
550     r = pSetVirtualResolution(hdc, 8000, 1000, 400, 200); /* 20 pix/mm x 5 pix/mm */
551     ok(r == TRUE, "got %d\n", r);
552     expect_LPtoDP(hdc, 1000, -500); /* No change, need to re-set the mapping mode */
553     SetMapMode(hdc, MM_TEXT);
554     SetMapMode(hdc, MM_LOMETRIC);
555     expect_LPtoDP(hdc, 2000, -500);
556     expect_viewport_ext(hdc, 8000, -1000);
557     expect_window_ext(hdc, 4000, 2000);
558
559     r = pSetVirtualResolution(hdc, 8000, 1000, 200, 200); /* 40 pix/mm x 5 pix/mm */
560     ok(r == TRUE, "got %d\n", r);
561     SetMapMode(hdc, MM_TEXT);
562     SetMapMode(hdc, MM_LOMETRIC);
563     expect_LPtoDP(hdc, 4000, -500);
564     expect_viewport_ext(hdc, 8000, -1000);
565     expect_window_ext(hdc, 2000, 2000);
566
567     r = pSetVirtualResolution(hdc, 8000, 1000, 200, 200); /* 40 pix/mm x 5 pix/mm */
568     ok(r == TRUE, "got %d\n", r);
569     SetMapMode(hdc, MM_TEXT);
570     SetMapMode(hdc, MM_LOMETRIC);
571     expect_LPtoDP(hdc, 4000, -500);
572     expect_viewport_ext(hdc, 8000, -1000);
573     expect_window_ext(hdc, 2000, 2000);
574
575     r = pSetVirtualResolution(hdc, 8000, 2000, 200, 200); /* 40 pix/mm x 10 pix/mm */
576     ok(r == TRUE, "got %d\n", r);
577     SetMapMode(hdc, MM_TEXT);
578     SetMapMode(hdc, MM_LOMETRIC);
579     expect_LPtoDP(hdc, 4000, -1000);
580     expect_viewport_ext(hdc, 8000, -2000);
581     expect_window_ext(hdc, 2000, 2000);
582
583     r = pSetVirtualResolution(hdc, 0, 0, 10, 0); /* Error */
584     ok(r == FALSE, "got %d\n", r);
585     SetMapMode(hdc, MM_TEXT);
586     SetMapMode(hdc, MM_LOMETRIC);
587     expect_LPtoDP(hdc, 4000, -1000);
588     expect_viewport_ext(hdc, 8000, -2000);
589     expect_window_ext(hdc, 2000, 2000);
590
591     r = pSetVirtualResolution(hdc, 0, 0, 0, 0); /* Reset to true resolution */
592     ok(r == TRUE, "got %d\n", r);
593     SetMapMode(hdc, MM_TEXT);
594     SetMapMode(hdc, MM_LOMETRIC);
595     expect_viewport_ext(hdc, orig_lometric_vp.cx, orig_lometric_vp.cy);
596     expect_window_ext(hdc, orig_lometric_wnd.cx, orig_lometric_wnd.cy);
597
598     DeleteDC(hdc);
599 }
600
601
602 static inline void expect_identity(int line, XFORM *xf)
603 {
604     ok(xf->eM11 == 1.0, "%d: got %f\n", line, xf->eM11);
605     ok(xf->eM12 == 0.0, "%d: got %f\n", line, xf->eM12);
606     ok(xf->eM21 == 0.0, "%d: got %f\n", line, xf->eM21);
607     ok(xf->eM22 == 1.0, "%d: got %f\n", line, xf->eM22);
608     ok(xf->eDx == 0.0, "%d: got %f\n", line, xf->eDx);
609     ok(xf->eDy == 0.0, "%d: got %f\n", line, xf->eDy);
610 }
611
612 static inline void xform_near_match(int line, XFORM *got, XFORM *expect)
613 {
614     ok(fabs(got->eM11 - expect->eM11) < 0.001, "%d: got %f expect %f\n", line, got->eM11, expect->eM11);
615     ok(fabs(got->eM12 - expect->eM12) < 0.001, "%d: got %f expect %f\n", line, got->eM12, expect->eM12);
616     ok(fabs(got->eM21 - expect->eM21) < 0.001, "%d: got %f expect %f\n", line, got->eM21, expect->eM21);
617     ok(fabs(got->eM22 - expect->eM22) < 0.001, "%d: got %f expect %f\n", line, got->eM22, expect->eM22);
618     ok(fabs(got->eDx - expect->eDx) < 0.001, "%d: got %f expect %f\n", line, got->eDx, expect->eDx);
619     ok(fabs(got->eDy - expect->eDy) < 0.001, "%d: got %f expect %f\n", line, got->eDy, expect->eDy);
620 }
621
622
623 static void test_gettransform(void)
624 {
625     HDC hdc = CreateICA("DISPLAY", NULL, NULL, NULL);
626     XFORM xform, expect;
627     BOOL r;
628     SIZE lometric_vp, lometric_wnd;
629
630     if(!pGetTransform)
631     {
632         win_skip("Don't have GetTransform\n");
633         return;
634     }
635
636     r = pGetTransform(hdc, 0x203, &xform); /* World -> Page */
637     ok(r == TRUE, "got %d\n", r);
638     expect_identity(__LINE__, &xform);
639     r = pGetTransform(hdc, 0x304, &xform); /* Page -> Device */
640     ok(r == TRUE, "got %d\n", r);
641     expect_identity(__LINE__, &xform);
642     r = pGetTransform(hdc, 0x204, &xform); /* World -> Device */
643     ok(r == TRUE, "got %d\n", r);
644     expect_identity(__LINE__, &xform);
645     r = pGetTransform(hdc, 0x402, &xform); /* Device -> World */
646     ok(r == TRUE, "got %d\n", r);
647     expect_identity(__LINE__, &xform);
648
649     SetMapMode(hdc, MM_LOMETRIC);
650     GetViewportExtEx(hdc, &lometric_vp);
651     GetWindowExtEx(hdc, &lometric_wnd);
652
653     r = pGetTransform(hdc, 0x203, &xform); /* World -> Page */
654     ok(r == TRUE, "got %d\n", r);
655     expect_identity(__LINE__, &xform);
656
657     r = pGetTransform(hdc, 0x304, &xform); /* Page -> Device */
658     ok(r == TRUE, "got %d\n", r);
659     expect.eM11 = (FLOAT) lometric_vp.cx / lometric_wnd.cx;
660     expect.eM12 = expect.eM21 = 0.0;
661     expect.eM22 = (FLOAT) lometric_vp.cy / lometric_wnd.cy;
662     expect.eDx = expect.eDy = 0.0;
663     xform_near_match(__LINE__, &xform, &expect);
664
665     r = pGetTransform(hdc, 0x204, &xform);  /* World -> Device */
666     ok(r == TRUE, "got %d\n", r);
667     xform_near_match(__LINE__, &xform, &expect);
668
669     r = pGetTransform(hdc, 0x402, &xform); /* Device -> World */
670     ok(r == TRUE, "got %d\n", r);
671     expect.eM11 = (FLOAT) lometric_wnd.cx / lometric_vp.cx;
672     expect.eM22 = (FLOAT) lometric_wnd.cy / lometric_vp.cy;
673     xform_near_match(__LINE__, &xform, &expect);
674
675
676     SetGraphicsMode(hdc, GM_ADVANCED);
677
678     expect.eM11 = 10.0;
679     expect.eM22 = 20.0;
680     SetWorldTransform(hdc, &expect);
681     r = pGetTransform(hdc, 0x203, &xform);  /* World -> Page */
682     ok(r == TRUE, "got %d\n", r);
683     xform_near_match(__LINE__, &xform, &expect);
684
685     r = pGetTransform(hdc, 0x304, &xform); /* Page -> Device */
686     ok(r == TRUE, "got %d\n", r);
687     expect.eM11 = (FLOAT) lometric_vp.cx / lometric_wnd.cx;
688     expect.eM22 = (FLOAT) lometric_vp.cy / lometric_wnd.cy;
689     xform_near_match(__LINE__, &xform, &expect);
690
691     r = pGetTransform(hdc, 0x204, &xform); /* World -> Device */
692     ok(r == TRUE, "got %d\n", r);
693     expect.eM11 *= 10.0;
694     expect.eM22 *= 20.0;
695     xform_near_match(__LINE__, &xform, &expect);
696
697     r = pGetTransform(hdc, 0x402, &xform); /* Device -> World */
698     ok(r == TRUE, "got %d\n", r);
699     expect.eM11 = 1 / expect.eM11;
700     expect.eM22 = 1 / expect.eM22;
701     xform_near_match(__LINE__, &xform, &expect);
702
703     r = pGetTransform(hdc, 0x102, &xform);
704     ok(r == FALSE, "got %d\n", r);
705     r = pGetTransform(hdc, 0x103, &xform);
706     ok(r == FALSE, "got %d\n", r);
707     r = pGetTransform(hdc, 0x104, &xform);
708     ok(r == FALSE, "got %d\n", r);
709     r = pGetTransform(hdc, 0x202, &xform);
710     ok(r == FALSE, "got %d\n", r);
711     r = pGetTransform(hdc, 0x302, &xform);
712     ok(r == FALSE, "got %d\n", r);
713     r = pGetTransform(hdc, 0x303, &xform);
714     ok(r == FALSE, "got %d\n", r);
715     r = pGetTransform(hdc, 0x403, &xform);
716     ok(r == FALSE, "got %d\n", r);
717     r = pGetTransform(hdc, 0x404, &xform);
718     ok(r == FALSE, "got %d\n", r);
719     r = pGetTransform(hdc, 0xffff, &xform);
720     ok(r == FALSE, "got %d\n", r);
721 }
722
723 START_TEST(mapping)
724 {
725     HMODULE mod = GetModuleHandleA("gdi32.dll");
726     pGetLayout = (void *)GetProcAddress( mod, "GetLayout" );
727     pSetLayout = (void *)GetProcAddress( mod, "SetLayout" );
728     pGetRandomRgn = (void *)GetProcAddress( mod, "GetRandomRgn" );
729     pGetTransform = (void *)GetProcAddress( mod, "GetTransform" );
730     pSetVirtualResolution = (void *)GetProcAddress( mod, "SetVirtualResolution" );
731
732     test_modify_world_transform();
733     test_world_transform();
734     test_dc_layout();
735     test_isotropic_mapping();
736     test_setvirtualresolution();
737     test_gettransform();
738 }