Sync win32k and gdi32_winetest from trunk.

Merged 24228-24229, 24231, 24234-24239,
24255-24257, 24260-24264, 24266-24268,
24270-24271, 24287-24288.

svn path=/branches/ros-branch-0_3_1/; revision=24328
This commit is contained in:
Andrew Munger 2006-10-01 04:37:32 +00:00
commit 550317611d
27 changed files with 3696 additions and 532 deletions

View file

@ -67,6 +67,6 @@
enable this (except they/you purchased a license from the patent owner). enable this (except they/you purchased a license from the patent owner).
This settings is disabled (0) by default. This settings is disabled (0) by default.
--> -->
<property name="NSWPAT" value="0" /> <property name="NSWPAT" value="1" />
</rbuild> </rbuild>

View file

@ -614,6 +614,7 @@ extern "C" {
#define OBJ_METADC 4 #define OBJ_METADC 4
#define OBJ_ENHMETAFILE 13 #define OBJ_ENHMETAFILE 13
#define OBJ_ENHMETADC 12 #define OBJ_ENHMETADC 12
#define OBJ_COLORSPACE 14
#define DRIVERVERSION 0 #define DRIVERVERSION 0
#define TECHNOLOGY 2 #define TECHNOLOGY 2
#define DT_PLOTTER 0 #define DT_PLOTTER 0
@ -933,6 +934,8 @@ extern "C" {
#define SP_NOTREPORTED 0x4000 #define SP_NOTREPORTED 0x4000
#define PR_JOBSTATUS 0 #define PR_JOBSTATUS 0
#define ASPECT_FILTERING 1 #define ASPECT_FILTERING 1
#define GS_8BIT_INDICES 0x00000001
#define GGI_MARK_NONEXISTING_GLYPHS 0X0001
#define BS_SOLID 0 #define BS_SOLID 0
#define BS_NULL 1 #define BS_NULL 1
#define BS_HOLLOW 1 #define BS_HOLLOW 1
@ -1184,6 +1187,9 @@ extern "C" {
#define CS_DISABLE 0x00000002 #define CS_DISABLE 0x00000002
#define CS_DELETE_TRANSFORM 0x00000003 #define CS_DELETE_TRANSFORM 0x00000003
#endif #endif
#if (WINVER > 0x500) #if (WINVER > 0x500)
#define GRADIENT_FILL_RECT_H 0x00 #define GRADIENT_FILL_RECT_H 0x00
#define GRADIENT_FILL_RECT_V 0x01 #define GRADIENT_FILL_RECT_V 0x01
@ -1336,7 +1342,7 @@ typedef struct {
typedef struct tagFONTSIGNATURE { typedef struct tagFONTSIGNATURE {
DWORD fsUsb[4]; DWORD fsUsb[4];
DWORD fsCsb[2]; DWORD fsCsb[2];
} FONTSIGNATURE,*LPFONTSIGNATURE; } FONTSIGNATURE, *PFONTSIGNATURE,*LPFONTSIGNATURE;
typedef struct { typedef struct {
UINT ciCharset; UINT ciCharset;
UINT ciACP; UINT ciACP;
@ -1483,6 +1489,15 @@ typedef struct tagEMR {
DWORD iType; DWORD iType;
DWORD nSize; DWORD nSize;
} EMR,*PEMR; } EMR,*PEMR;
#if(WINVER >= 0x0400)
typedef struct tagEMRGLSRECORD
{
EMR emr;
DWORD cbData;
BYTE Data[1];
} EMRGLSRECORD, *PEMRGLSRECORD;
#endif
typedef struct tagEMRANGLEARC { typedef struct tagEMRANGLEARC {
EMR emr; EMR emr;
POINTL ptlCenter; POINTL ptlCenter;
@ -1757,6 +1772,15 @@ typedef struct tagEMRFORMAT {
DWORD cbData; DWORD cbData;
DWORD offData; DWORD offData;
} EMRFORMAT; } EMRFORMAT;
typedef struct tagEMRSETCOLORSPACE
{
EMR emr;
DWORD ihCS;
} EMRSETCOLORSPACE, *PEMRSETCOLORSPACE, EMRSELECTCOLORSPACE, *PEMRSELECTCOLORSPACE,
EMRDELETECOLORSPACE, *PEMRDELETECOLORSPACE;
typedef struct tagEMRFRAMERGN { typedef struct tagEMRFRAMERGN {
EMR emr; EMR emr;
RECTL rclBounds; RECTL rclBounds;
@ -1909,10 +1933,8 @@ typedef struct tagEMRSCALEVIEWPORTEXTEX {
LONG yNum; LONG yNum;
LONG yDenom; LONG yDenom;
} EMRSCALEVIEWPORTEXTEX,*PEMRSCALEVIEWPORTEXTEX,EMRSCALEWINDOWEXTEX,*PEMRSCALEWINDOWEXTEX; } EMRSCALEVIEWPORTEXTEX,*PEMRSCALEVIEWPORTEXTEX,EMRSCALEWINDOWEXTEX,*PEMRSCALEWINDOWEXTEX;
typedef struct tagEMRSELECTCOLORSPACE {
EMR emr;
DWORD ihCS;
} EMRSELECTCOLORSPACE,*PEMRSELECTCOLORSPACE,EMRDELETECOLORSPACE,*PEMRDELETECOLORSPACE;
typedef struct tagEMRSELECTOBJECT { typedef struct tagEMRSELECTOBJECT {
EMR emr; EMR emr;
DWORD ihObject; DWORD ihObject;
@ -2026,7 +2048,14 @@ typedef struct tagABORTPATH {
typedef struct tagEMRSELECTCLIPPATH { typedef struct tagEMRSELECTCLIPPATH {
EMR emr; EMR emr;
DWORD iMode; DWORD iMode;
} EMRSELECTCLIPPATH,*PEMRSELECTCLIPPATH,EMRSETBKMODE,*PEMRSETBKMODE,EMRSETMAPMODE,*PEMRSETMAPMODE,EMRSETPOLYFILLMODE,*PEMRSETPOLYFILLMODE,EMRSETROP2,*PEMRSETROP2,EMRSETSTRETCHBLTMODE,*PEMRSETSTRETCHBLTMODE,EMRSETTEXTALIGN,*PEMRSETTEXTALIGN,EMRENABLEICM,*PEMRENABLEICM; } EMRSELECTCLIPPATH,*PEMRSELECTCLIPPATH, EMRSETBKMODE,*PEMRSETBKMODE, EMRSETMAPMODE, *PEMRSETMAPMODE,
EMRSETPOLYFILLMODE, *PEMRSETPOLYFILLMODE, EMRSETROP2, *PEMRSETROP2, EMRSETSTRETCHBLTMODE, *PEMRSETSTRETCHBLTMODE,
EMRSETICMMODE, *PEMRSETICMMODE, EMRSETTEXTALIGN,
#if(WINVER >= 0x0500)
EMRSETLAYOUT, *PEMRSETLAYOUT,
#endif
*PEMRSETTEXTALIGN;
#include "pshpack2.h" #include "pshpack2.h"
typedef struct tagMETAHEADER { typedef struct tagMETAHEADER {
WORD mtType; WORD mtType;
@ -2062,7 +2091,7 @@ typedef struct tagENHMETAHEADER {
#if (WINVER >= 0x0500) #if (WINVER >= 0x0500)
SIZEL szlMicrometers; SIZEL szlMicrometers;
#endif #endif
} ENHMETAHEADER,*LPENHMETAHEADER; } ENHMETAHEADER,*PENHMETAHEADER,*LPENHMETAHEADER;
typedef struct tagMETARECORD { typedef struct tagMETARECORD {
DWORD rdSize; DWORD rdSize;
WORD rdFunction; WORD rdFunction;
@ -2075,7 +2104,7 @@ typedef struct tagENHMETARECORD {
} ENHMETARECORD,*LPENHMETARECORD; } ENHMETARECORD,*LPENHMETARECORD;
typedef struct tagHANDLETABLE { typedef struct tagHANDLETABLE {
HGDIOBJ objectHandle[1]; HGDIOBJ objectHandle[1];
} HANDLETABLE,*LPHANDLETABLE; } HANDLETABLE,*PHANDLETABLE, *LPHANDLETABLE;
typedef struct tagTEXTMETRICA { typedef struct tagTEXTMETRICA {
LONG tmHeight; LONG tmHeight;
LONG tmAscent; LONG tmAscent;
@ -2120,6 +2149,7 @@ typedef struct tagTEXTMETRICW {
BYTE tmPitchAndFamily; BYTE tmPitchAndFamily;
BYTE tmCharSet; BYTE tmCharSet;
} TEXTMETRICW,*PTEXTMETRICW,*LPTEXTMETRICW; } TEXTMETRICW,*PTEXTMETRICW,*LPTEXTMETRICW;
typedef struct _RGNDATAHEADER { typedef struct _RGNDATAHEADER {
DWORD dwSize; DWORD dwSize;
DWORD iType; DWORD iType;
@ -2311,6 +2341,13 @@ typedef struct tagPIXELFORMATDESCRIPTOR {
DWORD dwVisibleMask; DWORD dwVisibleMask;
DWORD dwDamageMask; DWORD dwDamageMask;
} PIXELFORMATDESCRIPTOR,*PPIXELFORMATDESCRIPTOR,*LPPIXELFORMATDESCRIPTOR; } PIXELFORMATDESCRIPTOR,*PPIXELFORMATDESCRIPTOR,*LPPIXELFORMATDESCRIPTOR;
typedef struct tagEMRPIXELFORMAT
{
EMR emr;
PIXELFORMATDESCRIPTOR pfd;
} EMRPIXELFORMAT, *PEMRPIXELFORMAT;
typedef struct tagMETAFILEPICT { typedef struct tagMETAFILEPICT {
LONG mm; LONG mm;
LONG xExt; LONG xExt;
@ -2522,6 +2559,8 @@ typedef struct _DISPLAY_DEVICEW {
WCHAR DeviceKey[128]; WCHAR DeviceKey[128];
} DISPLAY_DEVICEW, *PDISPLAY_DEVICEW, *LPDISPLAY_DEVICEW; } DISPLAY_DEVICEW, *PDISPLAY_DEVICEW, *LPDISPLAY_DEVICEW;
typedef BOOL (CALLBACK *ABORTPROC)(HDC,int); typedef BOOL (CALLBACK *ABORTPROC)(HDC,int);
typedef int (CALLBACK *MFENUMPROC)(HDC,HANDLETABLE*,METARECORD*,int,LPARAM); typedef int (CALLBACK *MFENUMPROC)(HDC,HANDLETABLE*,METARECORD*,int,LPARAM);
typedef int (CALLBACK *ENHMFENUMPROC)(HDC,HANDLETABLE*,ENHMETARECORD*,int,LPARAM); typedef int (CALLBACK *ENHMFENUMPROC)(HDC,HANDLETABLE*,ENHMETARECORD*,int,LPARAM);

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,7 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <stdarg.h> #include <stdarg.h>
@ -56,7 +56,7 @@ static void test_solidbrush(void)
} }
else else
stockBrush = NULL; stockBrush = NULL;
memset(&br, sizeof(br), 0); memset(&br, 0, sizeof(br));
ret = GetObject(solidBrush, sizeof(br), &br); ret = GetObject(solidBrush, sizeof(br), &br);
ok( ret !=0, "GetObject on solid %s brush failed, error=%ld\n", stock[i].name, GetLastError()); ok( ret !=0, "GetObject on solid %s brush failed, error=%ld\n", stock[i].name, GetLastError());
ok(br.lbStyle==BS_SOLID, "%s brush has wrong style, got %d expected %d\n", stock[i].name, br.lbStyle, BS_SOLID); ok(br.lbStyle==BS_SOLID, "%s brush has wrong style, got %d expected %d\n", stock[i].name, br.lbStyle, BS_SOLID);

View file

@ -0,0 +1,125 @@
/*
* Unit test suite for clipping
*
* Copyright 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/test.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
static void test_GetRandomRgn(void)
{
HWND hwnd = CreateWindowExA(0,"BUTTON","test",WS_VISIBLE|WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0);
HDC hdc;
HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
int ret;
RECT rc, rc2;
RECT ret_rc, window_rc;
ok( hwnd != 0, "CreateWindow failed\n" );
SetRect(&window_rc, 400, 300, 500, 400);
MoveWindow(hwnd, window_rc.left, window_rc.top, window_rc.right - window_rc.left, window_rc.bottom - window_rc.top, FALSE);
hdc = GetDC(hwnd);
ret = GetRandomRgn(hdc, hrgn, 1);
ok(ret == 0, "GetRandomRgn rets %d\n", ret);
ret = GetRandomRgn(hdc, hrgn, 2);
ok(ret == 0, "GetRandomRgn rets %d\n", ret);
ret = GetRandomRgn(hdc, hrgn, 3);
ok(ret == 0, "GetRandomRgn rets %d\n", ret);
/* Set a clip region */
SetRect(&rc, 20, 20, 80, 80);
IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
ret = GetRandomRgn(hdc, hrgn, 1);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
ret = GetRandomRgn(hdc, hrgn, 2);
ok(ret == 0, "GetRandomRgn rets %d\n", ret);
ret = GetRandomRgn(hdc, hrgn, 3);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
/* Move the clip to the meta and clear the clip */
SetMetaRgn(hdc);
ret = GetRandomRgn(hdc, hrgn, 1);
ok(ret == 0, "GetRandomRgn rets %d\n", ret);
ret = GetRandomRgn(hdc, hrgn, 2);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
ret = GetRandomRgn(hdc, hrgn, 3);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
/* Set a new clip (still got the meta) */
SetRect(&rc2, 10, 30, 70, 90);
IntersectClipRect(hdc, rc2.left, rc2.top, rc2.right, rc2.bottom);
ret = GetRandomRgn(hdc, hrgn, 1);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc2, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
ret = GetRandomRgn(hdc, hrgn, 2);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
IntersectRect(&rc2, &rc, &rc2);
ret = GetRandomRgn(hdc, hrgn, 3);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc2, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
ret = GetRandomRgn(hdc, hrgn, SYSRGN);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
if(GetVersion() & 0x80000000)
OffsetRect(&window_rc, -window_rc.left, -window_rc.top);
ok(EqualRect(&window_rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
DeleteObject(hrgn);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
}
START_TEST(clipping)
{
test_GetRandomRgn();
}

View file

@ -0,0 +1,180 @@
/*
* Unit tests for dc functions
*
* Copyright (c) 2005 Huw Davies
* Copyright (c) 2005 Dmitry Timoshkov
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdio.h>
#include "wine/test.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
static void dump_region(HRGN hrgn)
{
DWORD i, size;
RGNDATA *data = NULL;
RECT *rect;
if (!hrgn)
{
printf( "(null) region\n" );
return;
}
if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
GetRegionData( hrgn, size, data );
printf( "%ld rects:", data->rdh.nCount );
for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom );
printf( "\n" );
HeapFree( GetProcessHeap(), 0, data );
}
static void test_savedc_2(void)
{
HWND hwnd;
HDC hdc;
HRGN hrgn;
RECT rc, rc_clip;
int ret;
hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
0, 0, 0, NULL);
assert(hwnd != 0);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
hrgn = CreateRectRgn(0, 0, 0, 0);
assert(hrgn != 0);
hdc = GetDC(hwnd);
ok(hdc != NULL, "CreateDC rets %p\n", hdc);
ret = GetClipBox(hdc, &rc_clip);
ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
ret = GetClipRgn(hdc, hrgn);
ok(ret == 0, "GetClipRgn returned %d instead of 0\n", ret);
ret = GetRgnBox(hrgn, &rc);
ok(ret == NULLREGION, "GetRgnBox returned %d (%ld,%ld-%ld,%ld) instead of NULLREGION\n",
ret, rc.left, rc.top, rc.right, rc.bottom);
/*dump_region(hrgn);*/
SetRect(&rc, 0, 0, 100, 100);
ok(EqualRect(&rc, &rc_clip),
"rects are not equal: (%ld,%ld-%ld,%ld) - (%ld,%ld-%ld,%ld)\n",
rc.left, rc.top, rc.right, rc.bottom,
rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
ret = SaveDC(hdc);
todo_wine
{
ok(ret == 1, "ret = %d\n", ret);
}
ret = IntersectClipRect(hdc, 0, 0, 50, 50);
#if 0 /* XP returns COMPLEXREGION although dump_region reports only 1 rect */
ok(ret == SIMPLEREGION, "IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
#endif
if (ret != SIMPLEREGION)
{
trace("Windows BUG: IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
/* let's make sure that it's a simple region */
ret = GetClipRgn(hdc, hrgn);
ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret);
dump_region(hrgn);
}
ret = GetClipBox(hdc, &rc_clip);
ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
SetRect(&rc, 0, 0, 50, 50);
ok(EqualRect(&rc, &rc_clip), "rects are not equal\n");
ret = RestoreDC(hdc, 1);
ok(ret, "ret = %d\n", ret);
ret = GetClipBox(hdc, &rc_clip);
ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
SetRect(&rc, 0, 0, 100, 100);
ok(EqualRect(&rc, &rc_clip), "rects are not equal\n");
DeleteObject(hrgn);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
}
static 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();
test_savedc_2();
}

View file

@ -0,0 +1,441 @@
/*
* Unit test suite for fonts
*
* Copyright 2002 Mike McCormack
* Copyright 2004 Dmitry Timoshkov
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/test.h"
static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
{
LOGFONTA getobj_lf;
int ret, minlen = 0;
if (!hfont)
return;
ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
/* NT4 tries to be clever and only returns the minimum length */
while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1)
minlen++;
minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n", test, ret);
ok(!memcmp(&lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "%s: fonts don't match\n", test);
ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName),
"%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
}
static HFONT create_font(const char* test, const LOGFONTA* lf)
{
HFONT hfont = CreateFontIndirectA(lf);
ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
if (hfont)
check_font(test, lf, hfont);
return hfont;
}
static void test_logfont(void)
{
LOGFONTA lf;
HFONT hfont;
memset(&lf, 0, sizeof lf);
lf.lfCharSet = ANSI_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfWeight = FW_DONTCARE;
lf.lfHeight = 16;
lf.lfWidth = 16;
lf.lfQuality = DEFAULT_QUALITY;
lstrcpyA(lf.lfFaceName, "Arial");
hfont = create_font("Arial", &lf);
DeleteObject(hfont);
memset(&lf, 'A', sizeof(lf));
hfont = CreateFontIndirectA(&lf);
ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
lf.lfFaceName[LF_FACESIZE - 1] = 0;
check_font("AAA...", &lf, hfont);
DeleteObject(hfont);
}
static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
{
if (type & RASTER_FONTTYPE)
{
LOGFONT *lf = (LOGFONT *)lParam;
*lf = *elf;
return 0; /* stop enumeration */
}
return 1; /* continue enumeration */
}
static void test_font_metrics(HDC hdc, HFONT hfont, const char *test_str,
INT test_str_len, const TEXTMETRICA *tm_orig,
const SIZE *size_orig, INT width_orig,
INT scale_x, INT scale_y)
{
HFONT old_hfont;
TEXTMETRICA tm;
SIZE size;
INT width;
if (!hfont)
return;
old_hfont = SelectObject(hdc, hfont);
GetTextMetricsA(hdc, &tm);
ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "%ld != %ld\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "%ld != %ld\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "%ld != %ld\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
ok(tm.tmAveCharWidth == tm_orig->tmAveCharWidth * scale_x, "%ld != %ld\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
ok(size.cx == size_orig->cx * scale_x, "%ld != %ld\n", size.cx, size_orig->cx * scale_x);
ok(size.cy == size_orig->cy * scale_y, "%ld != %ld\n", size.cy, size_orig->cy * scale_y);
GetCharWidthA(hdc, 'A', 'A', &width);
ok(width == width_orig * scale_x, "%d != %d\n", width, width_orig * scale_x);
SelectObject(hdc, old_hfont);
}
/* see whether GDI scales bitmap font metrics */
static void test_bitmap_font(void)
{
static const char test_str[11] = "Test String";
HDC hdc;
LOGFONTA bitmap_lf;
HFONT hfont, old_hfont;
TEXTMETRICA tm_orig;
SIZE size_orig;
INT ret, i, width_orig, height_orig;
hdc = GetDC(0);
/* "System" has only 1 pixel size defined, otherwise the test breaks */
ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
if (ret)
{
ReleaseDC(0, hdc);
trace("no bitmap fonts were found, skipping the test\n");
return;
}
trace("found bitmap font %s, height %ld\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
height_orig = bitmap_lf.lfHeight;
hfont = create_font("bitmap", &bitmap_lf);
old_hfont = SelectObject(hdc, hfont);
ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
SelectObject(hdc, old_hfont);
DeleteObject(hfont);
/* test fractional scaling */
for (i = 1; i < height_orig; i++)
{
hfont = create_font("fractional", &bitmap_lf);
test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
DeleteObject(hfont);
}
/* test integer scaling 3x2 */
bitmap_lf.lfHeight = height_orig * 2;
bitmap_lf.lfWidth *= 3;
hfont = create_font("3x2", &bitmap_lf);
todo_wine
{
test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
}
DeleteObject(hfont);
/* test integer scaling 3x3 */
bitmap_lf.lfHeight = height_orig * 3;
bitmap_lf.lfWidth = 0;
hfont = create_font("3x3", &bitmap_lf);
todo_wine
{
test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
}
DeleteObject(hfont);
ReleaseDC(0, hdc);
}
static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
{
LOGFONT *lf = (LOGFONT *)lParam;
if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
{
*lf = *elf;
return 0; /* stop enumeration */
}
return 1; /* continue enumeration */
}
static void test_bitmap_font_metrics(void)
{
static const struct font_data
{
const char face_name[LF_FACESIZE];
int weight, height, ascent, descent, int_leading, ext_leading;
int ave_char_width, max_char_width;
} fd[] =
{
{ "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11 },
{ "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14 },
{ "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16 },
{ "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20 },
{ "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25 },
{ "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32 },
{ "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8 },
{ "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9 },
{ "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12 },
{ "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16 },
{ "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19 },
{ "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23 },
{ "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27 },
{ "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34 },
{ "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8 },
{ "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9 },
{ "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12 },
{ "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15 },
{ "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2 },
{ "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4 },
{ "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13 },
{ "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7 },
{ "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8 },
{ "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9 }
/* FIXME: add "Fixedsys", "Terminal" */
};
HDC hdc;
LOGFONT lf;
HFONT hfont, old_hfont;
TEXTMETRIC tm;
INT ret, i;
hdc = CreateCompatibleDC(0);
assert(hdc);
for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
{
memset(&lf, 0, sizeof(lf));
lf.lfHeight = fd[i].height;
strcpy(lf.lfFaceName, fd[i].face_name);
ret = EnumFontFamilies(hdc, fd[i].face_name, find_font_proc, (LPARAM)&lf);
if (ret)
{
trace("font %s height %d not found\n", fd[i].face_name, fd[i].height);
continue;
}
trace("found font %s, height %ld\n", lf.lfFaceName, lf.lfHeight);
hfont = create_font(lf.lfFaceName, &lf);
old_hfont = SelectObject(hdc, hfont);
ok(GetTextMetrics(hdc, &tm), "GetTextMetrics error %ld\n", GetLastError());
ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmWeight, fd[i].weight);
ok(tm.tmHeight == fd[i].height, "%s(%d): tm.tmHeight %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmHeight, fd[i].height);
ok(tm.tmAscent == fd[i].ascent, "%s(%d): tm.tmAscent %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmAscent, fd[i].ascent);
ok(tm.tmDescent == fd[i].descent, "%s(%d): tm.tmDescent %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmDescent, fd[i].descent);
ok(tm.tmInternalLeading == fd[i].int_leading, "%s(%d): tm.tmInternalLeading %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmInternalLeading, fd[i].int_leading);
ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmExternalLeading, fd[i].ext_leading);
ok(tm.tmAveCharWidth == fd[i].ave_char_width, "%s(%d): tm.tmAveCharWidth %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmAveCharWidth, fd[i].ave_char_width);
ok(tm.tmMaxCharWidth == fd[i].max_char_width, "%s(%d): tm.tmMaxCharWidth %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmMaxCharWidth, fd[i].max_char_width);
SelectObject(hdc, old_hfont);
DeleteObject(hfont);
}
DeleteDC(hdc);
}
static void test_GdiGetCharDimensions(void)
{
HDC hdc;
TEXTMETRICW tm;
LONG ret;
SIZE size;
LONG avgwidth, height;
static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
typedef LONG (WINAPI *fnGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
fnGdiGetCharDimensions GdiGetCharDimensions = (fnGdiGetCharDimensions)GetProcAddress(LoadLibrary("gdi32"), "GdiGetCharDimensions");
if (!GdiGetCharDimensions) return;
hdc = CreateCompatibleDC(NULL);
GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size);
avgwidth = ((size.cx / 26) + 1) / 2;
ret = GdiGetCharDimensions(hdc, &tm, &height);
ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", tm.tmHeight, height);
ret = GdiGetCharDimensions(hdc, &tm, NULL);
ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
ret = GdiGetCharDimensions(hdc, NULL, NULL);
ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
height = 0;
ret = GdiGetCharDimensions(hdc, NULL, &height);
ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
ok(height == size.cy, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", size.cy, height);
DeleteDC(hdc);
}
static void test_GetCharABCWidthsW(void)
{
BOOL ret;
ABC abc[1];
typedef BOOL (WINAPI *fnGetCharABCWidthsW)(HDC hdc, UINT first, UINT last, LPABC abc);
fnGetCharABCWidthsW GetCharABCWidthsW = (fnGetCharABCWidthsW)GetProcAddress(LoadLibrary("gdi32"), "GetCharABCWidthsW");
if (!GetCharABCWidthsW) return;
ret = GetCharABCWidthsW(NULL, 'a', 'a', abc);
ok(!ret, "GetCharABCWidthsW should have returned FALSE\n");
}
static void test_text_extents(void)
{
static const WCHAR wt[] = {'O','n','e','\n','t','w','o',' ','3',0};
LPINT extents;
INT i, len, fit1, fit2;
LOGFONTA lf;
TEXTMETRICA tm;
HDC hdc;
HFONT hfont;
SIZE sz;
SIZE sz1, sz2;
memset(&lf, 0, sizeof(lf));
strcpy(lf.lfFaceName, "Arial");
lf.lfHeight = 20;
hfont = CreateFontIndirectA(&lf);
hdc = GetDC(0);
hfont = SelectObject(hdc, hfont);
GetTextMetricsA(hdc, &tm);
GetTextExtentPointA(hdc, "o", 1, &sz);
ok(sz.cy == tm.tmHeight, "cy %ld tmHeight %ld\n", sz.cy, tm.tmHeight);
len = lstrlenW(wt);
extents = HeapAlloc(GetProcessHeap(), 0, len * sizeof extents[0]);
memset(extents, 0, len * sizeof extents[0]);
extents[0] = 1; /* So that the increasing sequence test will fail
if the extents array is untouched. */
GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1);
GetTextExtentPointW(hdc, wt, len, &sz2);
ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
"results from GetTextExtentExPointW and GetTextExtentPointW differ\n");
for (i = 1; i < len; ++i)
ok(extents[i-1] <= extents[i],
"GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n",
i);
ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n");
ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1);
ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n");
GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2);
ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n");
ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n");
GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2);
ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n");
GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2);
ok(extents[0] == extents[2] && extents[1] == extents[3],
"GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n");
GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1);
ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy,
"GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n");
HeapFree(GetProcessHeap(), 0, extents);
SelectObject(hdc, hfont);
DeleteObject(hfont);
ReleaseDC(NULL, hdc);
}
static void test_GetGlyphIndices()
{
HDC hdc;
HFONT hfont;
DWORD charcount;
LOGFONTA lf;
DWORD flags = 0;
WCHAR testtext[] = {'T','e','s','t',0xffff,0};
WORD glyphs[(sizeof(testtext)/2)-1];
TEXTMETRIC textm;
typedef BOOL (WINAPI *fnGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
fnGetGlyphIndicesW GetGlyphIndicesW = (fnGetGlyphIndicesW)GetProcAddress(LoadLibrary("gdi32"),
"GetGlyphIndicesW");
if (!GetGlyphIndicesW) {
trace("GetGlyphIndices not available on platform\n");
return;
}
memset(&lf, 0, sizeof(lf));
strcpy(lf.lfFaceName, "Symbol");
lf.lfHeight = 20;
hfont = CreateFontIndirectA(&lf);
hdc = GetDC(0);
ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n");
flags |= GGI_MARK_NONEXISTING_GLYPHS;
charcount = GetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
ok(charcount == 5, "GetGlyphIndices count of glyphs should = 5 not %ld\n", charcount);
ok(glyphs[4] == 0x001f, "GetGlyphIndices should have returned a nonexistent char not %04x\n", glyphs[4]);
flags = 0;
charcount = GetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags);
ok(charcount == 5, "GetGlyphIndices count of glyphs should = 5 not %ld\n", charcount);
ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndices should have returned a %04x not %04x\n",
textm.tmDefaultChar, glyphs[4]);
}
START_TEST(font)
{
test_logfont();
test_bitmap_font();
test_bitmap_font_metrics();
test_GdiGetCharDimensions();
test_GetCharABCWidthsW();
test_text_extents();
test_GetGlyphIndices();
}

View file

@ -8,7 +8,12 @@
<library>advapi32</library> <library>advapi32</library>
<file>bitmap.c</file> <file>bitmap.c</file>
<file>brush.c</file> <file>brush.c</file>
<file>clipping.c</file>
<file>dc.c</file>
<file>gdiobj.c</file> <file>gdiobj.c</file>
<file>font.c</file>
<file>mapping.c</file>
<file>metafile.c</file> <file>metafile.c</file>
<file>palette.c</file>
<file>testlist.c</file> <file>testlist.c</file>
</module> </module>

View file

@ -16,10 +16,11 @@
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <stdarg.h> #include <stdarg.h>
#include <assert.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
@ -28,175 +29,6 @@
#include "wine/test.h" #include "wine/test.h"
static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
{
LOGFONTA getobj_lf;
int ret, minlen = 0;
if (!hfont)
return;
ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
/* NT4 tries to be clever and only returns the minimum length */
while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1)
minlen++;
minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
ok(ret == sizeof(LOGFONTA) || ret == minlen,
"%s: GetObject returned %d expected %d or %d\n", test, ret, sizeof(LOGFONTA), minlen);
ok(!memcmp(&lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "%s: fonts don't match\n", test);
ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName),
"%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
}
static HFONT create_font(const char* test, const LOGFONTA* lf)
{
HFONT hfont = CreateFontIndirectA(lf);
ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
if (hfont)
check_font(test, lf, hfont);
return hfont;
}
static void test_logfont(void)
{
LOGFONTA lf;
HFONT hfont;
memset(&lf, 0, sizeof lf);
lf.lfCharSet = ANSI_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfWeight = FW_DONTCARE;
lf.lfHeight = 16;
lf.lfWidth = 16;
lf.lfQuality = DEFAULT_QUALITY;
lstrcpyA(lf.lfFaceName, "Arial");
hfont = create_font("Arial", &lf);
DeleteObject(hfont);
memset(&lf, 'A', sizeof(lf));
hfont = CreateFontIndirectA(&lf);
ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
lf.lfFaceName[LF_FACESIZE - 1] = 0;
check_font("AAA...", &lf, hfont);
DeleteObject(hfont);
}
static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
{
if (type & RASTER_FONTTYPE)
{
LOGFONT *lf = (LOGFONT *)lParam;
*lf = *elf;
return 0; /* stop enumeration */
}
return 1; /* continue enumeration */
}
static void test_font_metrics(HDC hdc, HFONT hfont, const char *test_str,
INT test_str_len, const TEXTMETRICA *tm_orig,
const SIZE *size_orig, INT width_orig,
INT scale_x, INT scale_y)
{
HFONT old_hfont;
TEXTMETRICA tm;
SIZE size;
INT width;
if (!hfont)
return;
old_hfont = SelectObject(hdc, hfont);
GetTextMetricsA(hdc, &tm);
ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "%ld != %ld\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "%ld != %ld\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "%ld != %ld\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
ok(tm.tmAveCharWidth == tm_orig->tmAveCharWidth * scale_x, "%ld != %ld\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
ok(size.cx == size_orig->cx * scale_x, "%ld != %ld\n", size.cx, size_orig->cx * scale_x);
ok(size.cy == size_orig->cy * scale_y, "%ld != %ld\n", size.cy, size_orig->cy * scale_y);
GetCharWidthA(hdc, 'A', 'A', &width);
ok(width == width_orig * scale_x, "%d != %d\n", width, width_orig * scale_x);
SelectObject(hdc, old_hfont);
}
/* see whether GDI scales bitmap font metrics */
static void test_bitmap_font(void)
{
static const char test_str[11] = "Test String";
HDC hdc;
LOGFONTA bitmap_lf;
HFONT hfont, old_hfont;
TEXTMETRICA tm_orig;
SIZE size_orig;
INT ret, i, width_orig, height_orig;
hdc = GetDC(0);
/* "System" has only 1 pixel size defined, otherwise the test breaks */
ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
if (ret)
{
ReleaseDC(0, hdc);
trace("no bitmap fonts were found, skipping the test\n");
return;
}
trace("found bitmap font %s, height %ld\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
height_orig = bitmap_lf.lfHeight;
hfont = create_font("bitmap", &bitmap_lf);
old_hfont = SelectObject(hdc, hfont);
ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
SelectObject(hdc, old_hfont);
DeleteObject(hfont);
/* test fractional scaling */
for (i = 1; i < height_orig; i++)
{
hfont = create_font("fractional", &bitmap_lf);
test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
DeleteObject(hfont);
}
/* test integer scaling 3x2 */
bitmap_lf.lfHeight = height_orig * 2;
bitmap_lf.lfWidth *= 3;
hfont = create_font("3x2", &bitmap_lf);
todo_wine
{
test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
}
DeleteObject(hfont);
/* test integer scaling 3x3 */
bitmap_lf.lfHeight = height_orig * 3;
bitmap_lf.lfWidth = 0;
hfont = create_font("3x3", &bitmap_lf);
todo_wine
{
test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
}
DeleteObject(hfont);
ReleaseDC(0, hdc);
}
static void test_gdi_objects(void) static void test_gdi_objects(void)
{ {
BYTE buff[256]; BYTE buff[256];
@ -266,70 +98,177 @@ static void test_gdi_objects(void)
ReleaseDC(NULL, hdc); ReleaseDC(NULL, hdc);
} }
static void test_GdiGetCharDimensions(void) struct hgdiobj_event
{ {
HDC hdc; HDC hdc;
TEXTMETRICW tm; HGDIOBJ hgdiobj1;
LONG ret; HGDIOBJ hgdiobj2;
SIZE size; HANDLE stop_event;
LONG avgwidth, height; HANDLE ready_event;
static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; };
typedef LONG (WINAPI *fnGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
fnGdiGetCharDimensions GdiGetCharDimensions = (fnGdiGetCharDimensions)GetProcAddress(LoadLibrary("gdi32"), "GdiGetCharDimensions");
if (!GdiGetCharDimensions) return;
hdc = CreateCompatibleDC(NULL); static DWORD WINAPI thread_proc(void *param)
{
LOGPEN lp;
struct hgdiobj_event *hgdiobj_event = (struct hgdiobj_event *)param;
GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size); hgdiobj_event->hdc = CreateDC("display", NULL, NULL, NULL);
avgwidth = ((size.cx / 26) + 1) / 2; ok(hgdiobj_event->hdc != NULL, "CreateDC error %ld\n", GetLastError());
ret = GdiGetCharDimensions(hdc, &tm, &height); hgdiobj_event->hgdiobj1 = CreatePen(PS_DASHDOTDOT, 17, RGB(1, 2, 3));
ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); ok(hgdiobj_event->hgdiobj1 != 0, "Failed to create pen\n");
ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", tm.tmHeight, height);
ret = GdiGetCharDimensions(hdc, &tm, NULL); hgdiobj_event->hgdiobj2 = CreateRectRgn(0, 1, 12, 17);
ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); ok(hgdiobj_event->hgdiobj2 != 0, "Failed to create pen\n");
ret = GdiGetCharDimensions(hdc, NULL, NULL); SetEvent(hgdiobj_event->ready_event);
ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); ok(WaitForSingleObject(hgdiobj_event->stop_event, INFINITE) == WAIT_OBJECT_0,
"WaitForSingleObject error %ld\n", GetLastError());
height = 0; ok(!GetObject(hgdiobj_event->hgdiobj1, sizeof(lp), &lp), "GetObject should fail\n");
ret = GdiGetCharDimensions(hdc, NULL, &height);
ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); ok(!GetDeviceCaps(hgdiobj_event->hdc, TECHNOLOGY), "GetDeviceCaps(TECHNOLOGY) should fail\n");
ok(height == size.cy, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", size.cy, height);
return 0;
}
static void test_thread_objects(void)
{
LOGPEN lp;
DWORD tid, type;
HANDLE hthread;
struct hgdiobj_event hgdiobj_event;
INT ret;
hgdiobj_event.stop_event = CreateEvent(NULL, 0, 0, NULL);
ok(hgdiobj_event.stop_event != NULL, "CreateEvent error %ld\n", GetLastError());
hgdiobj_event.ready_event = CreateEvent(NULL, 0, 0, NULL);
ok(hgdiobj_event.ready_event != NULL, "CreateEvent error %ld\n", GetLastError());
hthread = CreateThread(NULL, 0, thread_proc, &hgdiobj_event, 0, &tid);
ok(hthread != NULL, "CreateThread error %ld\n", GetLastError());
ok(WaitForSingleObject(hgdiobj_event.ready_event, INFINITE) == WAIT_OBJECT_0,
"WaitForSingleObject error %ld\n", GetLastError());
ok(GetObject(hgdiobj_event.hgdiobj1, sizeof(lp), &lp) == sizeof(lp),
"GetObject error %ld\n", GetLastError());
ok(lp.lopnStyle == PS_DASHDOTDOT, "wrong pen style %d\n", lp.lopnStyle);
ok(lp.lopnWidth.x == 17, "wrong pen width.y %ld\n", lp.lopnWidth.x);
ok(lp.lopnWidth.y == 0, "wrong pen width.y %ld\n", lp.lopnWidth.y);
ok(lp.lopnColor == RGB(1, 2, 3), "wrong pen width.y %08lx\n", lp.lopnColor);
ret = GetDeviceCaps(hgdiobj_event.hdc, TECHNOLOGY);
ok(ret == DT_RASDISPLAY, "GetDeviceCaps(TECHNOLOGY) should return DT_RASDISPLAY not %d\n", ret);
ok(DeleteObject(hgdiobj_event.hgdiobj1), "DeleteObject error %ld\n", GetLastError());
ok(DeleteDC(hgdiobj_event.hdc), "DeleteDC error %ld\n", GetLastError());
type = GetObjectType(hgdiobj_event.hgdiobj2);
ok(type == OBJ_REGION, "GetObjectType returned %lu\n", type);
SetEvent(hgdiobj_event.stop_event);
ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0,
"WaitForSingleObject error %ld\n", GetLastError());
CloseHandle(hthread);
type = GetObjectType(hgdiobj_event.hgdiobj2);
ok(type == OBJ_REGION, "GetObjectType returned %lu\n", type);
ok(DeleteObject(hgdiobj_event.hgdiobj2), "DeleteObject error %ld\n", GetLastError());
CloseHandle(hgdiobj_event.stop_event);
CloseHandle(hgdiobj_event.ready_event);
}
static void test_GetCurrentObject(void)
{
DWORD type;
HPEN hpen;
HBRUSH hbrush;
HPALETTE hpal;
HFONT hfont;
HBITMAP hbmp;
HRGN hrgn;
HDC hdc;
HCOLORSPACE hcs;
HGDIOBJ hobj;
LOGBRUSH lb;
LOGCOLORSPACEA lcs;
hdc = CreateCompatibleDC(0);
assert(hdc != 0);
type = GetObjectType(hdc);
ok(type == OBJ_MEMDC, "GetObjectType returned %lu\n", type);
hpen = CreatePen(PS_SOLID, 10, RGB(10, 20, 30));
assert(hpen != 0);
SelectObject(hdc, hpen);
hobj = GetCurrentObject(hdc, OBJ_PEN);
ok(hobj == hpen, "OBJ_PEN is wrong: %p\n", hobj);
hobj = GetCurrentObject(hdc, OBJ_EXTPEN);
ok(hobj == hpen, "OBJ_EXTPEN is wrong: %p\n", hobj);
hbrush = CreateSolidBrush(RGB(10, 20, 30));
assert(hbrush != 0);
SelectObject(hdc, hbrush);
hobj = GetCurrentObject(hdc, OBJ_BRUSH);
ok(hobj == hbrush, "OBJ_BRUSH is wrong: %p\n", hobj);
hpal = CreateHalftonePalette(hdc);
assert(hpal != 0);
SelectPalette(hdc, hpal, FALSE);
hobj = GetCurrentObject(hdc, OBJ_PAL);
ok(hobj == hpal, "OBJ_PAL is wrong: %p\n", hobj);
hfont = CreateFontA(10, 5, 0, 0, FW_DONTCARE, 0, 0, 0, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH, "MS Sans Serif");
assert(hfont != 0);
SelectObject(hdc, hfont);
hobj = GetCurrentObject(hdc, OBJ_FONT);
ok(hobj == hfont, "OBJ_FONT is wrong: %p\n", hobj);
hbmp = CreateBitmap(100, 100, 1, 1, NULL);
assert(hbmp != 0);
SelectObject(hdc, hbmp);
hobj = GetCurrentObject(hdc, OBJ_BITMAP);
ok(hobj == hbmp, "OBJ_BITMAP is wrong: %p\n", hobj);
assert(GetObject(hbrush, sizeof(lb), &lb) == sizeof(lb));
hpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_SQUARE | PS_JOIN_BEVEL,
10, &lb, 0, NULL);
assert(hpen != 0);
SelectObject(hdc, hpen);
hobj = GetCurrentObject(hdc, OBJ_PEN);
ok(hobj == hpen, "OBJ_PEN is wrong: %p\n", hobj);
hobj = GetCurrentObject(hdc, OBJ_EXTPEN);
ok(hobj == hpen, "OBJ_EXTPEN is wrong: %p\n", hobj);
hcs = GetColorSpace(hdc);
if (hcs)
{
trace("current color space is not NULL\n");
ok(GetLogColorSpaceA(hcs, &lcs, sizeof(lcs)), "GetLogColorSpace failed\n");
hcs = CreateColorSpaceA(&lcs);
ok(hcs != 0, "CreateColorSpace failed\n");
SelectObject(hdc, hcs);
hobj = GetCurrentObject(hdc, OBJ_COLORSPACE);
ok(hobj == hcs, "OBJ_COLORSPACE is wrong: %p\n", hobj);
}
hrgn = CreateRectRgn(1, 1, 100, 100);
assert(hrgn != 0);
SelectObject(hdc, hrgn);
hobj = GetCurrentObject(hdc, OBJ_REGION);
ok(!hobj, "OBJ_REGION is wrong: %p\n", hobj);
DeleteDC(hdc); DeleteDC(hdc);
} }
static void test_text_extents(void)
{
LOGFONTA lf;
TEXTMETRICA tm;
HDC hdc;
HFONT hfont;
SIZE sz;
memset(&lf, 0, sizeof(lf));
strcpy(lf.lfFaceName, "Arial");
lf.lfHeight = 20;
hfont = CreateFontIndirectA(&lf);
hdc = GetDC(0);
hfont = SelectObject(hdc, hfont);
GetTextMetricsA(hdc, &tm);
GetTextExtentPointA(hdc, "o", 1, &sz);
ok(sz.cy == tm.tmHeight, "cy %ld tmHeight %ld\n", sz.cy, tm.tmHeight);
SelectObject(hdc, hfont);
DeleteObject(hfont);
ReleaseDC(NULL, hdc);
}
START_TEST(gdiobj) START_TEST(gdiobj)
{ {
test_logfont();
test_bitmap_font();
test_gdi_objects(); test_gdi_objects();
test_GdiGetCharDimensions(); test_thread_objects();
test_text_extents(); test_GetCurrentObject();
} }

View file

@ -0,0 +1,160 @@
/*
* Unit tests for mapping 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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_modify_world_transform(void)
{
HDC hdc = GetDC(0);
int ret;
ret = SetGraphicsMode(hdc, GM_ADVANCED);
if(!ret) /* running in win9x so quit */
{
ReleaseDC(0, hdc);
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);
}
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)
{
test_modify_world_transform();
test_isotropic_mapping();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,126 @@
/*
* Unit test suite for palettes
*
* Copyright 2005 Glenn Wurster
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmsystem.h"
#include "wine/test.h"
static const PALETTEENTRY logpalettedata[8] = {
{ 0x10, 0x20, 0x30, PC_NOCOLLAPSE },
{ 0x20, 0x30, 0x40, PC_NOCOLLAPSE },
{ 0x30, 0x40, 0x50, PC_NOCOLLAPSE },
{ 0x40, 0x50, 0x60, PC_NOCOLLAPSE },
{ 0x50, 0x60, 0x70, PC_NOCOLLAPSE },
{ 0x60, 0x70, 0x80, PC_NOCOLLAPSE },
{ 0x70, 0x80, 0x90, PC_NOCOLLAPSE },
{ 0x80, 0x90, 0xA0, PC_NOCOLLAPSE },
};
static void test_DIB_PAL_COLORS(void) {
HDC hdc = GetDC( NULL );
HDC memhdc = CreateCompatibleDC( hdc );
HBITMAP hbmp, hbmpOld;
char bmpbuf[sizeof(BITMAPINFO) + 10 * sizeof(WORD)];
PBITMAPINFO bmp = (PBITMAPINFO)bmpbuf;
WORD * bmpPalPtr;
char logpalettebuf[sizeof(LOGPALETTE) + sizeof(logpalettedata)];
PLOGPALETTE logpalette = (PLOGPALETTE)logpalettebuf;
HPALETTE hpal, hpalOld;
COLORREF setColor, chkColor, getColor;
int i;
/* Initalize the logical palette with a few colours */
logpalette->palVersion = 0x300;
logpalette->palNumEntries = 8;
memcpy( logpalette->palPalEntry, logpalettedata, sizeof(logpalettedata) );
hpal = CreatePalette( logpalette );
hpalOld = SelectPalette( memhdc, hpal, FALSE );
ok( hpalOld != NULL, "error=%ld\n", GetLastError() );
/* Create a DIB BMP which references colours in the logical palette */
memset( bmp, 0x00, sizeof(BITMAPINFO) );
bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmp->bmiHeader.biWidth = 1;
bmp->bmiHeader.biHeight = 1;
bmp->bmiHeader.biPlanes = 1;
bmp->bmiHeader.biBitCount = 8;
bmp->bmiHeader.biCompression = BI_RGB;
bmp->bmiHeader.biClrUsed = 10;
bmp->bmiHeader.biClrImportant = 0;
bmpPalPtr = (WORD *)&bmp->bmiColors;
for( i = 0; i < 8; i++ ) {
*bmpPalPtr++ = i;
}
*bmpPalPtr++ = 8; /* Pointer to logical palette index just outside range */
*bmpPalPtr++ = 19; /* Pointer to bad logical palette index */
hbmp = CreateDIBSection( memhdc, bmp, DIB_PAL_COLORS, 0, 0, 0 );
ok( hbmp != NULL, "error=%ld\n", GetLastError() );
hbmpOld = SelectObject( memhdc, hbmp );
ok( hbmpOld != NULL, "error=%ld\n", GetLastError() );
/* Test with a RGB to DIB_PAL_COLORS */
setColor = RGB( logpalettedata[1].peRed, logpalettedata[1].peGreen, logpalettedata[1].peBlue );
SetPixel( memhdc, 0, 0, setColor );
chkColor = RGB( logpalettedata[1].peRed, logpalettedata[1].peGreen, logpalettedata[1].peBlue );
getColor = GetPixel( memhdc, 0, 0 );
ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
/* Test with a valid DIBINDEX to DIB_PAL_COLORS */
setColor = DIBINDEX( 2 );
SetPixel( memhdc, 0, 0, setColor );
chkColor = RGB( logpalettedata[2].peRed, logpalettedata[2].peGreen, logpalettedata[2].peBlue );
getColor = GetPixel( memhdc, 0, 0 );
ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
/* Test with a invalid DIBINDEX to DIB_PAL_COLORS */
setColor = DIBINDEX( 12 );
SetPixel( memhdc, 0, 0, setColor );
chkColor = RGB( 0, 0, 0 );
getColor = GetPixel( memhdc, 0, 0 );
ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
/* Test for double wraparound on logical palette references from */
/* DIBINDEX by DIB_PAL_COLORS. */
setColor = DIBINDEX( 9 );
SetPixel( memhdc, 0, 0, setColor );
chkColor = RGB( logpalettedata[3].peRed, logpalettedata[3].peGreen, logpalettedata[3].peBlue );
getColor = GetPixel( memhdc, 0, 0 );
ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
SelectPalette( memhdc, hpalOld, FALSE );
DeleteObject( hpal );
SelectObject( memhdc, hbmpOld );
DeleteObject( hbmp );
DeleteDC( memhdc );
ReleaseDC( NULL, hdc );
}
START_TEST(palette)
{
test_DIB_PAL_COLORS();
}

View file

@ -22,14 +22,14 @@ const struct test winetest_testlist[] =
{ {
{ "bitmap", func_bitmap }, { "bitmap", func_bitmap },
{ "brush", func_brush }, { "brush", func_brush },
// { "clipping", func_clipping }, { "clipping", func_clipping },
// { "dc", func_dc }, { "dc", func_dc },
// { "font", func_font }, { "font", func_font },
{ "gdiobj", func_gdiobj }, { "gdiobj", func_gdiobj },
// { "generated", func_generated }, // { "generated", func_generated },
// { "mapping", func_mapping }, { "mapping", func_mapping },
{ "metafile", func_metafile }, { "metafile", func_metafile },
// { "palette", func_palette }, { "palette", func_palette },
// { "pen", func_pen }, // { "pen", func_pen },
{ 0, 0 } { 0, 0 }
}; };

View file

@ -72,6 +72,8 @@ typedef struct
#define BRUSHOBJ_FreeBrush(hBrush) GDIOBJ_FreeObj(GdiHandleTable, (HGDIOBJ)hBrush, GDI_OBJECT_TYPE_BRUSH) #define BRUSHOBJ_FreeBrush(hBrush) GDIOBJ_FreeObj(GdiHandleTable, (HGDIOBJ)hBrush, GDI_OBJECT_TYPE_BRUSH)
#define BRUSHOBJ_LockBrush(hBrush) ((PGDIBRUSHOBJ)GDIOBJ_LockObj(GdiHandleTable, (HGDIOBJ)hBrush, GDI_OBJECT_TYPE_BRUSH)) #define BRUSHOBJ_LockBrush(hBrush) ((PGDIBRUSHOBJ)GDIOBJ_LockObj(GdiHandleTable, (HGDIOBJ)hBrush, GDI_OBJECT_TYPE_BRUSH))
#define BRUSHOBJ_UnlockBrush(pBrush) GDIOBJ_UnlockObjByPtr(GdiHandleTable, pBrush) #define BRUSHOBJ_UnlockBrush(pBrush) GDIOBJ_UnlockObjByPtr(GdiHandleTable, pBrush)
INT FASTCALL BRUSH_GetObject (PGDIBRUSHOBJ GdiObject, INT Count, LPLOGBRUSH Buffer);
BOOL INTERNAL_CALL BRUSH_Cleanup(PVOID ObjectBody); BOOL INTERNAL_CALL BRUSH_Cleanup(PVOID ObjectBody);
#endif #endif

View file

@ -188,6 +188,11 @@ VOID FASTCALL DC_SetOwnership(HDC DC, PEPROCESS Owner);
VOID FASTCALL DC_UpdateXforms(PDC dc); VOID FASTCALL DC_UpdateXforms(PDC dc);
BOOL FASTCALL DC_InvertXform(const XFORM *xformSrc, XFORM *xformDest); BOOL FASTCALL DC_InvertXform(const XFORM *xformSrc, XFORM *xformDest);
VOID FASTCALL IntGetViewportExtEx(PDC dc, LPSIZE pt);
VOID FASTCALL IntGetViewportOrgEx(PDC dc, LPPOINT pt);
VOID FASTCALL IntGetWindowExtEx(PDC dc, LPSIZE pt);
VOID FASTCALL IntGetWindowOrgEx(PDC dc, LPPOINT pt);
/* For Metafile and MetaEnhFile not in windows this struct taken from wine cvs 15/9-2006*/ /* For Metafile and MetaEnhFile not in windows this struct taken from wine cvs 15/9-2006*/
typedef struct typedef struct
{ {
@ -195,5 +200,4 @@ typedef struct
BOOL on_disk; /* true if metafile is on disk */ BOOL on_disk; /* true if metafile is on disk */
} DD_ENHMETAFILEOBJ, *PDD_ENHMETAFILEOBJ; } DD_ENHMETAFILEOBJ, *PDD_ENHMETAFILEOBJ;
#endif /* __WIN32K_DC_H */
#endif

View file

@ -19,7 +19,7 @@ BOOL FASTCALL PATH_PolylineTo (PDC dc, const POINT *pts, DWORD cbPoints);
BOOL FASTCALL PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons); BOOL FASTCALL PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons);
BOOL FASTCALL PATH_PolyPolyline( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylines); BOOL FASTCALL PATH_PolyPolyline( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylines);
BOOL FASTCALL PATH_Rectangle (PDC dc, INT x1, INT y1, INT x2, INT y2); BOOL FASTCALL PATH_Rectangle (PDC dc, INT x1, INT y1, INT x2, INT y2);
BOOL FASTCALL PATH_RoundRect (PDC dc, INT x1, INT y1, INT x2, INT y2, INT xradius, INT yradius); BOOL FASTCALL PATH_RoundRect(DC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height);
BOOL FASTCALL PATH_PathToRegion (GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn); BOOL FASTCALL PATH_PathToRegion (GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn);
#endif /* _WIN32K_PATH_H */ #endif /* _WIN32K_PATH_H */

View file

@ -11,4 +11,6 @@
#define PENOBJ_LockPen(hBMObj) ((PGDIBRUSHOBJ)GDIOBJ_LockObj(GdiHandleTable, (HGDIOBJ) hBMObj, GDI_OBJECT_TYPE_PEN)) #define PENOBJ_LockPen(hBMObj) ((PGDIBRUSHOBJ)GDIOBJ_LockObj(GdiHandleTable, (HGDIOBJ) hBMObj, GDI_OBJECT_TYPE_PEN))
#define PENOBJ_UnlockPen(pPenObj) GDIOBJ_UnlockObjByPtr(GdiHandleTable, pPenObj) #define PENOBJ_UnlockPen(pPenObj) GDIOBJ_UnlockObjByPtr(GdiHandleTable, pPenObj)
INT STDCALL PEN_GetObject(PGDIBRUSHOBJ hPen, INT Count, PLOGPEN Buffer);
#endif #endif

View file

@ -437,7 +437,12 @@ IntCreateBitmapIndirect(CONST BITMAP *BM)
Size.cx, Size.cy, BitsPixel, hBitmap); Size.cx, Size.cy, BitsPixel, hBitmap);
bmp = BITMAPOBJ_LockBitmap( hBitmap ); bmp = BITMAPOBJ_LockBitmap( hBitmap );
/* FIXME - bmp can be NULL!!!!!! */ if (bmp == NULL)
{
/* FIXME should we free the hBitmap or return it ?? */
return 0;
}
bmp->flFlags = BITMAPOBJ_IS_APIBITMAP; bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
BITMAPOBJ_UnlockBitmap( bmp ); BITMAPOBJ_UnlockBitmap( bmp );
@ -1071,10 +1076,6 @@ NtGdiSetPixel(
DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color); DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
if (((Color>>24) & 0xff)<0x10)
{
Color = ((Color>>16) & 0x0000ff) | ((Color<<16) & 0xff0000) | (Color & 0x00ff00);
}
DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color); DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
@ -1083,7 +1084,6 @@ NtGdiSetPixel(
Color = NtGdiGetPixel(hDC,X,Y); Color = NtGdiGetPixel(hDC,X,Y);
DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color); DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
return Color; return Color;
} }
Color = ((COLORREF) -1); Color = ((COLORREF) -1);
@ -1561,8 +1561,12 @@ BITMAPOBJ_CopyBitmap(HBITMAP hBitmap)
INT STDCALL INT STDCALL
BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer) BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer)
{ {
if( !buffer ) return sizeof(BITMAP);
if (count < sizeof(BITMAP)) return 0;
if(bmp->dib) if(bmp->dib)
{ {
if(count < (INT) sizeof(DIBSECTION)) if(count < (INT) sizeof(DIBSECTION))
{ {
if (count > (INT) sizeof(BITMAP)) count = sizeof(BITMAP); if (count > (INT) sizeof(BITMAP)) count = sizeof(BITMAP);
@ -1584,7 +1588,8 @@ BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer)
Bitmap.bmWidthBytes = abs(bmp->SurfObj.lDelta); Bitmap.bmWidthBytes = abs(bmp->SurfObj.lDelta);
Bitmap.bmPlanes = 1; Bitmap.bmPlanes = 1;
Bitmap.bmBitsPixel = BitsPerFormat(bmp->SurfObj.iBitmapFormat); Bitmap.bmBitsPixel = BitsPerFormat(bmp->SurfObj.iBitmapFormat);
Bitmap.bmBits = bmp->SurfObj.pvBits; //Bitmap.bmBits = bmp->SurfObj.pvBits;
Bitmap.bmBits = NULL; /* not set accoring wine test confirm in win2k */
memcpy(buffer, &Bitmap, count); memcpy(buffer, &Bitmap, count);
return count; return count;
} }

View file

@ -49,6 +49,67 @@ BRUSH_Cleanup(PVOID ObjectBody)
return TRUE; return TRUE;
} }
INT FASTCALL
BRUSH_GetObject (PGDIBRUSHOBJ BrushObject, INT Count, LPLOGBRUSH Buffer)
{
if (Buffer)
{
/* Set colour */
Buffer->lbColor = BrushObject->BrushAttr.lbColor;
/* set Hatch */
if ((BrushObject->flAttrs & GDIBRUSH_IS_HATCH)!=0)
{
/* FIXME : is this right value */
Buffer->lbHatch = (LONG)BrushObject->hbmPattern;
}
else
{
Buffer->lbHatch = 0;
}
Buffer->lbStyle = 0;
/* Get the type of style */
if ((BrushObject->flAttrs & GDIBRUSH_IS_SOLID)!=0)
{
Buffer->lbStyle = BS_SOLID;
}
else if ((BrushObject->flAttrs & GDIBRUSH_IS_NULL)!=0)
{
Buffer->lbStyle = BS_NULL; // BS_HOLLOW
}
else if ((BrushObject->flAttrs & GDIBRUSH_IS_HATCH)!=0)
{
Buffer->lbStyle = BS_HATCHED;
}
else if ((BrushObject->flAttrs & GDIBRUSH_IS_BITMAP)!=0)
{
Buffer->lbStyle = BS_PATTERN;
}
else if ((BrushObject->flAttrs & GDIBRUSH_IS_DIB)!=0)
{
Buffer->lbStyle = BS_DIBPATTERN;
}
/* FIXME
else if ((BrushObject->flAttrs & )!=0)
{
Buffer->lbStyle = BS_INDEXED;
}
else if ((BrushObject->flAttrs & )!=0)
{
Buffer->lbStyle = BS_DIBPATTERNPT;
}
*/
}
return sizeof(BRUSHOBJ);
}
XLATEOBJ* FASTCALL XLATEOBJ* FASTCALL
IntGdiCreateBrushXlate(PDC Dc, GDIBRUSHOBJ *BrushObj, BOOLEAN *Failed) IntGdiCreateBrushXlate(PDC Dc, GDIBRUSHOBJ *BrushObj, BOOLEAN *Failed)
{ {
@ -402,7 +463,8 @@ IntGdiCreateSolidBrush(
ASSERT(BrushObject != NULL); ASSERT(BrushObject != NULL);
BrushObject->flAttrs |= GDIBRUSH_IS_SOLID; BrushObject->flAttrs |= GDIBRUSH_IS_SOLID;
BrushObject->BrushAttr.lbColor = Color & 0xFFFFFF;
BrushObject->BrushAttr.lbColor = Color;
/* FIXME: Fill in the rest of fields!!! */ /* FIXME: Fill in the rest of fields!!! */
BRUSHOBJ_UnlockBrush(BrushObject); BRUSHOBJ_UnlockBrush(BrushObject);

View file

@ -795,6 +795,12 @@ NtGdiSetViewportExtEx(HDC hDC,
1); 1);
Size->cx = dc->vportExtX; Size->cx = dc->vportExtX;
Size->cy = dc->vportExtY; Size->cy = dc->vportExtY;
dc->vportExtX = XExtent;
dc->vportExtY = YExtent;
if (dc->w.MapMode == MM_ISOTROPIC)
IntFixIsotropicMapping(dc);
} }
_SEH_HANDLE _SEH_HANDLE
{ {
@ -810,11 +816,7 @@ NtGdiSetViewportExtEx(HDC hDC,
} }
} }
dc->vportExtX = XExtent;
dc->vportExtY = YExtent;
if (dc->w.MapMode == MM_ISOTROPIC)
IntFixIsotropicMapping(dc);
DC_UpdateXforms(dc); DC_UpdateXforms(dc);
DC_UnlockDc(dc); DC_UnlockDc(dc);

View file

@ -1716,6 +1716,7 @@ NtGdiGetDeviceCaps(HDC hDC,
DC_GET_VAL( INT, NtGdiGetMapMode, w.MapMode ) DC_GET_VAL( INT, NtGdiGetMapMode, w.MapMode )
DC_GET_VAL( INT, NtGdiGetPolyFillMode, w.polyFillMode ) DC_GET_VAL( INT, NtGdiGetPolyFillMode, w.polyFillMode )
INT FASTCALL INT FASTCALL
IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer) IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer)
{ {
@ -1733,14 +1734,15 @@ IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer)
ObjectType = GDIOBJ_GetObjectType(Handle); ObjectType = GDIOBJ_GetObjectType(Handle);
switch (ObjectType) switch (ObjectType)
{ {
#if 0
case GDI_OBJECT_TYPE_PEN: case GDI_OBJECT_TYPE_PEN:
Result = PEN_GetObject((PENOBJ *) GdiObject, Count, Buffer); Result = PEN_GetObject((PGDIBRUSHOBJ) GdiObject, Count, (PLOGPEN) Buffer); // IntGdiCreatePenIndirect
break; break;
case GDI_OBJECT_TYPE_BRUSH: case GDI_OBJECT_TYPE_BRUSH:
Result = BRUSH_GetObject((BRUSHOBJ *) GdiObject, Count, Buffer); Result = BRUSH_GetObject((PGDIBRUSHOBJ ) GdiObject, Count, (LPLOGBRUSH)Buffer);
break; break;
#endif
case GDI_OBJECT_TYPE_BITMAP: case GDI_OBJECT_TYPE_BITMAP:
Result = BITMAP_GetObject((BITMAPOBJ *) GdiObject, Count, Buffer); Result = BITMAP_GetObject((BITMAPOBJ *) GdiObject, Count, Buffer);
break; break;
@ -1938,55 +1940,57 @@ NtGdiRestoreDC(HDC hDC, INT SaveLevel)
return FALSE; return FALSE;
} }
if (SaveLevel == -1) if(abs(SaveLevel) > dc->saveLevel || SaveLevel == 0)
SaveLevel = dc->saveLevel;
if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
{ {
DC_UnlockDc(dc); DC_UnlockDc(dc);
return FALSE; return FALSE;
} }
success = TRUE; /* FIXME this calc are not 100% correct I think ??*/
if (SaveLevel < 0) SaveLevel = dc->saveLevel + SaveLevel + 1;
success=TRUE;
while (dc->saveLevel >= SaveLevel) while (dc->saveLevel >= SaveLevel)
{ {
HDC hdcs = DC_GetNextDC (dc); HDC hdcs = DC_GetNextDC (dc);
dcs = DC_LockDc (hdcs); dcs = DC_LockDc (hdcs);
if (dcs == NULL) if (dcs == NULL)
{ {
DC_UnlockDc(dc); DC_UnlockDc(dc);
return FALSE; return FALSE;
} }
DC_SetNextDC (dcs, DC_GetNextDC (dcs));
if (--dc->saveLevel < SaveLevel) DC_SetNextDC (dc, DC_GetNextDC (dcs));
{ dcs->hNext = 0;
DC_UnlockDc( dc );
DC_UnlockDc( dcs ); if (--dc->saveLevel < SaveLevel)
NtGdiSetDCState(hDC, hdcs); {
#if 0 DC_UnlockDc( dc );
if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path )) DC_UnlockDc( dcs );
{
/* FIXME: This might not be quite right, since we're NtGdiSetDCState(hDC, hdcs);
* returning FALSE but still destroying the saved DC state */ //if (!PATH_AssignGdiPath( &dc->path, &dcs->path ))
success = FALSE; /* FIXME: This might not be quite right, since we're
} * returning FALSE but still destroying the saved DC state
#endif */
dc = DC_LockDc(hDC); success=FALSE;
if(!dc) dc = DC_LockDc(hDC);
{ if(!dc)
return FALSE; {
} return FALSE;
} }
else }
{ else
DC_UnlockDc( dcs ); {
} DC_UnlockDc( dcs );
NtGdiDeleteObjectApp (hdcs); }
NtGdiDeleteObjectApp (hdcs);
} }
DC_UnlockDc( dc ); DC_UnlockDc( dc );
return success; return success;
} }
INT STDCALL INT STDCALL
NtGdiSaveDC(HDC hDC) NtGdiSaveDC(HDC hDC)

View file

@ -793,7 +793,16 @@ HBITMAP STDCALL NtGdiCreateDIBitmap(HDC hDc, const BITMAPINFOHEADER *Header,
PDC Dc; PDC Dc;
HBITMAP Bmp; HBITMAP Bmp;
if (Header == NULL)
{
return NULL;
}
if (Header->biSize == 0)
{
return NULL;
}
if (NULL == hDc) if (NULL == hDc)
{ {
BITMAPINFOHEADER *change_Header = (BITMAPINFOHEADER *)Header; BITMAPINFOHEADER *change_Header = (BITMAPINFOHEADER *)Header;

View file

@ -37,21 +37,8 @@ NtGdiCloseEnhMetaFile(HDC hDC)
IO_STATUS_BLOCK Iosb; IO_STATUS_BLOCK Iosb;
NTSTATUS Status; NTSTATUS Status;
DPRINT1("NtGdiCloseEnhMetaFile\n");
/* Todo
Rewrite it to own api call IntGdiCloseEmhMetaFile
Translate follow api to kernel api
// hMapping = CreateFileMappingW(Dc->hFile, NULL, PAGE_READONLY, 0, 0, NULL);
// Dc->emh = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
// hmf = EMF_Create_HENHMETAFILE( Dc->emh, (Dc->hFile != 0) );
DC_SetOwnership(hdc,
*/
Dc = DC_LockDc(hDC); Dc = DC_LockDc(hDC);
if (Dc == NULL) if (Dc == NULL)
{ {
@ -121,34 +108,47 @@ NtGdiCloseEnhMetaFile(HDC hDC)
LARGE_INTEGER Distance ; LARGE_INTEGER Distance ;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
POBJECT_ATTRIBUTES ObjectAttributes = NULL;
ACCESS_MASK DesiredAccess;
PLARGE_INTEGER SectionSize = NULL;
DWORD flProtect;
ULONG Attributes;
LARGE_INTEGER SectionOffset;
ULONG ViewSize;
ULONG Protect;
LPVOID ViewBase;
Distance.u.LowPart = 0; Distance.u.LowPart = 0;
Distance.u.HighPart = 0; Distance.u.HighPart = 0;
FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart; FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
DPRINT1("Trying write to metafile and map it\n");
Status = NtSetInformationFile(Dc->hFile, &IoStatusBlock, &FilePosition, Status = NtSetInformationFile(Dc->hFile, &IoStatusBlock, &FilePosition,
sizeof(FILE_POSITION_INFORMATION), FilePositionInformation); sizeof(FILE_POSITION_INFORMATION), FilePositionInformation);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* FIXME */ // SetLastErrorByStatus(Status);
// SetLastErrorByStatus(errCode);
SetLastWin32Error(ERROR_INVALID_HANDLE); SetLastWin32Error(ERROR_INVALID_HANDLE);
NtClose( Dc->hFile ); NtClose( Dc->hFile );
DC_UnlockDc(Dc); DC_UnlockDc(Dc);
NtGdiDeleteObjectApp(hDC); NtGdiDeleteObjectApp(hDC);
DPRINT1("NtSetInformationFile fail\n");
return hmf; return hmf;
} }
if (FilePosition.CurrentByteOffset.u.LowPart != 0) if (FilePosition.CurrentByteOffset.u.LowPart != 0)
{ {
/* FIXME */ // SetLastErrorByStatus(Status);
// SetLastErrorByStatus(errCode);
SetLastWin32Error(ERROR_INVALID_HANDLE); SetLastWin32Error(ERROR_INVALID_HANDLE);
NtClose( Dc->hFile ); NtClose( Dc->hFile );
DC_UnlockDc(Dc); DC_UnlockDc(Dc);
NtGdiDeleteObjectApp(hDC); NtGdiDeleteObjectApp(hDC);
DPRINT1("FilePosition.CurrentByteOffset.u.LowPart is not 0\n");
return hmf; return hmf;
} }
@ -166,19 +166,68 @@ NtGdiCloseEnhMetaFile(HDC hDC)
{ {
NtClose( Dc->hFile ); NtClose( Dc->hFile );
DC_UnlockDc(Dc); DC_UnlockDc(Dc);
NtGdiDeleteObjectApp(hDC); NtGdiDeleteObjectApp(hDC);
DPRINT1("fail to write 0\n");
return hmf; return hmf;
} }
EngFreeMem(Dc->emh); EngFreeMem(Dc->emh);
/* FIXME */ /* create maping */
// hMapping = CreateFileMappingW(Dc->hFile, NULL, PAGE_READONLY, 0, 0, NULL); DesiredAccess = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
Attributes = (PAGE_READONLY & (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_NOCACHE | SEC_COMMIT));
/* FIXME */ flProtect = PAGE_READONLY ^ (PAGE_READONLY & (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_NOCACHE | SEC_COMMIT));
// Dc->emh = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
NtClose( hMapping ); if (!Attributes) Attributes = SEC_COMMIT;
NtClose( Dc->hFile );
if (Dc->hFile == INVALID_HANDLE_VALUE)
{
Dc->hFile = NULL;
if (!SectionSize)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
hMapping = NULL;
DPRINT1("fail !SectionSize \n");
}
}
else
{
Status = NtCreateSection(&hMapping, DesiredAccess, ObjectAttributes, SectionSize, flProtect, Attributes, Dc->hFile);
if (!NT_SUCCESS(Status))
{
//SetLastErrorByStatus(Status);
SetLastWin32Error(ERROR_INVALID_HANDLE);
hMapping = NULL;
DPRINT1("fail NtCreateSection \n");
}
}
/* MapViewOfFile */
SectionOffset.LowPart = 0;
SectionOffset.HighPart = 0;
ViewBase = NULL;
ViewSize = 0;
Protect = PAGE_READONLY;
Status = ZwMapViewOfSection(&hMapping, NtCurrentProcess(), &ViewBase, 0,
0, &SectionOffset, &ViewSize, ViewShare, 0, Protect);
if (!NT_SUCCESS(Status))
{
//SetLastErrorByStatus(Status);
SetLastWin32Error(ERROR_INVALID_HANDLE);
Dc->emh = NULL;
DPRINT1("fail ZwMapViewOfSection \n");
}
else
{
Dc->emh = ViewBase;
}
/* Close */
if (hMapping != NULL)
NtClose( hMapping );
if (Dc->hFile != NULL)
NtClose( Dc->hFile );
} }
hmf = GDIOBJ_AllocObj(GdiHandleTable, GDI_OBJECT_TYPE_ENHMETAFILE); hmf = GDIOBJ_AllocObj(GdiHandleTable, GDI_OBJECT_TYPE_ENHMETAFILE);

View file

@ -33,12 +33,12 @@ BOOL FASTCALL PATH_AddFlatBezier (GdiPath *pPath, POINT *pt, BOOL closed);
BOOL FASTCALL PATH_DoArcPart (GdiPath *pPath, FLOAT_POINT corners[], double angleStart, double angleEnd, BOOL addMoveTo); BOOL FASTCALL PATH_DoArcPart (GdiPath *pPath, FLOAT_POINT corners[], double angleStart, double angleEnd, BOOL addMoveTo);
BOOL FASTCALL PATH_FillPath( PDC dc, GdiPath *pPath ); BOOL FASTCALL PATH_FillPath( PDC dc, GdiPath *pPath );
BOOL FASTCALL PATH_FlattenPath (GdiPath *pPath); BOOL FASTCALL PATH_FlattenPath (GdiPath *pPath);
VOID FASTCALL PATH_GetPathFromDC (PDC dc, GdiPath **ppPath);
VOID FASTCALL PATH_NormalizePoint (FLOAT_POINT corners[], const FLOAT_POINT *pPoint, double *pX, double *pY); VOID FASTCALL PATH_NormalizePoint (FLOAT_POINT corners[], const FLOAT_POINT *pPoint, double *pX, double *pY);
BOOL FASTCALL PATH_PathToRegion (GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn); BOOL FASTCALL PATH_PathToRegion (GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn);
BOOL FASTCALL PATH_ReserveEntries (GdiPath *pPath, INT numEntries); BOOL FASTCALL PATH_ReserveEntries (GdiPath *pPath, INT numEntries);
VOID FASTCALL PATH_ScaleNormalizedPoint (FLOAT_POINT corners[], double x, double y, POINT *pPoint); VOID FASTCALL PATH_ScaleNormalizedPoint (FLOAT_POINT corners[], double x, double y, POINT *pPoint);
BOOL FASTCALL PATH_StrokePath(DC *dc, GdiPath *pPath);
BOOL PATH_CheckCorners(DC *dc, POINT corners[], INT x1, INT y1, INT x2, INT y2);
INT FASTCALL INT FASTCALL
IntGdiGetArcDirection(DC *dc); IntGdiGetArcDirection(DC *dc);
@ -51,16 +51,12 @@ BOOL
STDCALL STDCALL
NtGdiAbortPath(HDC hDC) NtGdiAbortPath(HDC hDC)
{ {
GdiPath *pPath;
BOOL ret = TRUE; BOOL ret = TRUE;
PDC dc = DC_LockDc ( hDC ); PDC dc = DC_LockDc ( hDC );
if( !dc ) return FALSE; if( !dc ) return FALSE;
/* Get pointer to path */ PATH_EmptyPath(&dc->w.path);
PATH_GetPathFromDC ( dc, &pPath );
PATH_EmptyPath( pPath );
DC_UnlockDc ( dc ); DC_UnlockDc ( dc );
return ret; return ret;
@ -70,24 +66,20 @@ BOOL
STDCALL STDCALL
NtGdiBeginPath( HDC hDC ) NtGdiBeginPath( HDC hDC )
{ {
GdiPath *pPath;
BOOL ret = TRUE; BOOL ret = TRUE;
PDC dc = DC_LockDc ( hDC ); PDC dc = DC_LockDc ( hDC );
if( !dc ) return FALSE; if( !dc ) return FALSE;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* If path is already open, do nothing */ /* If path is already open, do nothing */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
{ {
/* Make sure that path is empty */ /* Make sure that path is empty */
PATH_EmptyPath( pPath ); PATH_EmptyPath( &dc->w.path );
/* Initialize variables for new path */ /* Initialize variables for new path */
pPath->newStroke = TRUE; dc->w.path.newStroke = TRUE;
pPath->state = PATH_Open; dc->w.path.state = PATH_Open;
} }
DC_UnlockDc ( dc ); DC_UnlockDc ( dc );
@ -142,22 +134,18 @@ BOOL
STDCALL STDCALL
NtGdiEndPath(HDC hDC) NtGdiEndPath(HDC hDC)
{ {
GdiPath *pPath;
BOOL ret = TRUE; BOOL ret = TRUE;
PDC dc = DC_LockDc ( hDC ); PDC dc = DC_LockDc ( hDC );
if ( !dc ) return FALSE; if ( !dc ) return FALSE;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is currently being constructed */ /* Check that path is currently being constructed */
if( pPath->state != PATH_Open ) if( dc->w.path.state != PATH_Open )
{ {
ret = FALSE; ret = FALSE;
} }
/* Set flag to indicate that path is finished */ /* Set flag to indicate that path is finished */
else pPath->state = PATH_Closed; else dc->w.path.state = PATH_Closed;
DC_UnlockDc ( dc ); DC_UnlockDc ( dc );
return ret; return ret;
@ -167,21 +155,17 @@ BOOL
STDCALL STDCALL
NtGdiFillPath(HDC hDC) NtGdiFillPath(HDC hDC)
{ {
GdiPath *pPath;
BOOL ret = TRUE; BOOL ret = TRUE;
PDC dc = DC_LockDc ( hDC ); PDC dc = DC_LockDc ( hDC );
if ( !dc ) return FALSE; if ( !dc ) return FALSE;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
ret = PATH_FillPath( dc, pPath ); ret = PATH_FillPath( dc, &dc->w.path );
if( ret ) if( ret )
{ {
/* FIXME: Should the path be emptied even if conversion /* FIXME: Should the path be emptied even if conversion
failed? */ failed? */
PATH_EmptyPath( pPath ); PATH_EmptyPath( &dc->w.path );
} }
DC_UnlockDc ( dc ); DC_UnlockDc ( dc );
@ -259,8 +243,8 @@ NtGdiGetPath(
{ {
_SEH_TRY _SEH_TRY
{ {
RtlCopyMemory(Points, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed); memcpy(Points, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
RtlCopyMemory(Types, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed); memcpy(Types, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
/* Convert the points to logical coordinates */ /* Convert the points to logical coordinates */
IntDPtoLP(dc, Points, pPath->numEntriesUsed); IntDPtoLP(dc, Points, pPath->numEntriesUsed);
@ -323,18 +307,39 @@ NtGdiSetMiterLimit(
BOOL BOOL
STDCALL STDCALL
NtGdiStrokeAndFillPath(HDC hDC) NtGdiStrokeAndFillPath(HDC hDC)
{ {
UNIMPLEMENTED; DC *pDc;
return FALSE; BOOL bRet = FALSE;
DPRINT("Enter %s\n", __FUNCTION__);
if(!(pDc = DC_LockDc(hDC))) return FALSE;
bRet = PATH_FillPath(pDc, &pDc->w.path);
if(bRet) bRet = PATH_StrokePath(pDc, &pDc->w.path);
if(bRet) PATH_EmptyPath(&pDc->w.path);
DC_UnlockDc(pDc);
return bRet;
} }
BOOL BOOL
STDCALL STDCALL
NtGdiStrokePath(HDC hDC) NtGdiStrokePath(HDC hDC)
{ {
UNIMPLEMENTED; DC *pDc;
return FALSE; BOOL bRet = FALSE;
DPRINT("Enter %s\n", __FUNCTION__);
if(!(pDc = DC_LockDc(hDC))) return FALSE;
bRet = PATH_StrokePath(pDc, &pDc->w.path);
PATH_EmptyPath(&pDc->w.path);
DC_UnlockDc(pDc);
return bRet;
} }
BOOL BOOL
@ -348,30 +353,27 @@ NtGdiWidenPath(HDC hDC)
BOOL STDCALL NtGdiSelectClipPath(HDC hDC, BOOL STDCALL NtGdiSelectClipPath(HDC hDC,
int Mode) int Mode)
{ {
GdiPath *pPath;
HRGN hrgnPath; HRGN hrgnPath;
BOOL success = FALSE; BOOL success = FALSE;
PDC dc = DC_LockDc ( hDC ); PDC dc = DC_LockDc ( hDC );
if( !dc ) return FALSE; if( !dc ) return FALSE;
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is closed */ /* Check that path is closed */
if( pPath->state != PATH_Closed ) if( dc->w.path.state != PATH_Closed )
{ {
SetLastWin32Error(ERROR_CAN_NOT_COMPLETE); SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
return FALSE; return FALSE;
} }
/* Construct a region from the path */ /* Construct a region from the path */
else if( PATH_PathToRegion( pPath, dc->w.polyFillMode, &hrgnPath ) ) else if( PATH_PathToRegion( &dc->w.path, dc->w.polyFillMode, &hrgnPath ) )
{ {
success = IntGdiExtSelectClipRgn( dc, hrgnPath, Mode ) != ERROR; success = IntGdiExtSelectClipRgn( dc, hrgnPath, Mode ) != ERROR;
NtGdiDeleteObject( hrgnPath ); NtGdiDeleteObject( hrgnPath );
/* Empty the path */ /* Empty the path */
if( success ) if( success )
PATH_EmptyPath( pPath ); PATH_EmptyPath( &dc->w.path);
/* FIXME: Should this function delete the path even if it failed? */ /* FIXME: Should this function delete the path even if it failed? */
} }
@ -466,7 +468,7 @@ VOID
FASTCALL FASTCALL
PATH_InitGdiPath ( GdiPath *pPath ) PATH_InitGdiPath ( GdiPath *pPath )
{ {
assert(pPath!=NULL); ASSERT(pPath!=NULL);
pPath->state=PATH_Null; pPath->state=PATH_Null;
pPath->pPoints=NULL; pPath->pPoints=NULL;
@ -483,7 +485,7 @@ VOID
FASTCALL FASTCALL
PATH_DestroyGdiPath ( GdiPath *pPath ) PATH_DestroyGdiPath ( GdiPath *pPath )
{ {
assert(pPath!=NULL); ASSERT(pPath!=NULL);
ExFreePool(pPath->pPoints); ExFreePool(pPath->pPoints);
ExFreePool(pPath->pFlags); ExFreePool(pPath->pFlags);
@ -503,7 +505,7 @@ BOOL
FASTCALL FASTCALL
PATH_AssignGdiPath ( GdiPath *pPathDest, const GdiPath *pPathSrc ) PATH_AssignGdiPath ( GdiPath *pPathDest, const GdiPath *pPathSrc )
{ {
assert(pPathDest!=NULL && pPathSrc!=NULL); ASSERT(pPathDest!=NULL && pPathSrc!=NULL);
/* Make sure destination arrays are big enough */ /* Make sure destination arrays are big enough */
if ( !PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed) ) if ( !PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed) )
@ -532,18 +534,14 @@ BOOL
FASTCALL FASTCALL
PATH_MoveTo ( PDC dc ) PATH_MoveTo ( PDC dc )
{ {
GdiPath *pPath;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
/* FIXME: Do we have to call SetLastError? */ /* FIXME: Do we have to call SetLastError? */
return FALSE; return FALSE;
/* Start a new stroke */ /* Start a new stroke */
pPath->newStroke = TRUE; dc->w.path.newStroke = TRUE;
return TRUE; return TRUE;
} }
@ -559,14 +557,10 @@ BOOL
FASTCALL FASTCALL
PATH_LineTo ( PDC dc, INT x, INT y ) PATH_LineTo ( PDC dc, INT x, INT y )
{ {
GdiPath *pPath;
POINT point, pointCurPos; POINT point, pointCurPos;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
return FALSE; return FALSE;
/* Convert point to device coordinates */ /* Convert point to device coordinates */
@ -575,17 +569,17 @@ PATH_LineTo ( PDC dc, INT x, INT y )
CoordLPtoDP ( dc, &point ); CoordLPtoDP ( dc, &point );
/* Add a PT_MOVETO if necessary */ /* Add a PT_MOVETO if necessary */
if ( pPath->newStroke ) if ( dc->w.path.newStroke )
{ {
pPath->newStroke = FALSE; dc->w.path.newStroke = FALSE;
IntGetCurrentPositionEx ( dc, &pointCurPos ); IntGetCurrentPositionEx ( dc, &pointCurPos );
CoordLPtoDP ( dc, &pointCurPos ); CoordLPtoDP ( dc, &pointCurPos );
if ( !PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO) ) if ( !PATH_AddEntry(&dc->w.path, &pointCurPos, PT_MOVETO) )
return FALSE; return FALSE;
} }
/* Add a PT_LINETO entry */ /* Add a PT_LINETO entry */
return PATH_AddEntry(pPath, &point, PT_LINETO); return PATH_AddEntry(&dc->w.path, &point, PT_LINETO);
} }
/* PATH_Rectangle /* PATH_Rectangle
@ -597,15 +591,11 @@ BOOL
FASTCALL FASTCALL
PATH_Rectangle ( PDC dc, INT x1, INT y1, INT x2, INT y2 ) PATH_Rectangle ( PDC dc, INT x1, INT y1, INT x2, INT y2 )
{ {
GdiPath *pPath;
POINT corners[2], pointTemp; POINT corners[2], pointTemp;
INT temp; INT temp;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
return FALSE; return FALSE;
/* Convert points to device coordinates */ /* Convert points to device coordinates */
@ -642,15 +632,15 @@ PATH_Rectangle ( PDC dc, INT x1, INT y1, INT x2, INT y2 )
/* Add four points to the path */ /* Add four points to the path */
pointTemp.x=corners[1].x; pointTemp.x=corners[1].x;
pointTemp.y=corners[0].y; pointTemp.y=corners[0].y;
if ( !PATH_AddEntry(pPath, &pointTemp, PT_MOVETO) ) if ( !PATH_AddEntry(&dc->w.path, &pointTemp, PT_MOVETO) )
return FALSE; return FALSE;
if ( !PATH_AddEntry(pPath, corners, PT_LINETO) ) if ( !PATH_AddEntry(&dc->w.path, corners, PT_LINETO) )
return FALSE; return FALSE;
pointTemp.x=corners[0].x; pointTemp.x=corners[0].x;
pointTemp.y=corners[1].y; pointTemp.y=corners[1].y;
if ( !PATH_AddEntry(pPath, &pointTemp, PT_LINETO) ) if ( !PATH_AddEntry(&dc->w.path, &pointTemp, PT_LINETO) )
return FALSE; return FALSE;
if ( !PATH_AddEntry(pPath, corners+1, PT_LINETO) ) if ( !PATH_AddEntry(&dc->w.path, corners+1, PT_LINETO) )
return FALSE; return FALSE;
/* Close the rectangle figure */ /* Close the rectangle figure */
@ -659,12 +649,63 @@ PATH_Rectangle ( PDC dc, INT x1, INT y1, INT x2, INT y2 )
return TRUE; return TRUE;
} }
BOOL /* PATH_RoundRect
FASTCALL *
PATH_RoundRect (PDC dc, INT x1, INT y1, INT x2, INT y2, INT xradius, INT yradius) * Should be called when a call to RoundRect is performed on a DC that has
* an open path. Returns TRUE if successful, else FALSE.
*
* FIXME: it adds the same entries to the path as windows does, but there
* is an error in the bezier drawing code so that there are small pixel-size
* gaps when the resulting path is drawn by StrokePath()
*/
FASTCALL BOOL PATH_RoundRect(DC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height)
{ {
UNIMPLEMENTED; GdiPath *pPath = &dc->w.path;
return FALSE; POINT corners[2], pointTemp;
FLOAT_POINT ellCorners[2];
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
if(!PATH_CheckCorners(dc,corners,x1,y1,x2,y2))
return FALSE;
/* Add points to the roundrect path */
ellCorners[0].x = corners[1].x-ell_width;
ellCorners[0].y = corners[0].y;
ellCorners[1].x = corners[1].x;
ellCorners[1].y = corners[0].y+ell_height;
if(!PATH_DoArcPart(pPath, ellCorners, 0, -M_PI_2, TRUE))
return FALSE;
pointTemp.x = corners[0].x+ell_width/2;
pointTemp.y = corners[0].y;
if(!PATH_AddEntry(pPath, &pointTemp, PT_LINETO))
return FALSE;
ellCorners[0].x = corners[0].x;
ellCorners[1].x = corners[0].x+ell_width;
if(!PATH_DoArcPart(pPath, ellCorners, -M_PI_2, -M_PI, FALSE))
return FALSE;
pointTemp.x = corners[0].x;
pointTemp.y = corners[1].y-ell_height/2;
if(!PATH_AddEntry(pPath, &pointTemp, PT_LINETO))
return FALSE;
ellCorners[0].y = corners[1].y-ell_height;
ellCorners[1].y = corners[1].y;
if(!PATH_DoArcPart(pPath, ellCorners, M_PI, M_PI_2, FALSE))
return FALSE;
pointTemp.x = corners[1].x-ell_width/2;
pointTemp.y = corners[1].y;
if(!PATH_AddEntry(pPath, &pointTemp, PT_LINETO))
return FALSE;
ellCorners[0].x = corners[1].x-ell_width;
ellCorners[1].x = corners[1].x;
if(!PATH_DoArcPart(pPath, ellCorners, M_PI_2, 0, FALSE))
return FALSE;
IntGdiCloseFigure(dc);
return TRUE;
} }
/* PATH_Ellipse /* PATH_Ellipse
@ -693,7 +734,6 @@ FASTCALL
PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2, PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2,
INT xStart, INT yStart, INT xEnd, INT yEnd) INT xStart, INT yStart, INT xEnd, INT yEnd)
{ {
GdiPath *pPath;
double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0; double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0;
/* Initialize angleEndQuadrant to silence gcc's warning */ /* Initialize angleEndQuadrant to silence gcc's warning */
double x, y; double x, y;
@ -709,11 +749,8 @@ PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2,
clockwise = ( IntGdiGetArcDirection(dc) == AD_CLOCKWISE ); clockwise = ( IntGdiGetArcDirection(dc) == AD_CLOCKWISE );
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
return FALSE; return FALSE;
/* FIXME: Do we have to close the current figure? */ /* FIXME: Do we have to close the current figure? */
@ -763,7 +800,7 @@ PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2,
if ( angleEnd <= angleStart ) if ( angleEnd <= angleStart )
{ {
angleEnd+=2*M_PI; angleEnd+=2*M_PI;
assert(angleEnd>=angleStart); ASSERT(angleEnd>=angleStart);
} }
} }
else else
@ -771,7 +808,7 @@ PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2,
if(angleEnd>=angleStart) if(angleEnd>=angleStart)
{ {
angleEnd-=2*M_PI; angleEnd-=2*M_PI;
assert(angleEnd<=angleStart); ASSERT(angleEnd<=angleStart);
} }
} }
@ -817,7 +854,7 @@ PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2,
} }
/* Add the Bezier spline to the path */ /* Add the Bezier spline to the path */
PATH_DoArcPart ( pPath, corners, angleStartQuadrant, angleEndQuadrant, start ); PATH_DoArcPart ( &dc->w.path, corners, angleStartQuadrant, angleEndQuadrant, start );
start = FALSE; start = FALSE;
} while(!end); } while(!end);
@ -828,7 +865,6 @@ BOOL
FASTCALL FASTCALL
PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints ) PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{ {
GdiPath *pPath;
POINT pt; POINT pt;
ULONG i; ULONG i;
@ -836,19 +872,17 @@ PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints )
ASSERT ( pts ); ASSERT ( pts );
ASSERT ( cbPoints ); ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
return FALSE; return FALSE;
/* Add a PT_MOVETO if necessary */ /* Add a PT_MOVETO if necessary */
if ( pPath->newStroke ) if ( dc->w.path.newStroke )
{ {
pPath->newStroke=FALSE; dc->w.path.newStroke=FALSE;
IntGetCurrentPositionEx ( dc, &pt ); IntGetCurrentPositionEx ( dc, &pt );
CoordLPtoDP ( dc, &pt ); CoordLPtoDP ( dc, &pt );
if ( !PATH_AddEntry(pPath, &pt, PT_MOVETO) ) if ( !PATH_AddEntry(&dc->w.path, &pt, PT_MOVETO) )
return FALSE; return FALSE;
} }
@ -856,7 +890,7 @@ PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{ {
pt = pts[i]; pt = pts[i];
CoordLPtoDP ( dc, &pt ); CoordLPtoDP ( dc, &pt );
PATH_AddEntry(pPath, &pt, PT_BEZIERTO); PATH_AddEntry(&dc->w.path, &pt, PT_BEZIERTO);
} }
return TRUE; return TRUE;
} }
@ -865,7 +899,6 @@ BOOL
FASTCALL FASTCALL
PATH_PolyBezier ( PDC dc, const POINT *pts, DWORD cbPoints ) PATH_PolyBezier ( PDC dc, const POINT *pts, DWORD cbPoints )
{ {
GdiPath *pPath;
POINT pt; POINT pt;
ULONG i; ULONG i;
@ -873,17 +906,15 @@ PATH_PolyBezier ( PDC dc, const POINT *pts, DWORD cbPoints )
ASSERT ( pts ); ASSERT ( pts );
ASSERT ( cbPoints ); ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
return FALSE; return FALSE;
for ( i = 0; i < cbPoints; i++ ) for ( i = 0; i < cbPoints; i++ )
{ {
pt = pts[i]; pt = pts[i];
CoordLPtoDP ( dc, &pt ); CoordLPtoDP ( dc, &pt );
PATH_AddEntry ( pPath, &pt, (i == 0) ? PT_MOVETO : PT_BEZIERTO ); PATH_AddEntry ( &dc->w.path, &pt, (i == 0) ? PT_MOVETO : PT_BEZIERTO );
} }
return TRUE; return TRUE;
@ -893,7 +924,6 @@ BOOL
FASTCALL FASTCALL
PATH_Polyline ( PDC dc, const POINT *pts, DWORD cbPoints ) PATH_Polyline ( PDC dc, const POINT *pts, DWORD cbPoints )
{ {
GdiPath *pPath;
POINT pt; POINT pt;
ULONG i; ULONG i;
@ -901,17 +931,15 @@ PATH_Polyline ( PDC dc, const POINT *pts, DWORD cbPoints )
ASSERT ( pts ); ASSERT ( pts );
ASSERT ( cbPoints ); ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
return FALSE; return FALSE;
for ( i = 0; i < cbPoints; i++ ) for ( i = 0; i < cbPoints; i++ )
{ {
pt = pts[i]; pt = pts[i];
CoordLPtoDP ( dc, &pt ); CoordLPtoDP ( dc, &pt );
PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PT_LINETO); PATH_AddEntry(&dc->w.path, &pt, (i == 0) ? PT_MOVETO : PT_LINETO);
} }
return TRUE; return TRUE;
} }
@ -920,7 +948,6 @@ BOOL
FASTCALL FASTCALL
PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints ) PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{ {
GdiPath *pPath;
POINT pt; POINT pt;
ULONG i; ULONG i;
@ -928,19 +955,17 @@ PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints )
ASSERT ( pts ); ASSERT ( pts );
ASSERT ( cbPoints ); ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
return FALSE; return FALSE;
/* Add a PT_MOVETO if necessary */ /* Add a PT_MOVETO if necessary */
if ( pPath->newStroke ) if ( dc->w.path.newStroke )
{ {
pPath->newStroke = FALSE; dc->w.path.newStroke = FALSE;
IntGetCurrentPositionEx ( dc, &pt ); IntGetCurrentPositionEx ( dc, &pt );
CoordLPtoDP ( dc, &pt ); CoordLPtoDP ( dc, &pt );
if ( !PATH_AddEntry(pPath, &pt, PT_MOVETO) ) if ( !PATH_AddEntry(&dc->w.path, &pt, PT_MOVETO) )
return FALSE; return FALSE;
} }
@ -948,7 +973,7 @@ PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{ {
pt = pts[i]; pt = pts[i];
CoordLPtoDP ( dc, &pt ); CoordLPtoDP ( dc, &pt );
PATH_AddEntry(pPath, &pt, PT_LINETO); PATH_AddEntry(&dc->w.path, &pt, PT_LINETO);
} }
return TRUE; return TRUE;
@ -959,24 +984,21 @@ BOOL
FASTCALL FASTCALL
PATH_Polygon ( PDC dc, const POINT *pts, DWORD cbPoints ) PATH_Polygon ( PDC dc, const POINT *pts, DWORD cbPoints )
{ {
GdiPath *pPath;
POINT pt; POINT pt;
ULONG i; ULONG i;
ASSERT ( dc ); ASSERT ( dc );
ASSERT ( pts ); ASSERT ( pts );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
return FALSE; return FALSE;
for(i = 0; i < cbPoints; i++) for(i = 0; i < cbPoints; i++)
{ {
pt = pts[i]; pt = pts[i];
CoordLPtoDP ( dc, &pt ); CoordLPtoDP ( dc, &pt );
PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PATH_AddEntry(&dc->w.path, &pt, (i == 0) ? PT_MOVETO :
((i == cbPoints-1) ? PT_LINETO | PT_CLOSEFIGURE : ((i == cbPoints-1) ? PT_LINETO | PT_CLOSEFIGURE :
PT_LINETO)); PT_LINETO));
} }
@ -987,7 +1009,6 @@ BOOL
FASTCALL FASTCALL
PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons ) PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons )
{ {
GdiPath *pPath;
POINT pt, startpt; POINT pt, startpt;
ULONG poly, point, i; ULONG poly, point, i;
@ -996,10 +1017,8 @@ PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons )
ASSERT ( counts ); ASSERT ( counts );
ASSERT ( polygons ); ASSERT ( polygons );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ); if ( dc->w.path.state != PATH_Open );
return FALSE; return FALSE;
for(i = 0, poly = 0; poly < polygons; poly++) for(i = 0, poly = 0; poly < polygons; poly++)
@ -1009,10 +1028,10 @@ PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons )
pt = pts[i]; pt = pts[i];
CoordLPtoDP ( dc, &pt ); CoordLPtoDP ( dc, &pt );
if(point == 0) startpt = pt; if(point == 0) startpt = pt;
PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO); PATH_AddEntry(&dc->w.path, &pt, (point == 0) ? PT_MOVETO : PT_LINETO);
} }
/* win98 adds an extra line to close the figure for some reason */ /* win98 adds an extra line to close the figure for some reason */
PATH_AddEntry(pPath, &startpt, PT_LINETO | PT_CLOSEFIGURE); PATH_AddEntry(&dc->w.path, &startpt, PT_LINETO | PT_CLOSEFIGURE);
} }
return TRUE; return TRUE;
} }
@ -1021,7 +1040,6 @@ BOOL
FASTCALL FASTCALL
PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylines ) PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylines )
{ {
GdiPath *pPath;
POINT pt; POINT pt;
ULONG poly, point, i; ULONG poly, point, i;
@ -1030,10 +1048,8 @@ PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylin
ASSERT ( counts ); ASSERT ( counts );
ASSERT ( polylines ); ASSERT ( polylines );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */ /* Check that path is open */
if ( pPath->state != PATH_Open ) if ( dc->w.path.state != PATH_Open )
return FALSE; return FALSE;
for(i = 0, poly = 0; poly < polylines; poly++) for(i = 0, poly = 0; poly < polylines; poly++)
@ -1042,7 +1058,7 @@ PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylin
{ {
pt = pts[i]; pt = pts[i];
CoordLPtoDP ( dc, &pt ); CoordLPtoDP ( dc, &pt );
PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO); PATH_AddEntry(&dc->w.path, &pt, (point == 0) ? PT_MOVETO : PT_LINETO);
} }
} }
return TRUE; return TRUE;
@ -1052,6 +1068,46 @@ PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylin
* Internal functions * Internal functions
*/ */
/* PATH_CheckCorners
*
* Helper function for PATH_RoundRect() and PATH_Rectangle()
*/
BOOL PATH_CheckCorners(DC *dc, POINT corners[], INT x1, INT y1, INT x2, INT y2)
{
INT temp;
/* Convert points to device coordinates */
corners[0].x=x1;
corners[0].y=y1;
corners[1].x=x2;
corners[1].y=y2;
CoordLPtoDP(dc, &corners[0]);
CoordLPtoDP(dc, &corners[1]);
/* Make sure first corner is top left and second corner is bottom right */
if(corners[0].x>corners[1].x)
{
temp=corners[0].x;
corners[0].x=corners[1].x;
corners[1].x=temp;
}
if(corners[0].y>corners[1].y)
{
temp=corners[0].y;
corners[0].y=corners[1].y;
corners[1].y=temp;
}
/* In GM_COMPATIBLE, don't include bottom and right edges */
if(dc->w.GraphicsMode==GM_COMPATIBLE)
{
corners[1].x--;
corners[1].y--;
}
return TRUE;
}
/* PATH_AddFlatBezier /* PATH_AddFlatBezier
* *
@ -1085,7 +1141,7 @@ PATH_FlattenPath(GdiPath *pPath)
GdiPath newPath; GdiPath newPath;
INT srcpt; INT srcpt;
memset(&newPath, 0, sizeof(newPath)); RtlZeroMemory(&newPath, sizeof(newPath));
newPath.state = PATH_Open; newPath.state = PATH_Open;
for(srcpt = 0; srcpt < pPath->numEntriesUsed; srcpt++) { for(srcpt = 0; srcpt < pPath->numEntriesUsed; srcpt++) {
switch(pPath->pFlags[srcpt] & ~PT_CLOSEFIGURE) { switch(pPath->pFlags[srcpt] & ~PT_CLOSEFIGURE) {
@ -1123,8 +1179,8 @@ PATH_PathToRegion ( GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn )
INT *pNumPointsInStroke; INT *pNumPointsInStroke;
HRGN hrgn = 0; HRGN hrgn = 0;
assert ( pPath!=NULL ); ASSERT(pPath!=NULL);
assert ( pHrgn!=NULL ); ASSERT(pHrgn!=NULL);
PATH_FlattenPath ( pPath ); PATH_FlattenPath ( pPath );
@ -1184,7 +1240,7 @@ VOID
FASTCALL FASTCALL
PATH_EmptyPath ( GdiPath *pPath ) PATH_EmptyPath ( GdiPath *pPath )
{ {
assert(pPath!=NULL); ASSERT(pPath!=NULL);
pPath->state=PATH_Null; pPath->state=PATH_Null;
pPath->numEntriesUsed=0; pPath->numEntriesUsed=0;
@ -1200,7 +1256,7 @@ BOOL
FASTCALL FASTCALL
PATH_AddEntry ( GdiPath *pPath, const POINT *pPoint, BYTE flags ) PATH_AddEntry ( GdiPath *pPath, const POINT *pPoint, BYTE flags )
{ {
assert(pPath!=NULL); ASSERT(pPath!=NULL);
/* FIXME: If newStroke is true, perhaps we want to check that we're /* FIXME: If newStroke is true, perhaps we want to check that we're
* getting a PT_MOVETO * getting a PT_MOVETO
@ -1242,8 +1298,8 @@ PATH_ReserveEntries ( GdiPath *pPath, INT numEntries )
POINT *pPointsNew; POINT *pPointsNew;
BYTE *pFlagsNew; BYTE *pFlagsNew;
assert(pPath!=NULL); ASSERT(pPath!=NULL);
assert(numEntries>=0); ASSERT(numEntries>=0);
/* Do we have to allocate more memory? */ /* Do we have to allocate more memory? */
if(numEntries > pPath->numEntriesAllocated) if(numEntries > pPath->numEntriesAllocated)
@ -1273,7 +1329,7 @@ PATH_ReserveEntries ( GdiPath *pPath, INT numEntries )
/* Copy old arrays to new arrays and discard old arrays */ /* Copy old arrays to new arrays and discard old arrays */
if(pPath->pPoints) if(pPath->pPoints)
{ {
assert(pPath->pFlags); ASSERT(pPath->pFlags);
memcpy(pPointsNew, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed); memcpy(pPointsNew, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
memcpy(pFlagsNew, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed); memcpy(pFlagsNew, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
@ -1289,20 +1345,6 @@ PATH_ReserveEntries ( GdiPath *pPath, INT numEntries )
return TRUE; return TRUE;
} }
/* PATH_GetPathFromDC
*
* Retrieves a pointer to the GdiPath structure contained in an HDC and
* places it in *ppPath. TRUE is returned if successful, FALSE otherwise.
*/
VOID
FASTCALL
PATH_GetPathFromDC ( PDC dc, GdiPath **ppPath )
{
ASSERT ( dc );
ASSERT ( ppPath );
*ppPath = &dc->w.path;
}
/* PATH_DoArcPart /* PATH_DoArcPart
* *
* Creates a Bezier spline that corresponds to part of an arc and appends the * Creates a Bezier spline that corresponds to part of an arc and appends the
@ -1322,7 +1364,7 @@ PATH_DoArcPart ( GdiPath *pPath, FLOAT_POINT corners[],
POINT point; POINT point;
int i; int i;
assert(fabs(angleEnd-angleStart)<=M_PI_2); ASSERT(fabs(angleEnd-angleStart)<=M_PI_2);
/* FIXME: Is there an easier way of computing this? */ /* FIXME: Is there an easier way of computing this? */
@ -1401,4 +1443,176 @@ PATH_NormalizePoint ( FLOAT_POINT corners[],
*pX=(double)(pPoint->x-corners[0].x)/(double)(corners[1].x-corners[0].x) * 2.0 - 1.0; *pX=(double)(pPoint->x-corners[0].x)/(double)(corners[1].x-corners[0].x) * 2.0 - 1.0;
*pY=(double)(pPoint->y-corners[0].y)/(double)(corners[1].y-corners[0].y) * 2.0 - 1.0; *pY=(double)(pPoint->y-corners[0].y)/(double)(corners[1].y-corners[0].y) * 2.0 - 1.0;
} }
BOOL FASTCALL PATH_StrokePath(DC *dc, GdiPath *pPath)
{
BOOL ret = FALSE;
INT i=0;
INT nLinePts, nAlloc;
POINT *pLinePts = NULL;
POINT ptViewportOrg, ptWindowOrg;
SIZE szViewportExt, szWindowExt;
DWORD mapMode, graphicsMode;
XFORM xform;
DPRINT("Enter %s\n", __FUNCTION__);
if(pPath->state != PATH_Closed)
return FALSE;
/* Save the mapping mode info */
mapMode=dc->w.MapMode;
IntGetViewportExtEx(dc, &szViewportExt);
IntGetViewportOrgEx(dc, &ptViewportOrg);
IntGetWindowExtEx(dc, &szWindowExt);
IntGetWindowOrgEx(dc, &ptWindowOrg);
xform = dc->w.xformWorld2Wnd;
/* Set MM_TEXT */
dc->w.MapMode = MM_TEXT;
dc->vportOrgX = 0;
dc->vportOrgY = 0;
dc->wndOrgX = 0;
dc->wndOrgY = 0;
graphicsMode = dc->w.GraphicsMode;
dc->w.GraphicsMode = GM_ADVANCED;
IntGdiModifyWorldTransform(dc, &xform, MWT_IDENTITY);
dc->w.GraphicsMode = graphicsMode;
/* Allocate enough memory for the worst case without beziers (one PT_MOVETO
* and the rest PT_LINETO with PT_CLOSEFIGURE at the end) plus some buffer
* space in case we get one to keep the number of reallocations small. */
nAlloc = pPath->numEntriesUsed + 1 + 300;
pLinePts = ExAllocatePoolWithTag(PagedPool, nAlloc * sizeof(POINT), TAG_PATH);
if(!pLinePts)
{
DPRINT1("Can't allocate pool!\n");
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
goto end;
}
nLinePts = 0;
for(i = 0; i < pPath->numEntriesUsed; i++)
{
if((i == 0 || (pPath->pFlags[i-1] & PT_CLOSEFIGURE))
&& (pPath->pFlags[i] != PT_MOVETO))
{
DPRINT1("Expected PT_MOVETO %s, got path flag %d\n",
i == 0 ? "as first point" : "after PT_CLOSEFIGURE",
(INT)pPath->pFlags[i]);
goto end;
}
switch(pPath->pFlags[i])
{
case PT_MOVETO:
DPRINT("Got PT_MOVETO (%ld, %ld)\n",
pPath->pPoints[i].x, pPath->pPoints[i].y);
if(nLinePts >= 2) IntGdiPolyline(dc, pLinePts, nLinePts);
nLinePts = 0;
pLinePts[nLinePts++] = pPath->pPoints[i];
break;
case PT_LINETO:
case (PT_LINETO | PT_CLOSEFIGURE):
DPRINT("Got PT_LINETO (%ld, %ld)\n",
pPath->pPoints[i].x, pPath->pPoints[i].y);
pLinePts[nLinePts++] = pPath->pPoints[i];
break;
case PT_BEZIERTO:
DPRINT("Got PT_BEZIERTO\n");
if(pPath->pFlags[i+1] != PT_BEZIERTO ||
(pPath->pFlags[i+2] & ~PT_CLOSEFIGURE) != PT_BEZIERTO)
{
DPRINT1("Path didn't contain 3 successive PT_BEZIERTOs\n");
ret = FALSE;
goto end;
}
else
{
INT nBzrPts, nMinAlloc;
POINT *pBzrPts = GDI_Bezier(&pPath->pPoints[i-1], 4, &nBzrPts);
/* Make sure we have allocated enough memory for the lines of
* this bezier and the rest of the path, assuming we won't get
* another one (since we won't reallocate again then). */
nMinAlloc = nLinePts + (pPath->numEntriesUsed - i) + nBzrPts;
if(nAlloc < nMinAlloc)
{
// Reallocate memory
POINT *Realloc = NULL;
nAlloc = nMinAlloc * 2;
Realloc = ExAllocatePoolWithTag(PagedPool,
nAlloc * sizeof(POINT),
TAG_PATH);
if(!Realloc)
{
DPRINT1("Can't allocate pool!\n");
goto end;
}
memcpy(Realloc, pLinePts, nLinePts*sizeof(POINT));
ExFreePool(pLinePts);
pLinePts = Realloc;
}
memcpy(&pLinePts[nLinePts], &pBzrPts[1], (nBzrPts - 1) * sizeof(POINT));
nLinePts += nBzrPts - 1;
ExFreePool(pBzrPts);
i += 2;
}
break;
default:
DPRINT1("Got path flag %d (not supported)\n", (INT)pPath->pFlags[i]);
goto end;
}
if(pPath->pFlags[i] & PT_CLOSEFIGURE)
{
pLinePts[nLinePts++] = pLinePts[0];
}
}//for
if(nLinePts >= 2)
IntGdiPolyline(dc, pLinePts, nLinePts);
ret = TRUE;
end:
if(pLinePts)ExFreePool(pLinePts);
/* Restore the old mapping mode */
dc->w.MapMode = mapMode;
dc->wndExtX = szWindowExt.cx;
dc->wndExtY = szWindowExt.cy;
dc->wndOrgX = ptWindowOrg.x;
dc->wndOrgY = ptWindowOrg.y;
dc->vportExtX = szViewportExt.cx;
dc->vportExtY = szViewportExt.cy;
dc->vportOrgX = ptViewportOrg.x;
dc->vportOrgY = ptViewportOrg.y;
/* Restore the world transform */
dc->w.xformWorld2Wnd = xform;
/* If we've moved the current point then get its new position
which will be in device (MM_TEXT) co-ords, convert it to
logical co-ords and re-set it. This basically updates
dc->CurPosX|Y so that their values are in the correct mapping
mode.
*/
if(i > 0)
{
POINT pt;
IntGetCurrentPositionEx(dc, &pt);
IntDPtoLP(dc, &pt, 1);
IntGdiMoveToEx(dc, pt.x, pt.y, NULL);
}
DPRINT("Leave %s, ret=%d\n", __FUNCTION__, ret);
return ret;
}
/* EOF */ /* EOF */

View file

@ -84,7 +84,7 @@ IntGdiCreatePenIndirect(PLOGPEN LogPen)
break; break;
default: default:
DPRINT1("FIXME: IntGdiCreatePenIndirect is UNIMPLEMENTED\n"); DPRINT1("FIXME: IntGdiCreatePenIndirect is UNIMPLEMENTED pen %x\n",LogPen->lopnStyle);
} }
PENOBJ_UnlockPen(PenObject); PENOBJ_UnlockPen(PenObject);
@ -92,6 +92,23 @@ IntGdiCreatePenIndirect(PLOGPEN LogPen)
return hPen; return hPen;
} }
INT STDCALL
PEN_GetObject(PGDIBRUSHOBJ PenObject, INT Count, PLOGPEN Buffer)
{
LOGPEN LogPen;
if( Buffer == NULL ) return sizeof(LOGPEN);
LogPen.lopnWidth = PenObject->ptPenWidth;
LogPen.lopnStyle = PenObject->ulPenStyle;
LogPen.lopnColor = PenObject->BrushAttr.lbColor;
memcpy(Buffer, &LogPen, Count);
return Count;
}
/* PUBLIC FUNCTIONS ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
HPEN STDCALL HPEN STDCALL

View file

@ -3917,13 +3917,16 @@ TextIntRealizeFont(HFONT FontHandle)
INT FASTCALL INT FASTCALL
FontGetObject(PTEXTOBJ Font, INT Count, PVOID Buffer) FontGetObject(PTEXTOBJ Font, INT Count, PVOID Buffer)
{ {
if (Count < sizeof(LOGFONTW)) if (Buffer)
{ {
SetLastWin32Error(ERROR_BUFFER_OVERFLOW); if (Count < sizeof(LOGFONTW))
return 0; {
} SetLastWin32Error(ERROR_BUFFER_OVERFLOW);
return 0;
}
RtlCopyMemory(Buffer, &Font->logfont, sizeof(LOGFONTW)); RtlCopyMemory(Buffer, &Font->logfont, sizeof(LOGFONTW));
}
return sizeof(LOGFONTW); return sizeof(LOGFONTW);
} }