mapping.c 12.5 KB
Newer Older
1 2 3 4
/*
 * Unit tests for mapping functions
 *
 * Copyright (c) 2005 Huw Davies
5
 * Copyright (c) 2008 Dmitry  Timoshkov
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 23 24 25 26 27 28 29 30 31
 */

#include <assert.h>
#include <stdio.h>
#include <math.h>

#include "wine/test.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
#define rough_match(got, expected) (abs((got) - (expected)) <= 5)

#define expect_LPtoDP(_hdc, _x, _y) \
{ \
    POINT _pt = { 1000, 1000 }; \
    LPtoDP(_hdc, &_pt, 1); \
    ok(rough_match(_pt.x, _x), "expected x %d, got %d\n", (_x), _pt.x); \
    ok(rough_match(_pt.y, _y), "expected y %d, got %d\n", (_y), _pt.y); \
}

#define expect_world_trasform(_hdc, _em11, _em22) \
{ \
    BOOL _ret; \
    XFORM _xform; \
    SetLastError(0xdeadbeef); \
    _ret = GetWorldTransform(_hdc, &_xform); \
    if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) \
    { \
        ok(_ret, "GetWorldTransform error %u\n", GetLastError()); \
        ok(_xform.eM11 == (_em11), "expected %f, got %f\n", (_em11), _xform.eM11); \
        ok(_xform.eM12 == 0.0, "expected 0.0, got %f\n", _xform.eM12); \
        ok(_xform.eM21 == 0.0, "expected 0.0, got %f\n", _xform.eM21); \
        ok(_xform.eM22 == (_em22), "expected %f, got %f\n", (_em22), _xform.eM22); \
        ok(_xform.eDx == 0.0, "expected 0.0, got %f\n", _xform.eDx); \
        ok(_xform.eDy == 0.0, "expected 0.0, got %f\n", _xform.eDy); \
    } \
}

#define expect_dc_ext(_func, _hdc, _cx, _cy) \
{ \
    BOOL _ret; \
    SIZE _size; \
    SetLastError(0xdeadbeef); \
    _ret = _func(_hdc, &_size); \
    ok(_ret, #_func " error %u\n", GetLastError()); \
    ok(_size.cx == (_cx), "expected cx %d, got %d\n", (_cx), _size.cx); \
    ok(_size.cy == (_cy), "expected cy %d, got %d\n", (_cy), _size.cy); \
}

#define expect_viewport_ext(_hdc, _cx, _cy) expect_dc_ext(GetViewportExtEx, _hdc, _cx, _cy)
#define expect_window_ext(_hdc, _cx, _cy)  expect_dc_ext(GetWindowExtEx, _hdc, _cx, _cy)

static void test_world_transform(void)
{
    BOOL is_win9x;
    HDC hdc;
78
    INT ret, size_cx, size_cy, res_x, res_y, dpi_x, dpi_y;
79
    XFORM xform;
80
    SIZE size;
81 82 83 84 85 86 87

    SetLastError(0xdeadbeef);
    GetWorldTransform(0, NULL);
    is_win9x = GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;

    hdc = CreateCompatibleDC(0);

88 89 90 91 92 93 94 95 96
    xform.eM11 = 1.0f;
    xform.eM12 = 0.0f;
    xform.eM21 = 0.0f;
    xform.eM22 = 1.0f;
    xform.eDx = 0.0f;
    xform.eDy = 0.0f;
    ret = SetWorldTransform(hdc, &xform);
    ok(!ret, "SetWorldTransform should fail in GM_COMPATIBLE mode\n");

97 98 99 100
    size_cx = GetDeviceCaps(hdc, HORZSIZE);
    size_cy = GetDeviceCaps(hdc, VERTSIZE);
    res_x = GetDeviceCaps(hdc, HORZRES);
    res_y = GetDeviceCaps(hdc, VERTRES);
101 102 103 104
    dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
    dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
    trace("dc size %d x %d, resolution %d x %d dpi %d x %d\n",
          size_cx, size_cy, res_x, res_y, dpi_x, dpi_y );
105 106 107 108 109 110 111 112 113 114 115 116

    expect_viewport_ext(hdc, 1, 1);
    expect_window_ext(hdc, 1, 1);
    expect_world_trasform(hdc, 1.0, 1.0);
    expect_LPtoDP(hdc, 1000, 1000);

    SetLastError(0xdeadbeef);
    ret = SetMapMode(hdc, MM_LOMETRIC);
    ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret);

    if (is_win9x)
    {
117
        expect_viewport_ext(hdc, dpi_x, dpi_y);
118 119 120 121 122
        expect_window_ext(hdc, 254, -254);
    }
    else
    {
        expect_viewport_ext(hdc, res_x, -res_y);
123 124 125 126 127 128 129
        ok( GetWindowExtEx( hdc, &size ), "GetWindowExtEx failed\n" );
        ok( size.cx == size_cx * 10 ||
            size.cx == MulDiv( res_x, 254, dpi_x ),  /* Vista uses a more precise method */
            "expected cx %d or %d, got %d\n", size_cx * 10, MulDiv( res_x, 254, dpi_x ), size.cx );
        ok( size.cy == size_cy * 10 ||
            size.cy == MulDiv( res_y, 254, dpi_y ),  /* Vista uses a more precise method */
            "expected cy %d or %d, got %d\n", size_cy * 10, MulDiv( res_y, 254, dpi_y ), size.cy );
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
    }
    expect_world_trasform(hdc, 1.0, 1.0);
    expect_LPtoDP(hdc, MulDiv(1000 / 10, res_x, size_cx), -MulDiv(1000 / 10, res_y, size_cy));

    SetLastError(0xdeadbeef);
    ret = SetMapMode(hdc, MM_TEXT);
    ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d\n", ret);

    expect_viewport_ext(hdc, 1, 1);
    expect_window_ext(hdc, 1, 1);
    expect_world_trasform(hdc, 1.0, 1.0);
    expect_LPtoDP(hdc, 1000, 1000);

    ret = SetGraphicsMode(hdc, GM_ADVANCED);
    if (!ret)
    {
        DeleteDC(hdc);
        skip("GM_ADVANCED is not supported on this platform\n");
        return;
    }

    expect_viewport_ext(hdc, 1, 1);
    expect_window_ext(hdc, 1, 1);
    expect_world_trasform(hdc, 1.0, 1.0);
    expect_LPtoDP(hdc, 1000, 1000);

156 157 158 159 160 161 162 163
    /* The transform must conform to (eM11 * eM22 != eM12 * eM21) requirement */
    xform.eM11 = 1.0f;
    xform.eM12 = 2.0f;
    xform.eM21 = 1.0f;
    xform.eM22 = 2.0f;
    xform.eDx = 0.0f;
    xform.eDy = 0.0f;
    ret = SetWorldTransform(hdc, &xform);
164 165 166
    ok(!ret ||
       broken(ret), /* NT4 */
       "SetWorldTransform should fail with an invalid xform\n");
167

168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    xform.eM11 = 20.0f;
    xform.eM12 = 0.0f;
    xform.eM21 = 0.0f;
    xform.eM22 = 20.0f;
    xform.eDx = 0.0f;
    xform.eDy = 0.0f;
    SetLastError(0xdeadbeef);
    ret = SetWorldTransform(hdc, &xform);
    ok(ret, "SetWorldTransform error %u\n", GetLastError());

    expect_viewport_ext(hdc, 1, 1);
    expect_window_ext(hdc, 1, 1);
    expect_world_trasform(hdc, 20.0, 20.0);
    expect_LPtoDP(hdc, 20000, 20000);

    SetLastError(0xdeadbeef);
    ret = SetMapMode(hdc, MM_LOMETRIC);
    ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret);

    expect_viewport_ext(hdc, res_x, -res_y);
188 189 190 191 192 193 194
    ok( GetWindowExtEx( hdc, &size ), "GetWindowExtEx failed\n" );
    ok( size.cx == size_cx * 10 ||
        size.cx == MulDiv( res_x, 254, dpi_x ),  /* Vista uses a more precise method */
        "expected cx %d or %d, got %d\n", size_cx * 10, MulDiv( res_x, 254, dpi_x ), size.cx );
    ok( size.cy == size_cy * 10 ||
        size.cy == MulDiv( res_y, 254, dpi_y ),  /* Vista uses a more precise method */
        "expected cy %d or %d, got %d\n", size_cy * 10, MulDiv( res_y, 254, dpi_y ), size.cy );
195
    expect_world_trasform(hdc, 20.0, 20.0);
196
    expect_LPtoDP(hdc, MulDiv(20000, res_x, size.cx), -MulDiv(20000, res_y, size.cy));
197 198 199 200 201 202 203 204 205 206

    SetLastError(0xdeadbeef);
    ret = SetMapMode(hdc, MM_TEXT);
    ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d\n", ret);

    expect_viewport_ext(hdc, 1, 1);
    expect_window_ext(hdc, 1, 1);
    expect_world_trasform(hdc, 20.0, 20.0);
    expect_LPtoDP(hdc, 20000, 20000);

207 208 209 210 211 212 213 214 215 216
    ret = SetGraphicsMode(hdc, GM_COMPATIBLE);
    ok(ret, "SetGraphicsMode(GM_COMPATIBLE) should not fail if DC has't an identity transform\n");
    ret = GetGraphicsMode(hdc);
    ok(ret == GM_COMPATIBLE, "expected GM_COMPATIBLE, got %d\n", ret);

    expect_viewport_ext(hdc, 1, 1);
    expect_window_ext(hdc, 1, 1);
    expect_world_trasform(hdc, 20.0, 20.0);
    expect_LPtoDP(hdc, 20000, 20000);

217 218
    DeleteDC(hdc);
}
219

220
static void test_modify_world_transform(void)
221 222 223 224 225 226 227 228
{
    HDC hdc = GetDC(0);
    int ret;

    ret = SetGraphicsMode(hdc, GM_ADVANCED);
    if(!ret) /* running in win9x so quit */
    {
        ReleaseDC(0, hdc);
229
        skip("GM_ADVANCED is not supported on this platform\n");
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
        return;
    }

    ret = ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
    ok(ret, "ret = %d\n", ret);

    ret = ModifyWorldTransform(hdc, NULL, MWT_LEFTMULTIPLY);
    ok(!ret, "ret = %d\n", ret);

    ret = ModifyWorldTransform(hdc, NULL, MWT_RIGHTMULTIPLY);
    ok(!ret, "ret = %d\n", ret);

    ReleaseDC(0, hdc);
}

245
static void test_SetWindowExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy)
246 247 248 249 250 251 252 253 254 255
{
    SIZE windowExt, viewportExt;
    POINT windowOrg, windowOrgAfter, viewportOrg, viewportOrgAfter;

    GetWindowOrgEx(hdc, &windowOrg);
    GetViewportOrgEx(hdc, &viewportOrg);

    SetWindowExtEx(hdc, cx, cy, NULL);
    GetWindowExtEx(hdc, &windowExt);
    ok(windowExt.cx == cx && windowExt.cy == cy,
256
       "Window extension: Expected %dx%d, got %dx%d\n",
257 258 259
       cx, cy, windowExt.cx, windowExt.cy);

    GetViewportExtEx(hdc, &viewportExt);
260
    ok(rough_match(viewportExt.cx, expected_vp_cx) && rough_match(viewportExt.cy, expected_vp_cy),
261
        "Viewport extents have not been properly adjusted: Expected %dx%d, got %dx%d\n",
262 263 264 265
        expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy);

    GetWindowOrgEx(hdc, &windowOrgAfter);
    ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y,
266
        "Window origin changed from (%d,%d) to (%d,%d)\n",
267 268 269 270
        windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y);

    GetViewportOrgEx(hdc, &viewportOrgAfter);
    ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y,
271
        "Viewport origin changed from (%d,%d) to (%d,%d)\n",
272 273 274
        viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y);
}

275
static void test_SetViewportExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy)
276 277 278 279 280 281 282 283 284 285
{
    SIZE windowExt, windowExtAfter, viewportExt;
    POINT windowOrg, windowOrgAfter, viewportOrg, viewportOrgAfter;

    GetWindowOrgEx(hdc, &windowOrg);
    GetViewportOrgEx(hdc, &viewportOrg);
    GetWindowExtEx(hdc, &windowExt);

    SetViewportExtEx(hdc, cx, cy, NULL);
    GetViewportExtEx(hdc, &viewportExt);
286
    ok(rough_match(viewportExt.cx, expected_vp_cx) && rough_match(viewportExt.cy, expected_vp_cy),
287
        "Viewport extents have not been properly adjusted: Expected %dx%d, got %dx%d\n",
288 289 290 291
        expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy);

    GetWindowExtEx(hdc, &windowExtAfter);
    ok(windowExt.cx == windowExtAfter.cx && windowExt.cy == windowExtAfter.cy,
292
       "Window extension changed from %dx%d to %dx%d\n",
293 294 295 296
       windowExt.cx, windowExt.cy, windowExtAfter.cx, windowExtAfter.cy);

    GetWindowOrgEx(hdc, &windowOrgAfter);
    ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y,
297
        "Window origin changed from (%d,%d) to (%d,%d)\n",
298 299 300 301
        windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y);

    GetViewportOrgEx(hdc, &viewportOrgAfter);
    ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y,
302
        "Viewport origin changed from (%d,%d) to (%d,%d)\n",
303 304 305
        viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y);
}

306
static void test_isotropic_mapping(void)
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
{
    SIZE win, vp;
    HDC hdc = GetDC(0);
    
    SetMapMode(hdc, MM_ISOTROPIC);
    
    /* MM_ISOTROPIC is set up like MM_LOMETRIC.
       Initial values after SetMapMode():
       (1 inch = 25.4 mm)
       
                       Windows 9x:               Windows NT:
       Window Ext:     254 x -254                HORZSIZE*10 x VERTSIZE*10
       Viewport Ext:   LOGPIXELSX x LOGPIXELSY   HORZRES x -VERTRES
       
       To test without rounding errors, we have to use multiples of
       these values!
     */
    
    GetWindowExtEx(hdc, &win);
    GetViewportExtEx(hdc, &vp);
    
    test_SetViewportExt(hdc, 10 * vp.cx, 10 * vp.cy, 10 * vp.cx, 10 * vp.cy);
    test_SetWindowExt(hdc, win.cx, win.cy, 10 * vp.cx, 10 * vp.cy);
    test_SetWindowExt(hdc, 2 * win.cx, win.cy, 10 * vp.cx, 5 * vp.cy);
    test_SetWindowExt(hdc, win.cx, win.cy, 5 * vp.cx, 5 * vp.cy);
    test_SetViewportExt(hdc, 4 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
    test_SetViewportExt(hdc, vp.cx, 2 * vp.cy, vp.cx, vp.cy);
    test_SetViewportExt(hdc, 2 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
    test_SetViewportExt(hdc, 4 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
    test_SetWindowExt(hdc, 4 * win.cx, 2 * win.cy, 2 * vp.cx, vp.cy);
    test_SetViewportExt(hdc, -2 * vp.cx, -4 * vp.cy, -2 * vp.cx, -vp.cy);
    test_SetViewportExt(hdc, -2 * vp.cx, -1 * vp.cy, -2 * vp.cx, -vp.cy);    
    test_SetWindowExt(hdc, -4 * win.cx, -2 * win.cy, -2 * vp.cx, -vp.cy);
    test_SetWindowExt(hdc, 4 * win.cx, -4 * win.cy, -vp.cx, -vp.cy);
    
    ReleaseDC(0, hdc);
}

345 346 347
START_TEST(mapping)
{
    test_modify_world_transform();
348
    test_world_transform();
349
    test_isotropic_mapping();
350
}