GDI improvements

svn path=/trunk/; revision=1183
This commit is contained in:
Jason Filby 2000-06-16 07:25:41 +00:00
parent 94c0c4bab2
commit 0b34b1b746
27 changed files with 1722 additions and 89 deletions

View file

@ -7,10 +7,47 @@
int main (void)
{
HDC Desktop;
HDC Desktop, MyDC;
HPEN RedPen, GreenPen;
HBITMAP MyBitmap;
GdiDllInitialize (NULL, DLL_PROCESS_ATTACH, NULL);
// Set up a DC called Desktop that accesses DISPLAY
Desktop = CreateDCA("DISPLAY", NULL, NULL, NULL);
// Create a red pen and select it into the DC
RedPen = CreatePen(PS_SOLID, 1, 0xff0000);
SelectObject(Desktop, RedPen);
// Draw a shap on the DC
MoveToEx(Desktop, 50, 50, NULL);
LineTo(Desktop, 200, 60);
LineTo(Desktop, 200, 300);
LineTo(Desktop, 50, 50);
// Create a DC that is compatible with the DISPLAY DC along with a bitmap that is selected into it
MyDC = CreateCompatibleDC(Desktop);
MyBitmap = CreateCompatibleBitmap(Desktop, 151, 251);
SelectObject(MyDC, MyBitmap);
// Bitblt from the DISPLAY DC to MyDC and then back again in a different location
BitBlt(MyDC, 0, 0, 151, 251, Desktop, 50, 50, 0);
// Draw a rectangle on the memory DC before bltting back with a green pen
GreenPen = CreatePen(PS_SOLID, 1, 0x00ff00);
SelectObject(MyDC, GreenPen);
Rectangle(MyDC, 10, 10, 50, 50);
BitBlt(Desktop, 400, 100, 151, 251, MyDC, 0, 0, 0);
TextOutA(Desktop, 200, 0, "ReactOS", 7);
TextOutA(Desktop, 200, 9, "This is a test of the ReactOS GDI functionality", 47);
TextOutA(Desktop, 200, 18, "The font being used is an internal static one", 45);
// Free up everything
/* ReleaseDC(Desktop);
ReleaseDC(MyDC); */
return 0;
}

View file

@ -5,6 +5,7 @@
#include <windows.h>
#include <win32k/driver.h>
#include <win32k/gdiobj.h>
#include <win32k/path.h>
/* (RJJ) Taken from WINE */
typedef struct _DEVICECAPS
@ -54,12 +55,12 @@ typedef struct _WIN_DC_INFO
HBITMAP hBitmap;
HBITMAP hFirstBitmap; /* Bitmap selected at creation of the DC */
#if 0
// #if 0
HANDLE hDevice;
HPALETTE hPalette;
GdiPath path;
#endif
// #endif
WORD ROPmode;
WORD polyFillMode;
@ -207,7 +208,7 @@ BOOL STDCALL W32kGetWindowOrgEx(HDC hDC, LPPOINT windowOrg);
HDC STDCALL W32kResetDC(HDC hDC, CONST DEVMODE *InitData);
BOOL STDCALL W32kRestoreDC(HDC hDC, INT SavedDC);
INT STDCALL W32kSaveDC(HDC hDC);
HGDIOBJ STDCALL W32kSelectObject(HDC hDC, HGDIOBJ GDIObj);
HGDIOBJ STDCALL W32kSelectObject(HDC hDC, HGDIOBJ hGDIObj);
INT STDCALL W32kSetBkMode(HDC hDC, INT backgroundMode);
INT STDCALL W32kSetPolyFillMode(HDC hDC, INT polyFillMode);
INT STDCALL W32kSetRelAbs(HDC hDC, INT relAbsMode);

View file

@ -34,7 +34,7 @@ W32kArcTo(HDC hDC,
int XRadial2,
int YRadial2);
int
INT
STDCALL
W32kGetArcDirection(HDC hDC);

View file

@ -1,6 +1,24 @@
#ifndef __WIN32K_PATH_H
#define __WIN32K_PATH_H
typedef enum tagGdiPathState
{
PATH_Null,
PATH_Open,
PATH_Closed
} GdiPathState;
typedef struct tagGdiPath
{
GdiPathState state;
POINT *pPoints;
BYTE *pFlags;
int numEntriesUsed, numEntriesAllocated;
BOOL newStroke;
} GdiPath;
#define PATH_IsPathOpen(path) ((path).state==PATH_Open)
BOOL STDCALL W32kAbortPath(HDC hDC);
BOOL STDCALL W32kBeginPath(HDC hDC);

View file

@ -2,6 +2,26 @@
#ifndef __WIN32K_PEN_H
#define __WIN32K_PEN_H
#include <win32k/gdiobj.h>
/* GDI logical pen object */
typedef struct
{
LOGPEN logpen;
} PENOBJ, *PPENOBJ;
/* Internal interface */
#define PENOBJ_AllocPen() \
((PPENOBJ) GDIOBJ_AllocObject (sizeof (PENOBJ), GO_PEN_MAGIC))
#define PENOBJ_FreePen(hBMObj) GDIOBJ_FreeObject((HGDIOBJ) hBMObj)
#define PENOBJ_HandleToPtr(hBMObj) \
((PPENOBJ) GDIOBJ_HandleToPtr ((HGDIOBJ) hBMObj, GO_PEN_MAGIC))
#define PENOBJ_PtrToHandle(hBMObj) \
((HPEN) GDIOBJ_PtrToHandle ((PGDIOBJ) hBMObj, GO_PEN_MAGIC))
#define PENOBJ_LockPen(hBMObj) GDIOBJ_LockObject ((HGDIOBJ) hBMObj)
#define PENOBJ_UnlockPen(hBMObj) GDIOBJ_UnlockObject ((HGDIOBJ) hBMObj)
HPEN STDCALL W32kCreatePen(INT PenStyle,
INT Width,
COLORREF Color);

View file

@ -12,6 +12,9 @@
#include "handle.h"
// FIXME: Total rewrite..
// Place User and GDI objects in ONE object with the user items shown first
// See ..\objects\gdiobj
// To switch between user and gdi objects, just -\+ the size of all the user items
ULONG CreateGDIHandle(PVOID InternalObject, PVOID UserObject)
{

View file

@ -1,6 +1,8 @@
#include <ddk/winddi.h>
#include "objects.h"
// POSSIBLE FIXME: Switch X and Y's so that drawing a line doesn't try to draw from 150 to 50 (negative dx)
VOID LinePoint(SURFOBJ *Surface, SURFGDI *SurfGDI,
LONG x, LONG y, ULONG iColor)
{

View file

@ -20,7 +20,7 @@ typedef struct _CLIPGDI {
ULONG EnumPos;
ENUMRECTS EnumRects;
} CLIPGDI;
} CLIPGDI, *PCLIPGDI;
typedef struct _DRVFUNCTIONSGDI {
HDEV hdev;
@ -42,7 +42,7 @@ typedef struct _PALGDI {
ULONG RedMask;
ULONG GreenMask;
ULONG BlueMask;
} PALGDI;
} PALGDI, *PPALGDI;
typedef struct _PATHGDI {
@ -98,7 +98,7 @@ typedef struct _SURFGDI {
PFN_CopyBits CopyBits;
PFN_Synchronize Synchronize;
BOOL SynchronizeAccess;
} SURFGDI;
} SURFGDI, *PSURFGDI;
typedef struct _XFORMGDI {

View file

@ -82,6 +82,14 @@ HBITMAP EngCreateBitmap(IN SIZEL Size,
IN ULONG Flags,
IN PVOID Bits)
{
/* SHOULD CALL THIS */
/* HBITMAP STDCALL W32kCreateBitmap(INT Width,
INT Height,
UINT Planes,
UINT BitsPerPel,
CONST VOID *Bits) */
HBITMAP NewBitmap;
SURFOBJ *SurfObj;
SURFGDI *SurfGDI;
@ -216,8 +224,7 @@ BOOL EngDeleteSurface(HSURF Surface)
SURFOBJ *EngLockSurface(HSURF Surface)
{
// FIXME: Do we need to allocate new memory for this user object?? Since there's an unlock.. it appears to be so
// probably because win32k is supposed to do some kind of wierd handle\object thing that we don't
// FIXME: Call GDI_LockObject (see subsys/win32k/objects/gdi.c)
return AccessUserObject(Surface);
}

View file

@ -8,3 +8,11 @@ EngLoadImage (LPWSTR DriverName)
{
return (HANDLE) LdrLoadModule(DriverName);
}
HANDLE
STDCALL
EngLoadModule(LPWSTR ModuleName)
{
// FIXME: should load as readonly
return (HANDLE) LdrLoadModule(ModuleName);
}

View file

@ -1,4 +1,4 @@
/* $Id: dllmain.c,v 1.14 2000/04/02 13:09:50 jfilby Exp $
/* $Id: dllmain.c,v 1.15 2000/06/16 07:22:37 jfilby Exp $
*
* Entry Point for win32k.sys
*/
@ -63,6 +63,9 @@ W32kInitialize (VOID)
RtlInitUnicodeString (&DriverNameW, L"\\??\\C:\\reactos\\system32\\drivers\\vidport.sys");
EngLoadImage(&DriverNameW);
// Create surface used to draw the internal font onto
CreateCellCharSurface();
return TRUE;
}

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.20 2000/05/14 13:10:01 dwelch Exp $
# $Id: makefile,v 1.21 2000/06/16 07:22:36 jfilby Exp $
#
# WIN32K.SYS build spec
#
@ -12,18 +12,31 @@ ENG_OBJECTS= eng/debug.o eng/mem.o eng/brush.o eng/bitblt.o eng/clip.o eng/copyb
eng/surface.o eng/xlate.o
MAIN_OBJECTS = main/dllmain.o
MISC_OBJECTS = misc/driver.o
MATH_OBJECTS = math/acos.o math/acosh.o math/asin.o math/asinh.o math/atan.o math/atan2.o \
math/atanh.o math/ceil.o math/cos.o math/cosh.o math/exp.o math/fabs.o \
math/floor.o math/fmod.o math/frexp.o math/huge_val.o math/hypot.o \
math/ldexp.o math/log.o math/log10.o math/modf.o math/pow.o \
math/sin.o math/sinh.o math/sqrt.o math/tan.o \
math/tanh.o math/stubs.o math/j0_y0.o math/j1_y1.o math/jn_yn.o \
math/cabs.o math/ftol.o
FLOAT_OBJECTS = float/fpreset.o float/clearfp.o float/cntrlfp.o float/statfp.o float/logb.o\
float/chgsign.o float/fpclass.o float/isnan.o float/nafter.o float/scalb.o\
float/copysign.o
LDR_OBJECTS = ldr/loader.o
OBJECTS_OBJECTS = objects/bitmaps.o objects/brush.o objects/cliprgn.o \
objects/color.o objects/coord.o objects/dc.o \
objects/fillshap.o objects/gdiobj.o objects/icm.o \
objects/line.o objects/metafile.o objects/paint.o \
objects/path.o objects/pen.o objects/print.o \
objects/region.o objects/text.o objects/wingl.o
objects/region.o objects/text.o objects/wingl.o \
objects/bezier.o objects/objconv.o
FREETYPE_OBJECTS = freetype/grfont.o
RESOURCE_OBJECT = $(TARGET).coff
STUBS_OBJECTS = stubs/stubs.o
OBJECTS = $(ENG_OBJECTS) $(MAIN_OBJECTS) $(MISC_OBJECTS) $(LDR_OBJECTS) $(OBJECTS_OBJECTS) \
$(RESOURCE_OBJECT) $(STUBS_OBJECTS)
$(RESOURCE_OBJECT) $(STUBS_OBJECTS) $(MATH_OBJECTS) $(FLOAT_OBJECTS) $(FREETYPE_OBJECTS)
all: $(TARGET).sys

View file

@ -0,0 +1,193 @@
#include <windows.h>
#include <ddk/ntddk.h>
/******************************************************************
*
* *Very* simple bezier drawing code,
*
* It uses a recursive algorithm to divide the curve in a series
* of straight line segements. Not ideal but for me sufficient.
* If you are in need for something better look for some incremental
* algorithm.
*
* 7 July 1998 Rein Klazes
*/
/*
* some macro definitions for bezier drawing
*
* to avoid trucation errors the coordinates are
* shifted upwards. When used in drawing they are
* shifted down again, including correct rounding
* and avoiding floating point arithmatic
* 4 bits should allow 27 bits coordinates which I saw
* somewere in the win32 doc's
*
*/
#define BEZIERSHIFTBITS 4
#define BEZIERSHIFTUP(x) ((x)<<BEZIERSHIFTBITS)
#define BEZIERPIXEL BEZIERSHIFTUP(1)
#define BEZIERSHIFTDOWN(x) (((x)+(1<<(BEZIERSHIFTBITS-1)))>>BEZIERSHIFTBITS)
/* maximum depth of recursion */
#define BEZIERMAXDEPTH 8
/* size of array to store points on */
/* enough for one curve */
#define BEZIER_INITBUFSIZE (150)
/* calculate Bezier average, in this case the middle
* correctly rounded...
* */
#define BEZIERMIDDLE(Mid, P1, P2) \
(Mid).x=((P1).x+(P2).x + 1)/2;\
(Mid).y=((P1).y+(P2).y + 1)/2;
/**********************************************************
* BezierCheck helper function to check
* that recursion can be terminated
* Points[0] and Points[3] are begin and endpoint
* Points[1] and Points[2] are control points
* level is the recursion depth
* returns true if the recusion can be terminated
*/
static BOOL BezierCheck( int level, POINT *Points)
{
INT dx, dy;
dx=Points[3].x-Points[0].x;
dy=Points[3].y-Points[0].y;
if(abs(dy)<=abs(dx)){/* shallow line */
/* check that control points are between begin and end */
if(Points[1].x < Points[0].x){
if(Points[1].x < Points[3].x)
return FALSE;
}else
if(Points[1].x > Points[3].x)
return FALSE;
if(Points[2].x < Points[0].x){
if(Points[2].x < Points[3].x)
return FALSE;
}else
if(Points[2].x > Points[3].x)
return FALSE;
dx=BEZIERSHIFTDOWN(dx);
if(!dx) return TRUE;
if(abs(Points[1].y-Points[0].y-(dy/dx)*
BEZIERSHIFTDOWN(Points[1].x-Points[0].x)) > BEZIERPIXEL ||
abs(Points[2].y-Points[0].y-(dy/dx)*
BEZIERSHIFTDOWN(Points[2].x-Points[0].x)) > BEZIERPIXEL )
return FALSE;
else
return TRUE;
}else{ /* steep line */
/* check that control points are between begin and end */
if(Points[1].y < Points[0].y){
if(Points[1].y < Points[3].y)
return FALSE;
}else
if(Points[1].y > Points[3].y)
return FALSE;
if(Points[2].y < Points[0].y){
if(Points[2].y < Points[3].y)
return FALSE;
}else
if(Points[2].y > Points[3].y)
return FALSE;
dy=BEZIERSHIFTDOWN(dy);
if(!dy) return TRUE;
if(abs(Points[1].x-Points[0].x-(dx/dy)*
BEZIERSHIFTDOWN(Points[1].y-Points[0].y)) > BEZIERPIXEL ||
abs(Points[2].x-Points[0].x-(dx/dy)*
BEZIERSHIFTDOWN(Points[2].y-Points[0].y)) > BEZIERPIXEL )
return FALSE;
else
return TRUE;
}
}
/* Helper for GDI_Bezier.
* Just handles one Bezier, so Points should point to four POINTs
*/
static void GDI_InternalBezier( POINT *Points, POINT **PtsOut, INT *dwOut,
INT *nPtsOut, INT level )
{
if(*nPtsOut == *dwOut) {
*dwOut *= 2;
*PtsOut = ExAllocatePool(NonPagedPool, *dwOut * sizeof(POINT));
}
if(!level || BezierCheck(level, Points)) {
if(*nPtsOut == 0) {
(*PtsOut)[0].x = BEZIERSHIFTDOWN(Points[0].x);
(*PtsOut)[0].y = BEZIERSHIFTDOWN(Points[0].y);
*nPtsOut = 1;
}
(*PtsOut)[*nPtsOut].x = BEZIERSHIFTDOWN(Points[3].x);
(*PtsOut)[*nPtsOut].y = BEZIERSHIFTDOWN(Points[3].y);
(*nPtsOut) ++;
} else {
POINT Points2[4]; /* for the second recursive call */
Points2[3]=Points[3];
BEZIERMIDDLE(Points2[2], Points[2], Points[3]);
BEZIERMIDDLE(Points2[0], Points[1], Points[2]);
BEZIERMIDDLE(Points2[1],Points2[0],Points2[2]);
BEZIERMIDDLE(Points[1], Points[0], Points[1]);
BEZIERMIDDLE(Points[2], Points[1], Points2[0]);
BEZIERMIDDLE(Points[3], Points[2], Points2[1]);
Points2[0]=Points[3];
/* do the two halves */
GDI_InternalBezier(Points, PtsOut, dwOut, nPtsOut, level-1);
GDI_InternalBezier(Points2, PtsOut, dwOut, nPtsOut, level-1);
}
}
/***********************************************************************
* GDI_Bezier [INTERNAL]
* Calculate line segments that approximate -what microsoft calls- a bezier
* curve.
* The routine recursively divides the curve in two parts until a straight
* line can be drawn
*
* PARAMS
*
* Points [I] Ptr to count POINTs which are the end and control points
* of the set of Bezier curves to flatten.
* count [I] Number of Points. Must be 3n+1.
* nPtsOut [O] Will contain no of points that have been produced (i.e. no. of
* lines+1).
*
* RETURNS
*
* Ptr to an array of POINTs that contain the lines that approximinate the
* Beziers. The array is allocated on the process heap and it is the caller's
* responsibility to HeapFree it. [this is not a particularly nice interface
* but since we can't know in advance how many points will generate, the
* alternative would be to call the function twice, once to determine the size
* and a second time to do the work - I decided this was too much of a pain].
*/
POINT *GDI_Bezier( const POINT *Points, INT count, INT *nPtsOut )
{
POINT *out;
INT Bezier, dwOut = BEZIER_INITBUFSIZE, i;
if((count - 1) % 3 != 0) {
return NULL;
}
*nPtsOut = 0;
out = ExAllocatePool(NonPagedPool, dwOut * sizeof(POINT));
for(Bezier = 0; Bezier < (count-1)/3; Bezier++) {
POINT ptBuf[4];
memcpy(ptBuf, Points + Bezier * 3, sizeof(POINT) * 4);
for(i = 0; i < 4; i++) {
ptBuf[i].x = BEZIERSHIFTUP(ptBuf[i].x);
ptBuf[i].y = BEZIERSHIFTUP(ptBuf[i].y);
}
GDI_InternalBezier( ptBuf, &out, &dwOut, nPtsOut, BEZIERMAXDEPTH );
}
return out;
}

View file

@ -19,7 +19,58 @@ BOOL STDCALL W32kBitBlt(HDC hDCDest,
INT YSrc,
DWORD ROP)
{
UNIMPLEMENTED;
PDC DCDest = DC_HandleToPtr(hDCDest);
PDC DCSrc = DC_HandleToPtr(hDCSrc);
PSURFOBJ SurfDest;
PSURFOBJ SurfSrc;
RECTL DestRect;
POINTL SourcePoint;
PBITMAPOBJ DestBitmapObj;
PBITMAPOBJ SrcBitmapObj;
BOOL Status, SurfDestAlloc, SurfSrcAlloc;
DestRect.left = XDest;
DestRect.top = YDest;
DestRect.right = XDest+Width;
DestRect.bottom = YDest+Height;
SourcePoint.x = XSrc;
SourcePoint.y = YSrc;
SurfDestAlloc = FALSE;
SurfSrcAlloc = FALSE;
DbgPrint("Get surfdest.. ");
// Get the SurfDest
if(DCDest->Surface != NULL)
{
// Use the DC's surface if it has one
SurfDest = AccessUserObject(DCDest->Surface);
} else
return FALSE;
DbgPrint("Get surfsrc.. ");
// Get the SurfSrc
if(DCSrc->Surface != NULL)
{
DbgPrint("from DC's surface\n");
// Use the DC's surface if it has one
SurfSrc = AccessUserObject(DCSrc->Surface);
} else
return FALSE;
DbgPrint("Go to EngBitBlt\n");
Status = EngBitBlt(SurfDest, SurfSrc, NULL, NULL, NULL,
&DestRect, &SourcePoint, NULL, NULL, NULL, NULL); // FIXME: Color translation (xlateobj)
if(SurfDestAlloc == TRUE) ExFreePool(SurfDest);
if(SurfSrcAlloc == TRUE) ExFreePool(SurfSrc);
return Status;
}
HBITMAP STDCALL W32kCreateBitmap(INT Width,
@ -60,8 +111,8 @@ HBITMAP STDCALL W32kCreateBitmap(INT Width,
return 0;
}
DPRINT("%dx%d, %d colors returning %08x\n", Width, Height,
1 << (Planes * BitsPerPel), bmp);
DPRINT("W32kCreateBitmap:%dx%d, %d (%d BPP) colors returning %08x\n", Width, Height,
1 << (Planes * BitsPerPel), BitsPerPel, bmp);
bmp->size.cx = 0;
bmp->size.cy = 0;
@ -75,12 +126,17 @@ HBITMAP STDCALL W32kCreateBitmap(INT Width,
bmp->DDBitmap = NULL;
bmp->dib = NULL;
hBitmap = BITMAPOBJ_PtrToHandle (bmp);
// Allocate memory for bitmap bits
bmp->bitmap.bmBits = ExAllocatePool(NonPagedPool, bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight);
if (Bits) /* Set bitmap bits */
{
W32kSetBitmapBits(hBitmap,
Height * bmp->bitmap.bmWidthBytes,
Bits);
}
BITMAPOBJ_UnlockBitmap (hBitmap);
return hBitmap;
@ -94,8 +150,10 @@ HBITMAP STDCALL W32kCreateCompatibleBitmap(HDC hDC,
PDC dc;
hbmpRet = 0;
DPRINT("(%04x,%d,%d) = \n", hDC, Width, Height);
dc = DC_PtrToHandle (hDC);
dc = DC_HandleToPtr (hDC);
DPRINT("W32kCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, dc->w.bitsPerPixel);
if (!dc)
{
return 0;
@ -357,7 +415,7 @@ LONG STDCALL W32kSetBitmapBits(HBITMAP hBitmap,
height = bmp->bitmap.bmHeight;
}
Bytes = height * bmp->bitmap.bmWidthBytes;
DPRINT ("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
hBitmap,
Bytes,
Bits,

View file

@ -1,4 +1,4 @@
/* $Id: brush.c,v 1.8 2000/02/20 22:52:50 ea Exp $
/* $Id: brush.c,v 1.9 2000/06/16 07:22:37 jfilby Exp $
*/
@ -164,7 +164,13 @@ HBRUSH STDCALL W32kCreatePatternBrush(HBITMAP hBitmap)
HBRUSH STDCALL W32kCreateSolidBrush(COLORREF Color)
{
UNIMPLEMENTED;
LOGBRUSH logbrush;
logbrush.lbStyle = BS_SOLID;
logbrush.lbColor = Color;
logbrush.lbHatch = 0;
return W32kCreateBrushIndirect(&logbrush);
}
BOOL STDCALL W32kFixBrushOrgEx(VOID)
@ -189,5 +195,3 @@ BOOL STDCALL W32kSetBrushOrgEx(HDC hDC,
{
UNIMPLEMENTED;
}

View file

@ -1,4 +1,4 @@
/* $Id: dc.c,v 1.15 2000/04/03 19:55:33 jfilby Exp $
/* $Id: dc.c,v 1.16 2000/06/16 07:22:37 jfilby Exp $
*
* DC.C - Device context functions
*
@ -7,6 +7,8 @@
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ddk/ntddk.h>
/* FIXME: Surely we should just have one include file that includes all of these.. */
#include <win32k/bitmaps.h>
#include <win32k/coord.h>
#include <win32k/driver.h>
@ -14,6 +16,8 @@
#include <win32k/print.h>
#include <win32k/region.h>
#include <win32k/gdiobj.h>
#include <win32k/pen.h>
#include "../eng/objects.h"
// #define NDEBUG
#include <internal/debug.h>
@ -224,7 +228,7 @@ HDC STDCALL W32kCreateCompatableDC(HDC hDC)
return NULL;
}
NewDC->w.flags = DC_MEMORY;
NewDC->w.bitsPerPixel = 1;
NewDC->w.bitsPerPixel = 1; /* FIXME: OrigDC->w.bitsPerPixel ? */
NewDC->w.hBitmap = hBitmap;
NewDC->w.hFirstBitmap = hBitmap;
@ -243,6 +247,7 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver,
PDC NewDC;
HDC hDC = NULL;
DRVENABLEDATA DED;
int i; // DELETEME
/* Check for existing DC object */
if ((NewDC = DC_FindOpenDC(Driver)) != NULL)
@ -250,6 +255,8 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver,
hDC = DC_PtrToHandle(NewDC);
return W32kCreateCompatableDC(hDC);
}
DbgPrint("NAME: %S\n", Driver);
/* Allocate a DC object */
if ((NewDC = DC_AllocDC(Driver)) == NULL)
@ -280,6 +287,7 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver,
DbgPrint("DrvEnableDriver failed\n");
goto Failure;
}
DbgPrint("Building DDI Functions\n");
/* Construct DDI driver function dispatch table */
if (!DRIVER_BuildDDIFunctions(&DED, &NewDC->DriverFunctions))
@ -291,7 +299,8 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver,
/* Allocate a phyical device handle from the driver */
if (Device != NULL)
{
wcsncpy(NewDC->DMW.dmDeviceName, Device, DMMAXDEVICENAME);
DbgPrint("Device in u: %u\n", Device);
// wcsncpy(NewDC->DMW.dmDeviceName, Device, DMMAXDEVICENAME); FIXME: this crashes everything?
}
NewDC->DMW.dmSize = sizeof(NewDC->DMW);
NewDC->DMW.dmFields = 0x000fc000;
@ -305,6 +314,10 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver,
NewDC->DMW.dmDisplayFlags = 0;
NewDC->DMW.dmDisplayFrequency = 0;
NewDC->w.bitsPerPixel = 8; // FIXME: set this here??
DbgPrint("Enabling PDev\n");
NewDC->PDev = NewDC->DriverFunctions.EnablePDev(&NewDC->DMW,
L"",
HS_DDI_MAX,
@ -322,16 +335,24 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver,
goto Failure;
}
DbgPrint("calling completePDev\n");
/* Complete initialization of the physical device */
NewDC->DriverFunctions.CompletePDev(NewDC->PDev, NewDC);
DbgPrint("calling DRIVER_ReferenceDriver\n");
DRIVER_ReferenceDriver (Driver);
DbgPrint("calling EnableSurface\n");
/* Enable the drawing surface */
NewDC->Surface = NewDC->DriverFunctions.EnableSurface(NewDC->PDev); // hsurf
DbgPrint("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
/* Test EngXxx functions */
TestEngXxx(NewDC);
// TestEngXxx(NewDC);
/* Initialize the DC state */
DC_InitDC(NewDC);
@ -787,9 +808,63 @@ INT STDCALL W32kSaveDC(HDC hDC)
return ret;
}
HGDIOBJ STDCALL W32kSelectObject(HDC hDC, HGDIOBJ GDIObj)
HGDIOBJ STDCALL W32kSelectObject(HDC hDC, HGDIOBJ hGDIObj)
{
UNIMPLEMENTED;
HGDIOBJ objOrg;
GDIOBJHDR *GdiObjHdr;
BITMAPOBJ *pb;
PSURFOBJ surfobj;
PSURFGDI surfgdi;
PDC dc;
if(!hDC || !hGDIObj) return NULL;
dc = DC_HandleToPtr(hDC);
GdiObjHdr = hGDIObj;
// FIXME: Get object handle from GDIObj and use it instead of GDIObj below?
switch(GdiObjHdr->wMagic) {
case GO_PEN_MAGIC:
objOrg = (HGDIOBJ)dc->w.hPen;
dc->w.hPen = hGDIObj;
break;
case GO_BRUSH_MAGIC:
objOrg = (HGDIOBJ)dc->w.hBrush;
dc->w.hBrush = (BRUSHOBJ *)GdiObjHdr;
break;
case GO_FONT_MAGIC:
objOrg = (HGDIOBJ)dc->w.hFont;
dc->w.hFont = (FONTOBJ *)GdiObjHdr;
break;
case GO_BITMAP_MAGIC:
// must be memory dc to select bitmap
if (!(dc->w.flags & DC_MEMORY))
return NULL;
objOrg = (HGDIOBJ)dc->w.hBitmap;
// setup mem dc for drawing into bitmap
pb = BITMAPOBJ_HandleToPtr(GdiObjHdr);
surfobj = ExAllocatePool(NonPagedPool, sizeof(SURFOBJ));
surfgdi = ExAllocatePool(NonPagedPool, sizeof(SURFGDI));
BitmapToSurf(surfgdi, surfobj, pb);
dc->w.hBitmap = (BITMAPOBJ *)GdiObjHdr;
dc->Surface = CreateGDIHandle(surfgdi, surfobj);
break;
#if UPDATEREGIONS
case GO_REGION_MAGIC:
/* objOrg = (HGDIOBJ)hDC->region; */
objOrg = NULL; /* FIXME? hDC->region is destroyed below */
SelectClipRgn(hDC, (HRGN)GdiObjHdr);
break;
#endif
default:
return NULL;
}
return objOrg;
}
DC_SET_MODE( W32kSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE )
@ -1038,5 +1113,3 @@ DC_InvertXform(const XFORM *xformSrc,
return TRUE;
}

View file

@ -3,6 +3,8 @@
#include <windows.h>
#include <ddk/ntddk.h>
#include <win32k/fillshap.h>
#include <win32k/dc.h>
#include <win32k/pen.h>
// #define NDEBUG
#include <internal/debug.h>
@ -75,7 +77,57 @@ W32kRectangle(HDC hDC,
int RightRect,
int BottomRect)
{
UNIMPLEMENTED;
DC *dc = DC_HandleToPtr(hDC);
SURFOBJ *SurfObj = AccessUserObject(dc->Surface);
PBRUSHOBJ BrushObj;
BOOL ret;
PRECTL RectBounds = GDIOBJ_HandleToPtr(dc->w.hGCClipRgn, GO_REGION_MAGIC);
if(!dc) return FALSE;
if(PATH_IsPathOpen(dc->w.path)) {
ret = PATH_Rectangle(hDC, LeftRect, TopRect, RightRect, BottomRect);
} else {
DbgPrint("W32kRectangle pen: ");
DbgPrint("--- %08x\n", GDIOBJ_HandleToPtr(dc->w.hPen, GO_PEN_MAGIC));
BrushObj = PenToBrushObj(dc, GDIOBJ_HandleToPtr(dc->w.hPen, GO_PEN_MAGIC));
ret = EngLineTo(SurfObj,
NULL, // ClipObj,
BrushObj,
LeftRect, TopRect, RightRect, TopRect,
RectBounds, // Bounding rectangle
dc->w.ROPmode); // MIX
ret = EngLineTo(SurfObj,
NULL, // ClipObj,
BrushObj,
RightRect, TopRect, RightRect, BottomRect,
RectBounds, // Bounding rectangle
dc->w.ROPmode); // MIX
ret = EngLineTo(SurfObj,
NULL, // ClipObj,
BrushObj,
LeftRect, BottomRect, RightRect, BottomRect,
RectBounds, // Bounding rectangle
dc->w.ROPmode); // MIX
ret = EngLineTo(SurfObj,
NULL, // ClipObj,
BrushObj,
LeftRect, TopRect, LeftRect, BottomRect,
RectBounds, // Bounding rectangle
dc->w.ROPmode); // MIX */
ExFreePool(BrushObj);
}
// FIXME: Move current position in DC?
return TRUE;
}
BOOL

View file

@ -0,0 +1,2 @@
/* EMPTY FOR NOW */
/* Hope I didn't delete existing defs!! Check CVS version of this file.. */

View file

@ -1,7 +1,7 @@
/*
* GDIOBJ.C - GDI object manipulation routines
*
* $Id: gdiobj.c,v 1.5 2000/03/01 03:23:57 ekohl Exp $
* $Id: gdiobj.c,v 1.6 2000/06/16 07:22:39 jfilby Exp $
*
*/
@ -14,7 +14,7 @@ PGDIOBJ GDIOBJ_AllocObject(WORD Size, WORD Magic)
{
PGDIOBJHDR NewObj;
NewObj = ExAllocatePool(PagedPool, Size + sizeof (GDIOBJHDR));
NewObj = ExAllocatePool(PagedPool, Size + sizeof (GDIOBJHDR)); // FIXME: Allocate with tag of MAGIC?
if (NewObj == NULL)
{
return NULL;
@ -46,6 +46,7 @@ HGDIOBJ GDIOBJ_PtrToHandle (PGDIOBJ Obj, WORD Magic)
{
PGDIOBJHDR objHeader;
if (Obj == NULL) return NULL;
objHeader = (PGDIOBJHDR) (((PCHAR)Obj) - sizeof (GDIOBJHDR));
if (objHeader->wMagic != Magic)
{
@ -58,12 +59,14 @@ HGDIOBJ GDIOBJ_PtrToHandle (PGDIOBJ Obj, WORD Magic)
PGDIOBJ GDIOBJ_HandleToPtr (HGDIOBJ Obj, WORD Magic)
{
PGDIOBJHDR objHeader;
if (Obj == NULL) return NULL;
objHeader = (PGDIOBJHDR) Obj;
/* FIXME: Lock object for duration */
if (objHeader->wMagic != Magic)
if ((objHeader->wMagic != Magic) && (Magic != GO_MAGIC_DONTCARE))
{
return 0;
}

View file

@ -1,10 +1,12 @@
// Some code from the WINE project source (www.winehq.com)
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ddk/ntddk.h>
#include <win32k/dc.h>
#include <win32k/line.h>
#include <win32k/path.h>
#include <win32k/pen.h>
// #define NDEBUG
#include <internal/debug.h>
@ -33,7 +35,15 @@ W32kArc(HDC hDC,
int XEndArc,
int YEndArc)
{
UNIMPLEMENTED;
DC *dc = DC_HandleToPtr(hDC);
if(!dc) return FALSE;
if(PATH_IsPathOpen(dc->w.path))
return PATH_Arc(hDC, LeftRect, TopRect, RightRect, BottomRect,
XStartArc, YStartArc, XEndArc, YEndArc);
// EngArc(dc, LeftRect, TopRect, RightRect, BottomRect, UNIMPLEMENTED
// XStartArc, YStartArc, XEndArc, YEndArc);
}
BOOL
@ -48,26 +58,43 @@ W32kArcTo(HDC hDC,
int XRadial2,
int YRadial2)
{
UNIMPLEMENTED;
BOOL result;
DC *dc = DC_HandleToPtr(hDC);
if(!dc) return FALSE;
// Line from current position to starting point of arc
W32kLineTo(hDC, XRadial1, YRadial1);
// Then the arc is drawn.
result = W32kArc(hDC, LeftRect, TopRect, RightRect, BottomRect,
XRadial1, YRadial1, XRadial2, YRadial2);
// If no error occured, the current position is moved to the ending point of the arc.
if(result)
{
W32kMoveToEx(hDC, XRadial2, YRadial2, NULL);
}
return result;
}
int
INT
STDCALL
W32kGetArcDirection(HDC hDC)
{
PDC dc;
int ret;
PDC dc;
int ret;
dc = DC_HandleToPtr (hDC);
if (!dc)
{
dc = DC_HandleToPtr (hDC);
if (!dc)
{
return 0;
}
}
ret = dc->w.ArcDirection;
DC_UnlockDC (hDC);
ret = dc->w.ArcDirection;
DC_UnlockDC (hDC);
return ret;
return ret;
}
BOOL
@ -76,7 +103,32 @@ W32kLineTo(HDC hDC,
int XEnd,
int YEnd)
{
UNIMPLEMENTED;
DC *dc = DC_HandleToPtr(hDC);
SURFOBJ *SurfObj = AccessUserObject(dc->Surface);
BOOL ret;
if(!dc) return FALSE;
if(PATH_IsPathOpen(dc->w.path)) {
ret = PATH_LineTo(hDC, XEnd, YEnd);
} else {
DbgPrint("W32kLineTo on DC:%08x (h:%08x) with pen handle %08x\n", dc, hDC, dc->w.hPen);
DbgPrint("--- %08x\n", GDIOBJ_HandleToPtr(dc->w.hPen, GO_PEN_MAGIC));
ret = EngLineTo(SurfObj,
NULL, // ClipObj
PenToBrushObj(dc, GDIOBJ_HandleToPtr(dc->w.hPen, GO_PEN_MAGIC)),
dc->w.CursPosX, dc->w.CursPosY, XEnd, YEnd,
GDIOBJ_HandleToPtr(dc->w.hGCClipRgn, GO_REGION_MAGIC), // Bounding rectangle
dc->w.ROPmode); // MIX
}
if(ret) {
dc->w.CursPosX = XEnd;
dc->w.CursPosY = YEnd;
}
return ret;
}
BOOL
@ -86,7 +138,21 @@ W32kMoveToEx(HDC hDC,
int Y,
LPPOINT Point)
{
UNIMPLEMENTED;
DC *dc = DC_HandleToPtr( hDC );
if(!dc) return FALSE;
if(Point) {
Point->x = dc->w.CursPosX;
Point->y = dc->w.CursPosY;
}
dc->w.CursPosX = X;
dc->w.CursPosY = Y;
if(PATH_IsPathOpen(dc->w.path))
return PATH_MoveTo(hDC);
return FALSE;
}
BOOL
@ -95,7 +161,25 @@ W32kPolyBezier(HDC hDC,
CONST LPPOINT pt,
DWORD Count)
{
UNIMPLEMENTED;
DC *dc = DC_HandleToPtr(hDC);
if(!dc) return FALSE;
if(PATH_IsPathOpen(dc->w.path))
return PATH_PolyBezier(hDC, pt, Count);
/* We'll convert it into line segments and draw them using Polyline */
{
POINT *Pts;
INT nOut;
BOOL ret;
Pts = GDI_Bezier(pt, Count, &nOut);
if(!Pts) return FALSE;
DbgPrint("Pts = %p, no = %d\n", Pts, nOut);
ret = W32kPolyline(dc->hSelf, Pts, nOut);
ExFreePool(Pts);
return ret;
}
}
BOOL
@ -104,7 +188,28 @@ W32kPolyBezierTo(HDC hDC,
CONST LPPOINT pt,
DWORD Count)
{
UNIMPLEMENTED;
DC *dc = DC_HandleToPtr(hDC);
BOOL ret;
if(!dc) return FALSE;
if(PATH_IsPathOpen(dc->w.path))
ret = PATH_PolyBezierTo(hDC, pt, Count);
else { /* We'll do it using PolyBezier */
POINT *npt;
npt = ExAllocatePool(NonPagedPool, sizeof(POINT) * (Count + 1));
if(!npt) return FALSE;
npt[0].x = dc->w.CursPosX;
npt[0].y = dc->w.CursPosY;
memcpy(npt + 1, pt, sizeof(POINT) * Count);
ret = W32kPolyBezier(dc->hSelf, npt, Count+1);
ExFreePool(npt);
}
if(ret) {
dc->w.CursPosX = pt[Count-1].x;
dc->w.CursPosY = pt[Count-1].y;
}
return ret;
}
BOOL
@ -123,7 +228,7 @@ W32kPolyline(HDC hDC,
CONST LPPOINT pt,
int Count)
{
UNIMPLEMENTED;
UNIMPLEMENTED;
}
BOOL
@ -132,7 +237,30 @@ W32kPolylineTo(HDC hDC,
CONST LPPOINT pt,
DWORD Count)
{
UNIMPLEMENTED;
DC *dc = DC_HandleToPtr(hDC);
BOOL ret;
if(!dc) return FALSE;
if(PATH_IsPathOpen(dc->w.path))
{
ret = PATH_PolylineTo(hDC, pt, Count);
}
else { /* do it using Polyline */
POINT *pts = ExAllocatePool(NonPagedPool, sizeof(POINT) * (Count + 1));
if(!pts) return FALSE;
pts[0].x = dc->w.CursPosX;
pts[0].y = dc->w.CursPosY;
memcpy( pts + 1, pt, sizeof(POINT) * Count);
ret = W32kPolyline(hDC, pts, Count + 1);
ExFreePool(pts);
}
if(ret) {
dc->w.CursPosX = pt[Count-1].x;
dc->w.CursPosY = pt[Count-1].y;
}
return ret;
}
BOOL
@ -142,7 +270,7 @@ W32kPolyPolyline(HDC hDC,
CONST LPDWORD PolyPoints,
DWORD Count)
{
UNIMPLEMENTED;
UNIMPLEMENTED;
}
int
@ -150,23 +278,22 @@ STDCALL
W32kSetArcDirection(HDC hDC,
int ArcDirection)
{
PDC dc;
INT nOldDirection;
PDC dc;
INT nOldDirection;
dc = DC_HandleToPtr (hDC);
if (!dc)
{
dc = DC_HandleToPtr (hDC);
if (!dc)
{
return 0;
}
if (ArcDirection != AD_COUNTERCLOCKWISE && ArcDirection != AD_CLOCKWISE)
{
}
if (ArcDirection != AD_COUNTERCLOCKWISE && ArcDirection != AD_CLOCKWISE)
{
// SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
}
nOldDirection = dc->w.ArcDirection;
dc->w.ArcDirection = ArcDirection;
nOldDirection = dc->w.ArcDirection;
dc->w.ArcDirection = ArcDirection;
return nOldDirection;
return nOldDirection;
}

View file

@ -0,0 +1,56 @@
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ddk/ntddk.h>
/* FIXME: Surely we should just have one include file that includes all of these.. */
#include <win32k/bitmaps.h>
#include <win32k/coord.h>
#include <win32k/driver.h>
#include <win32k/dc.h>
#include <win32k/print.h>
#include <win32k/region.h>
#include <win32k/gdiobj.h>
#include <win32k/pen.h>
#include "../eng/objects.h"
PBRUSHOBJ PenToBrushObj(PDC dc, PENOBJ *pen)
{
BRUSHOBJ *BrushObj;
XLATEOBJ *RGBtoVGA16;
// FIXME: move color translation routines to W32kSelectObject
DbgPrint("PenToBrushObj:%08x ", pen);
BrushObj = ExAllocatePool(NonPagedPool, sizeof(BRUSHOBJ));
RGBtoVGA16 = EngCreateXlate(PAL_INDEXED, PAL_RGB,
dc->DevInfo.hpalDefault, NULL);
BrushObj->iSolidColor = XLATEOBJ_iXlate(RGBtoVGA16, pen->logpen.lopnColor);
DbgPrint("BrushObj->iSolidColor:%u\n", BrushObj->iSolidColor);
return BrushObj;
// CreateGDIHandle(BrushGDI, BrushObj);
}
VOID BitmapToSurf(PSURFGDI SurfGDI, PSURFOBJ SurfObj, PBITMAPOBJ Bitmap)
{
SurfObj->dhsurf = NULL;
SurfObj->hsurf = NULL;
SurfObj->dhpdev = NULL;
SurfObj->hdev = NULL;
SurfObj->sizlBitmap = Bitmap->size;
SurfObj->cjBits = Bitmap->bitmap.bmHeight * Bitmap->bitmap.bmWidthBytes;
SurfObj->pvBits = Bitmap->bitmap.bmBits;
SurfObj->pvScan0 = NULL; // start of bitmap
SurfObj->lDelta = Bitmap->bitmap.bmWidthBytes;
SurfObj->iUniq = 0; // not sure..
SurfObj->iBitmapFormat = BMF_4BPP; /* FIXME */
SurfObj->iType = STYPE_BITMAP;
SurfObj->fjBitmap = BMF_TOPDOWN;
SurfGDI->BytesPerPixel = bytesPerPixel(SurfObj->iType);
DbgPrint("Bitmap2Surf: cjBits: %u lDelta: %u width: %u height: %u\n",
SurfObj->cjBits, SurfObj->lDelta, Bitmap->bitmap.bmWidth, Bitmap->bitmap.bmHeight);
}

View file

@ -1,13 +1,36 @@
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ddk/ntddk.h>
#include <win32k/brush.h>
#include <win32k/dc.h>
#include <win32k/path.h>
#include <win32k/math.h>
#include <win32k/float.h>
#include <win32k/coord.h>
#include <win32k/line.h>
// #define NDEBUG
#include <internal/debug.h>
#define NUM_ENTRIES_INITIAL 16 /* Initial size of points / flags arrays */
#define GROW_FACTOR_NUMER 2 /* Numerator of grow factor for the array */
#define GROW_FACTOR_DENOM 1 /* Denominator of grow factor */
static BOOL PATH_PathToRegion(const GdiPath *pPath, INT nPolyFillMode,
HRGN *pHrgn);
static void PATH_EmptyPath(GdiPath *pPath);
static BOOL PATH_AddEntry(GdiPath *pPath, const POINT *pPoint,
BYTE flags);
static BOOL PATH_ReserveEntries(GdiPath *pPath, INT numEntries);
static BOOL PATH_GetPathFromHDC(HDC hdc, GdiPath **ppPath);
static BOOL PATH_DoArcPart(GdiPath *pPath, FLOAT_POINT corners[],
double angleStart, double angleEnd, BOOL addMoveTo);
static void PATH_ScaleNormalizedPoint(FLOAT_POINT corners[], double x,
double y, POINT *pPoint);
static void PATH_NormalizePoint(FLOAT_POINT corners[], const FLOAT_POINT
*pPoint, double *pX, double *pY);
BOOL
STDCALL
W32kAbortPath(HDC hDC)
@ -103,7 +126,905 @@ BOOL
STDCALL
W32kWidenPath(HDC hDC)
{
UNIMPLEMENTED;
UNIMPLEMENTED;
}
/***********************************************************************
* Exported functions
*/
/* PATH_InitGdiPath
*
* Initializes the GdiPath structure.
*/
void PATH_InitGdiPath(GdiPath *pPath)
{
assert(pPath!=NULL);
pPath->state=PATH_Null;
pPath->pPoints=NULL;
pPath->pFlags=NULL;
pPath->numEntriesUsed=0;
pPath->numEntriesAllocated=0;
}
/* PATH_DestroyGdiPath
*
* Destroys a GdiPath structure (frees the memory in the arrays).
*/
void PATH_DestroyGdiPath(GdiPath *pPath)
{
assert(pPath!=NULL);
ExFreePool(pPath->pPoints);
ExFreePool(pPath->pFlags);
}
/* PATH_AssignGdiPath
*
* Copies the GdiPath structure "pPathSrc" to "pPathDest". A deep copy is
* performed, i.e. the contents of the pPoints and pFlags arrays are copied,
* not just the pointers. Since this means that the arrays in pPathDest may
* need to be resized, pPathDest should have been initialized using
* PATH_InitGdiPath (in C++, this function would be an assignment operator,
* not a copy constructor).
* Returns TRUE if successful, else FALSE.
*/
BOOL PATH_AssignGdiPath(GdiPath *pPathDest, const GdiPath *pPathSrc)
{
assert(pPathDest!=NULL && pPathSrc!=NULL);
/* Make sure destination arrays are big enough */
if(!PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed))
return FALSE;
/* Perform the copy operation */
memcpy(pPathDest->pPoints, pPathSrc->pPoints,
sizeof(POINT)*pPathSrc->numEntriesUsed);
memcpy(pPathDest->pFlags, pPathSrc->pFlags,
sizeof(BYTE)*pPathSrc->numEntriesUsed);
pPathDest->state=pPathSrc->state;
pPathDest->numEntriesUsed=pPathSrc->numEntriesUsed;
pPathDest->newStroke=pPathSrc->newStroke;
return TRUE;
}
/* PATH_MoveTo
*
* Should be called when a MoveTo is performed on a DC that has an
* open path. This starts a new stroke. Returns TRUE if successful, else
* FALSE.
*/
BOOL PATH_MoveTo(HDC hdc)
{
GdiPath *pPath;
/* Get pointer to path */
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
/* FIXME: Do we have to call SetLastError? */
return FALSE;
/* Start a new stroke */
pPath->newStroke=TRUE;
return TRUE;
}
/* PATH_LineTo
*
* Should be called when a LineTo is performed on a DC that has an
* open path. This adds a PT_LINETO entry to the path (and possibly
* a PT_MOVETO entry, if this is the first LineTo in a stroke).
* Returns TRUE if successful, else FALSE.
*/
BOOL PATH_LineTo(HDC hdc, INT x, INT y)
{
GdiPath *pPath;
POINT point, pointCurPos;
/* Get pointer to path */
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
/* Convert point to device coordinates */
point.x=x;
point.y=y;
if(!W32kLPtoDP(hdc, &point, 1))
return FALSE;
/* Add a PT_MOVETO if necessary */
if(pPath->newStroke)
{
pPath->newStroke=FALSE;
if(!W32kGetCurrentPositionEx(hdc, &pointCurPos) ||
!W32kLPtoDP(hdc, &pointCurPos, 1))
return FALSE;
if(!PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO))
return FALSE;
}
/* Add a PT_LINETO entry */
return PATH_AddEntry(pPath, &point, PT_LINETO);
}
/* PATH_Rectangle
*
* Should be called when a call to Rectangle is performed on a DC that has
* an open path. Returns TRUE if successful, else FALSE.
*/
BOOL PATH_Rectangle(HDC hdc, INT x1, INT y1, INT x2, INT y2)
{
GdiPath *pPath;
POINT corners[2], pointTemp;
INT temp;
/* Get pointer to path */
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
/* Convert points to device coordinates */
corners[0].x=x1;
corners[0].y=y1;
corners[1].x=x2;
corners[1].y=y2;
if(!W32kLPtoDP(hdc, corners, 2))
return FALSE;
/* 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(W32kGetGraphicsMode(hdc)==GM_COMPATIBLE)
{
corners[1].x--;
corners[1].y--;
}
/* Close any previous figure */
if(!W32kCloseFigure(hdc))
{
/* The W32kCloseFigure call shouldn't have failed */
assert(FALSE);
return FALSE;
}
/* Add four points to the path */
pointTemp.x=corners[1].x;
pointTemp.y=corners[0].y;
if(!PATH_AddEntry(pPath, &pointTemp, PT_MOVETO))
return FALSE;
if(!PATH_AddEntry(pPath, corners, PT_LINETO))
return FALSE;
pointTemp.x=corners[0].x;
pointTemp.y=corners[1].y;
if(!PATH_AddEntry(pPath, &pointTemp, PT_LINETO))
return FALSE;
if(!PATH_AddEntry(pPath, corners+1, PT_LINETO))
return FALSE;
/* Close the rectangle figure */
if(!W32kCloseFigure(hdc))
{
/* The W32kCloseFigure call shouldn't have failed */
assert(FALSE);
return FALSE;
}
return TRUE;
}
/* PATH_Ellipse
*
* Should be called when a call to Ellipse is performed on a DC that has
* an open path. This adds four Bezier splines representing the ellipse
* to the path. Returns TRUE if successful, else FALSE.
*/
BOOL PATH_Ellipse(HDC hdc, INT x1, INT y1, INT x2, INT y2)
{
/* TODO: This should probably be revised to call PATH_AngleArc */
/* (once it exists) */
return PATH_Arc(hdc, x1, y1, x2, y2, x1, (y1+y2)/2, x1, (y1+y2)/2);
}
/* PATH_Arc
*
* Should be called when a call to Arc is performed on a DC that has
* an open path. This adds up to five Bezier splines representing the arc
* to the path. Returns TRUE if successful, else FALSE.
*/
BOOL PATH_Arc(HDC hdc, INT x1, INT y1, INT x2, INT y2,
INT xStart, INT yStart, INT xEnd, INT yEnd)
{
GdiPath *pPath;
DC *pDC;
double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0;
/* Initialize angleEndQuadrant to silence gcc's warning */
double x, y;
FLOAT_POINT corners[2], pointStart, pointEnd;
BOOL start, end;
INT temp;
/* FIXME: This function should check for all possible error returns */
/* FIXME: Do we have to respect newStroke? */
/* Get pointer to DC */
pDC=DC_HandleToPtr(hdc);
if(pDC==NULL)
return FALSE;
/* Get pointer to path */
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
/* FIXME: Do we have to close the current figure? */
/* Check for zero height / width */
/* FIXME: Only in GM_COMPATIBLE? */
if(x1==x2 || y1==y2)
return TRUE;
/* Convert points to device coordinates */
corners[0].x=(FLOAT)x1;
corners[0].y=(FLOAT)y1;
corners[1].x=(FLOAT)x2;
corners[1].y=(FLOAT)y2;
pointStart.x=(FLOAT)xStart;
pointStart.y=(FLOAT)yStart;
pointEnd.x=(FLOAT)xEnd;
pointEnd.y=(FLOAT)yEnd;
INTERNAL_LPTODP_FLOAT(pDC, corners);
INTERNAL_LPTODP_FLOAT(pDC, corners+1);
INTERNAL_LPTODP_FLOAT(pDC, &pointStart);
INTERNAL_LPTODP_FLOAT(pDC, &pointEnd);
/* 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;
}
/* Compute start and end angle */
PATH_NormalizePoint(corners, &pointStart, &x, &y);
angleStart=atan2(y, x);
PATH_NormalizePoint(corners, &pointEnd, &x, &y);
angleEnd=atan2(y, x);
/* Make sure the end angle is "on the right side" of the start angle */
if(W32kGetArcDirection(hdc)==AD_CLOCKWISE)
{
if(angleEnd<=angleStart)
{
angleEnd+=2*M_PI;
assert(angleEnd>=angleStart);
}
}
else
{
if(angleEnd>=angleStart)
{
angleEnd-=2*M_PI;
assert(angleEnd<=angleStart);
}
}
/* In GM_COMPATIBLE, don't include bottom and right edges */
if(W32kGetGraphicsMode(hdc)==GM_COMPATIBLE)
{
corners[1].x--;
corners[1].y--;
}
/* Add the arc to the path with one Bezier spline per quadrant that the
* arc spans */
start=TRUE;
end=FALSE;
do
{
/* Determine the start and end angles for this quadrant */
if(start)
{
angleStartQuadrant=angleStart;
if(W32kGetArcDirection(hdc)==AD_CLOCKWISE)
angleEndQuadrant=(floor(angleStart/M_PI_2)+1.0)*M_PI_2;
else
angleEndQuadrant=(ceil(angleStart/M_PI_2)-1.0)*M_PI_2;
}
else
{
angleStartQuadrant=angleEndQuadrant;
if(W32kGetArcDirection(hdc)==AD_CLOCKWISE)
angleEndQuadrant+=M_PI_2;
else
angleEndQuadrant-=M_PI_2;
}
/* Have we reached the last part of the arc? */
if((W32kGetArcDirection(hdc)==AD_CLOCKWISE &&
angleEnd<angleEndQuadrant) ||
(W32kGetArcDirection(hdc)==AD_COUNTERCLOCKWISE &&
angleEnd>angleEndQuadrant))
{
/* Adjust the end angle for this quadrant */
angleEndQuadrant=angleEnd;
end=TRUE;
}
/* Add the Bezier spline to the path */
PATH_DoArcPart(pPath, corners, angleStartQuadrant, angleEndQuadrant,
start);
start=FALSE;
} while(!end);
return TRUE;
}
BOOL PATH_PolyBezierTo(HDC hdc, const POINT *pts, DWORD cbPoints)
{
GdiPath *pPath;
POINT pt;
INT i;
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
/* Add a PT_MOVETO if necessary */
if(pPath->newStroke)
{
pPath->newStroke=FALSE;
if(!W32kGetCurrentPositionEx(hdc, &pt) ||
!W32kLPtoDP(hdc, &pt, 1))
return FALSE;
if(!PATH_AddEntry(pPath, &pt, PT_MOVETO))
return FALSE;
}
for(i = 0; i < cbPoints; i++) {
pt = pts[i];
if(!W32kLPtoDP(hdc, &pt, 1))
return FALSE;
PATH_AddEntry(pPath, &pt, PT_BEZIERTO);
}
return TRUE;
}
BOOL PATH_PolyBezier(HDC hdc, const POINT *pts, DWORD cbPoints)
{
GdiPath *pPath;
POINT pt;
INT i;
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
for(i = 0; i < cbPoints; i++) {
pt = pts[i];
if(!W32kLPtoDP(hdc, &pt, 1))
return FALSE;
PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PT_BEZIERTO);
}
return TRUE;
}
BOOL PATH_Polyline(HDC hdc, const POINT *pts, DWORD cbPoints)
{
GdiPath *pPath;
POINT pt;
INT i;
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
for(i = 0; i < cbPoints; i++) {
pt = pts[i];
if(!W32kLPtoDP(hdc, &pt, 1))
return FALSE;
PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PT_LINETO);
}
return TRUE;
}
BOOL PATH_PolylineTo(HDC hdc, const POINT *pts, DWORD cbPoints)
{
GdiPath *pPath;
POINT pt;
INT i;
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
/* Add a PT_MOVETO if necessary */
if(pPath->newStroke)
{
pPath->newStroke=FALSE;
if(!W32kGetCurrentPositionEx(hdc, &pt) ||
!W32kLPtoDP(hdc, &pt, 1))
return FALSE;
if(!PATH_AddEntry(pPath, &pt, PT_MOVETO))
return FALSE;
}
for(i = 0; i < cbPoints; i++) {
pt = pts[i];
if(!W32kLPtoDP(hdc, &pt, 1))
return FALSE;
PATH_AddEntry(pPath, &pt, PT_LINETO);
}
return TRUE;
}
BOOL PATH_Polygon(HDC hdc, const POINT *pts, DWORD cbPoints)
{
GdiPath *pPath;
POINT pt;
INT i;
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
for(i = 0; i < cbPoints; i++) {
pt = pts[i];
if(!W32kLPtoDP(hdc, &pt, 1))
return FALSE;
PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO :
((i == cbPoints-1) ? PT_LINETO | PT_CLOSEFIGURE :
PT_LINETO));
}
return TRUE;
}
BOOL PATH_PolyPolygon( HDC hdc, const POINT* pts, const INT* counts,
UINT polygons )
{
GdiPath *pPath;
POINT pt, startpt;
INT poly, point, i;
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
for(i = 0, poly = 0; poly < polygons; poly++) {
for(point = 0; point < counts[poly]; point++, i++) {
pt = pts[i];
if(!W32kLPtoDP(hdc, &pt, 1))
return FALSE;
if(point == 0) startpt = pt;
PATH_AddEntry(pPath, &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);
}
return TRUE;
}
BOOL PATH_PolyPolyline( HDC hdc, const POINT* pts, const DWORD* counts,
DWORD polylines )
{
GdiPath *pPath;
POINT pt;
INT poly, point, i;
if(!PATH_GetPathFromHDC(hdc, &pPath))
return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
for(i = 0, poly = 0; poly < polylines; poly++) {
for(point = 0; point < counts[poly]; point++, i++) {
pt = pts[i];
if(!W32kLPtoDP(hdc, &pt, 1))
return FALSE;
PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO);
}
}
return TRUE;
}
/***********************************************************************
* Internal functions
*/
/* PATH_AddFlatBezier
*
*/
static BOOL PATH_AddFlatBezier(GdiPath *pPath, POINT *pt, BOOL closed)
{
POINT *pts;
INT no, i;
pts = GDI_Bezier( pt, 4, &no );
if(!pts) return FALSE;
for(i = 1; i < no; i++)
PATH_AddEntry(pPath, &pts[i],
(i == no-1 && closed) ? PT_LINETO | PT_CLOSEFIGURE : PT_LINETO);
ExFreePool(pts);
return TRUE;
}
/* PATH_FlattenPath
*
* Replaces Beziers with line segments
*
*/
static BOOL PATH_FlattenPath(GdiPath *pPath)
{
GdiPath newPath;
INT srcpt;
memset(&newPath, 0, sizeof(newPath));
newPath.state = PATH_Open;
for(srcpt = 0; srcpt < pPath->numEntriesUsed; srcpt++) {
switch(pPath->pFlags[srcpt] & ~PT_CLOSEFIGURE) {
case PT_MOVETO:
case PT_LINETO:
PATH_AddEntry(&newPath, &pPath->pPoints[srcpt],
pPath->pFlags[srcpt]);
break;
case PT_BEZIERTO:
PATH_AddFlatBezier(&newPath, &pPath->pPoints[srcpt-1],
pPath->pFlags[srcpt+2] & PT_CLOSEFIGURE);
srcpt += 2;
break;
}
}
newPath.state = PATH_Closed;
PATH_AssignGdiPath(pPath, &newPath);
PATH_EmptyPath(&newPath);
return TRUE;
}
/* PATH_PathToRegion
*
* Creates a region from the specified path using the specified polygon
* filling mode. The path is left unchanged. A handle to the region that
* was created is stored in *pHrgn. If successful, TRUE is returned; if an
* error occurs, SetLastError is called with the appropriate value and
* FALSE is returned.
*/
static BOOL PATH_PathToRegion(const GdiPath *pPath, INT nPolyFillMode,
HRGN *pHrgn)
{
int numStrokes, iStroke, i;
INT *pNumPointsInStroke;
HRGN hrgn;
assert(pPath!=NULL);
assert(pHrgn!=NULL);
PATH_FlattenPath(pPath);
/* FIXME: What happens when number of points is zero? */
/* First pass: Find out how many strokes there are in the path */
/* FIXME: We could eliminate this with some bookkeeping in GdiPath */
numStrokes=0;
for(i=0; i<pPath->numEntriesUsed; i++)
if((pPath->pFlags[i] & ~PT_CLOSEFIGURE) == PT_MOVETO)
numStrokes++;
/* Allocate memory for number-of-points-in-stroke array */
pNumPointsInStroke=(int *)ExAllocatePool(NonPagedPool, sizeof(int) * numStrokes);
if(!pNumPointsInStroke)
{
// SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
/* Second pass: remember number of points in each polygon */
iStroke=-1; /* Will get incremented to 0 at beginning of first stroke */
for(i=0; i<pPath->numEntriesUsed; i++)
{
/* Is this the beginning of a new stroke? */
if((pPath->pFlags[i] & ~PT_CLOSEFIGURE) == PT_MOVETO)
{
iStroke++;
pNumPointsInStroke[iStroke]=0;
}
pNumPointsInStroke[iStroke]++;
}
/* Create a region from the strokes */
/* hrgn=CreatePolyPolygonRgn(pPath->pPoints, pNumPointsInStroke,
numStrokes, nPolyFillMode); FIXME: reinclude when region code implemented */
if(hrgn==(HRGN)0)
{
// SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
/* Free memory for number-of-points-in-stroke array */
ExFreePool(pNumPointsInStroke);
/* Success! */
*pHrgn=hrgn;
return TRUE;
}
/* PATH_EmptyPath
*
* Removes all entries from the path and sets the path state to PATH_Null.
*/
static void PATH_EmptyPath(GdiPath *pPath)
{
assert(pPath!=NULL);
pPath->state=PATH_Null;
pPath->numEntriesUsed=0;
}
/* PATH_AddEntry
*
* Adds an entry to the path. For "flags", pass either PT_MOVETO, PT_LINETO
* or PT_BEZIERTO, optionally ORed with PT_CLOSEFIGURE. Returns TRUE if
* successful, FALSE otherwise (e.g. if not enough memory was available).
*/
BOOL PATH_AddEntry(GdiPath *pPath, const POINT *pPoint, BYTE flags)
{
assert(pPath!=NULL);
/* FIXME: If newStroke is true, perhaps we want to check that we're
* getting a PT_MOVETO
*/
/* Check that path is open */
if(pPath->state!=PATH_Open)
return FALSE;
/* Reserve enough memory for an extra path entry */
if(!PATH_ReserveEntries(pPath, pPath->numEntriesUsed+1))
return FALSE;
/* Store information in path entry */
pPath->pPoints[pPath->numEntriesUsed]=*pPoint;
pPath->pFlags[pPath->numEntriesUsed]=flags;
/* If this is PT_CLOSEFIGURE, we have to start a new stroke next time */
if((flags & PT_CLOSEFIGURE) == PT_CLOSEFIGURE)
pPath->newStroke=TRUE;
/* Increment entry count */
pPath->numEntriesUsed++;
return TRUE;
}
/* PATH_ReserveEntries
*
* Ensures that at least "numEntries" entries (for points and flags) have
* been allocated; allocates larger arrays and copies the existing entries
* to those arrays, if necessary. Returns TRUE if successful, else FALSE.
*/
static BOOL PATH_ReserveEntries(GdiPath *pPath, INT numEntries)
{
INT numEntriesToAllocate;
POINT *pPointsNew;
BYTE *pFlagsNew;
assert(pPath!=NULL);
assert(numEntries>=0);
/* Do we have to allocate more memory? */
if(numEntries > pPath->numEntriesAllocated)
{
/* Find number of entries to allocate. We let the size of the array
* grow exponentially, since that will guarantee linear time
* complexity. */
if(pPath->numEntriesAllocated)
{
numEntriesToAllocate=pPath->numEntriesAllocated;
while(numEntriesToAllocate<numEntries)
numEntriesToAllocate=numEntriesToAllocate*GROW_FACTOR_NUMER/
GROW_FACTOR_DENOM;
}
else
numEntriesToAllocate=numEntries;
/* Allocate new arrays */
pPointsNew=(POINT *)ExAllocatePool(NonPagedPool, numEntriesToAllocate * sizeof(POINT));
if(!pPointsNew)
return FALSE;
pFlagsNew=(BYTE *)ExAllocatePool(NonPagedPool, numEntriesToAllocate * sizeof(BYTE));
if(!pFlagsNew)
{
ExFreePool(pPointsNew);
return FALSE;
}
/* Copy old arrays to new arrays and discard old arrays */
if(pPath->pPoints)
{
assert(pPath->pFlags);
memcpy(pPointsNew, pPath->pPoints,
sizeof(POINT)*pPath->numEntriesUsed);
memcpy(pFlagsNew, pPath->pFlags,
sizeof(BYTE)*pPath->numEntriesUsed);
ExFreePool(pPath->pPoints);
ExFreePool(pPath->pFlags);
}
pPath->pPoints=pPointsNew;
pPath->pFlags=pFlagsNew;
pPath->numEntriesAllocated=numEntriesToAllocate;
}
return TRUE;
}
/* PATH_GetPathFromHDC
*
* Retrieves a pointer to the GdiPath structure contained in an HDC and
* places it in *ppPath. TRUE is returned if successful, FALSE otherwise.
*/
static BOOL PATH_GetPathFromHDC(HDC hdc, GdiPath **ppPath)
{
DC *pDC;
pDC=DC_HandleToPtr(hdc);
if(pDC)
{
*ppPath=&pDC->w.path;
return TRUE;
}
else
return FALSE;
}
/* PATH_DoArcPart
*
* Creates a Bezier spline that corresponds to part of an arc and appends the
* corresponding points to the path. The start and end angles are passed in
* "angleStart" and "angleEnd"; these angles should span a quarter circle
* at most. If "addMoveTo" is true, a PT_MOVETO entry for the first control
* point is added to the path; otherwise, it is assumed that the current
* position is equal to the first control point.
*/
static BOOL PATH_DoArcPart(GdiPath *pPath, FLOAT_POINT corners[],
double angleStart, double angleEnd, BOOL addMoveTo)
{
double halfAngle, a;
double xNorm[4], yNorm[4];
POINT point;
int i;
assert(fabs(angleEnd-angleStart)<=M_PI_2);
/* FIXME: Is there an easier way of computing this? */
/* Compute control points */
halfAngle=(angleEnd-angleStart)/2.0;
if(fabs(halfAngle)>1e-8)
{
a=4.0/3.0*(1-cos(halfAngle))/sin(halfAngle);
xNorm[0]=cos(angleStart);
yNorm[0]=sin(angleStart);
xNorm[1]=xNorm[0] - a*yNorm[0];
yNorm[1]=yNorm[0] + a*xNorm[0];
xNorm[3]=cos(angleEnd);
yNorm[3]=sin(angleEnd);
xNorm[2]=xNorm[3] + a*yNorm[3];
yNorm[2]=yNorm[3] - a*xNorm[3];
}
else
for(i=0; i<4; i++)
{
xNorm[i]=cos(angleStart);
yNorm[i]=sin(angleStart);
}
/* Add starting point to path if desired */
if(addMoveTo)
{
PATH_ScaleNormalizedPoint(corners, xNorm[0], yNorm[0], &point);
if(!PATH_AddEntry(pPath, &point, PT_MOVETO))
return FALSE;
}
/* Add remaining control points */
for(i=1; i<4; i++)
{
PATH_ScaleNormalizedPoint(corners, xNorm[i], yNorm[i], &point);
if(!PATH_AddEntry(pPath, &point, PT_BEZIERTO))
return FALSE;
}
return TRUE;
}
/* PATH_ScaleNormalizedPoint
*
* Scales a normalized point (x, y) with respect to the box whose corners are
* passed in "corners". The point is stored in "*pPoint". The normalized
* coordinates (-1.0, -1.0) correspond to corners[0], the coordinates
* (1.0, 1.0) correspond to corners[1].
*/
static void PATH_ScaleNormalizedPoint(FLOAT_POINT corners[], double x,
double y, POINT *pPoint)
{
pPoint->x=GDI_ROUND( (double)corners[0].x +
(double)(corners[1].x-corners[0].x)*0.5*(x+1.0) );
pPoint->y=GDI_ROUND( (double)corners[0].y +
(double)(corners[1].y-corners[0].y)*0.5*(y+1.0) );
}
/* PATH_NormalizePoint
*
* Normalizes a point with respect to the box whose corners are passed in
* corners. The normalized coordinates are stored in *pX and *pY.
*/
static void PATH_NormalizePoint(FLOAT_POINT corners[],
const FLOAT_POINT *pPoint,
double *pX, double *pY)
{
*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;
}

View file

@ -10,18 +10,39 @@
HPEN
STDCALL
W32kCreatePen(INT PenStyle,
INT Width,
COLORREF Color)
W32kCreatePen(INT PenStyle, INT Width, COLORREF Color)
{
UNIMPLEMENTED;
LOGPEN logpen;
logpen.lopnStyle = PenStyle;
logpen.lopnWidth.x = Width;
logpen.lopnWidth.y = 0;
logpen.lopnColor = Color;
return W32kCreatePenIndirect(&logpen);
}
HPEN
STDCALL
W32kCreatePenIndirect(CONST PLOGPEN lgpn)
W32kCreatePenIndirect(CONST PLOGPEN lgpn)
{
UNIMPLEMENTED;
PPENOBJ penPtr;
HPEN hpen;
if (lgpn->lopnStyle > PS_INSIDEFRAME) return 0;
penPtr = PENOBJ_AllocPen();
hpen = PENOBJ_PtrToHandle(penPtr);
if (!hpen) return 0;
PENOBJ_LockPen(hpen);
penPtr->logpen.lopnStyle = lgpn->lopnStyle;
penPtr->logpen.lopnWidth = lgpn->lopnWidth;
penPtr->logpen.lopnColor = lgpn->lopnColor;
PENOBJ_UnlockPen(hpen);
return hpen;
}
HPEN
@ -34,6 +55,3 @@ W32kExtCreatePen(DWORD PenStyle,
{
UNIMPLEMENTED;
}

View file

@ -5,6 +5,7 @@
#include <ddk/ntddk.h>
#include <win32k/dc.h>
#include <win32k/text.h>
#include <win32k/kapi.h>
// #define NDEBUG
#include <internal/debug.h>
@ -186,6 +187,8 @@ W32kGetGlyphOutline(HDC hDC,
CONST LPMAT2 mat2)
{
UNIMPLEMENTED;
}
DWORD
@ -361,7 +364,19 @@ W32kTextOut(HDC hDC,
LPCWSTR String,
int Count)
{
UNIMPLEMENTED;
DC *dc = DC_HandleToPtr(hDC);
SURFOBJ *SurfObj = AccessUserObject(dc->Surface);
PUNICODE_STRING UString;
PANSI_STRING AString;
RtlCreateUnicodeString(UString, (PWSTR)String);
RtlUnicodeStringToAnsiString(AString, UString, TRUE);
// For now we're just going to use an internal font
grWriteCellString(SurfObj, XStart, YStart, AString->Buffer, 0xffffff);
RtlFreeAnsiString(AString);
RtlFreeUnicodeString(UString);
}
UINT

View file

@ -42,7 +42,6 @@ STUB(EngGetPrinterData)
STUB(EngGetPrinterDataFileName)
STUB(EngGetProcessHandle)
STUB(EngGetType1FontList)
STUB(EngLoadModule)
STUB(EngLoadModuleForWrite)
STUB(EngLockDriverObj)
STUB(EngMapEvent)

View file

@ -1,4 +1,4 @@
; $Id: win32k.def,v 1.10 2000/04/11 20:56:11 jfilby Exp $
; $Id: win32k.def,v 1.11 2000/06/16 07:22:36 jfilby Exp $
;
; win32k.def
;
@ -64,7 +64,7 @@ EngGetProcessHandle
EngGetType1FontList
EngLineTo
EngLoadImage@4
EngLoadModule
EngLoadModule@4
EngLoadModuleForWrite
EngLockDriverObj
EngLockSurface

View file

@ -1,4 +1,4 @@
; $Id: win32k.edf,v 1.2 2000/03/17 21:56:43 jfilby Exp $
; $Id: win32k.edf,v 1.3 2000/06/16 07:22:36 jfilby Exp $
;
; win32k.def
;
@ -64,7 +64,7 @@ EngGetProcessHandle
EngGetType1FontList
EngLineTo
EngLoadImage=EngLoadImage@4
EngLoadModule
EngLoadModule=EngLoadModule@4
EngLoadModuleForWrite
EngLockDriverObj
EngLockSurface