/*
- * ReactOS W32 Subsystem
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ * Graphics paths (BeginPath, EndPath etc.)
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Copyright 1997, 1998 Martin Boehme
+ * 1999 Huw D M Davies
+ * Copyright 2005 Dmitry Timoshkov
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+/*
+ *
+ * Addaped for the use in ReactOS.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * PROJECT: ReactOS win32 kernel mode subsystem
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: subsystems/win32/win32k/objects/path.c
+ * PURPOSE: Path support
+ * PROGRAMMER:
*/
-#include <w32k.h>
-#include "math.h"
+#include <win32k.h>
+#define _USE_MATH_DEFINES
+#include <math.h>
#define NDEBUG
#include <debug.h>
FASTCALL
PATH_Delete(HPATH hPath)
{
+ PPATH pPath;
if (!hPath) return FALSE;
- PPATH pPath = PATH_LockPath( hPath );
+ pPath = PATH_LockPath( hPath );
if (!pPath) return FALSE;
PATH_DestroyGdiPath( pPath );
PATH_UnlockPath( pPath );
FASTCALL
PATH_FillPath( PDC dc, PPATH pPath )
{
- INT mapMode, graphicsMode;
- SIZE ptViewportExt, ptWindowExt;
- POINTL ptViewportOrg, ptWindowOrg;
+ //INT mapMode, graphicsMode;
+ //SIZE ptViewportExt, ptWindowExt;
+ //POINTL ptViewportOrg, ptWindowOrg;
XFORM xform;
HRGN hrgn;
- PDC_ATTR Dc_Attr = dc->pDc_Attr;
-
- if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+ PDC_ATTR pdcattr = dc->pdcattr;
if( pPath->state != PATH_Closed )
{
- SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+ EngSetLastError(ERROR_CAN_NOT_COMPLETE);
return FALSE;
}
- if( PATH_PathToRegion( pPath, Dc_Attr->jFillMode, &hrgn ))
+ if( PATH_PathToRegion( pPath, pdcattr->jFillMode, &hrgn ))
{
/* Since PaintRgn interprets the region as being in logical coordinates
* but the points we store for the path are already in device
*/
/* Save the information about the old mapping mode */
- mapMode = Dc_Attr->iMapMode;
- ptViewportExt = Dc_Attr->szlViewportExt;
- ptViewportOrg = Dc_Attr->ptlViewportOrg;
- ptWindowExt = Dc_Attr->szlWindowExt;
- ptWindowOrg = Dc_Attr->ptlWindowOrg;
+ //mapMode = pdcattr->iMapMode;
+ //ptViewportExt = pdcattr->szlViewportExt;
+ //ptViewportOrg = pdcattr->ptlViewportOrg;
+ //ptWindowExt = pdcattr->szlWindowExt;
+ //ptWindowOrg = pdcattr->ptlWindowOrg;
/* Save world transform
* NB: The Windows documentation on world transforms would lead one to
* tests show that resetting the graphics mode to GM_COMPATIBLE does
* not reset the world transform.
*/
- MatrixS2XForm(&xform, &dc->DcLevel.mxWorldToPage);
+ MatrixS2XForm(&xform, &dc->dclevel.mxWorldToPage);
/* Set MM_TEXT */
// IntGdiSetMapMode( dc, MM_TEXT );
-// Dc_Attr->ptlViewportOrg.x = 0;
-// Dc_Attr->ptlViewportOrg.y = 0;
-// Dc_Attr->ptlWindowOrg.x = 0;
-// Dc_Attr->ptlWindowOrg.y = 0;
+// pdcattr->ptlViewportOrg.x = 0;
+// pdcattr->ptlViewportOrg.y = 0;
+// pdcattr->ptlWindowOrg.x = 0;
+// pdcattr->ptlWindowOrg.y = 0;
- graphicsMode = Dc_Attr->iGraphicsMode;
-// Dc_Attr->iGraphicsMode = GM_ADVANCED;
+ // graphicsMode = pdcattr->iGraphicsMode;
+// pdcattr->iGraphicsMode = GM_ADVANCED;
// IntGdiModifyWorldTransform( dc, &xform, MWT_IDENTITY );
-// Dc_Attr->iGraphicsMode = graphicsMode;
+// pdcattr->iGraphicsMode = graphicsMode;
/* Paint the region */
IntGdiPaintRgn( dc, hrgn );
- NtGdiDeleteObject( hrgn );
+ GreDeleteObject( hrgn );
/* Restore the old mapping mode */
// IntGdiSetMapMode( dc, mapMode );
-// Dc_Attr->szlViewportExt = ptViewportExt;
-// Dc_Attr->ptlViewportOrg = ptViewportOrg;
-// Dc_Attr->szlWindowExt = ptWindowExt;
-// Dc_Attr->ptlWindowOrg = ptWindowOrg;
+// pdcattr->szlViewportExt = ptViewportExt;
+// pdcattr->ptlViewportOrg = ptViewportOrg;
+// pdcattr->szlWindowExt = ptWindowExt;
+// pdcattr->ptlWindowOrg = ptWindowOrg;
/* Go to GM_ADVANCED temporarily to restore the world transform */
- graphicsMode = Dc_Attr->iGraphicsMode;
-// Dc_Attr->iGraphicsMode = GM_ADVANCED;
+ //graphicsMode = pdcattr->iGraphicsMode;
+// pdcattr->iGraphicsMode = GM_ADVANCED;
// IntGdiModifyWorldTransform( dc, &xform, MWT_MAX+1 );
-// Dc_Attr->iGraphicsMode = graphicsMode;
+// pdcattr->iGraphicsMode = graphicsMode;
return TRUE;
}
return FALSE;
FASTCALL
PATH_MoveTo ( PDC dc )
{
- PPATH pPath = PATH_LockPath( dc->DcLevel.hPath );
+ PPATH pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
/* Check that path is open */
PPATH pPath;
POINT point, pointCurPos;
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
/* Check that path is open */
POINT corners[2], pointTemp;
INT temp;
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
/* Check that path is open */
}
/* In GM_COMPATIBLE, don't include bottom and right edges */
- if ( IntGetGraphicsMode(dc) == GM_COMPATIBLE )
+ if (dc->pdcattr->iGraphicsMode == GM_COMPATIBLE)
{
corners[1].x--;
corners[1].y--;
POINT corners[2], pointTemp;
FLOAT_POINT ellCorners[2];
- pPath = PATH_LockPath( dc->DcLevel.hPath );
- if (!pPath) return FALSE;
+ pPath = PATH_LockPath( dc->dclevel.hPath );
+ if (!pPath) return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
BOOL Ret = PATH_Arc ( dc, x1, y1, x2, y2, x1, (y1+y2)/2, x1, (y1+y2)/2, GdiTypeArc );
if (Ret)
{
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
IntGdiCloseFigure(pPath);
PATH_UnlockPath( pPath );
ASSERT ( dc );
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
- clockwise = ((dc->DcLevel.flPath & DCPATH_CLOCKWISE) != 0);
+ clockwise = ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
/* Check that path is open */
if ( pPath->state != PATH_Open )
{
Ret = FALSE;
- goto ArcExit;
+ goto ArcExit;
}
/* Check for zero height / width */
}
/* In GM_COMPATIBLE, don't include bottom and right edges */
- if ( IntGetGraphicsMode(dc) == GM_COMPATIBLE )
+ if (dc->pdcattr->iGraphicsMode == GM_COMPATIBLE )
{
corners[1].x--;
corners[1].y--;
ASSERT ( pts );
ASSERT ( cbPoints );
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
-
+
/* Check that path is open */
if ( pPath->state != PATH_Open )
{
ASSERT ( pts );
ASSERT ( cbPoints );
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
/* Check that path is open */
ASSERT ( pts );
ASSERT ( cbPoints );
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
/* Check that path is open */
ASSERT ( pts );
ASSERT ( cbPoints );
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
-
+
/* Check that path is open */
if ( pPath->state != PATH_Open )
{
ASSERT ( dc );
ASSERT ( pts );
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
/* Check that path is open */
ASSERT ( counts );
ASSERT ( polygons );
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
/* Check that path is open */
ASSERT ( counts );
ASSERT ( polylines );
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
/* Check that path is open */
BOOL PATH_CheckCorners(DC *dc, POINT corners[], INT x1, INT y1, INT x2, INT y2)
{
INT temp;
- PDC_ATTR Dc_Attr = dc->pDc_Attr;
- if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+ PDC_ATTR pdcattr = dc->pdcattr;
/* Convert points to device coordinates */
corners[0].x=x1;
}
/* In GM_COMPATIBLE, don't include bottom and right edges */
- if(Dc_Attr->iGraphicsMode==GM_COMPATIBLE)
+ if(pdcattr->iGraphicsMode==GM_COMPATIBLE)
{
corners[1].x--;
corners[1].y--;
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;
if((pPath->pFlags[i] & ~PT_CLOSEFIGURE) == PT_MOVETO)
numStrokes++;
+ if(numStrokes == 0)
+ {
+ return FALSE;
+ }
+
/* Allocate memory for number-of-points-in-stroke array */
pNumPointsInStroke = ExAllocatePoolWithTag(PagedPool, sizeof(ULONG) * numStrokes, TAG_PATH);
if(!pNumPointsInStroke)
{
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
nPolyFillMode);
if(hrgn==(HRGN)0)
{
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
SIZE szViewportExt, szWindowExt;
DWORD mapMode, graphicsMode;
XFORM xform;
- PDC_ATTR Dc_Attr = dc->pDc_Attr;
+ PDC_ATTR pdcattr = dc->pdcattr;
DPRINT("Enter %s\n", __FUNCTION__);
if (pPath->state != PATH_Closed)
return FALSE;
- if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
/* Save the mapping mode info */
- mapMode = Dc_Attr->iMapMode;
- IntGetViewportExtEx(dc, &szViewportExt);
- IntGetViewportOrgEx(dc, &ptViewportOrg);
- IntGetWindowExtEx(dc, &szWindowExt);
- IntGetWindowOrgEx(dc, &ptWindowOrg);
-
- MatrixS2XForm(&xform, &dc->DcLevel.mxWorldToPage);
+ mapMode = pdcattr->iMapMode;
+
+ DC_vUpdateViewportExt(dc);
+ szViewportExt = dc->pdcattr->szlViewportExt;
+ ptViewportOrg = dc->pdcattr->ptlViewportOrg;
+ szWindowExt = dc->pdcattr->szlWindowExt;
+ ptWindowOrg = dc->pdcattr->ptlWindowOrg;
+
+ MatrixS2XForm(&xform, &dc->dclevel.mxWorldToPage);
/* Set MM_TEXT */
- Dc_Attr->iMapMode = MM_TEXT;
- Dc_Attr->ptlViewportOrg.x = 0;
- Dc_Attr->ptlViewportOrg.y = 0;
- Dc_Attr->ptlWindowOrg.x = 0;
- Dc_Attr->ptlWindowOrg.y = 0;
- graphicsMode = Dc_Attr->iGraphicsMode;
- Dc_Attr->iGraphicsMode = GM_ADVANCED;
+ pdcattr->iMapMode = MM_TEXT;
+ pdcattr->ptlViewportOrg.x = 0;
+ pdcattr->ptlViewportOrg.y = 0;
+ pdcattr->ptlWindowOrg.x = 0;
+ pdcattr->ptlWindowOrg.y = 0;
+ graphicsMode = pdcattr->iGraphicsMode;
+ pdcattr->iGraphicsMode = GM_ADVANCED;
IntGdiModifyWorldTransform(dc, &xform, MWT_IDENTITY);
- Dc_Attr->iGraphicsMode = graphicsMode;
+ pdcattr->iGraphicsMode = graphicsMode;
/* Allocate enough memory for the worst case without beziers (one PT_MOVETO
* and the rest PT_LINETO with PT_CLOSEFIGURE at the end) plus some buffer
if(!pLinePts)
{
DPRINT1("Can't allocate pool!\n");
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto end;
}
nLinePts = 0;
if(pLinePts) ExFreePoolWithTag(pLinePts, TAG_PATH);
/* Restore the old mapping mode */
- Dc_Attr->iMapMode = mapMode;
- Dc_Attr->szlWindowExt.cx = szWindowExt.cx;
- Dc_Attr->szlWindowExt.cy = szWindowExt.cy;
- Dc_Attr->ptlWindowOrg.x = ptWindowOrg.x;
- Dc_Attr->ptlWindowOrg.y = ptWindowOrg.y;
+ pdcattr->iMapMode = mapMode;
+ pdcattr->szlWindowExt.cx = szWindowExt.cx;
+ pdcattr->szlWindowExt.cy = szWindowExt.cy;
+ pdcattr->ptlWindowOrg.x = ptWindowOrg.x;
+ pdcattr->ptlWindowOrg.y = ptWindowOrg.y;
- Dc_Attr->szlViewportExt.cx = szViewportExt.cx;
- Dc_Attr->szlViewportExt.cy = szViewportExt.cy;
- Dc_Attr->ptlViewportOrg.x = ptViewportOrg.x;
- Dc_Attr->ptlViewportOrg.y = ptViewportOrg.y;
+ pdcattr->szlViewportExt.cx = szViewportExt.cx;
+ pdcattr->szlViewportExt.cy = szViewportExt.cy;
+ pdcattr->ptlViewportOrg.x = ptViewportOrg.x;
+ pdcattr->ptlViewportOrg.y = ptViewportOrg.y;
/* Restore the world transform */
- XForm2MatrixS(&dc->DcLevel.mxWorldToPage, &xform);
+ XForm2MatrixS(&dc->dclevel.mxWorldToPage, &xform);
/* If we've moved the current point then get its new position
which will be in device (MM_TEXT) co-ords, convert it to
POINT pt;
IntGetCurrentPositionEx(dc, &pt);
IntDPtoLP(dc, &pt, 1);
- IntGdiMoveToEx(dc, pt.x, pt.y, NULL);
+ IntGdiMoveToEx(dc, pt.x, pt.y, NULL, FALSE);
}
DPRINT("Leave %s, ret=%d\n", __FUNCTION__, ret);
return ret;
FASTCALL
PATH_WidenPath(DC *dc)
{
- INT i, j, numStrokes, numOldStrokes, penWidth, penWidthIn, penWidthOut, size, penStyle;
+ INT i, j, numStrokes, penWidth, penWidthIn, penWidthOut, size, penStyle;
BOOL ret = FALSE;
- PPATH pPath, pNewPath, *pStrokes, *pOldStrokes, pUpPath, pDownPath;
+ PPATH pPath, pNewPath, *pStrokes = NULL, *pOldStrokes, pUpPath, pDownPath;
EXTLOGPEN *elp;
DWORD obj_type, joint, endcap, penType;
- PDC_ATTR Dc_Attr = dc->pDc_Attr;
+ PDC_ATTR pdcattr = dc->pdcattr;
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
if(pPath->state == PATH_Open)
{
PATH_UnlockPath( pPath );
- SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+ EngSetLastError(ERROR_CAN_NOT_COMPLETE);
return FALSE;
}
- if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-
PATH_FlattenPath(pPath);
- size = IntGdiGetObject( Dc_Attr->hpen, 0, NULL);
+ size = IntGdiGetObject( pdcattr->hpen, 0, NULL);
if (!size)
{
PATH_UnlockPath( pPath );
- SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+ EngSetLastError(ERROR_CAN_NOT_COMPLETE);
return FALSE;
}
elp = ExAllocatePoolWithTag(PagedPool, size, TAG_PATH);
- (VOID) IntGdiGetObject( Dc_Attr->hpen, size, elp);
+ (VOID) IntGdiGetObject( pdcattr->hpen, size, elp);
- obj_type = GDIOBJ_GetObjectType(Dc_Attr->hpen);
+ obj_type = GDIOBJ_GetObjectType(pdcattr->hpen);
if(obj_type == GDI_OBJECT_TYPE_PEN)
{
penStyle = ((LOGPEN*)elp)->lopnStyle;
}
else
{
- SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+ EngSetLastError(ERROR_CAN_NOT_COMPLETE);
ExFreePoolWithTag(elp, TAG_PATH);
PATH_UnlockPath( pPath );
return FALSE;
if(obj_type == GDI_OBJECT_TYPE_EXTPEN && penType == PS_COSMETIC)
{
PATH_UnlockPath( pPath );
- SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+ EngSetLastError(ERROR_CAN_NOT_COMPLETE);
return FALSE;
}
penWidthOut++;
numStrokes = 0;
- numOldStrokes = 1;
-
- pStrokes = ExAllocatePoolWithTag(PagedPool, sizeof(PPATH), TAG_PATH);
- pStrokes[0] = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
- PATH_InitGdiPath(pStrokes[0]);
- pStrokes[0]->pFlags = ExAllocatePoolWithTag(PagedPool, pPath->numEntriesUsed * sizeof(INT), TAG_PATH);
- pStrokes[0]->pPoints = ExAllocatePoolWithTag(PagedPool, pPath->numEntriesUsed * sizeof(POINT), TAG_PATH);
- pStrokes[0]->numEntriesUsed = 0;
for(i = 0, j = 0; i < pPath->numEntriesUsed; i++, j++)
{
}
numStrokes++;
j = 0;
- pOldStrokes = pStrokes; // Save old pointer.
- pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(PPATH), TAG_PATH);
- RtlCopyMemory(pStrokes, pOldStrokes, numOldStrokes * sizeof(PPATH));
- numOldStrokes = numStrokes; // Save orig count.
- ExFreePoolWithTag(pOldStrokes, TAG_PATH); // Free old pointer.
+ if (numStrokes == 1)
+ pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(PPATH), TAG_PATH);
+ else
+ {
+ pOldStrokes = pStrokes; // Save old pointer.
+ pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(PPATH), TAG_PATH);
+ if (!pStrokes) return FALSE;
+ RtlCopyMemory(pStrokes, pOldStrokes, numStrokes * sizeof(PPATH));
+ ExFreePoolWithTag(pOldStrokes, TAG_PATH); // Free old pointer.
+ }
+ if (!pStrokes) return FALSE;
pStrokes[numStrokes - 1] = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
PATH_InitGdiPath(pStrokes[numStrokes - 1]);
}
}
- pNewPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
+ pNewPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
PATH_InitGdiPath(pNewPath);
pNewPath->state = PATH_Open;
alpha = atan2( yb - yo, xb - xo ) - theta;
if (alpha > 0) alpha -= M_PI;
else alpha += M_PI;
- if(_joint == PS_JOIN_MITER && dc->DcLevel.laPath.eMiterLimit < fabs(1 / sin(alpha/2)))
+ if(_joint == PS_JOIN_MITER && dc->dclevel.laPath.eMiterLimit < fabs(1 / sin(alpha/2)))
{
_joint = PS_JOIN_BEVEL;
}
return ret;
}
+static inline INT int_from_fixed(FIXED f)
+{
+ return (f.fract >= 0x8000) ? (f.value + 1) : f.value;
+}
+
+/**********************************************************************
+ * PATH_BezierTo
+ *
+ * internally used by PATH_add_outline
+ */
+static
+VOID
+FASTCALL
+PATH_BezierTo(PPATH pPath, POINT *lppt, INT n)
+{
+ if (n < 2) return;
+
+ if (n == 2)
+ {
+ PATH_AddEntry(pPath, &lppt[1], PT_LINETO);
+ }
+ else if (n == 3)
+ {
+ PATH_AddEntry(pPath, &lppt[0], PT_BEZIERTO);
+ PATH_AddEntry(pPath, &lppt[1], PT_BEZIERTO);
+ PATH_AddEntry(pPath, &lppt[2], PT_BEZIERTO);
+ }
+ else
+ {
+ POINT pt[3];
+ INT i = 0;
+
+ pt[2] = lppt[0];
+ n--;
+
+ while (n > 2)
+ {
+ pt[0] = pt[2];
+ pt[1] = lppt[i+1];
+ pt[2].x = (lppt[i+2].x + lppt[i+1].x) / 2;
+ pt[2].y = (lppt[i+2].y + lppt[i+1].y) / 2;
+ PATH_BezierTo(pPath, pt, 3);
+ n--;
+ i++;
+ }
+
+ pt[0] = pt[2];
+ pt[1] = lppt[i+1];
+ pt[2] = lppt[i+2];
+ PATH_BezierTo(pPath, pt, 3);
+ }
+}
+
+static
+BOOL
+FASTCALL
+PATH_add_outline(PDC dc, INT x, INT y, TTPOLYGONHEADER *header, DWORD size)
+{
+ PPATH pPath;
+ TTPOLYGONHEADER *start;
+ POINT pt;
+
+ start = header;
+
+ pPath = PATH_LockPath(dc->dclevel.hPath);
+ {
+ return FALSE;
+ }
+
+ while ((char *)header < (char *)start + size)
+ {
+ TTPOLYCURVE *curve;
+
+ if (header->dwType != TT_POLYGON_TYPE)
+ {
+ DPRINT1("Unknown header type %d\n", header->dwType);
+ return FALSE;
+ }
+
+ pt.x = x + int_from_fixed(header->pfxStart.x);
+ pt.y = y - int_from_fixed(header->pfxStart.y);
+ IntLPtoDP(dc, &pt, 1);
+ PATH_AddEntry(pPath, &pt, PT_MOVETO);
+
+ curve = (TTPOLYCURVE *)(header + 1);
+
+ while ((char *)curve < (char *)header + header->cb)
+ {
+ /*DPRINT1("curve->wType %d\n", curve->wType);*/
+
+ switch(curve->wType)
+ {
+ case TT_PRIM_LINE:
+ {
+ WORD i;
+
+ for (i = 0; i < curve->cpfx; i++)
+ {
+ pt.x = x + int_from_fixed(curve->apfx[i].x);
+ pt.y = y - int_from_fixed(curve->apfx[i].y);
+ IntLPtoDP(dc, &pt, 1);
+ PATH_AddEntry(pPath, &pt, PT_LINETO);
+ }
+ break;
+ }
+
+ case TT_PRIM_QSPLINE:
+ case TT_PRIM_CSPLINE:
+ {
+ WORD i;
+ POINTFX ptfx;
+ POINT *pts = ExAllocatePoolWithTag(PagedPool, (curve->cpfx + 1) * sizeof(POINT), TAG_PATH);
+
+ if (!pts) return FALSE;
+
+ ptfx = *(POINTFX *)((char *)curve - sizeof(POINTFX));
+
+ pts[0].x = x + int_from_fixed(ptfx.x);
+ pts[0].y = y - int_from_fixed(ptfx.y);
+ IntLPtoDP(dc, &pts[0], 1);
+
+ for (i = 0; i < curve->cpfx; i++)
+ {
+ pts[i + 1].x = x + int_from_fixed(curve->apfx[i].x);
+ pts[i + 1].y = y - int_from_fixed(curve->apfx[i].y);
+ IntLPtoDP(dc, &pts[i + 1], 1);
+ }
+
+ PATH_BezierTo(pPath, pts, curve->cpfx + 1);
+
+ ExFreePoolWithTag(pts, TAG_PATH);
+ break;
+ }
+
+ default:
+ DPRINT1("Unknown curve type %04x\n", curve->wType);
+ return FALSE;
+ }
+
+ curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
+ }
+ header = (TTPOLYGONHEADER *)((char *)header + header->cb);
+ }
+
+ IntGdiCloseFigure( pPath );
+ PATH_UnlockPath( pPath );
+ return TRUE;
+}
+
+/**********************************************************************
+ * PATH_ExtTextOut
+ */
+BOOL
+FASTCALL
+PATH_ExtTextOut(PDC dc, INT x, INT y, UINT flags, const RECTL *lprc,
+ LPCWSTR str, UINT count, const INT *dx)
+{
+ unsigned int idx;
+ double cosEsc, sinEsc;
+ PDC_ATTR pdcattr;
+ PTEXTOBJ TextObj;
+ LOGFONTW lf;
+ POINTL org;
+ INT offset = 0, xoff = 0, yoff = 0;
+
+ if (!count) return TRUE;
+
+ pdcattr = dc->pdcattr;
+
+ TextObj = RealizeFontInit( pdcattr->hlfntNew);
+ if ( !TextObj ) return FALSE;
+
+ FontGetObject( TextObj, sizeof(lf), &lf);
+ TEXTOBJ_UnlockText(TextObj);
+
+ if (lf.lfEscapement != 0)
+ {
+ cosEsc = cos(lf.lfEscapement * M_PI / 1800);
+ sinEsc = sin(lf.lfEscapement * M_PI / 1800);
+ } else
+ {
+ cosEsc = 1;
+ sinEsc = 0;
+ }
+
+ org = dc->ptlDCOrig;
+
+ for (idx = 0; idx < count; idx++)
+ {
+ GLYPHMETRICS gm;
+ DWORD dwSize;
+ void *outline;
+
+ dwSize = ftGdiGetGlyphOutline( dc,
+ str[idx],
+ GGO_GLYPH_INDEX | GGO_NATIVE,
+ &gm,
+ 0,
+ NULL,
+ NULL,
+ TRUE);
+ if (!dwSize) return FALSE;
+
+ outline = ExAllocatePoolWithTag(PagedPool, dwSize, TAG_PATH);
+ if (!outline) return FALSE;
+
+ ftGdiGetGlyphOutline( dc,
+ str[idx],
+ GGO_GLYPH_INDEX | GGO_NATIVE,
+ &gm,
+ dwSize,
+ outline,
+ NULL,
+ TRUE);
+
+ PATH_add_outline(dc, org.x + x + xoff, org.x + y + yoff, outline, dwSize);
+
+ ExFreePoolWithTag(outline, TAG_PATH);
+
+ if (dx)
+ {
+ offset += dx[idx];
+ xoff = offset * cosEsc;
+ yoff = offset * -sinEsc;
+ }
+ else
+ {
+ xoff += gm.gmCellIncX;
+ yoff += gm.gmCellIncY;
+ }
+ }
+ return TRUE;
+}
/***********************************************************************
*/
BOOL
-STDCALL
+APIENTRY
NtGdiAbortPath(HDC hDC)
{
PPATH pPath;
PDC dc = DC_LockDc ( hDC );
if ( !dc )
{
- SetLastWin32Error(ERROR_INVALID_HANDLE);
+ EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
- pPath = PATH_LockPath(dc->DcLevel.hPath);
+ pPath = PATH_LockPath(dc->dclevel.hPath);
{
DC_UnlockDc(dc);
return FALSE;
}
BOOL
-STDCALL
+APIENTRY
NtGdiBeginPath( HDC hDC )
{
PPATH pPath;
dc = DC_LockDc ( hDC );
if ( !dc )
{
- SetLastWin32Error(ERROR_INVALID_HANDLE);
+ EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
/* If path is already open, do nothing. Check if not Save DC state */
- if ((dc->DcLevel.flPath & DCPATH_ACTIVE) && !(dc->DcLevel.flPath & DCPATH_SAVE))
+ if ((dc->dclevel.flPath & DCPATH_ACTIVE) && !(dc->dclevel.flPath & DCPATH_SAVE))
{
DC_UnlockDc ( dc );
return TRUE;
}
- if ( dc->DcLevel.hPath )
+ if ( dc->dclevel.hPath )
{
- DPRINT1("BeginPath 1 0x%x\n", dc->DcLevel.hPath);
- if ( !(dc->DcLevel.flPath & DCPATH_SAVE) )
+ DPRINT("BeginPath 1 0x%x\n", dc->dclevel.hPath);
+ if ( !(dc->dclevel.flPath & DCPATH_SAVE) )
{ // Remove previous handle.
- if (!PATH_Delete(dc->DcLevel.hPath))
+ if (!PATH_Delete(dc->dclevel.hPath))
{
DC_UnlockDc ( dc );
return FALSE;
}
else
{ // Clear flags and Handle.
- dc->DcLevel.flPath &= ~(DCPATH_SAVE|DCPATH_ACTIVE);
- dc->DcLevel.hPath = NULL;
+ dc->dclevel.flPath &= ~(DCPATH_SAVE|DCPATH_ACTIVE);
+ dc->dclevel.hPath = NULL;
}
}
pPath = PATH_AllocPathWithHandle();
if (!pPath)
{
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
- dc->DcLevel.flPath |= DCPATH_ACTIVE; // Set active ASAP!
+ dc->dclevel.flPath |= DCPATH_ACTIVE; // Set active ASAP!
- dc->DcLevel.hPath = pPath->BaseObject.hHmgr;
+ dc->dclevel.hPath = pPath->BaseObject.hHmgr;
- DPRINT1("BeginPath 2 h 0x%x p 0x%x\n", dc->DcLevel.hPath, pPath);
+ DPRINT("BeginPath 2 h 0x%x p 0x%x\n", dc->dclevel.hPath, pPath);
// Path handles are shared. Also due to recursion with in the same thread.
GDIOBJ_UnlockObjByPtr((POBJ)pPath); // Unlock
- pPath = PATH_LockPath(dc->DcLevel.hPath); // Share Lock.
+ pPath = PATH_LockPath(dc->dclevel.hPath); // Share Lock.
/* Make sure that path is empty */
PATH_EmptyPath( pPath );
}
BOOL
-STDCALL
+APIENTRY
NtGdiCloseFigure(HDC hDC)
{
BOOL Ret = FALSE; // default to failure
pDc = DC_LockDc(hDC);
if (!pDc)
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
- }
- pPath = PATH_LockPath( pDc->DcLevel.hPath );
+ }
+ pPath = PATH_LockPath( pDc->dclevel.hPath );
if (!pPath)
{
DC_UnlockDc(pDc);
else
{
// FIXME: check if lasterror is set correctly
- SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+ EngSetLastError(ERROR_CAN_NOT_COMPLETE);
}
PATH_UnlockPath( pPath );
}
BOOL
-STDCALL
+APIENTRY
NtGdiEndPath(HDC hDC)
{
BOOL ret = TRUE;
if ( !dc )
{
- SetLastWin32Error(ERROR_INVALID_HANDLE);
+ EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath)
{
DC_UnlockDc ( dc );
return FALSE;
}
/* Check that path is currently being constructed */
- if ( (pPath->state != PATH_Open) || !(dc->DcLevel.flPath & DCPATH_ACTIVE) )
+ if ( (pPath->state != PATH_Open) || !(dc->dclevel.flPath & DCPATH_ACTIVE) )
{
- DPRINT1("EndPath ERROR! 0x%x\n", dc->DcLevel.hPath);
- SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+ DPRINT1("EndPath ERROR! 0x%x\n", dc->dclevel.hPath);
+ EngSetLastError(ERROR_CAN_NOT_COMPLETE);
ret = FALSE;
}
/* Set flag to indicate that path is finished */
else
{
- DPRINT1("EndPath 0x%x\n", dc->DcLevel.hPath);
+ DPRINT("EndPath 0x%x\n", dc->dclevel.hPath);
pPath->state = PATH_Closed;
- dc->DcLevel.flPath &= ~DCPATH_ACTIVE;
+ dc->dclevel.flPath &= ~DCPATH_ACTIVE;
}
PATH_UnlockPath( pPath );
DC_UnlockDc ( dc );
}
BOOL
-STDCALL
+APIENTRY
NtGdiFillPath(HDC hDC)
{
- BOOL ret = TRUE;
+ BOOL ret = FALSE;
PPATH pPath;
- PDC dc = DC_LockDc ( hDC );
-
- if ( !dc )
+ PDC_ATTR pdcattr;
+ PDC dc;
+
+ dc = DC_LockDc(hDC);
+ if (!dc)
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath)
{
DC_UnlockDc ( dc );
return FALSE;
}
+ DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+ NULL, dc->rosdc.CombinedClip->rclBounds);
+
+ pdcattr = dc->pdcattr;
+
+ if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(dc);
+
+ if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(dc);
+
ret = PATH_FillPath( dc, pPath );
if ( ret )
{
}
PATH_UnlockPath( pPath );
+ DC_vFinishBlit(dc, NULL);
DC_UnlockDc ( dc );
return ret;
}
BOOL
-STDCALL
+APIENTRY
NtGdiFlattenPath(HDC hDC)
{
BOOL Ret = FALSE;
pDc = DC_LockDc(hDC);
if (!pDc)
{
- SetLastWin32Error(ERROR_INVALID_HANDLE);
+ EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
- pPath = PATH_LockPath( pDc->DcLevel.hPath );
+ pPath = PATH_LockPath( pDc->dclevel.hPath );
if (!pPath)
{
DC_UnlockDc ( pDc );
if (!(pDc = DC_LockDc(hdc)))
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
- worker.f = pDc->DcLevel.laPath.eMiterLimit;
+ worker.f = pDc->dclevel.laPath.eMiterLimit;
if (pdwOut)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForWrite(pdwOut,
sizeof(DWORD),
1);
*pdwOut = worker.l;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
}
INT
-STDCALL
+APIENTRY
NtGdiGetPath(
HDC hDC,
LPPOINT Points,
if (!dc)
{
DPRINT1("Can't lock dc!\n");
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
- pPath = PATH_LockPath( dc->DcLevel.hPath );
+ pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath)
{
DC_UnlockDc ( dc );
if (pPath->state != PATH_Closed)
{
- SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+ EngSetLastError(ERROR_CAN_NOT_COMPLETE);
goto done;
}
}
else if(nSize<pPath->numEntriesUsed)
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
goto done;
}
else
{
- _SEH_TRY
+ _SEH2_TRY
{
memcpy(Points, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
memcpy(Types, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
ret = pPath->numEntriesUsed;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- SetLastNtError(_SEH_GetExceptionCode());
+ SetLastNtError(_SEH2_GetExceptionCode());
}
- _SEH_END
+ _SEH2_END
}
done:
}
HRGN
-STDCALL
+APIENTRY
NtGdiPathToRegion(HDC hDC)
{
PPATH pPath;
HRGN hrgnRval = 0;
DC *pDc;
- PDC_ATTR Dc_Attr;
+ PDC_ATTR pdcattr;
DPRINT("Enter %s\n", __FUNCTION__);
pDc = DC_LockDc(hDC);
if (!pDc)
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
- Dc_Attr = pDc->pDc_Attr;
- if(!Dc_Attr) Dc_Attr = &pDc->Dc_Attr;
+ pdcattr = pDc->pdcattr;
- pPath = PATH_LockPath( pDc->DcLevel.hPath );
+ pPath = PATH_LockPath( pDc->dclevel.hPath );
if (!pPath)
{
DC_UnlockDc ( pDc );
if (pPath->state!=PATH_Closed)
{
//FIXME: check that setlasterror is being called correctly
- SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+ EngSetLastError(ERROR_CAN_NOT_COMPLETE);
}
else
{
/* FIXME: Should we empty the path even if conversion failed? */
- if(PATH_PathToRegion(pPath, Dc_Attr->jFillMode, &hrgnRval))
+ if(PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgnRval))
PATH_EmptyPath(pPath);
}
if (!(pDc = DC_LockDc(hdc)))
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
worker.l = dwNew;
- worker1.f = pDc->DcLevel.laPath.eMiterLimit;
- pDc->DcLevel.laPath.eMiterLimit = worker.f;
+ worker1.f = pDc->dclevel.laPath.eMiterLimit;
+ pDc->dclevel.laPath.eMiterLimit = worker.f;
if (pdwOut)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForWrite(pdwOut,
sizeof(DWORD),
1);
*pdwOut = worker1.l;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
}
BOOL
-STDCALL
+APIENTRY
NtGdiStrokeAndFillPath(HDC hDC)
{
DC *pDc;
+ PDC_ATTR pdcattr;
PPATH pPath;
BOOL bRet = FALSE;
if (!(pDc = DC_LockDc(hDC)))
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
- pPath = PATH_LockPath( pDc->DcLevel.hPath );
+ pPath = PATH_LockPath( pDc->dclevel.hPath );
if (!pPath)
{
DC_UnlockDc ( pDc );
return FALSE;
}
+
+ DC_vPrepareDCsForBlit(pDc, pDc->rosdc.CombinedClip->rclBounds,
+ NULL, pDc->rosdc.CombinedClip->rclBounds);
+
+ pdcattr = pDc->pdcattr;
+
+ if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(pDc);
+
+ if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(pDc);
+
bRet = PATH_FillPath(pDc, pPath);
if (bRet) bRet = PATH_StrokePath(pDc, pPath);
if (bRet) PATH_EmptyPath(pPath);
PATH_UnlockPath( pPath );
+ DC_vFinishBlit(pDc, NULL);
DC_UnlockDc(pDc);
return bRet;
}
BOOL
-STDCALL
+APIENTRY
NtGdiStrokePath(HDC hDC)
{
DC *pDc;
+ PDC_ATTR pdcattr;
PPATH pPath;
BOOL bRet = FALSE;
if (!(pDc = DC_LockDc(hDC)))
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
- pPath = PATH_LockPath( pDc->DcLevel.hPath );
+ pPath = PATH_LockPath( pDc->dclevel.hPath );
if (!pPath)
{
DC_UnlockDc ( pDc );
return FALSE;
}
+ DC_vPrepareDCsForBlit(pDc, pDc->rosdc.CombinedClip->rclBounds,
+ NULL, pDc->rosdc.CombinedClip->rclBounds);
+
+ pdcattr = pDc->pdcattr;
+
+ if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(pDc);
+
bRet = PATH_StrokePath(pDc, pPath);
+
+ DC_vFinishBlit(pDc, NULL);
PATH_EmptyPath(pPath);
PATH_UnlockPath( pPath );
}
BOOL
-STDCALL
+APIENTRY
NtGdiWidenPath(HDC hDC)
{
BOOL Ret;
- PDC pdc = DC_LockDc ( hDC );
+ PDC pdc = DC_LockDc ( hDC );
if ( !pdc )
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
Ret = PATH_WidenPath(pdc);
return Ret;
}
-BOOL
-STDCALL
-NtGdiSelectClipPath(HDC hDC,
- int Mode)
-{
- HRGN hrgnPath;
- PPATH pPath;
- BOOL success = FALSE;
- PDC_ATTR Dc_Attr;
- PDC dc = DC_LockDc ( hDC );
-
- if ( !dc )
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- Dc_Attr = dc->pDc_Attr;
- if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-
- pPath = PATH_LockPath( dc->DcLevel.hPath );
- if (!pPath)
- {
- DC_UnlockDc ( dc );
- return FALSE;
- }
- /* Check that path is closed */
- if( pPath->state != PATH_Closed )
- {
- SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
- return FALSE;
- }
- /* Construct a region from the path */
- else if( PATH_PathToRegion( pPath, Dc_Attr->jFillMode, &hrgnPath ) )
- {
- success = GdiExtSelectClipRgn( dc, hrgnPath, Mode ) != ERROR;
- NtGdiDeleteObject( hrgnPath );
-
- /* Empty the path */
- if( success )
- PATH_EmptyPath( pPath);
- /* FIXME: Should this function delete the path even if it failed? */
- }
- PATH_UnlockPath( pPath );
- DC_UnlockDc ( dc );
- return success;
-}
-
/* EOF */