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.
This commit is contained in:
parent
be29e3708b
commit
0d23ac479b
|
@ -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)
|
||||
{
|
||||
success = dc->funcs->pRestoreDC( dc->physDev, level );
|
||||
GDI_ReleaseObj( hdc );
|
||||
return success;
|
||||
}
|
||||
|
||||
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(abs(level) > dc->saveLevel || level == 0)
|
||||
{
|
||||
GDI_ReleaseObj( hdc );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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 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 \
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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();
|
||||
|
|
Loading…
Reference in New Issue