mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
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:
commit
550317611d
27 changed files with 3696 additions and 532 deletions
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
0
reactos/regtests/winetests/gdi/.gitignore
vendored
0
reactos/regtests/winetests/gdi/.gitignore
vendored
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||||
|
|
125
reactos/regtests/winetests/gdi32/clipping.c
Normal file
125
reactos/regtests/winetests/gdi32/clipping.c
Normal 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();
|
||||||
|
}
|
180
reactos/regtests/winetests/gdi32/dc.c
Normal file
180
reactos/regtests/winetests/gdi32/dc.c
Normal 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();
|
||||||
|
}
|
441
reactos/regtests/winetests/gdi32/font.c
Normal file
441
reactos/regtests/winetests/gdi32/font.c
Normal 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();
|
||||||
|
}
|
|
@ -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>
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
160
reactos/regtests/winetests/gdi32/mapping.c
Normal file
160
reactos/regtests/winetests/gdi32/mapping.c
Normal 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
126
reactos/regtests/winetests/gdi32/palette.c
Normal file
126
reactos/regtests/winetests/gdi32/palette.c
Normal 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();
|
||||||
|
}
|
|
@ -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 }
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue