gdi: Fixes for the isotropic mapping mode.

- Isotropic mapping mode: Adjust the viewport extension in
  SetWindowExtEx, handle negative extents.
- Support the isotropic mapping mode in the enhanced metafile driver.
- New tests.
This commit is contained in:
Michael Kaufmann 2006-01-31 12:56:57 +01:00 committed by Alexandre Julliard
parent cf1ccfb712
commit 5c6301a5c9
3 changed files with 149 additions and 13 deletions

View File

@ -595,6 +595,33 @@ static void EMF_SetMapMode(HDC hdc, enum_emh_data *info)
} }
} }
/***********************************************************************
* EMF_FixIsotropic
*
* Fix viewport extensions for isotropic mode.
*/
static void EMF_FixIsotropic(HDC hdc, enum_emh_data *info)
{
double xdim = fabs((double)info->vportExtX * GetDeviceCaps( hdc, HORZSIZE ) /
(GetDeviceCaps( hdc, HORZRES ) * info->wndExtX));
double ydim = fabs((double)info->vportExtY * GetDeviceCaps( hdc, VERTSIZE ) /
(GetDeviceCaps( hdc, VERTRES ) * info->wndExtY));
if (xdim > ydim)
{
INT mincx = (info->vportExtX >= 0) ? 1 : -1;
info->vportExtX = floor(info->vportExtX * ydim / xdim + 0.5);
if (!info->vportExtX) info->vportExtX = mincx;
}
else
{
INT mincy = (info->vportExtY >= 0) ? 1 : -1;
info->vportExtY = floor(info->vportExtY * xdim / ydim + 0.5);
if (!info->vportExtY) info->vportExtY = mincy;
}
}
/***************************************************************************** /*****************************************************************************
* emr_produces_output * emr_produces_output
* *
@ -829,6 +856,8 @@ BOOL WINAPI PlayEnhMetaFileRecord(
break; break;
info->wndExtX = pSetWindowExtEx->szlExtent.cx; info->wndExtX = pSetWindowExtEx->szlExtent.cx;
info->wndExtY = pSetWindowExtEx->szlExtent.cy; info->wndExtY = pSetWindowExtEx->szlExtent.cy;
if (info->mode == MM_ISOTROPIC)
EMF_FixIsotropic(hdc, info);
TRACE("SetWindowExtEx: %d,%d\n",info->wndExtX,info->wndExtY); TRACE("SetWindowExtEx: %d,%d\n",info->wndExtX,info->wndExtY);
break; break;
@ -852,6 +881,8 @@ BOOL WINAPI PlayEnhMetaFileRecord(
break; break;
info->vportExtX = pSetViewportExtEx->szlExtent.cx; info->vportExtX = pSetViewportExtEx->szlExtent.cx;
info->vportExtY = pSetViewportExtEx->szlExtent.cy; info->vportExtY = pSetViewportExtEx->szlExtent.cy;
if (info->mode == MM_ISOTROPIC)
EMF_FixIsotropic(hdc, info);
TRACE("SetViewportExtEx: %d,%d\n",info->vportExtX,info->vportExtY); TRACE("SetViewportExtEx: %d,%d\n",info->vportExtX,info->vportExtY);
break; break;
} }
@ -1316,8 +1347,7 @@ BOOL WINAPI PlayEnhMetaFileRecord(
if (info->vportExtX == 0) info->vportExtX = 1; if (info->vportExtX == 0) info->vportExtX = 1;
if (info->vportExtY == 0) info->vportExtY = 1; if (info->vportExtY == 0) info->vportExtY = 1;
if (info->mode == MM_ISOTROPIC) if (info->mode == MM_ISOTROPIC)
FIXME("EMRSCALEVIEWPORTEXTEX MM_ISOTROPIC mapping\n"); EMF_FixIsotropic(hdc, info);
/* MAPPING_FixIsotropic( dc ); */
TRACE("EMRSCALEVIEWPORTEXTEX %ld/%ld %ld/%ld\n", TRACE("EMRSCALEVIEWPORTEXTEX %ld/%ld %ld/%ld\n",
lpScaleViewportExtEx->xNum,lpScaleViewportExtEx->xDenom, lpScaleViewportExtEx->xNum,lpScaleViewportExtEx->xDenom,
@ -1342,8 +1372,7 @@ BOOL WINAPI PlayEnhMetaFileRecord(
if (info->wndExtX == 0) info->wndExtX = 1; if (info->wndExtX == 0) info->wndExtX = 1;
if (info->wndExtY == 0) info->wndExtY = 1; if (info->wndExtY == 0) info->wndExtY = 1;
if (info->mode == MM_ISOTROPIC) if (info->mode == MM_ISOTROPIC)
FIXME("EMRSCALEWINDOWEXTEX MM_ISOTROPIC mapping\n"); EMF_FixIsotropic(hdc, info);
/* MAPPING_FixIsotropic( dc ); */
TRACE("EMRSCALEWINDOWEXTEX %ld/%ld %ld/%ld\n", TRACE("EMRSCALEWINDOWEXTEX %ld/%ld %ld/%ld\n",
lpScaleWindowExtEx->xNum,lpScaleWindowExtEx->xDenom, lpScaleWindowExtEx->xNum,lpScaleWindowExtEx->xDenom,

View File

@ -33,19 +33,22 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdi);
*/ */
void MAPPING_FixIsotropic( DC * dc ) void MAPPING_FixIsotropic( DC * dc )
{ {
double xdim = (double)dc->vportExtX * GetDeviceCaps( dc->hSelf, HORZSIZE ) / double xdim = fabs((double)dc->vportExtX * GetDeviceCaps( dc->hSelf, HORZSIZE ) /
(GetDeviceCaps( dc->hSelf, HORZRES ) * dc->wndExtX); (GetDeviceCaps( dc->hSelf, HORZRES ) * dc->wndExtX));
double ydim = (double)dc->vportExtY * GetDeviceCaps( dc->hSelf, VERTSIZE ) / double ydim = fabs((double)dc->vportExtY * GetDeviceCaps( dc->hSelf, VERTSIZE ) /
(GetDeviceCaps( dc->hSelf, VERTRES ) * dc->wndExtY); (GetDeviceCaps( dc->hSelf, VERTRES ) * dc->wndExtY));
if (xdim > ydim) if (xdim > ydim)
{ {
dc->vportExtX = floor(dc->vportExtX * fabs( ydim / xdim ) + 0.5); INT mincx = (dc->vportExtX >= 0) ? 1 : -1;
if (!dc->vportExtX) dc->vportExtX = 1; dc->vportExtX = floor(dc->vportExtX * ydim / xdim + 0.5);
if (!dc->vportExtX) dc->vportExtX = mincx;
} }
else else
{ {
dc->vportExtY = floor(dc->vportExtY * fabs( xdim / ydim ) + 0.5); INT mincy = (dc->vportExtY >= 0) ? 1 : -1;
if (!dc->vportExtY) dc->vportExtY = 1; dc->vportExtY = floor(dc->vportExtY * xdim / ydim + 0.5);
if (!dc->vportExtY) dc->vportExtY = mincy;
} }
} }
@ -326,7 +329,10 @@ BOOL WINAPI SetWindowExtEx( HDC hdc, INT x, INT y, LPSIZE size )
} }
dc->wndExtX = x; dc->wndExtX = x;
dc->wndExtY = y; dc->wndExtY = y;
/* Windows fixes MM_ISOTROPIC mode only in SetViewportExtEx() */ /* The API docs say that you should call SetWindowExtEx before
SetViewportExtEx. This advice does not imply that Windows
doesn't ensure the isotropic mapping after SetWindowExtEx! */
if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
DC_UpdateXforms( dc ); DC_UpdateXforms( dc );
done: done:
GDI_ReleaseObj( hdc ); GDI_ReleaseObj( hdc );

View File

@ -53,7 +53,108 @@ void test_modify_world_transform(void)
ReleaseDC(0, hdc); ReleaseDC(0, hdc);
} }
void test_SetWindowExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy)
{
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,
"Window extension: Expected %ldx%ld, got %ldx%ld\n",
cx, cy, windowExt.cx, windowExt.cy);
GetViewportExtEx(hdc, &viewportExt);
ok(viewportExt.cx == expected_vp_cx && viewportExt.cy == expected_vp_cy,
"Viewport extents have not been properly adjusted: Expected %ldx%ld, got %ldx%ld\n",
expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy);
GetWindowOrgEx(hdc, &windowOrgAfter);
ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y,
"Window origin changed from (%ld,%ld) to (%ld,%ld)\n",
windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y);
GetViewportOrgEx(hdc, &viewportOrgAfter);
ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y,
"Viewport origin changed from (%ld,%ld) to (%ld,%ld)\n",
viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y);
}
void test_SetViewportExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy)
{
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);
ok(viewportExt.cx == expected_vp_cx && viewportExt.cy == expected_vp_cy,
"Viewport extents have not been properly adjusted: Expected %ldx%ld, got %ldx%ld\n",
expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy);
GetWindowExtEx(hdc, &windowExtAfter);
ok(windowExt.cx == windowExtAfter.cx && windowExt.cy == windowExtAfter.cy,
"Window extension changed from %ldx%ld to %ldx%ld\n",
windowExt.cx, windowExt.cy, windowExtAfter.cx, windowExtAfter.cy);
GetWindowOrgEx(hdc, &windowOrgAfter);
ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y,
"Window origin changed from (%ld,%ld) to (%ld,%ld)\n",
windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y);
GetViewportOrgEx(hdc, &viewportOrgAfter);
ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y,
"Viewport origin changed from (%ld,%ld) to (%ld,%ld)\n",
viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y);
}
void test_isotropic_mapping(void)
{
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);
}
START_TEST(mapping) START_TEST(mapping)
{ {
test_modify_world_transform(); test_modify_world_transform();
test_isotropic_mapping();
} }