Commit 0d23ac47 authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

Fix handling of relative state indices in RestoreDC.

Fix return value of SaveDC when writing to an emf. Before writing the EMR_EOF record we should ensure that we clear the state stack.
parent be29e370
......@@ -504,8 +504,9 @@ INT WINAPI SaveDC( HDC hdc )
if(dc->funcs->pSaveDC)
{
ret = dc->funcs->pSaveDC( dc->physDev );
if(ret)
ret = ++dc->saveLevel;
GDI_ReleaseObj( hdc );
/* FIXME: ret is just a success flag, we should return a proper value */
return ret;
}
......@@ -551,26 +552,24 @@ BOOL WINAPI RestoreDC( HDC hdc, INT level )
TRACE("%p %d\n", hdc, level );
dc = DC_GetDCUpdate( hdc );
if(!dc) return FALSE;
if(dc->funcs->pRestoreDC)
if(abs(level) > dc->saveLevel || level == 0)
{
success = dc->funcs->pRestoreDC( dc->physDev, level );
GDI_ReleaseObj( hdc );
return success;
return FALSE;
}
if (level == -1) level = dc->saveLevel;
if ((level < 1)
/* This pair of checks disagrees with MSDN "Platform SDK:
Windows GDI" July 2000 which says all negative values
for level will be interpreted as an instance relative
to the current state. Restricting it to just -1 does
not satisfy this */
|| (level > dc->saveLevel))
if(dc->funcs->pRestoreDC)
{
success = dc->funcs->pRestoreDC( dc->physDev, level );
if(level < 0) level = dc->saveLevel + level + 1;
if(success)
dc->saveLevel = level - 1;
GDI_ReleaseObj( hdc );
return FALSE;
return success;
}
if (level < 0) level = dc->saveLevel + level + 1;
success=TRUE;
while (dc->saveLevel >= level)
{
......
......@@ -38,19 +38,15 @@ BOOL EMFDRV_RestoreDC( PHYSDEV dev, INT level )
emr.emr.iType = EMR_RESTOREDC;
emr.emr.nSize = sizeof(emr);
emr.iRelative = -1;
if (level == -1)
return EMFDRV_WriteRecord( dev, &emr.emr );
else if (level > 0 && level <= physDev->dc->saveLevel)
{
while (level >= physDev->dc->saveLevel)
{
EMFDRV_WriteRecord( dev, &emr.emr );
level--;
}
return TRUE;
}
return FALSE;
if (level < 0)
emr.iRelative = level;
else
emr.iRelative = level - physDev->dc->saveLevel - 1;
EMFDRV_WriteRecord( dev, &emr.emr );
return TRUE;
}
UINT EMFDRV_SetTextAlign( PHYSDEV dev, UINT align )
......
......@@ -422,6 +422,9 @@ HENHMETAFILE WINAPI CloseEnhMetaFile(HDC hdc) /* [in] metafile DC */
if (!(dc = (DC *) GDI_GetObjPtr( hdc, ENHMETAFILE_DC_MAGIC ))) return 0;
physDev = (EMFDRV_PDEVICE *)dc->physDev;
if(dc->saveLevel)
RestoreDC(hdc, 1);
emr.emr.iType = EMR_EOF;
emr.emr.nSize = sizeof(emr);
emr.nPalEntries = 0;
......
......@@ -2,6 +2,7 @@ Makefile
bitmap.ok
brush.ok
clipping.ok
dc.ok
gdiobj.ok
generated.ok
mapping.ok
......
......@@ -9,6 +9,7 @@ CTESTS = \
bitmap.c \
brush.c \
clipping.c \
dc.c \
gdiobj.c \
generated.c \
mapping.c \
......
/*
* Unit tests for dc functions
*
* Copyright (c) 2005 Huw Davies
*
* 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
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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"
void test_savedc(void)
{
HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
int ret;
ok(hdc != NULL, "CreateDC rets %p\n", hdc);
ret = SaveDC(hdc);
ok(ret == 1, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 2, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 3, "ret = %d\n", ret);
ret = RestoreDC(hdc, -1);
ok(ret, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 3, "ret = %d\n", ret);
ret = RestoreDC(hdc, 1);
ok(ret, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 1, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 2, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 3, "ret = %d\n", ret);
ret = RestoreDC(hdc, -2);
ok(ret, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 2, "ret = %d\n", ret);
ret = RestoreDC(hdc, -2);
ok(ret, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 1, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 2, "ret = %d\n", ret);
ret = RestoreDC(hdc, -4);
ok(!ret, "ret = %d\n", ret);
ret = RestoreDC(hdc, 3);
ok(!ret, "ret = %d\n", ret);
/* Under win98 the following two succeed and both clear the save stack
ret = RestoreDC(hdc, -3);
ok(!ret, "ret = %d\n", ret);
ret = RestoreDC(hdc, 0);
ok(!ret, "ret = %d\n", ret);
*/
ret = RestoreDC(hdc, 1);
ok(ret, "ret = %d\n", ret);
DeleteDC(hdc);
}
START_TEST(dc)
{
test_savedc();
}
......@@ -56,7 +56,7 @@ static void init_function_pointers(void)
GDI_GET_PROC(SetRelAbs);
}
static int CALLBACK emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
const ENHMETARECORD *emr, int n_objs, LPARAM param)
{
static int n_record;
......@@ -234,7 +234,7 @@ static void test_ExtTextOut(void)
if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
SetBkMode(hdcDisplay, OPAQUE);
ret = EnumEnhMetaFile(hdcDisplay, hMetafile, emf_enum_proc, dx, &rc);
ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
ok( ret, "EnumEnhMetaFile error %ld\n", GetLastError());
ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
......@@ -248,16 +248,122 @@ static void test_ExtTextOut(void)
ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, emf_enum_proc, dx, NULL),
ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
"A valid hdc has to require a valid rc\n");
ok(EnumEnhMetaFile(NULL, hMetafile, emf_enum_proc, dx, NULL),
ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
"A null hdc does not require a valid rc\n");
ret = DeleteEnhMetaFile(hMetafile);
ok( ret, "DeleteEnhMetaFile error %ld\n", GetLastError());
ret = ReleaseDC(hwnd, hdcDisplay);
ok( ret, "ReleaseDC error %ld\n", GetLastError());
DestroyWindow(hwnd);
}
static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
const ENHMETARECORD *emr, int n_objs, LPARAM param)
{
static int save_state;
static int restore_no;
switch (emr->iType)
{
case EMR_HEADER:
save_state = 0;
restore_no = 0;
break;
case EMR_SAVEDC:
save_state++;
break;
case EMR_RESTOREDC:
{
EMRRESTOREDC *restoredc = (EMRRESTOREDC *)emr;
switch(++restore_no)
{
case 1:
ok(restoredc->iRelative == -1, "first restore %ld\n", restoredc->iRelative);
break;
case 2:
ok(restoredc->iRelative == -3, "second restore %ld\n", restoredc->iRelative);
break;
case 3:
ok(restoredc->iRelative == -2, "third restore %ld\n", restoredc->iRelative);
break;
}
ok(restore_no <= 3, "restore_no %d\n", restore_no);
save_state += restoredc->iRelative;
break;
}
case EMR_EOF:
ok(save_state == 0, "EOF save_state %d\n", save_state);
break;
}
return 1;
}
void test_SaveDC(void)
{
HDC hdcMetafile, hdcDisplay;
HENHMETAFILE hMetafile;
HWND hwnd;
int ret;
static const RECT rc = { 0, 0, 100, 100 };
/* Win9x doesn't play EMFs on invisible windows */
hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
0, 0, 200, 200, 0, 0, 0, NULL);
ok(hwnd != 0, "CreateWindowExA error %ld\n", GetLastError());
hdcDisplay = GetDC(hwnd);
ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError());
hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\n", GetLastError());
/* Need to write something to the emf, otherwise Windows won't play it back */
LineTo(hdcMetafile, 100, 100);
ret = SaveDC(hdcMetafile);
ok(ret == 1, "ret = %d\n", ret);
ret = SaveDC(hdcMetafile);
ok(ret == 2, "ret = %d\n", ret);
ret = SaveDC(hdcMetafile);
ok(ret == 3, "ret = %d\n", ret);
ret = RestoreDC(hdcMetafile, -1);
ok(ret, "ret = %d\n", ret);
ret = SaveDC(hdcMetafile);
ok(ret == 3, "ret = %d\n", ret);
ret = RestoreDC(hdcMetafile, 1);
ok(ret, "ret = %d\n", ret);
ret = SaveDC(hdcMetafile);
ok(ret == 1, "ret = %d\n", ret);
ret = SaveDC(hdcMetafile);
ok(ret == 2, "ret = %d\n", ret);
hMetafile = CloseEnhMetaFile(hdcMetafile);
ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError());
ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
ret = DeleteEnhMetaFile(hMetafile);
ok( ret, "DeleteEnhMetaFile error %ld\n", GetLastError());
ret = ReleaseDC(hwnd, hdcDisplay);
ok( ret, "ReleaseDC error %ld\n", GetLastError());
DestroyWindow(hwnd);
}
/* Win-format metafile (mfdrv) tests */
......@@ -813,6 +919,7 @@ START_TEST(metafile)
/* For enhanced metafiles (enhmfdrv) */
test_ExtTextOut();
test_SaveDC();
/* For win-format metafiles (mfdrv) */
test_mf_Blank();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment