mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00
GDI improvements
svn path=/trunk/; revision=1183
This commit is contained in:
parent
94c0c4bab2
commit
0b34b1b746
27 changed files with 1722 additions and 89 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -34,7 +34,7 @@ W32kArcTo(HDC hDC,
|
|||
int XRadial2,
|
||||
int YRadial2);
|
||||
|
||||
int
|
||||
INT
|
||||
STDCALL
|
||||
W32kGetArcDirection(HDC hDC);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
193
reactos/subsys/win32k/objects/bezier.c
Normal file
193
reactos/subsys/win32k/objects/bezier.c
Normal 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;
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -251,6 +256,8 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver,
|
|||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
2
reactos/subsys/win32k/objects/font.c
Normal file
2
reactos/subsys/win32k/objects/font.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
/* EMPTY FOR NOW */
|
||||
/* Hope I didn't delete existing defs!! Check CVS version of this 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)
|
||||
{
|
||||
|
@ -59,11 +60,13 @@ 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
56
reactos/subsys/win32k/objects/objconv.c
Normal file
56
reactos/subsys/win32k/objects/objconv.c
Normal 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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,7 +42,6 @@ STUB(EngGetPrinterData)
|
|||
STUB(EngGetPrinterDataFileName)
|
||||
STUB(EngGetProcessHandle)
|
||||
STUB(EngGetType1FontList)
|
||||
STUB(EngLoadModule)
|
||||
STUB(EngLoadModuleForWrite)
|
||||
STUB(EngLockDriverObj)
|
||||
STUB(EngMapEvent)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue