Sync win32k and gdi32_winetest from trunk.

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

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU Lesser General Public
* 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>
@ -56,7 +56,7 @@ static void test_solidbrush(void)
}
else
stockBrush = NULL;
memset(&br, sizeof(br), 0);
memset(&br, 0, sizeof(br));
ret = GetObject(solidBrush, sizeof(br), &br);
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);

View file

@ -0,0 +1,125 @@
/*
* Unit test suite for clipping
*
* Copyright 2005 Huw Davies
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/test.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
static void test_GetRandomRgn(void)
{
HWND hwnd = CreateWindowExA(0,"BUTTON","test",WS_VISIBLE|WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0);
HDC hdc;
HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
int ret;
RECT rc, rc2;
RECT ret_rc, window_rc;
ok( hwnd != 0, "CreateWindow failed\n" );
SetRect(&window_rc, 400, 300, 500, 400);
MoveWindow(hwnd, window_rc.left, window_rc.top, window_rc.right - window_rc.left, window_rc.bottom - window_rc.top, FALSE);
hdc = GetDC(hwnd);
ret = GetRandomRgn(hdc, hrgn, 1);
ok(ret == 0, "GetRandomRgn rets %d\n", ret);
ret = GetRandomRgn(hdc, hrgn, 2);
ok(ret == 0, "GetRandomRgn rets %d\n", ret);
ret = GetRandomRgn(hdc, hrgn, 3);
ok(ret == 0, "GetRandomRgn rets %d\n", ret);
/* Set a clip region */
SetRect(&rc, 20, 20, 80, 80);
IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
ret = GetRandomRgn(hdc, hrgn, 1);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
ret = GetRandomRgn(hdc, hrgn, 2);
ok(ret == 0, "GetRandomRgn rets %d\n", ret);
ret = GetRandomRgn(hdc, hrgn, 3);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
/* Move the clip to the meta and clear the clip */
SetMetaRgn(hdc);
ret = GetRandomRgn(hdc, hrgn, 1);
ok(ret == 0, "GetRandomRgn rets %d\n", ret);
ret = GetRandomRgn(hdc, hrgn, 2);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
ret = GetRandomRgn(hdc, hrgn, 3);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
/* Set a new clip (still got the meta) */
SetRect(&rc2, 10, 30, 70, 90);
IntersectClipRect(hdc, rc2.left, rc2.top, rc2.right, rc2.bottom);
ret = GetRandomRgn(hdc, hrgn, 1);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc2, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
ret = GetRandomRgn(hdc, hrgn, 2);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
IntersectRect(&rc2, &rc, &rc2);
ret = GetRandomRgn(hdc, hrgn, 3);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
ok(EqualRect(&rc2, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
ret = GetRandomRgn(hdc, hrgn, SYSRGN);
ok(ret != 0, "GetRandomRgn rets %d\n", ret);
GetRgnBox(hrgn, &ret_rc);
if(GetVersion() & 0x80000000)
OffsetRect(&window_rc, -window_rc.left, -window_rc.top);
ok(EqualRect(&window_rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
DeleteObject(hrgn);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
}
START_TEST(clipping)
{
test_GetRandomRgn();
}

View file

@ -0,0 +1,180 @@
/*
* Unit tests for dc functions
*
* Copyright (c) 2005 Huw Davies
* Copyright (c) 2005 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdio.h>
#include "wine/test.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
static void dump_region(HRGN hrgn)
{
DWORD i, size;
RGNDATA *data = NULL;
RECT *rect;
if (!hrgn)
{
printf( "(null) region\n" );
return;
}
if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
GetRegionData( hrgn, size, data );
printf( "%ld rects:", data->rdh.nCount );
for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom );
printf( "\n" );
HeapFree( GetProcessHeap(), 0, data );
}
static void test_savedc_2(void)
{
HWND hwnd;
HDC hdc;
HRGN hrgn;
RECT rc, rc_clip;
int ret;
hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
0, 0, 0, NULL);
assert(hwnd != 0);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
hrgn = CreateRectRgn(0, 0, 0, 0);
assert(hrgn != 0);
hdc = GetDC(hwnd);
ok(hdc != NULL, "CreateDC rets %p\n", hdc);
ret = GetClipBox(hdc, &rc_clip);
ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
ret = GetClipRgn(hdc, hrgn);
ok(ret == 0, "GetClipRgn returned %d instead of 0\n", ret);
ret = GetRgnBox(hrgn, &rc);
ok(ret == NULLREGION, "GetRgnBox returned %d (%ld,%ld-%ld,%ld) instead of NULLREGION\n",
ret, rc.left, rc.top, rc.right, rc.bottom);
/*dump_region(hrgn);*/
SetRect(&rc, 0, 0, 100, 100);
ok(EqualRect(&rc, &rc_clip),
"rects are not equal: (%ld,%ld-%ld,%ld) - (%ld,%ld-%ld,%ld)\n",
rc.left, rc.top, rc.right, rc.bottom,
rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
ret = SaveDC(hdc);
todo_wine
{
ok(ret == 1, "ret = %d\n", ret);
}
ret = IntersectClipRect(hdc, 0, 0, 50, 50);
#if 0 /* XP returns COMPLEXREGION although dump_region reports only 1 rect */
ok(ret == SIMPLEREGION, "IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
#endif
if (ret != SIMPLEREGION)
{
trace("Windows BUG: IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
/* let's make sure that it's a simple region */
ret = GetClipRgn(hdc, hrgn);
ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret);
dump_region(hrgn);
}
ret = GetClipBox(hdc, &rc_clip);
ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
SetRect(&rc, 0, 0, 50, 50);
ok(EqualRect(&rc, &rc_clip), "rects are not equal\n");
ret = RestoreDC(hdc, 1);
ok(ret, "ret = %d\n", ret);
ret = GetClipBox(hdc, &rc_clip);
ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
SetRect(&rc, 0, 0, 100, 100);
ok(EqualRect(&rc, &rc_clip), "rects are not equal\n");
DeleteObject(hrgn);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
}
static void test_savedc(void)
{
HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
int ret;
ok(hdc != NULL, "CreateDC rets %p\n", hdc);
ret = SaveDC(hdc);
ok(ret == 1, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 2, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 3, "ret = %d\n", ret);
ret = RestoreDC(hdc, -1);
ok(ret, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 3, "ret = %d\n", ret);
ret = RestoreDC(hdc, 1);
ok(ret, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 1, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 2, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 3, "ret = %d\n", ret);
ret = RestoreDC(hdc, -2);
ok(ret, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 2, "ret = %d\n", ret);
ret = RestoreDC(hdc, -2);
ok(ret, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 1, "ret = %d\n", ret);
ret = SaveDC(hdc);
ok(ret == 2, "ret = %d\n", ret);
ret = RestoreDC(hdc, -4);
ok(!ret, "ret = %d\n", ret);
ret = RestoreDC(hdc, 3);
ok(!ret, "ret = %d\n", ret);
/* Under win98 the following two succeed and both clear the save stack
ret = RestoreDC(hdc, -3);
ok(!ret, "ret = %d\n", ret);
ret = RestoreDC(hdc, 0);
ok(!ret, "ret = %d\n", ret);
*/
ret = RestoreDC(hdc, 1);
ok(ret, "ret = %d\n", ret);
DeleteDC(hdc);
}
START_TEST(dc)
{
test_savedc();
test_savedc_2();
}

View file

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

View file

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

View file

@ -16,10 +16,11 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
@ -28,175 +29,6 @@
#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)
{
BYTE buff[256];
@ -266,70 +98,177 @@ static void test_gdi_objects(void)
ReleaseDC(NULL, hdc);
}
static void test_GdiGetCharDimensions(void)
struct hgdiobj_event
{
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;
HGDIOBJ hgdiobj1;
HGDIOBJ hgdiobj2;
HANDLE stop_event;
HANDLE ready_event;
};
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);
avgwidth = ((size.cx / 26) + 1) / 2;
hgdiobj_event->hdc = CreateDC("display", NULL, NULL, NULL);
ok(hgdiobj_event->hdc != NULL, "CreateDC error %ld\n", GetLastError());
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);
hgdiobj_event->hgdiobj1 = CreatePen(PS_DASHDOTDOT, 17, RGB(1, 2, 3));
ok(hgdiobj_event->hgdiobj1 != 0, "Failed to create pen\n");
ret = GdiGetCharDimensions(hdc, &tm, NULL);
ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
hgdiobj_event->hgdiobj2 = CreateRectRgn(0, 1, 12, 17);
ok(hgdiobj_event->hgdiobj2 != 0, "Failed to create pen\n");
ret = GdiGetCharDimensions(hdc, NULL, NULL);
ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
SetEvent(hgdiobj_event->ready_event);
ok(WaitForSingleObject(hgdiobj_event->stop_event, INFINITE) == WAIT_OBJECT_0,
"WaitForSingleObject error %ld\n", GetLastError());
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);
ok(!GetObject(hgdiobj_event->hgdiobj1, sizeof(lp), &lp), "GetObject should fail\n");
ok(!GetDeviceCaps(hgdiobj_event->hdc, TECHNOLOGY), "GetDeviceCaps(TECHNOLOGY) should fail\n");
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);
}
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)
{
test_logfont();
test_bitmap_font();
test_gdi_objects();
test_GdiGetCharDimensions();
test_text_extents();
test_thread_objects();
test_GetCurrentObject();
}

View file

@ -0,0 +1,160 @@
/*
* Unit tests for mapping functions
*
* Copyright (c) 2005 Huw Davies
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdio.h>
#include <math.h>
#include "wine/test.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
void test_modify_world_transform(void)
{
HDC hdc = GetDC(0);
int ret;
ret = SetGraphicsMode(hdc, GM_ADVANCED);
if(!ret) /* running in win9x so quit */
{
ReleaseDC(0, hdc);
return;
}
ret = ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
ok(ret, "ret = %d\n", ret);
ret = ModifyWorldTransform(hdc, NULL, MWT_LEFTMULTIPLY);
ok(!ret, "ret = %d\n", ret);
ret = ModifyWorldTransform(hdc, NULL, MWT_RIGHTMULTIPLY);
ok(!ret, "ret = %d\n", ret);
ReleaseDC(0, hdc);
}
void test_SetWindowExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy)
{
SIZE windowExt, viewportExt;
POINT windowOrg, windowOrgAfter, viewportOrg, viewportOrgAfter;
GetWindowOrgEx(hdc, &windowOrg);
GetViewportOrgEx(hdc, &viewportOrg);
SetWindowExtEx(hdc, cx, cy, NULL);
GetWindowExtEx(hdc, &windowExt);
ok(windowExt.cx == cx && windowExt.cy == cy,
"Window extension: Expected %ldx%ld, got %ldx%ld\n",
cx, cy, windowExt.cx, windowExt.cy);
GetViewportExtEx(hdc, &viewportExt);
ok(viewportExt.cx == expected_vp_cx && viewportExt.cy == expected_vp_cy,
"Viewport extents have not been properly adjusted: Expected %ldx%ld, got %ldx%ld\n",
expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy);
GetWindowOrgEx(hdc, &windowOrgAfter);
ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y,
"Window origin changed from (%ld,%ld) to (%ld,%ld)\n",
windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y);
GetViewportOrgEx(hdc, &viewportOrgAfter);
ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y,
"Viewport origin changed from (%ld,%ld) to (%ld,%ld)\n",
viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y);
}
void test_SetViewportExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy)
{
SIZE windowExt, windowExtAfter, viewportExt;
POINT windowOrg, windowOrgAfter, viewportOrg, viewportOrgAfter;
GetWindowOrgEx(hdc, &windowOrg);
GetViewportOrgEx(hdc, &viewportOrg);
GetWindowExtEx(hdc, &windowExt);
SetViewportExtEx(hdc, cx, cy, NULL);
GetViewportExtEx(hdc, &viewportExt);
ok(viewportExt.cx == expected_vp_cx && viewportExt.cy == expected_vp_cy,
"Viewport extents have not been properly adjusted: Expected %ldx%ld, got %ldx%ld\n",
expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy);
GetWindowExtEx(hdc, &windowExtAfter);
ok(windowExt.cx == windowExtAfter.cx && windowExt.cy == windowExtAfter.cy,
"Window extension changed from %ldx%ld to %ldx%ld\n",
windowExt.cx, windowExt.cy, windowExtAfter.cx, windowExtAfter.cy);
GetWindowOrgEx(hdc, &windowOrgAfter);
ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y,
"Window origin changed from (%ld,%ld) to (%ld,%ld)\n",
windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y);
GetViewportOrgEx(hdc, &viewportOrgAfter);
ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y,
"Viewport origin changed from (%ld,%ld) to (%ld,%ld)\n",
viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y);
}
void test_isotropic_mapping(void)
{
SIZE win, vp;
HDC hdc = GetDC(0);
SetMapMode(hdc, MM_ISOTROPIC);
/* MM_ISOTROPIC is set up like MM_LOMETRIC.
Initial values after SetMapMode():
(1 inch = 25.4 mm)
Windows 9x: Windows NT:
Window Ext: 254 x -254 HORZSIZE*10 x VERTSIZE*10
Viewport Ext: LOGPIXELSX x LOGPIXELSY HORZRES x -VERTRES
To test without rounding errors, we have to use multiples of
these values!
*/
GetWindowExtEx(hdc, &win);
GetViewportExtEx(hdc, &vp);
test_SetViewportExt(hdc, 10 * vp.cx, 10 * vp.cy, 10 * vp.cx, 10 * vp.cy);
test_SetWindowExt(hdc, win.cx, win.cy, 10 * vp.cx, 10 * vp.cy);
test_SetWindowExt(hdc, 2 * win.cx, win.cy, 10 * vp.cx, 5 * vp.cy);
test_SetWindowExt(hdc, win.cx, win.cy, 5 * vp.cx, 5 * vp.cy);
test_SetViewportExt(hdc, 4 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
test_SetViewportExt(hdc, vp.cx, 2 * vp.cy, vp.cx, vp.cy);
test_SetViewportExt(hdc, 2 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
test_SetViewportExt(hdc, 4 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
test_SetWindowExt(hdc, 4 * win.cx, 2 * win.cy, 2 * vp.cx, vp.cy);
test_SetViewportExt(hdc, -2 * vp.cx, -4 * vp.cy, -2 * vp.cx, -vp.cy);
test_SetViewportExt(hdc, -2 * vp.cx, -1 * vp.cy, -2 * vp.cx, -vp.cy);
test_SetWindowExt(hdc, -4 * win.cx, -2 * win.cy, -2 * vp.cx, -vp.cy);
test_SetWindowExt(hdc, 4 * win.cx, -4 * win.cy, -vp.cx, -vp.cy);
ReleaseDC(0, hdc);
}
START_TEST(mapping)
{
test_modify_world_transform();
test_isotropic_mapping();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,126 @@
/*
* Unit test suite for palettes
*
* Copyright 2005 Glenn Wurster
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmsystem.h"
#include "wine/test.h"
static const PALETTEENTRY logpalettedata[8] = {
{ 0x10, 0x20, 0x30, PC_NOCOLLAPSE },
{ 0x20, 0x30, 0x40, PC_NOCOLLAPSE },
{ 0x30, 0x40, 0x50, PC_NOCOLLAPSE },
{ 0x40, 0x50, 0x60, PC_NOCOLLAPSE },
{ 0x50, 0x60, 0x70, PC_NOCOLLAPSE },
{ 0x60, 0x70, 0x80, PC_NOCOLLAPSE },
{ 0x70, 0x80, 0x90, PC_NOCOLLAPSE },
{ 0x80, 0x90, 0xA0, PC_NOCOLLAPSE },
};
static void test_DIB_PAL_COLORS(void) {
HDC hdc = GetDC( NULL );
HDC memhdc = CreateCompatibleDC( hdc );
HBITMAP hbmp, hbmpOld;
char bmpbuf[sizeof(BITMAPINFO) + 10 * sizeof(WORD)];
PBITMAPINFO bmp = (PBITMAPINFO)bmpbuf;
WORD * bmpPalPtr;
char logpalettebuf[sizeof(LOGPALETTE) + sizeof(logpalettedata)];
PLOGPALETTE logpalette = (PLOGPALETTE)logpalettebuf;
HPALETTE hpal, hpalOld;
COLORREF setColor, chkColor, getColor;
int i;
/* Initalize the logical palette with a few colours */
logpalette->palVersion = 0x300;
logpalette->palNumEntries = 8;
memcpy( logpalette->palPalEntry, logpalettedata, sizeof(logpalettedata) );
hpal = CreatePalette( logpalette );
hpalOld = SelectPalette( memhdc, hpal, FALSE );
ok( hpalOld != NULL, "error=%ld\n", GetLastError() );
/* Create a DIB BMP which references colours in the logical palette */
memset( bmp, 0x00, sizeof(BITMAPINFO) );
bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmp->bmiHeader.biWidth = 1;
bmp->bmiHeader.biHeight = 1;
bmp->bmiHeader.biPlanes = 1;
bmp->bmiHeader.biBitCount = 8;
bmp->bmiHeader.biCompression = BI_RGB;
bmp->bmiHeader.biClrUsed = 10;
bmp->bmiHeader.biClrImportant = 0;
bmpPalPtr = (WORD *)&bmp->bmiColors;
for( i = 0; i < 8; i++ ) {
*bmpPalPtr++ = i;
}
*bmpPalPtr++ = 8; /* Pointer to logical palette index just outside range */
*bmpPalPtr++ = 19; /* Pointer to bad logical palette index */
hbmp = CreateDIBSection( memhdc, bmp, DIB_PAL_COLORS, 0, 0, 0 );
ok( hbmp != NULL, "error=%ld\n", GetLastError() );
hbmpOld = SelectObject( memhdc, hbmp );
ok( hbmpOld != NULL, "error=%ld\n", GetLastError() );
/* Test with a RGB to DIB_PAL_COLORS */
setColor = RGB( logpalettedata[1].peRed, logpalettedata[1].peGreen, logpalettedata[1].peBlue );
SetPixel( memhdc, 0, 0, setColor );
chkColor = RGB( logpalettedata[1].peRed, logpalettedata[1].peGreen, logpalettedata[1].peBlue );
getColor = GetPixel( memhdc, 0, 0 );
ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
/* Test with a valid DIBINDEX to DIB_PAL_COLORS */
setColor = DIBINDEX( 2 );
SetPixel( memhdc, 0, 0, setColor );
chkColor = RGB( logpalettedata[2].peRed, logpalettedata[2].peGreen, logpalettedata[2].peBlue );
getColor = GetPixel( memhdc, 0, 0 );
ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
/* Test with a invalid DIBINDEX to DIB_PAL_COLORS */
setColor = DIBINDEX( 12 );
SetPixel( memhdc, 0, 0, setColor );
chkColor = RGB( 0, 0, 0 );
getColor = GetPixel( memhdc, 0, 0 );
ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
/* Test for double wraparound on logical palette references from */
/* DIBINDEX by DIB_PAL_COLORS. */
setColor = DIBINDEX( 9 );
SetPixel( memhdc, 0, 0, setColor );
chkColor = RGB( logpalettedata[3].peRed, logpalettedata[3].peGreen, logpalettedata[3].peBlue );
getColor = GetPixel( memhdc, 0, 0 );
ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
SelectPalette( memhdc, hpalOld, FALSE );
DeleteObject( hpal );
SelectObject( memhdc, hbmpOld );
DeleteObject( hbmp );
DeleteDC( memhdc );
ReleaseDC( NULL, hdc );
}
START_TEST(palette)
{
test_DIB_PAL_COLORS();
}

View file

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

View file

@ -72,6 +72,8 @@ typedef struct
#define BRUSHOBJ_FreeBrush(hBrush) GDIOBJ_FreeObj(GdiHandleTable, (HGDIOBJ)hBrush, GDI_OBJECT_TYPE_BRUSH)
#define BRUSHOBJ_LockBrush(hBrush) ((PGDIBRUSHOBJ)GDIOBJ_LockObj(GdiHandleTable, (HGDIOBJ)hBrush, GDI_OBJECT_TYPE_BRUSH))
#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);
#endif

View file

@ -188,6 +188,11 @@ VOID FASTCALL DC_SetOwnership(HDC DC, PEPROCESS Owner);
VOID FASTCALL DC_UpdateXforms(PDC dc);
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*/
typedef struct
{
@ -195,5 +200,4 @@ typedef struct
BOOL on_disk; /* true if metafile is on disk */
} DD_ENHMETAFILEOBJ, *PDD_ENHMETAFILEOBJ;
#endif
#endif /* __WIN32K_DC_H */

View file

@ -19,7 +19,7 @@ BOOL FASTCALL PATH_PolylineTo (PDC dc, const POINT *pts, DWORD cbPoints);
BOOL FASTCALL PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons);
BOOL FASTCALL PATH_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_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);
#endif /* _WIN32K_PATH_H */

View file

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

View file

@ -437,7 +437,12 @@ IntCreateBitmapIndirect(CONST BITMAP *BM)
Size.cx, Size.cy, BitsPixel, 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;
BITMAPOBJ_UnlockBitmap( bmp );
@ -1071,10 +1076,6 @@ NtGdiSetPixel(
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);
@ -1083,7 +1084,6 @@ NtGdiSetPixel(
Color = NtGdiGetPixel(hDC,X,Y);
DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
return Color;
}
Color = ((COLORREF) -1);
@ -1561,8 +1561,12 @@ BITMAPOBJ_CopyBitmap(HBITMAP hBitmap)
INT STDCALL
BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer)
{
if( !buffer ) return sizeof(BITMAP);
if (count < sizeof(BITMAP)) return 0;
if(bmp->dib)
{
if(count < (INT) sizeof(DIBSECTION))
{
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.bmPlanes = 1;
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);
return count;
}

View file

@ -49,6 +49,67 @@ BRUSH_Cleanup(PVOID ObjectBody)
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
IntGdiCreateBrushXlate(PDC Dc, GDIBRUSHOBJ *BrushObj, BOOLEAN *Failed)
{
@ -402,7 +463,8 @@ IntGdiCreateSolidBrush(
ASSERT(BrushObject != NULL);
BrushObject->flAttrs |= GDIBRUSH_IS_SOLID;
BrushObject->BrushAttr.lbColor = Color & 0xFFFFFF;
BrushObject->BrushAttr.lbColor = Color;
/* FIXME: Fill in the rest of fields!!! */
BRUSHOBJ_UnlockBrush(BrushObject);

View file

@ -795,6 +795,12 @@ NtGdiSetViewportExtEx(HDC hDC,
1);
Size->cx = dc->vportExtX;
Size->cy = dc->vportExtY;
dc->vportExtX = XExtent;
dc->vportExtY = YExtent;
if (dc->w.MapMode == MM_ISOTROPIC)
IntFixIsotropicMapping(dc);
}
_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_UnlockDc(dc);

View file

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

View file

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

View file

@ -37,19 +37,6 @@ NtGdiCloseEnhMetaFile(HDC hDC)
IO_STATUS_BLOCK Iosb;
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);
@ -121,34 +108,47 @@ NtGdiCloseEnhMetaFile(HDC hDC)
LARGE_INTEGER Distance ;
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.HighPart = 0;
FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
DPRINT1("Trying write to metafile and map it\n");
Status = NtSetInformationFile(Dc->hFile, &IoStatusBlock, &FilePosition,
sizeof(FILE_POSITION_INFORMATION), FilePositionInformation);
if (!NT_SUCCESS(Status))
{
/* FIXME */
// SetLastErrorByStatus(errCode);
// SetLastErrorByStatus(Status);
SetLastWin32Error(ERROR_INVALID_HANDLE);
NtClose( Dc->hFile );
DC_UnlockDc(Dc);
NtGdiDeleteObjectApp(hDC);
DPRINT1("NtSetInformationFile fail\n");
return hmf;
}
if (FilePosition.CurrentByteOffset.u.LowPart != 0)
{
/* FIXME */
// SetLastErrorByStatus(errCode);
// SetLastErrorByStatus(Status);
SetLastWin32Error(ERROR_INVALID_HANDLE);
NtClose( Dc->hFile );
DC_UnlockDc(Dc);
NtGdiDeleteObjectApp(hDC);
DPRINT1("FilePosition.CurrentByteOffset.u.LowPart is not 0\n");
return hmf;
}
@ -167,18 +167,67 @@ NtGdiCloseEnhMetaFile(HDC hDC)
NtClose( Dc->hFile );
DC_UnlockDc(Dc);
NtGdiDeleteObjectApp(hDC);
DPRINT1("fail to write 0\n");
return hmf;
}
EngFreeMem(Dc->emh);
/* FIXME */
// hMapping = CreateFileMappingW(Dc->hFile, NULL, PAGE_READONLY, 0, 0, NULL);
/* create maping */
DesiredAccess = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
Attributes = (PAGE_READONLY & (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_NOCACHE | SEC_COMMIT));
flProtect = PAGE_READONLY ^ (PAGE_READONLY & (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_NOCACHE | SEC_COMMIT));
/* FIXME */
// Dc->emh = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
NtClose( hMapping );
NtClose( Dc->hFile );
if (!Attributes) Attributes = SEC_COMMIT;
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);

View file

@ -33,12 +33,12 @@ BOOL FASTCALL PATH_AddFlatBezier (GdiPath *pPath, POINT *pt, BOOL closed);
BOOL FASTCALL PATH_DoArcPart (GdiPath *pPath, FLOAT_POINT corners[], double angleStart, double angleEnd, BOOL addMoveTo);
BOOL FASTCALL PATH_FillPath( PDC dc, 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);
BOOL FASTCALL PATH_PathToRegion (GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn);
BOOL FASTCALL PATH_ReserveEntries (GdiPath *pPath, INT numEntries);
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
IntGdiGetArcDirection(DC *dc);
@ -51,16 +51,12 @@ BOOL
STDCALL
NtGdiAbortPath(HDC hDC)
{
GdiPath *pPath;
BOOL ret = TRUE;
PDC dc = DC_LockDc ( hDC );
if( !dc ) return FALSE;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
PATH_EmptyPath( pPath );
PATH_EmptyPath(&dc->w.path);
DC_UnlockDc ( dc );
return ret;
@ -70,24 +66,20 @@ BOOL
STDCALL
NtGdiBeginPath( HDC hDC )
{
GdiPath *pPath;
BOOL ret = TRUE;
PDC dc = DC_LockDc ( hDC );
if( !dc ) return FALSE;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* 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 */
PATH_EmptyPath( pPath );
PATH_EmptyPath( &dc->w.path );
/* Initialize variables for new path */
pPath->newStroke = TRUE;
pPath->state = PATH_Open;
dc->w.path.newStroke = TRUE;
dc->w.path.state = PATH_Open;
}
DC_UnlockDc ( dc );
@ -142,22 +134,18 @@ BOOL
STDCALL
NtGdiEndPath(HDC hDC)
{
GdiPath *pPath;
BOOL ret = TRUE;
PDC dc = DC_LockDc ( hDC );
if ( !dc ) return FALSE;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is currently being constructed */
if( pPath->state != PATH_Open )
if( dc->w.path.state != PATH_Open )
{
ret = FALSE;
}
/* Set flag to indicate that path is finished */
else pPath->state = PATH_Closed;
else dc->w.path.state = PATH_Closed;
DC_UnlockDc ( dc );
return ret;
@ -167,21 +155,17 @@ BOOL
STDCALL
NtGdiFillPath(HDC hDC)
{
GdiPath *pPath;
BOOL ret = TRUE;
PDC dc = DC_LockDc ( hDC );
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 )
{
/* FIXME: Should the path be emptied even if conversion
failed? */
PATH_EmptyPath( pPath );
PATH_EmptyPath( &dc->w.path );
}
DC_UnlockDc ( dc );
@ -259,8 +243,8 @@ NtGdiGetPath(
{
_SEH_TRY
{
RtlCopyMemory(Points, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
RtlCopyMemory(Types, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
memcpy(Points, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
memcpy(Types, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
/* Convert the points to logical coordinates */
IntDPtoLP(dc, Points, pPath->numEntriesUsed);
@ -323,18 +307,39 @@ NtGdiSetMiterLimit(
BOOL
STDCALL
NtGdiStrokeAndFillPath(HDC hDC)
NtGdiStrokeAndFillPath(HDC hDC)
{
UNIMPLEMENTED;
return FALSE;
DC *pDc;
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
STDCALL
NtGdiStrokePath(HDC hDC)
NtGdiStrokePath(HDC hDC)
{
UNIMPLEMENTED;
return FALSE;
DC *pDc;
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
@ -348,30 +353,27 @@ NtGdiWidenPath(HDC hDC)
BOOL STDCALL NtGdiSelectClipPath(HDC hDC,
int Mode)
{
GdiPath *pPath;
HRGN hrgnPath;
BOOL success = FALSE;
PDC dc = DC_LockDc ( hDC );
if( !dc ) return FALSE;
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is closed */
if( pPath->state != PATH_Closed )
if( dc->w.path.state != PATH_Closed )
{
SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
return FALSE;
}
/* 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;
NtGdiDeleteObject( hrgnPath );
/* Empty the path */
if( success )
PATH_EmptyPath( pPath );
PATH_EmptyPath( &dc->w.path);
/* FIXME: Should this function delete the path even if it failed? */
}
@ -466,7 +468,7 @@ VOID
FASTCALL
PATH_InitGdiPath ( GdiPath *pPath )
{
assert(pPath!=NULL);
ASSERT(pPath!=NULL);
pPath->state=PATH_Null;
pPath->pPoints=NULL;
@ -483,7 +485,7 @@ VOID
FASTCALL
PATH_DestroyGdiPath ( GdiPath *pPath )
{
assert(pPath!=NULL);
ASSERT(pPath!=NULL);
ExFreePool(pPath->pPoints);
ExFreePool(pPath->pFlags);
@ -503,7 +505,7 @@ BOOL
FASTCALL
PATH_AssignGdiPath ( GdiPath *pPathDest, const GdiPath *pPathSrc )
{
assert(pPathDest!=NULL && pPathSrc!=NULL);
ASSERT(pPathDest!=NULL && pPathSrc!=NULL);
/* Make sure destination arrays are big enough */
if ( !PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed) )
@ -532,18 +534,14 @@ BOOL
FASTCALL
PATH_MoveTo ( PDC dc )
{
GdiPath *pPath;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
if ( dc->w.path.state != PATH_Open )
/* FIXME: Do we have to call SetLastError? */
return FALSE;
/* Start a new stroke */
pPath->newStroke = TRUE;
dc->w.path.newStroke = TRUE;
return TRUE;
}
@ -559,14 +557,10 @@ BOOL
FASTCALL
PATH_LineTo ( PDC dc, INT x, INT y )
{
GdiPath *pPath;
POINT point, pointCurPos;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
if ( dc->w.path.state != PATH_Open )
return FALSE;
/* Convert point to device coordinates */
@ -575,17 +569,17 @@ PATH_LineTo ( PDC dc, INT x, INT y )
CoordLPtoDP ( dc, &point );
/* 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 );
CoordLPtoDP ( dc, &pointCurPos );
if ( !PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO) )
if ( !PATH_AddEntry(&dc->w.path, &pointCurPos, PT_MOVETO) )
return FALSE;
}
/* Add a PT_LINETO entry */
return PATH_AddEntry(pPath, &point, PT_LINETO);
return PATH_AddEntry(&dc->w.path, &point, PT_LINETO);
}
/* PATH_Rectangle
@ -597,15 +591,11 @@ BOOL
FASTCALL
PATH_Rectangle ( PDC dc, INT x1, INT y1, INT x2, INT y2 )
{
GdiPath *pPath;
POINT corners[2], pointTemp;
INT temp;
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
if ( dc->w.path.state != PATH_Open )
return FALSE;
/* 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 */
pointTemp.x=corners[1].x;
pointTemp.y=corners[0].y;
if ( !PATH_AddEntry(pPath, &pointTemp, PT_MOVETO) )
if ( !PATH_AddEntry(&dc->w.path, &pointTemp, PT_MOVETO) )
return FALSE;
if ( !PATH_AddEntry(pPath, corners, PT_LINETO) )
if ( !PATH_AddEntry(&dc->w.path, corners, PT_LINETO) )
return FALSE;
pointTemp.x=corners[0].x;
pointTemp.y=corners[1].y;
if ( !PATH_AddEntry(pPath, &pointTemp, PT_LINETO) )
if ( !PATH_AddEntry(&dc->w.path, &pointTemp, PT_LINETO) )
return FALSE;
if ( !PATH_AddEntry(pPath, corners+1, PT_LINETO) )
if ( !PATH_AddEntry(&dc->w.path, corners+1, PT_LINETO) )
return FALSE;
/* Close the rectangle figure */
@ -659,12 +649,63 @@ PATH_Rectangle ( PDC dc, INT x1, INT y1, INT x2, INT y2 )
return TRUE;
}
BOOL
FASTCALL
PATH_RoundRect (PDC dc, INT x1, INT y1, INT x2, INT y2, INT xradius, INT yradius)
/* PATH_RoundRect
*
* 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;
return FALSE;
GdiPath *pPath = &dc->w.path;
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
@ -693,7 +734,6 @@ FASTCALL
PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2,
INT xStart, INT yStart, INT xEnd, INT yEnd)
{
GdiPath *pPath;
double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0;
/* Initialize angleEndQuadrant to silence gcc's warning */
double x, y;
@ -709,11 +749,8 @@ PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2,
clockwise = ( IntGdiGetArcDirection(dc) == AD_CLOCKWISE );
/* Get pointer to path */
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
if ( dc->w.path.state != PATH_Open )
return FALSE;
/* 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 )
{
angleEnd+=2*M_PI;
assert(angleEnd>=angleStart);
ASSERT(angleEnd>=angleStart);
}
}
else
@ -771,7 +808,7 @@ PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2,
if(angleEnd>=angleStart)
{
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 */
PATH_DoArcPart ( pPath, corners, angleStartQuadrant, angleEndQuadrant, start );
PATH_DoArcPart ( &dc->w.path, corners, angleStartQuadrant, angleEndQuadrant, start );
start = FALSE;
} while(!end);
@ -828,7 +865,6 @@ BOOL
FASTCALL
PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{
GdiPath *pPath;
POINT pt;
ULONG i;
@ -836,19 +872,17 @@ PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints )
ASSERT ( pts );
ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
if ( dc->w.path.state != PATH_Open )
return FALSE;
/* 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 );
CoordLPtoDP ( dc, &pt );
if ( !PATH_AddEntry(pPath, &pt, PT_MOVETO) )
if ( !PATH_AddEntry(&dc->w.path, &pt, PT_MOVETO) )
return FALSE;
}
@ -856,7 +890,7 @@ PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{
pt = pts[i];
CoordLPtoDP ( dc, &pt );
PATH_AddEntry(pPath, &pt, PT_BEZIERTO);
PATH_AddEntry(&dc->w.path, &pt, PT_BEZIERTO);
}
return TRUE;
}
@ -865,7 +899,6 @@ BOOL
FASTCALL
PATH_PolyBezier ( PDC dc, const POINT *pts, DWORD cbPoints )
{
GdiPath *pPath;
POINT pt;
ULONG i;
@ -873,17 +906,15 @@ PATH_PolyBezier ( PDC dc, const POINT *pts, DWORD cbPoints )
ASSERT ( pts );
ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
if ( dc->w.path.state != PATH_Open )
return FALSE;
for ( i = 0; i < cbPoints; i++ )
{
pt = pts[i];
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;
@ -893,7 +924,6 @@ BOOL
FASTCALL
PATH_Polyline ( PDC dc, const POINT *pts, DWORD cbPoints )
{
GdiPath *pPath;
POINT pt;
ULONG i;
@ -901,17 +931,15 @@ PATH_Polyline ( PDC dc, const POINT *pts, DWORD cbPoints )
ASSERT ( pts );
ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
if ( dc->w.path.state != PATH_Open )
return FALSE;
for ( i = 0; i < cbPoints; i++ )
{
pt = pts[i];
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;
}
@ -920,7 +948,6 @@ BOOL
FASTCALL
PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{
GdiPath *pPath;
POINT pt;
ULONG i;
@ -928,19 +955,17 @@ PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints )
ASSERT ( pts );
ASSERT ( cbPoints );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
if ( dc->w.path.state != PATH_Open )
return FALSE;
/* 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 );
CoordLPtoDP ( dc, &pt );
if ( !PATH_AddEntry(pPath, &pt, PT_MOVETO) )
if ( !PATH_AddEntry(&dc->w.path, &pt, PT_MOVETO) )
return FALSE;
}
@ -948,7 +973,7 @@ PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{
pt = pts[i];
CoordLPtoDP ( dc, &pt );
PATH_AddEntry(pPath, &pt, PT_LINETO);
PATH_AddEntry(&dc->w.path, &pt, PT_LINETO);
}
return TRUE;
@ -959,24 +984,21 @@ BOOL
FASTCALL
PATH_Polygon ( PDC dc, const POINT *pts, DWORD cbPoints )
{
GdiPath *pPath;
POINT pt;
ULONG i;
ASSERT ( dc );
ASSERT ( pts );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
if ( dc->w.path.state != PATH_Open )
return FALSE;
for(i = 0; i < cbPoints; i++)
{
pt = pts[i];
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 :
PT_LINETO));
}
@ -987,7 +1009,6 @@ BOOL
FASTCALL
PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons )
{
GdiPath *pPath;
POINT pt, startpt;
ULONG poly, point, i;
@ -996,10 +1017,8 @@ PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons )
ASSERT ( counts );
ASSERT ( polygons );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open );
if ( dc->w.path.state != PATH_Open );
return FALSE;
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];
CoordLPtoDP ( dc, &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 */
PATH_AddEntry(pPath, &startpt, PT_LINETO | PT_CLOSEFIGURE);
PATH_AddEntry(&dc->w.path, &startpt, PT_LINETO | PT_CLOSEFIGURE);
}
return TRUE;
}
@ -1021,7 +1040,6 @@ BOOL
FASTCALL
PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylines )
{
GdiPath *pPath;
POINT pt;
ULONG poly, point, i;
@ -1030,10 +1048,8 @@ PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylin
ASSERT ( counts );
ASSERT ( polylines );
PATH_GetPathFromDC ( dc, &pPath );
/* Check that path is open */
if ( pPath->state != PATH_Open )
if ( dc->w.path.state != PATH_Open )
return FALSE;
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];
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;
@ -1052,6 +1068,46 @@ PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylin
* 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
*
@ -1085,7 +1141,7 @@ PATH_FlattenPath(GdiPath *pPath)
GdiPath newPath;
INT srcpt;
memset(&newPath, 0, sizeof(newPath));
RtlZeroMemory(&newPath, sizeof(newPath));
newPath.state = PATH_Open;
for(srcpt = 0; srcpt < pPath->numEntriesUsed; srcpt++) {
switch(pPath->pFlags[srcpt] & ~PT_CLOSEFIGURE) {
@ -1123,8 +1179,8 @@ PATH_PathToRegion ( GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn )
INT *pNumPointsInStroke;
HRGN hrgn = 0;
assert ( pPath!=NULL );
assert ( pHrgn!=NULL );
ASSERT(pPath!=NULL);
ASSERT(pHrgn!=NULL);
PATH_FlattenPath ( pPath );
@ -1184,7 +1240,7 @@ VOID
FASTCALL
PATH_EmptyPath ( GdiPath *pPath )
{
assert(pPath!=NULL);
ASSERT(pPath!=NULL);
pPath->state=PATH_Null;
pPath->numEntriesUsed=0;
@ -1200,7 +1256,7 @@ BOOL
FASTCALL
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
* getting a PT_MOVETO
@ -1242,8 +1298,8 @@ PATH_ReserveEntries ( GdiPath *pPath, INT numEntries )
POINT *pPointsNew;
BYTE *pFlagsNew;
assert(pPath!=NULL);
assert(numEntries>=0);
ASSERT(pPath!=NULL);
ASSERT(numEntries>=0);
/* Do we have to allocate more memory? */
if(numEntries > pPath->numEntriesAllocated)
@ -1273,7 +1329,7 @@ PATH_ReserveEntries ( GdiPath *pPath, INT numEntries )
/* Copy old arrays to new arrays and discard old arrays */
if(pPath->pPoints)
{
assert(pPath->pFlags);
ASSERT(pPath->pFlags);
memcpy(pPointsNew, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
memcpy(pFlagsNew, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
@ -1289,20 +1345,6 @@ PATH_ReserveEntries ( GdiPath *pPath, INT numEntries )
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
*
* 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;
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? */
@ -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;
*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 */

View file

@ -84,7 +84,7 @@ IntGdiCreatePenIndirect(PLOGPEN LogPen)
break;
default:
DPRINT1("FIXME: IntGdiCreatePenIndirect is UNIMPLEMENTED\n");
DPRINT1("FIXME: IntGdiCreatePenIndirect is UNIMPLEMENTED pen %x\n",LogPen->lopnStyle);
}
PENOBJ_UnlockPen(PenObject);
@ -92,6 +92,23 @@ IntGdiCreatePenIndirect(PLOGPEN LogPen)
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 ***********************************************************/
HPEN STDCALL

View file

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