ReactOS 0.4.17-dev-51-g1dc2e6d
path.c File Reference
#include <win32k.h>
#include <suppress.h>
Include dependency graph for path.c:

Go to the source code of this file.

Macros

#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 */
 
#define round(x)   ((int)((x)>0?(x)+0.5:(x)-0.5))
 

Functions

 DBG_DEFAULT_CHANNEL (GdiPath)
 
PPATH FASTCALL PATH_CreatePath (int count)
 
VOID FASTCALL PATH_DestroyGdiPath (PPATH pPath)
 
BOOL FASTCALL PATH_Delete (HPATH hPath)
 
VOID FASTCALL IntGdiCloseFigure (PPATH pPath)
 
BOOL FASTCALL GdiPathDPtoLP (PDC pdc, PPOINT ppt, INT count)
 
VOID FASTCALL PATH_InitGdiPath (PPATH pPath)
 
BOOL FASTCALL PATH_AssignGdiPath (PPATH pPathDest, const PPATH pPathSrc)
 
BOOL PATH_SavePath (DC *dst, DC *src)
 
BOOL PATH_RestorePath (DC *dst, DC *src)
 
VOID FASTCALL PATH_EmptyPath (PPATH pPath)
 
BOOL FASTCALL PATH_AddEntry (PPATH pPath, const POINT *pPoint, BYTE flags)
 
BOOL FASTCALL PATH_ReserveEntries (PPATH pPath, INT numEntries)
 
static BOOLEAN PATH_ScaleNormalizedPoint (POINT corners[], FLOATL x, FLOATL y, POINT *pPoint)
 
static VOID PATH_NormalizePoint (POINTL corners[], const POINTL *pPoint, FLOATL *pX, FLOATL *pY)
 
static BOOL PATH_CheckRect (DC *dc, RECTL *rect, INT x1, INT y1, INT x2, INT y2)
 
static BYTEadd_log_points (DC *dc, PPATH path, const POINT *points, DWORD count, BYTE type, BOOL bExtraPt)
 
static BYTEadd_points (PPATH path, const POINT *points, DWORD count, BYTE type)
 
static void reverse_points (POINT *points, UINT count)
 
static BOOL start_new_stroke (PPATH path)
 
static void update_current_pos (PPATH path)
 
static void close_figure (PPATH path)
 
static BOOL add_log_points_new_stroke (DC *dc, PPATH path, const POINT *points, DWORD count, BYTE type, BOOL bExtraPt)
 
BOOL FASTCALL PATH_MoveTo (PDC dc, PPATH pPath)
 
BOOL FASTCALL PATH_LineTo (PDC dc, INT x, INT y)
 
BOOL FASTCALL PATH_Rectangle (PDC dc, INT x1, INT y1, INT x2, INT y2)
 
BOOL PATH_RoundRect (DC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height)
 
BOOL PATH_Ellipse (PDC dc, INT x1, INT y1, INT x2, INT y2)
 
static BOOL PATH_DoArcPart (PPATH pPath, POINT corners[], double angleStart, double angleEnd, BYTE startEntryType)
 
BOOL FASTCALL PATH_Arc (PDC dc, INT x1, INT y1, INT x2, INT y2, INT xStart, INT yStart, INT xEnd, INT yEnd, INT direction, INT lines)
 
BOOL FASTCALL PATH_PolyBezierTo (PDC dc, const POINT *pts, DWORD cbPoints)
 
BOOL FASTCALL PATH_PolyBezier (PDC dc, const POINT *pts, DWORD cbPoints)
 
BOOL FASTCALL PATH_PolyDraw (PDC dc, const POINT *pts, const BYTE *types, DWORD cbPoints)
 
BOOL FASTCALL PATH_PolylineTo (PDC dc, const POINT *pts, DWORD cbPoints)
 
BOOL FASTCALL PATH_PolyPolygon (PDC dc, const POINT *pts, const INT *counts, UINT polygons)
 
BOOL FASTCALL PATH_PolyPolyline (PDC dc, const POINT *pts, const DWORD *counts, DWORD polylines)
 
BOOL FASTCALL PATH_AddFlatBezier (PPATH pPath, POINT *pt, BOOL closed)
 
PPATH FASTCALL PATH_FlattenPath (PPATH pPath)
 
BOOL FASTCALL PATH_PathToRegion (PPATH pPath, INT Mode, PREGION Rgn)
 
BOOL FASTCALL PATH_FillPath (PDC dc, PPATH pPath)
 
BOOL FASTCALL PATH_FillPathEx (PDC dc, PPATH pPath, PBRUSH pbrFill)
 
BOOL FASTCALL PATH_StrokePath (DC *dc, PPATH pPath)
 
PPATH FASTCALL IntGdiWidenPath (PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit)
 
static PPATH FASTCALL PATH_WidenPath (DC *dc)
 
PPATH FASTCALL PATH_WidenPathEx (DC *dc, PPATH pPath)
 
static INT int_from_fixed (FIXED f)
 
static VOID FASTCALL PATH_BezierTo (PPATH pPath, POINT *lppt, INT n)
 
static BOOL FASTCALL PATH_add_outline (PDC dc, PPATH pPath, INT x, INT y, TTPOLYGONHEADER *header, DWORD size)
 
BOOL FASTCALL PATH_ExtTextOut (PDC dc, INT x, INT y, UINT flags, const RECTL *lprc, LPCWSTR str, UINT count, const INT *dx)
 
BOOL APIENTRY NtGdiAbortPath (HDC hDC)
 
BOOL APIENTRY NtGdiBeginPath (HDC hDC)
 
BOOL APIENTRY NtGdiCloseFigure (HDC hDC)
 
BOOL APIENTRY NtGdiEndPath (HDC hDC)
 
BOOL APIENTRY NtGdiFillPath (HDC hDC)
 
BOOL APIENTRY NtGdiFlattenPath (HDC hDC)
 
 _Success_ (return !=FALSE)
 
INT APIENTRY NtGdiGetPath (HDC hDC, LPPOINT Points, LPBYTE Types, INT nSize)
 
HRGN APIENTRY NtGdiPathToRegion (HDC hDC)
 
BOOL APIENTRY NtGdiSetMiterLimit (IN HDC hdc, IN DWORD dwNew, IN OUT OPTIONAL PDWORD pdwOut)
 
BOOL APIENTRY NtGdiStrokeAndFillPath (HDC hDC)
 
BOOL APIENTRY NtGdiStrokePath (HDC hDC)
 
BOOL APIENTRY NtGdiWidenPath (HDC hDC)
 

Macro Definition Documentation

◆ GROW_FACTOR_DENOM

#define GROW_FACTOR_DENOM   1 /* Denominator of grow factor */

Definition at line 24 of file path.c.

◆ GROW_FACTOR_NUMER

#define GROW_FACTOR_NUMER   2 /* Numerator of grow factor for the array */

Definition at line 23 of file path.c.

◆ NUM_ENTRIES_INITIAL

#define NUM_ENTRIES_INITIAL   16 /* Initial size of points / flags arrays */

Definition at line 21 of file path.c.

◆ round

#define round (   x)    ((int)((x)>0?(x)+0.5:(x)-0.5))

Definition at line 1799 of file path.c.

Function Documentation

◆ _Success_()

_Success_ ( return = FALSE)

Definition at line 2741 of file path.c.

2747{
2748 DC *pDc;
2749 BOOL bResult = TRUE;
2750
2751 if (!(pDc = DC_LockDc(hdc)))
2752 {
2754 return FALSE;
2755 }
2756
2757 _SEH2_TRY
2758 {
2759 ProbeForWrite(pdwOut, sizeof(DWORD), 1);
2760 *pdwOut = pDc->dclevel.laPath.eMiterLimit;
2761 }
2763 {
2765 bResult = FALSE;
2766 }
2767 _SEH2_END;
2768
2769 DC_UnlockDc(pDc);
2770 return bResult;
2771
2772}
FORCEINLINE VOID DC_UnlockDc(PDC pdc)
Definition: dc.h:238
FORCEINLINE PDC DC_LockDc(HDC hdc)
Definition: dc.h:220
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
HDC hdc
Definition: main.c:9
_Out_ PDWORD pdwOut
Definition: ntgdi.h:1813
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
Definition: polytest.cpp:41
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:30
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:21

◆ add_log_points()

static BYTE * add_log_points ( DC dc,
PPATH  path,
const POINT points,
DWORD  count,
BYTE  type,
BOOL  bExtraPt 
)
static

Definition at line 463 of file path.c.

465{
466 BYTE *ret;
467
468 if (!PATH_ReserveEntries( path, path->numEntriesUsed + count )) return NULL;
469
470 ret = &path->pFlags[path->numEntriesUsed];
471
472 if (bExtraPt && path->numEntriesUsed == 1)
473 {
474 memcpy(&path->pPoints[0], points, (count + 1) * sizeof(*points));
475 IntLPtoDP(dc, &path->pPoints[0], count + 1);
476 }
477 else
478 {
479 memcpy(&path->pPoints[path->numEntriesUsed], points, count * sizeof(*points));
480 IntLPtoDP(dc, &path->pPoints[path->numEntriesUsed], count);
481 }
482
483 memset( ret, type, count );
484 path->numEntriesUsed += count;
485 return ret;
486}
static BOOLEAN IntLPtoDP(DC *pdc, PPOINTL ppt, UINT count)
Definition: coord.h:182
HDC dc
Definition: cylfrac.c:34
#define NULL
Definition: types.h:112
return ret
Definition: mutex.c:146
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLsizei const GLfloat * points
Definition: glext.h:8112
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memset(x, y, z)
Definition: compat.h:39
BOOL FASTCALL PATH_ReserveEntries(PPATH pPath, INT numEntries)
Definition: path.c:296
unsigned char BYTE
Definition: xxhash.c:193

Referenced by add_log_points_new_stroke(), PATH_PolyBezier(), and PATH_PolyPolygon().

◆ add_log_points_new_stroke()

static BOOL add_log_points_new_stroke ( DC dc,
PPATH  path,
const POINT points,
DWORD  count,
BYTE  type,
BOOL  bExtraPt 
)
static

Definition at line 543 of file path.c.

545{
546 if (!start_new_stroke( path )) return FALSE;
547 if (!add_log_points(dc, path, points, count, type, bExtraPt)) return FALSE;
549
550 TRACE("ALPNS : Pos X %d Y %d\n",path->pos.x, path->pos.y);
551 IntGdiMoveToEx(dc, path->pos.x, path->pos.y, NULL);
552
553 return TRUE;
554}
BOOL FASTCALL IntGdiMoveToEx(DC *dc, int X, int Y, LPPOINT Point)
Definition: line.c:80
#define TRACE(s)
Definition: solgame.cpp:4
static void update_current_pos(PPATH path)
Definition: path.c:529
static BOOL start_new_stroke(PPATH path)
Definition: path.c:516
static BYTE * add_log_points(DC *dc, PPATH path, const POINT *points, DWORD count, BYTE type, BOOL bExtraPt)
Definition: path.c:463

Referenced by PATH_LineTo(), PATH_PolyBezierTo(), PATH_PolyDraw(), and PATH_PolylineTo().

◆ add_points()

static BYTE * add_points ( PPATH  path,
const POINT points,
DWORD  count,
BYTE  type 
)
static

Definition at line 490 of file path.c.

491{
492 BYTE *ret;
493
494 if (!PATH_ReserveEntries( path, path->numEntriesUsed + count )) return NULL;
495
496 ret = &path->pFlags[path->numEntriesUsed];
497 memcpy( &path->pPoints[path->numEntriesUsed], points, count * sizeof(*points) );
498 memset( ret, type, count );
499 path->numEntriesUsed += count;
500 return ret;
501}

Referenced by IntGdiWidenPath(), PATH_BezierTo(), PATH_DoArcPart(), PATH_Ellipse(), PATH_Rectangle(), PATH_RoundRect(), and start_new_stroke().

◆ close_figure()

static void close_figure ( PPATH  path)
static

Definition at line 536 of file path.c.

537{
538 ASSERT(path->numEntriesUsed);
539 path->pFlags[path->numEntriesUsed - 1] |= PT_CLOSEFIGURE;
540}
#define ASSERT(a)
Definition: mode.c:44
#define PT_CLOSEFIGURE
Definition: wingdi.h:887

Referenced by PATH_PolyDraw().

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( GdiPath  )

◆ GdiPathDPtoLP()

BOOL FASTCALL GdiPathDPtoLP ( PDC  pdc,
PPOINT  ppt,
INT  count 
)

Definition at line 125 of file path.c.

129{
130 XFORMOBJ xo;
131
132 XFORMOBJ_vInit(&xo, &pdc->pdcattr->mxDeviceToWorld);
133 return XFORMOBJ_bApplyXform(&xo, XF_LTOL, count, (PPOINTL)ppt, (PPOINTL)ppt);
134}
#define XF_LTOL
Definition: winddi.h:3109
#define XFORMOBJ_vInit
Definition: xformobj.h:12
#define XFORMOBJ_bApplyXform
Definition: xformobj.h:11

Referenced by NtGdiGetPath().

◆ int_from_fixed()

static INT int_from_fixed ( FIXED  f)
inlinestatic

Definition at line 2216 of file path.c.

2217{
2218 return (f.fract >= 0x8000) ? (f.value + 1) : f.value;
2219}
GLfloat f
Definition: glext.h:7540

Referenced by PATH_add_outline().

◆ IntGdiCloseFigure()

VOID FASTCALL IntGdiCloseFigure ( PPATH  pPath)

Definition at line 108 of file path.c.

109{
110 ASSERT(pPath->state == PATH_Open);
111
112 // FIXME: Shouldn't we draw a line to the beginning of the figure?
113 // Set PT_CLOSEFIGURE on the last entry and start a new stroke
114 if (pPath->numEntriesUsed)
115 {
116 pPath->pFlags[pPath->numEntriesUsed - 1] |= PT_CLOSEFIGURE;
117 pPath->newStroke = TRUE;
118 }
119}
@ PATH_Open
Definition: path.h:19
BOOL newStroke
Definition: path.h:57
FLONG state
Definition: path.h:52
BYTE * pFlags
Definition: path.h:54
int numEntriesUsed
Definition: path.h:55

Referenced by NtGdiCloseFigure(), PATH_add_outline(), PATH_Arc(), PATH_Ellipse(), PATH_Rectangle(), and PATH_RoundRect().

◆ IntGdiWidenPath()

PPATH FASTCALL IntGdiWidenPath ( PPATH  pPath,
UINT  penWidth,
UINT  penStyle,
FLOAT  eMiterLimit 
)

Definition at line 1802 of file path.c.

1803{
1804 INT i, j, numStrokes, numOldStrokes, penWidthIn, penWidthOut;
1805 PPATH flat_path, pNewPath = NULL, *pStrokes = NULL, *pOldStrokes, pUpPath, pDownPath;
1806 BYTE *type;
1807 DWORD joint, endcap;
1808 KFLOATING_SAVE fpsave;
1809
1810 endcap = (PS_ENDCAP_MASK & penStyle);
1811 joint = (PS_JOIN_MASK & penStyle);
1812
1813 if (!(flat_path = PATH_FlattenPath(pPath)))
1814 {
1815 ERR("PATH_FlattenPath\n");
1816 return NULL;
1817 }
1818
1819 penWidthIn = penWidth / 2;
1820 penWidthOut = penWidth / 2;
1821 if (penWidthIn + penWidthOut < penWidth)
1822 penWidthOut++;
1823
1824 numStrokes = 0;
1825
1826 for (i = 0, j = 0; i < flat_path->numEntriesUsed; i++, j++)
1827 {
1828 POINT point;
1829 if ((i == 0 || (flat_path->pFlags[i - 1] & PT_CLOSEFIGURE)) &&
1830 (flat_path->pFlags[i] != PT_MOVETO))
1831 {
1832 ERR("Expected PT_MOVETO %s, got path flag %c\n",
1833 i == 0 ? "as first point" : "after PT_CLOSEFIGURE",
1834 flat_path->pFlags[i]);
1835 goto Exit;
1836 }
1837 switch(flat_path->pFlags[i])
1838 {
1839 case PT_MOVETO:
1840 if (numStrokes > 0)
1841 {
1842 pStrokes[numStrokes - 1]->state = PATH_Closed;
1843 }
1844 numOldStrokes = numStrokes;
1845 numStrokes++;
1846 j = 0;
1847 if (numStrokes == 1)
1848 pStrokes = ExAllocatePoolWithTag(PagedPool, sizeof(*pStrokes), TAG_PATH);
1849 else
1850 {
1851 pOldStrokes = pStrokes; // Save old pointer.
1852 pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(*pStrokes), TAG_PATH);
1853 if (!pStrokes)
1854 {
1855 ExFreePoolWithTag(pOldStrokes, TAG_PATH);
1856 goto Exit;
1857 }
1858 RtlCopyMemory(pStrokes, pOldStrokes, numOldStrokes * sizeof(PPATH));
1859 ExFreePoolWithTag(pOldStrokes, TAG_PATH); // Free old pointer.
1860 }
1861 if (!pStrokes)
1862 {
1863 goto Exit;
1864 }
1865 pStrokes[numStrokes - 1] = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
1866 if (!pStrokes[numStrokes - 1])
1867 {
1868 ASSERT(FALSE); // FIXME
1869 }
1870 PATH_InitGdiPath(pStrokes[numStrokes - 1]);
1871 pStrokes[numStrokes - 1]->state = PATH_Open;
1872 case PT_LINETO:
1873 case (PT_LINETO | PT_CLOSEFIGURE):
1874 point.x = flat_path->pPoints[i].x;
1875 point.y = flat_path->pPoints[i].y;
1876 PATH_AddEntry(pStrokes[numStrokes - 1], &point, flat_path->pFlags[i]);
1877 break;
1878 case PT_BEZIERTO:
1879 /* Should never happen because of the FlattenPath call */
1880 ERR("Should never happen\n");
1881 break;
1882 default:
1883 ERR("Got path flag %c\n", flat_path->pFlags[i]);
1884 goto Exit;
1885 }
1886 }
1887
1888 pNewPath = PATH_CreatePath( flat_path->numEntriesUsed );
1889 if (pNewPath == NULL)
1890 {
1891 ERR("PATH_CreatePath\n");
1892 goto Exit;
1893 }
1894
1895 KeSaveFloatingPointState(&fpsave);
1896
1897 for (i = 0; i < numStrokes; i++)
1898 {
1899 pUpPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
1900 PATH_InitGdiPath(pUpPath);
1901 pUpPath->state = PATH_Open;
1902 pDownPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
1903 PATH_InitGdiPath(pDownPath);
1904 pDownPath->state = PATH_Open;
1905
1906 for (j = 0; j < pStrokes[i]->numEntriesUsed; j++)
1907 {
1908 /* Beginning or end of the path if not closed */
1909 if ((!(pStrokes[i]->pFlags[pStrokes[i]->numEntriesUsed - 1] & PT_CLOSEFIGURE)) && (j == 0 || j == pStrokes[i]->numEntriesUsed - 1))
1910 {
1911 /* Compute segment angle */
1912 INT xo, yo, xa, ya;
1913 double theta;
1914 POINT pt;
1915 POINT corners[2];
1916 if (j == 0)
1917 {
1918 xo = pStrokes[i]->pPoints[j].x;
1919 yo = pStrokes[i]->pPoints[j].y;
1920 xa = pStrokes[i]->pPoints[1].x;
1921 ya = pStrokes[i]->pPoints[1].y;
1922 }
1923 else
1924 {
1925 xa = pStrokes[i]->pPoints[j - 1].x;
1926 ya = pStrokes[i]->pPoints[j - 1].y;
1927 xo = pStrokes[i]->pPoints[j].x;
1928 yo = pStrokes[i]->pPoints[j].y;
1929 }
1930 theta = atan2(ya - yo, xa - xo);
1931 switch(endcap)
1932 {
1933 case PS_ENDCAP_SQUARE :
1934 pt.x = xo + round(sqrt(2) * penWidthOut * cos(M_PI_4 + theta));
1935 pt.y = yo + round(sqrt(2) * penWidthOut * sin(M_PI_4 + theta));
1936 PATH_AddEntry(pUpPath, &pt, (j == 0 ? PT_MOVETO : PT_LINETO));
1937 pt.x = xo + round(sqrt(2) * penWidthIn * cos(- M_PI_4 + theta));
1938 pt.y = yo + round(sqrt(2) * penWidthIn * sin(- M_PI_4 + theta));
1939 PATH_AddEntry(pUpPath, &pt, PT_LINETO);
1940 break;
1941 case PS_ENDCAP_FLAT :
1942 pt.x = xo + round(penWidthOut * cos(theta + M_PI_2));
1943 pt.y = yo + round(penWidthOut * sin(theta + M_PI_2));
1944 PATH_AddEntry(pUpPath, &pt, (j == 0 ? PT_MOVETO : PT_LINETO));
1945 pt.x = xo - round(penWidthIn * cos(theta + M_PI_2));
1946 pt.y = yo - round(penWidthIn * sin(theta + M_PI_2));
1947 PATH_AddEntry(pUpPath, &pt, PT_LINETO);
1948 break;
1949 case PS_ENDCAP_ROUND :
1950 default :
1951 corners[0].x = xo - penWidthIn;
1952 corners[0].y = yo - penWidthIn;
1953 corners[1].x = xo + penWidthOut;
1954 corners[1].y = yo + penWidthOut;
1955 PATH_DoArcPart(pUpPath , corners, theta + M_PI_2 , theta + 3 * M_PI_4, (j == 0 ? PT_MOVETO : FALSE));
1956 PATH_DoArcPart(pUpPath , corners, theta + 3 * M_PI_4 , theta + M_PI, FALSE);
1957 PATH_DoArcPart(pUpPath , corners, theta + M_PI, theta + 5 * M_PI_4, FALSE);
1958 PATH_DoArcPart(pUpPath , corners, theta + 5 * M_PI_4 , theta + 3 * M_PI_2, FALSE);
1959 break;
1960 }
1961 }
1962 /* Corpse of the path */
1963 else
1964 {
1965 /* Compute angle */
1966 INT previous, next;
1967 double xa, ya, xb, yb, xo, yo;
1968 double alpha, theta, miterWidth;
1969 DWORD _joint = joint;
1970 POINT pt;
1971 PPATH pInsidePath, pOutsidePath;
1972 if (j > 0 && j < pStrokes[i]->numEntriesUsed - 1)
1973 {
1974 previous = j - 1;
1975 next = j + 1;
1976 }
1977 else if (j == 0)
1978 {
1979 previous = pStrokes[i]->numEntriesUsed - 1;
1980 next = j + 1;
1981 }
1982 else
1983 {
1984 previous = j - 1;
1985 next = 0;
1986 }
1987 xo = pStrokes[i]->pPoints[j].x;
1988 yo = pStrokes[i]->pPoints[j].y;
1989 xa = pStrokes[i]->pPoints[previous].x;
1990 ya = pStrokes[i]->pPoints[previous].y;
1991 xb = pStrokes[i]->pPoints[next].x;
1992 yb = pStrokes[i]->pPoints[next].y;
1993 theta = atan2(yo - ya, xo - xa);
1994 alpha = atan2(yb - yo, xb - xo) - theta;
1995 if (alpha > 0) alpha -= M_PI;
1996 else alpha += M_PI;
1997 if (_joint == PS_JOIN_MITER && eMiterLimit < fabs(1 / sin(alpha / 2)))
1998 {
1999 _joint = PS_JOIN_BEVEL;
2000 }
2001 if (alpha > 0)
2002 {
2003 pInsidePath = pUpPath;
2004 pOutsidePath = pDownPath;
2005 }
2006 else if (alpha < 0)
2007 {
2008 pInsidePath = pDownPath;
2009 pOutsidePath = pUpPath;
2010 }
2011 else
2012 {
2013 continue;
2014 }
2015 /* Inside angle points */
2016 if (alpha > 0)
2017 {
2018 pt.x = xo - round(penWidthIn * cos(theta + M_PI_2));
2019 pt.y = yo - round(penWidthIn * sin(theta + M_PI_2));
2020 }
2021 else
2022 {
2023 pt.x = xo + round(penWidthIn * cos(theta + M_PI_2));
2024 pt.y = yo + round(penWidthIn * sin(theta + M_PI_2));
2025 }
2026 PATH_AddEntry(pInsidePath, &pt, PT_LINETO);
2027 if (alpha > 0)
2028 {
2029 pt.x = xo + round(penWidthIn * cos(M_PI_2 + alpha + theta));
2030 pt.y = yo + round(penWidthIn * sin(M_PI_2 + alpha + theta));
2031 }
2032 else
2033 {
2034 pt.x = xo - round(penWidthIn * cos(M_PI_2 + alpha + theta));
2035 pt.y = yo - round(penWidthIn * sin(M_PI_2 + alpha + theta));
2036 }
2037 PATH_AddEntry(pInsidePath, &pt, PT_LINETO);
2038 /* Outside angle point */
2039 switch(_joint)
2040 {
2041 case PS_JOIN_MITER :
2042 miterWidth = fabs(penWidthOut / cos(M_PI_2 - fabs(alpha) / 2));
2043 pt.x = xo + round(miterWidth * cos(theta + alpha / 2));
2044 pt.y = yo + round(miterWidth * sin(theta + alpha / 2));
2045 PATH_AddEntry(pOutsidePath, &pt, PT_LINETO);
2046 break;
2047 case PS_JOIN_BEVEL :
2048 if (alpha > 0)
2049 {
2050 pt.x = xo + round(penWidthOut * cos(theta + M_PI_2));
2051 pt.y = yo + round(penWidthOut * sin(theta + M_PI_2));
2052 }
2053 else
2054 {
2055 pt.x = xo - round(penWidthOut * cos(theta + M_PI_2));
2056 pt.y = yo - round(penWidthOut * sin(theta + M_PI_2));
2057 }
2058 PATH_AddEntry(pOutsidePath, &pt, PT_LINETO);
2059 if (alpha > 0)
2060 {
2061 pt.x = xo - round(penWidthOut * cos(M_PI_2 + alpha + theta));
2062 pt.y = yo - round(penWidthOut * sin(M_PI_2 + alpha + theta));
2063 }
2064 else
2065 {
2066 pt.x = xo + round(penWidthOut * cos(M_PI_2 + alpha + theta));
2067 pt.y = yo + round(penWidthOut * sin(M_PI_2 + alpha + theta));
2068 }
2069 PATH_AddEntry(pOutsidePath, &pt, PT_LINETO);
2070 break;
2071 case PS_JOIN_ROUND :
2072 default :
2073 if (alpha > 0)
2074 {
2075 pt.x = xo + round(penWidthOut * cos(theta + M_PI_2));
2076 pt.y = yo + round(penWidthOut * sin(theta + M_PI_2));
2077 }
2078 else
2079 {
2080 pt.x = xo - round(penWidthOut * cos(theta + M_PI_2));
2081 pt.y = yo - round(penWidthOut * sin(theta + M_PI_2));
2082 }
2083 PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO);
2084 pt.x = xo + round(penWidthOut * cos(theta + alpha / 2));
2085 pt.y = yo + round(penWidthOut * sin(theta + alpha / 2));
2086 PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO);
2087 if (alpha > 0)
2088 {
2089 pt.x = xo - round(penWidthOut * cos(M_PI_2 + alpha + theta));
2090 pt.y = yo - round(penWidthOut * sin(M_PI_2 + alpha + theta));
2091 }
2092 else
2093 {
2094 pt.x = xo + round(penWidthOut * cos(M_PI_2 + alpha + theta));
2095 pt.y = yo + round(penWidthOut * sin(M_PI_2 + alpha + theta));
2096 }
2097 PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO);
2098 break;
2099 }
2100 }
2101 }
2102 type = add_points( pNewPath, pUpPath->pPoints, pUpPath->numEntriesUsed, PT_LINETO );
2103 type[0] = PT_MOVETO;
2104 reverse_points( pDownPath->pPoints, pDownPath->numEntriesUsed );
2105 type = add_points( pNewPath, pDownPath->pPoints, pDownPath->numEntriesUsed, PT_LINETO );
2106 if (pStrokes[i]->pFlags[pStrokes[i]->numEntriesUsed - 1] & PT_CLOSEFIGURE) type[0] = PT_MOVETO;
2107
2108 PATH_DestroyGdiPath(pStrokes[i]);
2109 ExFreePoolWithTag(pStrokes[i], TAG_PATH);
2110 PATH_DestroyGdiPath(pUpPath);
2111 ExFreePoolWithTag(pUpPath, TAG_PATH);
2112 PATH_DestroyGdiPath(pDownPath);
2113 ExFreePoolWithTag(pDownPath, TAG_PATH);
2114 }
2115
2116 pNewPath->state = PATH_Closed;
2117 PATH_UnlockPath(pNewPath);
2118
2120
2121Exit:
2122 if (pStrokes) ExFreePoolWithTag(pStrokes, TAG_PATH);
2123 HPATH hpathToDelete = flat_path->BaseObject.hHmgr;
2124 PATH_UnlockPath(flat_path);
2125 PATH_Delete(hpathToDelete);
2126
2127 return pNewPath;
2128}
#define ERR(fmt,...)
Definition: precomp.h:57
HGDIOBJ hHmgr(VOID)
Definition: baseobj.hpp:95
_ACRTIMP double __cdecl sqrt(double)
Definition: sqrt.c:5
_ACRTIMP double __cdecl fabs(double)
_ACRTIMP double __cdecl sin(double)
Definition: sin.c:21
#define M_PI_2
Definition: math.h:410
_ACRTIMP double __cdecl cos(double)
Definition: cos.c:21
_ACRTIMP double __cdecl atan2(double, double)
Definition: atan2.c:52
#define M_PI_4
Definition: math.h:411
#define pt(x, y)
Definition: drawing.c:79
POINTL point
Definition: edittest.c:50
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define KeSaveFloatingPointState(x)
Definition: kmixer.h:32
#define KeRestoreFloatingPointState(x)
Definition: kmixer.h:33
#define M_PI
Definition: macros.h:263
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define PATH_UnlockPath(pPath)
Definition: path.h:71
@ PATH_Closed
Definition: path.h:20
static unsigned __int64 next
Definition: rand_nt.c:6
static void Exit(void)
Definition: sock.c:1330
Definition: path.h:35
BASEOBJECT BaseObject
Definition: path.h:36
POINT * pPoints
Definition: path.h:53
LONG y
Definition: windef.h:130
LONG x
Definition: windef.h:129
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
BOOL FASTCALL PATH_Delete(HPATH hPath)
Definition: path.c:90
VOID FASTCALL PATH_DestroyGdiPath(PPATH pPath)
Definition: path.c:80
VOID FASTCALL PATH_InitGdiPath(PPATH pPath)
Definition: path.c:142
#define round(x)
Definition: path.c:1799
static BOOL PATH_DoArcPart(PPATH pPath, POINT corners[], double angleStart, double angleEnd, BYTE startEntryType)
Definition: path.c:900
PPATH FASTCALL PATH_FlattenPath(PPATH pPath)
Definition: path.c:1420
BOOL FASTCALL PATH_AddEntry(PPATH pPath, const POINT *pPoint, BYTE flags)
Definition: path.c:262
PPATH FASTCALL PATH_CreatePath(int count)
Definition: path.c:35
static BYTE * add_points(PPATH path, const POINT *points, DWORD count, BYTE type)
Definition: path.c:490
static void reverse_points(POINT *points, UINT count)
Definition: path.c:504
#define TAG_PATH
Definition: tags.h:25
#define PS_JOIN_BEVEL
Definition: wingdi.h:597
#define PS_ENDCAP_SQUARE
Definition: wingdi.h:595
#define PS_JOIN_ROUND
Definition: wingdi.h:599
#define PS_ENDCAP_ROUND
Definition: wingdi.h:594
#define PT_LINETO
Definition: wingdi.h:885
#define PS_JOIN_MASK
Definition: wingdi.h:600
#define PT_MOVETO
Definition: wingdi.h:884
#define PT_BEZIERTO
Definition: wingdi.h:886
#define PS_JOIN_MITER
Definition: wingdi.h:598
#define PS_ENDCAP_MASK
Definition: wingdi.h:602
#define PS_ENDCAP_FLAT
Definition: wingdi.h:596

Referenced by PATH_WidenPathEx().

◆ NtGdiAbortPath()

BOOL APIENTRY NtGdiAbortPath ( HDC  hDC)

Definition at line 2474 of file path.c.

2475{
2476 PDC dc = DC_LockDc(hDC);
2477 if (!dc)
2478 {
2480 return FALSE;
2481 }
2482
2483 if (!dc->dclevel.hPath)
2484 {
2485 DC_UnlockDc(dc);
2486 return TRUE;
2487 }
2488
2489 if (!PATH_Delete(dc->dclevel.hPath))
2490 {
2491 DC_UnlockDc(dc);
2492 return FALSE;
2493 }
2494
2495 dc->dclevel.hPath = 0;
2496 dc->dclevel.flPath &= ~DCPATH_ACTIVE;
2497
2498 DC_UnlockDc(dc);
2499 return TRUE;
2500}
static HDC hDC
Definition: 3dtext.c:33
#define ERROR_INVALID_HANDLE
Definition: compat.h:98

◆ NtGdiBeginPath()

BOOL APIENTRY NtGdiBeginPath ( HDC  hDC)

Definition at line 2504 of file path.c.

2505{
2506 PPATH pPath;
2507 PDC dc;
2508
2509 dc = DC_LockDc(hDC);
2510 if (!dc)
2511 {
2513 return FALSE;
2514 }
2515
2516 /* If path is already open, do nothing. Check if not Save DC state */
2517 if ((dc->dclevel.flPath & DCPATH_ACTIVE) && !(dc->dclevel.flPath & DCPATH_SAVE))
2518 {
2519 DC_UnlockDc(dc);
2520 return TRUE;
2521 }
2522
2523 if (dc->dclevel.hPath)
2524 {
2525 TRACE("BeginPath 1 0x%p\n", dc->dclevel.hPath);
2526 if (!(dc->dclevel.flPath & DCPATH_SAVE))
2527 {
2528 // Remove previous handle.
2529 if (!PATH_Delete(dc->dclevel.hPath))
2530 {
2531 DC_UnlockDc(dc);
2532 return FALSE;
2533 }
2534 }
2535 else
2536 {
2537 // Clear flags and Handle.
2538 dc->dclevel.flPath &= ~(DCPATH_SAVE | DCPATH_ACTIVE);
2539 dc->dclevel.hPath = NULL;
2540 }
2541 }
2543 dc->dclevel.flPath |= DCPATH_ACTIVE; // Set active ASAP!
2544 dc->dclevel.hPath = pPath->BaseObject.hHmgr;
2545 IntGetCurrentPositionEx(dc, &pPath->pos);
2546 IntLPtoDP( dc, &pPath->pos, 1 );
2547 TRACE("BP : Current pos X %d Y %d\n",pPath->pos.x, pPath->pos.y);
2548 PATH_UnlockPath(pPath);
2549 DC_UnlockDc(dc);
2550
2551 if (!pPath)
2552 {
2553 return FALSE;
2554 }
2555 return TRUE;
2556}
@ DCPATH_SAVE
Definition: path.h:7
@ DCPATH_ACTIVE
Definition: path.h:6
POINT pos
Definition: path.h:58
VOID FASTCALL IntGetCurrentPositionEx(PDC dc, LPPOINT pt)
Definition: line.c:130
#define NUM_ENTRIES_INITIAL
Definition: path.c:21

◆ NtGdiCloseFigure()

BOOL APIENTRY NtGdiCloseFigure ( HDC  hDC)

Definition at line 2560 of file path.c.

2561{
2562 BOOL Ret = FALSE; // Default to failure
2563 PDC pDc;
2564 PPATH pPath;
2565
2566 TRACE("Enter %s\n", __FUNCTION__);
2567
2568 pDc = DC_LockDc(hDC);
2569 if (!pDc)
2570 {
2572 return FALSE;
2573 }
2574
2575 pPath = PATH_LockPath(pDc->dclevel.hPath);
2576 if (!pPath)
2577 {
2578 DC_UnlockDc(pDc);
2579 return FALSE;
2580 }
2581
2582 if (pPath->state == PATH_Open)
2583 {
2584 IntGdiCloseFigure(pPath);
2585 Ret = TRUE;
2586 }
2587 else
2588 {
2590 }
2591
2592 PATH_UnlockPath(pPath);
2593 DC_UnlockDc(pDc);
2594 return Ret;
2595}
#define __FUNCTION__
Definition: types.h:116
#define PATH_LockPath(hPath)
Definition: path.h:70
VOID FASTCALL IntGdiCloseFigure(PPATH pPath)
Definition: path.c:108
#define ERROR_CAN_NOT_COMPLETE
Definition: winerror.h:906

◆ NtGdiEndPath()

BOOL APIENTRY NtGdiEndPath ( HDC  hDC)

Definition at line 2599 of file path.c.

2600{
2601 BOOL ret = TRUE;
2602 PPATH pPath;
2603 PDC dc;
2604
2605 dc = DC_LockDc(hDC);
2606 if (!dc)
2607 {
2609 return FALSE;
2610 }
2611
2612 pPath = PATH_LockPath(dc->dclevel.hPath);
2613 if (!pPath)
2614 {
2615 DC_UnlockDc(dc);
2616 return FALSE;
2617 }
2618
2619 /* Check that path is currently being constructed */
2620 if ((pPath->state != PATH_Open) || !(dc->dclevel.flPath & DCPATH_ACTIVE))
2621 {
2622 TRACE("EndPath ERROR! 0x%p\n", dc->dclevel.hPath);
2624 ret = FALSE;
2625 }
2626 /* Set flag to indicate that path is finished */
2627 else
2628 {
2629 TRACE("EndPath 0x%p\n", dc->dclevel.hPath);
2630 pPath->state = PATH_Closed;
2631 dc->dclevel.flPath &= ~DCPATH_ACTIVE;
2632 }
2633
2634 PATH_UnlockPath(pPath);
2635 DC_UnlockDc(dc);
2636 return ret;
2637}

◆ NtGdiFillPath()

BOOL APIENTRY NtGdiFillPath ( HDC  hDC)

Definition at line 2641 of file path.c.

2642{
2643 BOOL ret = FALSE;
2644 PPATH pPath, pNewPath;
2645 PDC_ATTR pdcattr;
2646 PDC dc;
2647
2648 dc = DC_LockDc(hDC);
2649 if (!dc)
2650 {
2652 return FALSE;
2653 }
2654
2655 pPath = PATH_LockPath(dc->dclevel.hPath);
2656 if (!pPath)
2657 {
2658 DC_UnlockDc(dc);
2659 return FALSE;
2660 }
2661
2663
2664 pdcattr = dc->pdcattr;
2665
2666 if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
2668
2669 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
2671
2672 pNewPath = PATH_FlattenPath(pPath);
2673
2674 if (pNewPath->state != PATH_Closed)
2675 {
2677 }
2678 else if (pNewPath->numEntriesUsed)
2679 {
2680 ret = PATH_FillPath(dc, pNewPath);
2681 }
2682 else ret = TRUE;
2683
2684 PATH_UnlockPath(pNewPath);
2685 PATH_Delete(pNewPath->BaseObject.hHmgr);
2686
2687 PATH_UnlockPath(pPath);
2689 dc->dclevel.hPath = 0;
2690 dc->dclevel.flPath &= ~DCPATH_ACTIVE;
2691
2693 DC_UnlockDc(dc);
2694 return ret;
2695}
VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdcDest, const RECT *rcDest, PDC pdcSrc, const RECT *rcSrc)
Definition: dclife.c:505
VOID FASTCALL DC_vUpdateLineBrush(PDC pdc)
Definition: dcobjs.c:62
VOID FASTCALL DC_vFinishBlit(PDC pdc1, PDC pdc2)
Definition: dclife.c:614
VOID FASTCALL DC_vUpdateFillBrush(PDC pdc)
Definition: dcobjs.c:16
#define DIRTY_FILL
Definition: ntgdihdl.h:123
#define DC_PEN_DIRTY
Definition: ntgdihdl.h:136
#define DIRTY_LINE
Definition: ntgdihdl.h:124
#define DC_BRUSH_DIRTY
Definition: ntgdihdl.h:135
ULONG ulDirty_
Definition: ntgdihdl.h:294
BOOL FASTCALL PATH_FillPath(PDC dc, PPATH pPath)
Definition: path.c:1518

◆ NtGdiFlattenPath()

BOOL APIENTRY NtGdiFlattenPath ( HDC  hDC)

Definition at line 2699 of file path.c.

2700{
2701 BOOL Ret = FALSE;
2702 DC *pDc;
2703 PPATH pPath, pNewPath = NULL;
2704
2705 TRACE("Enter %s\n", __FUNCTION__);
2706
2707 pDc = DC_LockDc(hDC);
2708 if (!pDc)
2709 {
2711 return FALSE;
2712 }
2713
2714 pPath = PATH_LockPath(pDc->dclevel.hPath);
2715 if (!pPath)
2716 {
2718 DC_UnlockDc(pDc);
2719 return FALSE;
2720 }
2721
2722 if (pPath->state == PATH_Closed)
2723 {
2724 pNewPath = PATH_FlattenPath(pPath);
2725 }
2726
2727 PATH_UnlockPath(pPath);
2728
2729 if (pNewPath)
2730 {
2731 PATH_Delete(pDc->dclevel.hPath);
2732 pDc->dclevel.hPath = pNewPath->BaseObject.hHmgr;
2733 PATH_UnlockPath(pNewPath);
2734 Ret = TRUE;
2735 }
2736
2737 DC_UnlockDc(pDc);
2738 return Ret;
2739}

◆ NtGdiGetPath()

INT APIENTRY NtGdiGetPath ( HDC  hDC,
LPPOINT  Points,
LPBYTE  Types,
INT  nSize 
)

Definition at line 2776 of file path.c.

2781{
2782 INT ret = -1;
2783 PPATH pPath;
2784 DC *dc;
2785
2786 _SEH2_TRY
2787 {
2788 ProbeForWrite(Points, nSize * sizeof(*Points), sizeof(ULONG));
2790 }
2792 {
2794 _SEH2_YIELD(return -1);
2795 }
2796 _SEH2_END
2797
2798 dc = DC_LockDc(hDC);
2799 TRACE("NtGdiGetPath start\n");
2800 if (!dc)
2801 {
2802 ERR("Can't lock dc!\n");
2804 return -1;
2805 }
2806
2807 pPath = PATH_LockPath(dc->dclevel.hPath);
2808 if (!pPath)
2809 {
2810 DC_UnlockDc(dc);
2811 return -1;
2812 }
2813
2814 if (pPath->state != PATH_Closed)
2815 {
2817 goto done;
2818 }
2819
2820 if (nSize == 0)
2821 {
2822 ret = pPath->numEntriesUsed;
2823 }
2824 else if (nSize < pPath->numEntriesUsed)
2825 {
2827 goto done;
2828 }
2829 else
2830 {
2831 _SEH2_TRY
2832 {
2833 memcpy(Points, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
2834 memcpy(Types, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
2835
2836 /* Convert the points to logical coordinates */
2837 if (!GdiPathDPtoLP(dc, Points, pPath->numEntriesUsed))
2838 {
2841 }
2842
2843 ret = pPath->numEntriesUsed;
2844 }
2846 {
2848 }
2849 _SEH2_END
2850 }
2851
2852done:
2853 TRACE("NtGdiGetPath exit %d\n",ret);
2854 PATH_UnlockPath(pPath);
2855 DC_UnlockDc(dc);
2856 return ret;
2857}
char ACPI_OBJECT_TYPE * Types
Definition: acdebug.h:354
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:207
#define _SEH2_LEAVE
Definition: pseh2_64.h:206
uint32_t ULONG
Definition: typedefs.h:59
BOOL FASTCALL GdiPathDPtoLP(PDC pdc, PPOINT ppt, INT count)
Definition: path.c:125
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:1834
#define ERROR_ARITHMETIC_OVERFLOW
Definition: winerror.h:623

◆ NtGdiPathToRegion()

HRGN APIENTRY NtGdiPathToRegion ( HDC  hDC)

Definition at line 2861 of file path.c.

2862{
2863 PPATH pPath, pNewPath;
2864 HRGN hrgnRval = 0;
2865 int Ret;
2866 PREGION Rgn;
2867 DC *pDc;
2868 PDC_ATTR pdcattr;
2869
2870 TRACE("Enter %s\n", __FUNCTION__);
2871
2872 pDc = DC_LockDc(hDC);
2873 if (!pDc)
2874 {
2875 ERR("Failed to lock DC %p\n", hDC);
2877 return NULL;
2878 }
2879
2880 pdcattr = pDc->pdcattr;
2881
2882 pPath = PATH_LockPath(pDc->dclevel.hPath);
2883 if (!pPath)
2884 {
2885 ERR("Failed to lock DC path %p\n", pDc->dclevel.hPath);
2886 DC_UnlockDc(pDc);
2887 return NULL;
2888 }
2889
2890 if (pPath->state != PATH_Closed)
2891 {
2892 // FIXME: Check that setlasterror is being called correctly
2893 ERR("Path is not closed!\n");
2895 }
2896 else
2897 {
2898 /* Create the region and fill it with the path strokes */
2900 if (!Rgn)
2901 {
2902 ERR("Failed to allocate a region\n");
2903 PATH_UnlockPath(pPath);
2904 DC_UnlockDc(pDc);
2905 return NULL;
2906 }
2907 hrgnRval = Rgn->BaseObject.hHmgr;
2908
2909 pNewPath = PATH_FlattenPath(pPath);
2910 if (pNewPath == NULL)
2911 {
2912 ERR("Failed to flatten path %p\n", pDc->dclevel.hPath);
2913 REGION_Delete(Rgn);
2914 PATH_UnlockPath(pPath);
2915 DC_UnlockDc(pDc);
2916 return NULL;
2917 }
2918
2919 Ret = PATH_PathToRegion(pNewPath, pdcattr->jFillMode, Rgn);
2920
2921 PATH_UnlockPath(pNewPath);
2922 PATH_Delete(pNewPath->BaseObject.hHmgr);
2923
2924 if (!Ret)
2925 {
2926 ERR("PATH_PathToRegion failed\n");
2927 REGION_Delete(Rgn);
2928 hrgnRval = NULL;
2929 }
2930 else
2931 REGION_UnlockRgn(Rgn);
2932 }
2933
2934 PATH_UnlockPath(pPath);
2935 PATH_Delete(pDc->dclevel.hPath);
2936 pDc->dclevel.hPath = NULL;
2937 pDc->dclevel.flPath &= ~DCPATH_ACTIVE;
2938
2939 DC_UnlockDc(pDc);
2940 return hrgnRval;
2941}
BYTE jFillMode
Definition: ntgdihdl.h:309
Definition: region.h:8
BASEOBJECT BaseObject
Definition: region.h:11
BOOL FASTCALL PATH_PathToRegion(PPATH pPath, INT Mode, PREGION Rgn)
Definition: path.c:1463
VOID FASTCALL REGION_Delete(PREGION pRgn)
Definition: region.c:2449
VOID FASTCALL REGION_UnlockRgn(_In_ PREGION prgn)
Definition: region.c:2373
PREGION FASTCALL REGION_AllocUserRgnWithHandle(INT nRgn)
Definition: region.c:2294

◆ NtGdiSetMiterLimit()

BOOL APIENTRY NtGdiSetMiterLimit ( IN HDC  hdc,
IN DWORD  dwNew,
IN OUT OPTIONAL PDWORD  pdwOut 
)

Definition at line 2945 of file path.c.

2949{
2950 DC *pDc;
2951 gxf_long worker, worker1;
2952 BOOL bResult = TRUE;
2953
2954 if (!(pDc = DC_LockDc(hdc)))
2955 {
2957 return FALSE;
2958 }
2959
2960 worker.l = dwNew;
2961 worker1.f = pDc->dclevel.laPath.eMiterLimit;
2962 pDc->dclevel.laPath.eMiterLimit = worker.f;
2963
2964 if (pdwOut)
2965 {
2966 _SEH2_TRY
2967 {
2968 ProbeForWrite(pdwOut, sizeof(DWORD), 1);
2969 *pdwOut = worker1.l;
2970 }
2972 {
2974 bResult = FALSE;
2975 }
2976 _SEH2_END;
2977 }
2978
2979 DC_UnlockDc(pDc);
2980 return bResult;
2981}
ULONG l
Definition: ntgdityp.h:427
FLOAT f
Definition: ntgdityp.h:426

◆ NtGdiStrokeAndFillPath()

BOOL APIENTRY NtGdiStrokeAndFillPath ( HDC  hDC)

Definition at line 2985 of file path.c.

2986{
2987 DC *pDc;
2988 PDC_ATTR pdcattr;
2989 PPATH pPath, pNewPath;
2990 BOOL bRet = FALSE;
2991
2992 TRACE("Enter %s\n", __FUNCTION__);
2993
2994 if (!(pDc = DC_LockDc(hDC)))
2995 {
2997 return FALSE;
2998 }
2999 pPath = PATH_LockPath(pDc->dclevel.hPath);
3000 if (!pPath)
3001 {
3002 DC_UnlockDc(pDc);
3003 return FALSE;
3004 }
3005
3007
3008 pdcattr = pDc->pdcattr;
3009
3010 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
3012
3013 if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
3015
3016 pNewPath = PATH_FlattenPath(pPath);
3017
3018 if (pNewPath->state != PATH_Closed)
3019 {
3021 }
3022 else if (pNewPath->numEntriesUsed)
3023 {
3024 bRet = PATH_FillPath(pDc, pNewPath);
3025 if (bRet) bRet = PATH_StrokePath(pDc, pNewPath);
3026 }
3027 else bRet = TRUE;
3028
3029 PATH_UnlockPath(pNewPath);
3030 PATH_Delete(pNewPath->BaseObject.hHmgr);
3031
3032 PATH_UnlockPath(pPath);
3034 pDc->dclevel.hPath = 0;
3035 pDc->dclevel.flPath &= ~DCPATH_ACTIVE;
3036
3037 DC_vFinishBlit(pDc, NULL);
3038 DC_UnlockDc(pDc);
3039 return bRet;
3040}
BOOL FASTCALL PATH_StrokePath(DC *dc, PPATH pPath)
Definition: path.c:1610

◆ NtGdiStrokePath()

BOOL APIENTRY NtGdiStrokePath ( HDC  hDC)

Definition at line 3044 of file path.c.

3045{
3046 DC *pDc;
3047 PDC_ATTR pdcattr;
3048 PPATH pPath, pNewPath;
3049 BOOL bRet = FALSE;
3050
3051 TRACE("Enter %s\n", __FUNCTION__);
3052
3053 if (!(pDc = DC_LockDc(hDC)))
3054 {
3056 return FALSE;
3057 }
3058
3059 pPath = PATH_LockPath(pDc->dclevel.hPath);
3060 if (!pPath)
3061 {
3062 DC_UnlockDc(pDc);
3063 return FALSE;
3064 }
3065
3067
3068 pdcattr = pDc->pdcattr;
3069
3070 if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
3072
3073 pNewPath = PATH_FlattenPath(pPath);
3074
3075 if (pNewPath->state != PATH_Closed)
3076 {
3078 }
3079 else bRet = PATH_StrokePath(pDc, pNewPath);
3080
3081 PATH_UnlockPath(pNewPath);
3082 PATH_Delete(pNewPath->BaseObject.hHmgr);
3083
3084 DC_vFinishBlit(pDc, NULL);
3085
3086 PATH_UnlockPath(pPath);
3088 pDc->dclevel.hPath = 0;
3089 pDc->dclevel.flPath &= ~DCPATH_ACTIVE;
3090
3091 DC_UnlockDc(pDc);
3092 return bRet;
3093}

◆ NtGdiWidenPath()

BOOL APIENTRY NtGdiWidenPath ( HDC  hDC)

Definition at line 3097 of file path.c.

3098{
3099 PPATH pPath;
3100 BOOL Ret = FALSE;
3101 PDC pdc = DC_LockDc(hDC);
3102 TRACE("NtGdiWidenPat Enter\n");
3103 if (!pdc)
3104 {
3106 return FALSE;
3107 }
3108
3109 pPath = PATH_WidenPath(pdc);
3110 if (pPath)
3111 {
3112 TRACE("WindenPath New Path\n");
3113 PATH_Delete(pdc->dclevel.hPath);
3114 pdc->dclevel.hPath = pPath->BaseObject.hHmgr;
3115 Ret = TRUE;
3116 }
3117 DC_UnlockDc(pdc);
3118 TRACE("NtGdiWidenPat Ret %d\n",Ret);
3119 return Ret;
3120}
static PPATH FASTCALL PATH_WidenPath(DC *dc)
Definition: path.c:2133

◆ PATH_add_outline()

static BOOL FASTCALL PATH_add_outline ( PDC  dc,
PPATH  pPath,
INT  x,
INT  y,
TTPOLYGONHEADER header,
DWORD  size 
)
static

Definition at line 2273 of file path.c.

2280{
2282 POINT pt;
2283 BOOL bResult = FALSE;
2284
2285 start = header;
2286
2287 while ((char *)header < (char *)start + size)
2288 {
2289 TTPOLYCURVE *curve;
2290
2291 if (header->dwType != TT_POLYGON_TYPE)
2292 {
2293 ERR("Unknown header type %lu\n", header->dwType);
2294 goto cleanup;
2295 }
2296
2297 pt.x = x + int_from_fixed(header->pfxStart.x);
2298 pt.y = y - int_from_fixed(header->pfxStart.y);
2299 PATH_AddEntry(pPath, &pt, PT_MOVETO);
2300
2301 curve = (TTPOLYCURVE *)(header + 1);
2302
2303 while ((char *)curve < (char *)header + header->cb)
2304 {
2305 TRACE("curve->wType %d\n", curve->wType);
2306
2307 switch(curve->wType)
2308 {
2309 case TT_PRIM_LINE:
2310 {
2311 WORD i;
2312
2313 for (i = 0; i < curve->cpfx; i++)
2314 {
2315 pt.x = x + int_from_fixed(curve->apfx[i].x);
2316 pt.y = y - int_from_fixed(curve->apfx[i].y);
2317 PATH_AddEntry(pPath, &pt, PT_LINETO);
2318 }
2319 break;
2320 }
2321
2322 case TT_PRIM_QSPLINE:
2323 case TT_PRIM_CSPLINE:
2324 {
2325 WORD i;
2326 POINTFX ptfx;
2327 POINT *pts = ExAllocatePoolWithTag(PagedPool, (curve->cpfx + 1) * sizeof(POINT), TAG_PATH);
2328
2329 if (!pts) goto cleanup;
2330
2331 ptfx = *(POINTFX *)((char *)curve - sizeof(POINTFX));
2332
2333 pts[0].x = x + int_from_fixed(ptfx.x);
2334 pts[0].y = y - int_from_fixed(ptfx.y);
2335
2336 for (i = 0; i < curve->cpfx; i++)
2337 {
2338 pts[i + 1].x = x + int_from_fixed(curve->apfx[i].x);
2339 pts[i + 1].y = y - int_from_fixed(curve->apfx[i].y);
2340 }
2341
2342 PATH_BezierTo(pPath, pts, curve->cpfx + 1);
2343
2345 break;
2346 }
2347
2348 default:
2349 ERR("Unknown curve type %04x\n", curve->wType);
2350 goto cleanup;
2351 }
2352
2353 curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
2354 }
2355 header = (TTPOLYGONHEADER *)((char *)header + header->cb);
2356 }
2357
2358 bResult = TRUE;
2359
2360cleanup:
2361 IntGdiCloseFigure(pPath);
2362 return bResult;
2363}
static void cleanup(void)
Definition: main.c:1335
unsigned short WORD
Definition: ntddk_ex.h:93
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLsizeiptr size
Definition: glext.h:5919
FIXED y
Definition: wingdi.h:3155
FIXED x
Definition: wingdi.h:3154
POINTFX apfx[1]
Definition: wingdi.h:3160
static VOID FASTCALL PATH_BezierTo(PPATH pPath, POINT *lppt, INT n)
Definition: path.c:2229
static INT int_from_fixed(FIXED f)
Definition: path.c:2216
struct tagPOINTFX POINTFX
#define TT_PRIM_CSPLINE
Definition: wingdi.h:1321
#define TT_POLYGON_TYPE
Definition: wingdi.h:1318
#define TT_PRIM_QSPLINE
Definition: wingdi.h:1320
#define TT_PRIM_LINE
Definition: wingdi.h:1319

Referenced by PATH_ExtTextOut().

◆ PATH_AddEntry()

BOOL FASTCALL PATH_AddEntry ( PPATH  pPath,
const POINT pPoint,
BYTE  flags 
)

Definition at line 262 of file path.c.

266{
267 ASSERT(pPath != NULL);
268
269 /* FIXME: If newStroke is true, perhaps we want to check that we're
270 * getting a PT_MOVETO
271 */
272 TRACE("(%d,%d) - %d\n", pPoint->x, pPoint->y, flags);
273
274 /* Reserve enough memory for an extra path entry */
275 if (!PATH_ReserveEntries(pPath, pPath->numEntriesUsed + 1))
276 return FALSE;
277
278 /* Store information in path entry */
279 pPath->pPoints[pPath->numEntriesUsed] = *pPoint;
280 pPath->pFlags[pPath->numEntriesUsed] = flags;
281
282 /* Increment entry count */
283 pPath->numEntriesUsed++;
284
285 return TRUE;
286}
GLbitfield flags
Definition: glext.h:7161

Referenced by IntGdiWidenPath(), PATH_add_outline(), PATH_AddFlatBezier(), PATH_Arc(), PATH_BezierTo(), PATH_FlattenPath(), PATH_LineTo(), and PATH_PolyPolyline().

◆ PATH_AddFlatBezier()

BOOL FASTCALL PATH_AddFlatBezier ( PPATH  pPath,
POINT pt,
BOOL  closed 
)

Definition at line 1391 of file path.c.

1395{
1396 POINT *pts;
1397 BOOL ret = FALSE;
1398 INT no, i;
1399
1400 pts = GDI_Bezier(pt, 4, &no);
1401 if (!pts) return FALSE;
1402
1403 for (i = 1; i < no; i++)
1404 {
1405 if (!(ret = PATH_AddEntry(pPath, &pts[i], (i == no - 1 && closed) ? PT_LINETO | PT_CLOSEFIGURE : PT_LINETO)))
1406 break;
1407 }
1408
1410 return ret;
1411}
POINT * GDI_Bezier(const POINT *Points, INT count, INT *nPtsOut)
Definition: bezier.c:189
static WCHAR no[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2340
#define TAG_BEZIER
Definition: tags.h:13

Referenced by PATH_FlattenPath().

◆ PATH_Arc()

BOOL FASTCALL PATH_Arc ( PDC  dc,
INT  x1,
INT  y1,
INT  x2,
INT  y2,
INT  xStart,
INT  yStart,
INT  xEnd,
INT  yEnd,
INT  direction,
INT  lines 
)

Definition at line 965 of file path.c.

977{
978 double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant = 0.0;
979 /* Initialize angleEndQuadrant to silence gcc's warning */
980 FLOATL x, y;
981 POINT corners[2], pointStart, pointEnd;
982 POINT centre, pointCurPos;
983 BOOL start, end, Ret = TRUE;
984 INT temp;
985 BOOL clockwise;
986 PPATH pPath;
987
988 /* FIXME: This function should check for all possible error returns */
989 /* FIXME: Do we have to respect newStroke? */
990
991 ASSERT(dc);
992
993 pPath = PATH_LockPath(dc->dclevel.hPath);
994 if (!pPath) return FALSE;
995
996 if (direction)
997 clockwise = ((direction == AD_CLOCKWISE) !=0 );
998 else
999 clockwise = ((dc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
1000
1001 /* Check for zero height / width */
1002 /* FIXME: Only in GM_COMPATIBLE? */
1003 if (x1 == x2 || y1 == y2)
1004 {
1005 Ret = TRUE;
1006 goto ArcExit;
1007 }
1008 /* Convert points to device coordinates */
1009 corners[0].x = x1; corners[0].y = y1;
1010 corners[1].x = x2; corners[1].y = y2;
1011 pointStart.x = xStart; pointStart.y = yStart;
1012 pointEnd.x = xEnd; pointEnd.y = yEnd;
1013 INTERNAL_LPTODP(dc, corners, 2);
1014 INTERNAL_LPTODP(dc, &pointStart, 1);
1015 INTERNAL_LPTODP(dc, &pointEnd, 1);
1016
1017 /* Make sure first corner is top left and second corner is bottom right */
1018 if (corners[0].x > corners[1].x)
1019 {
1020 temp = corners[0].x;
1021 corners[0].x = corners[1].x;
1022 corners[1].x = temp;
1023 }
1024 if (corners[0].y > corners[1].y)
1025 {
1026 temp = corners[0].y;
1027 corners[0].y = corners[1].y;
1028 corners[1].y = temp;
1029 }
1030
1031 /* Compute start and end angle */
1032 PATH_NormalizePoint(corners, &pointStart, &x, &y);
1033 angleStart = atan2(*(FLOAT*)&y, *(FLOAT*)&x);
1034 PATH_NormalizePoint(corners, &pointEnd, &x, &y);
1035 angleEnd = atan2(*(FLOAT*)&y, *(FLOAT*)&x);
1036
1037 /* Make sure the end angle is "on the right side" of the start angle */
1038 if (clockwise)
1039 {
1040 if (angleEnd <= angleStart)
1041 {
1042 angleEnd += 2 * M_PI;
1043 ASSERT(angleEnd >= angleStart);
1044 }
1045 }
1046 else
1047 {
1048 if (angleEnd >= angleStart)
1049 {
1050 angleEnd -= 2 * M_PI;
1051 ASSERT(angleEnd <= angleStart);
1052 }
1053 }
1054
1055 /* In GM_COMPATIBLE, don't include bottom and right edges */
1056 if (dc->pdcattr->iGraphicsMode == GM_COMPATIBLE)
1057 {
1058 corners[1].x--;
1059 corners[1].y--;
1060 }
1061
1062 /* arcto: Add a PT_MOVETO only if this is the first entry in a stroke */
1063 if (lines == GdiTypeArcTo && pPath->newStroke) // -1
1064 {
1065 pPath->newStroke = FALSE;
1066 IntGetCurrentPositionEx(dc, &pointCurPos);
1067 CoordLPtoDP(dc, &pointCurPos);
1068 if (!PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO))
1069 {
1070 Ret = FALSE;
1071 goto ArcExit;
1072 }
1073 }
1074
1075 /* Add the arc to the path with one Bezier spline per quadrant that the
1076 * arc spans */
1077 start = TRUE;
1078 end = FALSE;
1079 do
1080 {
1081 /* Determine the start and end angles for this quadrant */
1082 if (start)
1083 {
1084 angleStartQuadrant = angleStart;
1085 if (clockwise)
1086 angleEndQuadrant = (floor(angleStart / M_PI_2) + 1.0) * M_PI_2;
1087 else
1088 angleEndQuadrant = (ceil(angleStart / M_PI_2) - 1.0) * M_PI_2;
1089 }
1090 else
1091 {
1092 angleStartQuadrant = angleEndQuadrant;
1093 if (clockwise)
1094 angleEndQuadrant += M_PI_2;
1095 else
1096 angleEndQuadrant -= M_PI_2;
1097 }
1098
1099 /* Have we reached the last part of the arc? */
1100 if ((clockwise && angleEnd < angleEndQuadrant) ||
1101 (!clockwise && angleEnd > angleEndQuadrant))
1102 {
1103 /* Adjust the end angle for this quadrant */
1104 angleEndQuadrant = angleEnd;
1105 end = TRUE;
1106 }
1107
1108 /* Add the Bezier spline to the path */
1109 PATH_DoArcPart(pPath,
1110 corners,
1111 angleStartQuadrant,
1112 angleEndQuadrant,
1113 start ? (lines == GdiTypeArcTo ? PT_LINETO : PT_MOVETO) : FALSE); // -1
1114 start = FALSE;
1115 }
1116 while (!end);
1117
1118 if (lines == GdiTypeArcTo)
1119 {
1120 update_current_pos( pPath );
1121 }
1122 else /* chord: close figure. pie: add line and close figure */
1123 if (lines == GdiTypeChord) // 1
1124 {
1125 IntGdiCloseFigure(pPath);
1126 }
1127 else if (lines == GdiTypePie) // 2
1128 {
1129 centre.x = (corners[0].x + corners[1].x) / 2;
1130 centre.y = (corners[0].y + corners[1].y) / 2;
1131 if (!PATH_AddEntry(pPath, &centre, PT_LINETO | PT_CLOSEFIGURE))
1132 Ret = FALSE;
1133 }
1134ArcExit:
1135 PATH_UnlockPath(pPath);
1136 return Ret;
1137}
#define CoordLPtoDP(pdc, ppt)
Definition: coord.h:187
static BOOLEAN INTERNAL_LPTODP(DC *dc, LPPOINT points, UINT count)
Definition: coord.h:47
_ACRTIMP double __cdecl ceil(double)
Definition: ceil.c:18
_ACRTIMP double __cdecl floor(double)
Definition: floor.c:18
GLuint GLuint end
Definition: gl.h:1545
direction
Definition: netio.c:882
@ GdiTypeChord
Definition: ntgdityp.h:22
@ GdiTypeArcTo
Definition: ntgdityp.h:21
@ GdiTypePie
Definition: ntgdityp.h:23
@ DCPATH_CLOCKWISE
Definition: path.h:8
static calc_node_t temp
Definition: rpn_ieee.c:38
eMaj lines
Definition: tritemp.h:206
float FLOAT
Definition: typedefs.h:69
static VOID PATH_NormalizePoint(POINTL corners[], const POINTL *pPoint, FLOATL *pX, FLOATL *pY)
Definition: path.c:401
FLOAT FLOATL
Definition: winddi.h:114
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3709
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3711
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
#define GM_COMPATIBLE
Definition: wingdi.h:864
#define AD_CLOCKWISE
Definition: wingdi.h:668

Referenced by IntGdiArcInternal().

◆ PATH_AssignGdiPath()

BOOL FASTCALL PATH_AssignGdiPath ( PPATH  pPathDest,
const PPATH  pPathSrc 
)

Definition at line 166 of file path.c.

169{
170 ASSERT(pPathDest != NULL && pPathSrc != NULL);
171
172 /* Make sure destination arrays are big enough */
173 if (!PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed))
174 return FALSE;
175
176 /* Perform the copy operation */
177 memcpy(pPathDest->pPoints, pPathSrc->pPoints, sizeof(POINT)*pPathSrc->numEntriesUsed);
178 memcpy(pPathDest->pFlags, pPathSrc->pFlags, sizeof(BYTE)*pPathSrc->numEntriesUsed);
179
180 pPathDest->pos = pPathSrc->pos;
181 pPathDest->state = pPathSrc->state;
182 pPathDest->numEntriesUsed = pPathSrc->numEntriesUsed;
183 pPathDest->newStroke = pPathSrc->newStroke;
184 return TRUE;
185}

Referenced by PATH_RestorePath(), and PATH_SavePath().

◆ PATH_BezierTo()

static VOID FASTCALL PATH_BezierTo ( PPATH  pPath,
POINT lppt,
INT  n 
)
static

Definition at line 2229 of file path.c.

2233{
2234 if (n < 2) return;
2235
2236 if (n == 2)
2237 {
2238 PATH_AddEntry(pPath, &lppt[1], PT_LINETO);
2239 }
2240 else if (n == 3)
2241 {
2242 add_points( pPath, lppt, 3, PT_BEZIERTO );
2243 }
2244 else
2245 {
2246 POINT pt[3];
2247 INT i = 0;
2248
2249 pt[2] = lppt[0];
2250 n--;
2251
2252 while (n > 2)
2253 {
2254 pt[0] = pt[2];
2255 pt[1] = lppt[i + 1];
2256 pt[2].x = (lppt[i + 2].x + lppt[i + 1].x) / 2;
2257 pt[2].y = (lppt[i + 2].y + lppt[i + 1].y) / 2;
2258 add_points( pPath, pt, 3, PT_BEZIERTO );
2259 n--;
2260 i++;
2261 }
2262
2263 pt[0] = pt[2];
2264 pt[1] = lppt[i + 1];
2265 pt[2] = lppt[i + 2];
2266 add_points( pPath, pt, 3, PT_BEZIERTO );
2267 }
2268}
GLdouble n
Definition: glext.h:7729

Referenced by PATH_add_outline().

◆ PATH_CheckRect()

static BOOL PATH_CheckRect ( DC dc,
RECTL rect,
INT  x1,
INT  y1,
INT  x2,
INT  y2 
)
static

Definition at line 433 of file path.c.

440{
441 PDC_ATTR pdcattr = dc->pdcattr;
442
443 /* Convert points to device coordinates */
445 IntLPtoDP(dc, (PPOINT)rect, 2);
446
447 /* Make sure first corner is top left and second corner is bottom right */
449
450 /* In GM_COMPATIBLE, don't include bottom and right edges */
451 if (pdcattr->iGraphicsMode == GM_COMPATIBLE)
452 {
453 if (rect->left == rect->right) return FALSE;
454 if (rect->top == rect->bottom) return FALSE;
455 rect->right--;
456 rect->bottom--;
457 }
458 return TRUE;
459}
RECT rect
Definition: combotst.c:67
INT iGraphicsMode
Definition: ntgdihdl.h:306
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
VOID FASTCALL RECTL_vMakeWellOrdered(_Inout_ RECTL *prcl)
Definition: rect.c:81
FORCEINLINE VOID RECTL_vSetRect(_Out_ RECTL *prcl, _In_ LONG left, _In_ LONG top, _In_ LONG right, _In_ LONG bottom)
Definition: rect.h:5

Referenced by PATH_Ellipse(), PATH_Rectangle(), and PATH_RoundRect().

◆ PATH_CreatePath()

PPATH FASTCALL PATH_CreatePath ( int  count)

Definition at line 35 of file path.c.

36{
38
39 if (!pPath)
40 {
42 return NULL;
43 }
44
45 TRACE("CreatePath p 0x%p\n", pPath);
46 // Path handles are shared. Also due to recursion with in the same thread.
47 GDIOBJ_vUnlockObject((POBJ)pPath); // Unlock
48 pPath = PATH_LockPath(pPath->BaseObject.hHmgr); // Share Lock.
49
50 /* Make sure that path is empty */
51 PATH_EmptyPath(pPath);
52
54
56
58 RtlZeroMemory( pPath->pPoints, count * sizeof(POINT));
60 RtlZeroMemory( pPath->pFlags, count * sizeof(BYTE));
61
62 /* Initialize variables for new path */
63 pPath->numEntriesUsed = 0;
64 pPath->newStroke = TRUE;
65 pPath->state = PATH_Open;
66 pPath->pos.x = pPath->pos.y = 0;
67#if DBG
68 PathCount++;
69 TRACE("Create Path %d\n",PathCount);
70#endif
71 return pPath;
72}
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define PATH_AllocPathWithHandle()
Definition: path.h:69
int numEntriesAllocated
Definition: path.h:56
#define max(a, b)
Definition: svc.c:63
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
VOID NTAPI GDIOBJ_vUnlockObject(POBJ pobj)
Definition: gdiobj.c:887
VOID FASTCALL PATH_EmptyPath(PPATH pPath)
Definition: path.c:246

Referenced by IntGdiLineTo(), IntGdiPolygon(), IntGdiPolyline(), IntGdiWidenPath(), IntRectangle(), NtGdiBeginPath(), PATH_FlattenPath(), PATH_RestorePath(), and PATH_SavePath().

◆ PATH_Delete()

BOOL FASTCALL PATH_Delete ( HPATH  hPath)

Definition at line 90 of file path.c.

91{
92 PPATH pPath;
93 if (!hPath) return FALSE;
94 pPath = PATH_LockPath(hPath);
95 if (!pPath) return FALSE;
98#if DBG
99 PathCount--;
100 TRACE("Delete Path %d\n",PathCount);
101#endif
102 return TRUE;
103}
VOID NTAPI GDIOBJ_vDeleteObject(POBJ pobj)
Definition: gdiobj.c:1118

Referenced by DC_vCleanup(), IntGdiCleanDC(), IntGdiLineTo(), IntGdiPolygon(), IntGdiPolyline(), IntGdiWidenPath(), IntRectangle(), NtGdiAbortPath(), NtGdiBeginPath(), NtGdiFillPath(), NtGdiFlattenPath(), NtGdiPathToRegion(), NtGdiSelectClipPath(), NtGdiStrokeAndFillPath(), NtGdiStrokePath(), NtGdiWidenPath(), PATH_FlattenPath(), and PATH_StrokePath().

◆ PATH_DestroyGdiPath()

VOID FASTCALL PATH_DestroyGdiPath ( PPATH  pPath)

Definition at line 80 of file path.c.

81{
82 ASSERT(pPath != NULL);
83
84 if (pPath->pPoints) ExFreePoolWithTag(pPath->pPoints, TAG_PATH);
85 if (pPath->pFlags) ExFreePoolWithTag(pPath->pFlags, TAG_PATH);
86}

Referenced by IntGdiWidenPath(), and PATH_Delete().

◆ PATH_DoArcPart()

static BOOL PATH_DoArcPart ( PPATH  pPath,
POINT  corners[],
double  angleStart,
double  angleEnd,
BYTE  startEntryType 
)
static

Definition at line 900 of file path.c.

906{
907 double halfAngle, a;
908 float xNorm[4], yNorm[4];
909 POINT points[4];
910 BYTE *type;
911 int i, start;
912
913 ASSERT(fabs(angleEnd - angleStart) <= M_PI_2);
914
915 /* FIXME: Is there an easier way of computing this? */
916
917 /* Compute control points */
918 halfAngle = (angleEnd - angleStart) / 2.0;
919 if (fabs(halfAngle) > 1e-8)
920 {
921 a = 4.0 / 3.0 * (1 - cos(halfAngle)) / sin(halfAngle);
922 xNorm[0] = cos(angleStart);
923 yNorm[0] = sin(angleStart);
924 xNorm[1] = xNorm[0] - a * yNorm[0];
925 yNorm[1] = yNorm[0] + a * xNorm[0];
926 xNorm[3] = cos(angleEnd);
927 yNorm[3] = sin(angleEnd);
928 xNorm[2] = xNorm[3] + a * yNorm[3];
929 yNorm[2] = yNorm[3] - a * xNorm[3];
930 }
931 else
932 for (i = 0; i < 4; i++)
933 {
934 xNorm[i] = cos(angleStart);
935 yNorm[i] = sin(angleStart);
936 }
937
938 /* Add starting point to path if desired */
939 start = !startEntryType;
940
941 /* Add remaining control points */
942 for (i = start; i < 4; i++)
943 {
944 if (!PATH_ScaleNormalizedPoint(corners, *(FLOATL*)&xNorm[i], *(FLOATL*)&yNorm[i], &points[i]))
945 return FALSE;
946 }
947 if (!(type = add_points( pPath, points + start, 4 - start, PT_BEZIERTO ))) return FALSE;
948 if (!start) type[0] = startEntryType;
949
950 return TRUE;
951}
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
#define e
Definition: ke_i.h:82
#define a
Definition: ke_i.h:78
static BOOLEAN PATH_ScaleNormalizedPoint(POINT corners[], FLOATL x, FLOATL y, POINT *pPoint)
Definition: path.c:363

Referenced by IntGdiWidenPath(), and PATH_Arc().

◆ PATH_Ellipse()

BOOL PATH_Ellipse ( PDC  dc,
INT  x1,
INT  y1,
INT  x2,
INT  y2 
)

Definition at line 792 of file path.c.

798{
799 PPATH pPath;
800 POINT points[13];
801 RECTL rect;
802 BYTE *type;
803 LONG xRadius, yRadius, xOffset, yOffset;
805
806 TRACE("PATH_Ellipse: %p -> (%d, %d) - (%d, %d)\n",
807 dc, x1, y1, x2, y2);
808
809 if (!PATH_CheckRect(dc, &rect, x1, y1, x2, y2))
810 {
811 return TRUE;
812 }
813
814 xRadius = RECTL_lGetWidth(&rect) / 2;
815 yRadius = RECTL_lGetHeight(&rect) / 2;
816
817 /* Get the four points which box our ellipse */
818 left.x = rect.left; left.y = rect.top + yRadius;
819 top.x = rect.left + xRadius; top.y = rect.top;
820 right.x = rect.right; right.y = rect.bottom - yRadius;
821 bottom.x = rect.right - xRadius; bottom.y = rect.bottom;
822
823 /*
824 * See here to understand what's happening
825 * https://stackoverflow.com/questions/1734745/how-to-create-circle-with-b%C3%A9zier-curves
826 */
827 xOffset = EngMulDiv(RECTL_lGetWidth(&rect), 55428475, 200000000); /* w * 0.55428475 / 2 */
828 yOffset = EngMulDiv(RECTL_lGetHeight(&rect), 55428475, 200000000); /* h * 0.55428475 / 2 */
829 TRACE("xOffset %d, yOffset %d, Rect WxH: %dx%d.\n",
831
832 pPath = PATH_LockPath(dc->dclevel.hPath);
833 if (!pPath)
834 return FALSE;
835
836 /* Starting point: Right */
837 points[0] = right;
838
839 /* first curve - going up, left */
840 points[1] = right;
841 points[1].y -= yOffset;
842 points[2] = top;
843 points[2].x += xOffset;
844
845 /* top */
846 points[3] = top;
847
848 /* second curve - going left, down*/
849 points[4] = top;
850 points[4].x -= xOffset;
851 points[5] = left;
852 points[5].y -= yOffset;
853
854 /* Left */
855 points[6] = left;
856
857 /* Third curve - going down, right */
858 points[7] = left;
859 points[7].y += yOffset;
860 points[8] = bottom;
861 points[8].x -= xOffset;
862
863 /* bottom */
864 points[9] = bottom;
865
866 /* Fourth curve - Going right, up */
867 points[10] = bottom;
868 points[10].x += xOffset;
869 points[11] = right;
870 points[11].y += yOffset;
871
872 /* Back to starting point */
873 points[12] = right;
874
875 if (dc->dclevel.flPath & DCPATH_CLOCKWISE) reverse_points( points, 13 );
876 if (!(type = add_points( pPath, points, 13, PT_BEZIERTO )))
877 {
878 ERR("PATH_Ellipse No add\n");
879 PATH_UnlockPath(pPath);
880 return FALSE;
881 }
882 type[0] = PT_MOVETO;
883
884 IntGdiCloseFigure(pPath);
885 PATH_UnlockPath(pPath);
886 return TRUE;
887}
int yOffset
Definition: appswitch.c:58
int xOffset
Definition: appswitch.c:58
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLdouble GLdouble right
Definition: glext.h:10859
GLint left
Definition: glext.h:7726
GLint GLint bottom
Definition: glext.h:7726
long LONG
Definition: pedump.c:60
static BOOL PATH_CheckRect(DC *dc, RECTL *rect, INT x1, INT y1, INT x2, INT y2)
Definition: path.c:433
FORCEINLINE LONG RECTL_lGetWidth(_In_ const RECTL *prcl)
Definition: rect.h:93
FORCEINLINE LONG RECTL_lGetHeight(_In_ const RECTL *prcl)
Definition: rect.h:86
ENGAPI INT APIENTRY EngMulDiv(_In_ INT a, _In_ INT b, _In_ INT c)
Definition: math.c:26

Referenced by NtGdiEllipse().

◆ PATH_EmptyPath()

VOID FASTCALL PATH_EmptyPath ( PPATH  pPath)

Definition at line 246 of file path.c.

247{
248 ASSERT(pPath != NULL);
249
250 pPath->state = PATH_Null;
251 pPath->numEntriesUsed = 0;
252}
@ PATH_Null
Definition: path.h:18

Referenced by PATH_CreatePath().

◆ PATH_ExtTextOut()

BOOL FASTCALL PATH_ExtTextOut ( PDC  dc,
INT  x,
INT  y,
UINT  flags,
const RECTL lprc,
LPCWSTR  str,
UINT  count,
const INT dx 
)

Definition at line 2370 of file path.c.

2379{
2380 PPATH pPath;
2381 unsigned int idx, ggo_flags = GGO_NATIVE;
2382 POINT offset = {0, 0};
2383
2384 pPath = PATH_LockPath(dc->dclevel.hPath);
2385 if (!pPath)
2386 {
2387 return FALSE;
2388 }
2389
2390 if (pPath->state != PATH_Open)
2391 {
2392 ERR("PATH_ExtTextOut not open\n");
2393 return FALSE;
2394 }
2395
2396 if (!count) return TRUE;
2397 if (flags & ETO_GLYPH_INDEX) ggo_flags |= GGO_GLYPH_INDEX;
2398
2399 for (idx = 0; idx < count; idx++)
2400 {
2401 MAT2 identity = { {0, 1}, {0, 0}, {0, 0}, {0, 1} };
2402 GLYPHMETRICS gm;
2403 DWORD dwSize;
2404 void *outline;
2405
2407 str[idx],
2408 ggo_flags,
2409 &gm,
2410 0,
2411 NULL,
2412 &identity,
2413 TRUE);
2414 if (dwSize == GDI_ERROR)
2415 {
2416 // With default DC font,,, bitmap font?
2417 // ExtTextOut on a path with bitmap font selected shouldn't fail.
2418 // This just leads to empty path generated.
2419 // Ref : test_emf_ExtTextOut_on_path
2420 continue;
2421 }
2422
2423 /* Add outline only if char is printable */
2424 if (dwSize)
2425 {
2427 if (!outline)
2428 {
2429 PATH_UnlockPath(pPath);
2430 return FALSE;
2431 }
2432
2434 str[idx],
2435 ggo_flags,
2436 &gm,
2437 dwSize,
2438 outline,
2439 &identity,
2440 TRUE);
2441
2442 PATH_add_outline(dc, pPath, x + offset.x, y + offset.y, outline, dwSize);
2443
2445 }
2446
2447 if (dx)
2448 {
2449 if (flags & ETO_PDY)
2450 {
2451 offset.x += dx[idx * 2];
2452 offset.y += dx[idx * 2 + 1];
2453 }
2454 else
2455 offset.x += dx[idx];
2456 }
2457 else
2458 {
2459 offset.x += gm.gmCellIncX;
2460 offset.y += gm.gmCellIncY;
2461 }
2462 }
2463 PATH_UnlockPath(pPath);
2464 return TRUE;
2465}
unsigned int idx
Definition: utils.c:41
ULONG FASTCALL ftGdiGetGlyphOutline(PDC dc, WCHAR wch, UINT iFormat, LPGLYPHMETRICS pgm, ULONG cjBuf, PVOID pvBuf, const MAT2 *pmat2, BOOL bIgnoreRotation)
Definition: freetype.c:4444
GLintptr offset
Definition: glext.h:5920
GLint dx
Definition: linetemp.h:97
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
const WCHAR * str
short gmCellIncX
Definition: wingdi.h:2891
short gmCellIncY
Definition: wingdi.h:2892
Definition: wingdi.h:2918
Definition: mesh.c:5330
static BOOL FASTCALL PATH_add_outline(PDC dc, PPATH pPath, INT x, INT y, TTPOLYGONHEADER *header, DWORD size)
Definition: path.c:2273
#define GGO_GLYPH_INDEX
Definition: wingdi.h:855
#define GDI_ERROR
Definition: wingdi.h:1309
#define ETO_PDY
Definition: wingdi.h:657
#define GGO_NATIVE
Definition: wingdi.h:850

Referenced by IntExtTextOutW().

◆ PATH_FillPath()

BOOL FASTCALL PATH_FillPath ( PDC  dc,
PPATH  pPath 
)

Definition at line 1518 of file path.c.

1521{
1522 return PATH_FillPathEx(dc, pPath, NULL);
1523}
BOOL FASTCALL PATH_FillPathEx(PDC dc, PPATH pPath, PBRUSH pbrFill)
Definition: path.c:1527

Referenced by NtGdiFillPath(), and NtGdiStrokeAndFillPath().

◆ PATH_FillPathEx()

BOOL FASTCALL PATH_FillPathEx ( PDC  dc,
PPATH  pPath,
PBRUSH  pbrFill 
)

Definition at line 1527 of file path.c.

1531{
1532 INT mapMode, graphicsMode;
1533 SIZE ptViewportExt, ptWindowExt;
1534 POINTL ptViewportOrg, ptWindowOrg;
1535 XFORML xform;
1536 PREGION Rgn;
1537 PDC_ATTR pdcattr = dc->pdcattr;
1538
1539 /* Allocate a temporary region */
1540 Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
1541 if (!Rgn)
1542 {
1544 return FALSE;
1545 }
1546
1547 if (!PATH_PathToRegion(pPath, pdcattr->jFillMode, Rgn))
1548 {
1549 TRACE("PFP : Fail P2R\n");
1550 /* EngSetLastError ? */
1551 REGION_Delete(Rgn);
1552 return FALSE;
1553 }
1554
1555 /* Since PaintRgn interprets the region as being in logical coordinates
1556 * but the points we store for the path are already in device
1557 * coordinates, we have to set the mapping mode to MM_TEXT temporarily.
1558 * Using SaveDC to save information about the mapping mode / world
1559 * transform would be easier but would require more overhead, especially
1560 * now that SaveDC saves the current path.
1561 */
1562
1563 /* Save the information about the old mapping mode */
1564 mapMode = pdcattr->iMapMode;
1565 ptViewportExt = pdcattr->szlViewportExt;
1566 ptViewportOrg = pdcattr->ptlViewportOrg;
1567 ptWindowExt = pdcattr->szlWindowExt;
1568 ptWindowOrg = pdcattr->ptlWindowOrg;
1569
1570 /* Save world transform
1571 * NB: The Windows documentation on world transforms would lead one to
1572 * believe that this has to be done only in GM_ADVANCED; however, my
1573 * tests show that resetting the graphics mode to GM_COMPATIBLE does
1574 * not reset the world transform.
1575 */
1576 MatrixS2XForm(&xform, &dc->pdcattr->mxWorldToPage);
1577
1578 /* Set MM_TEXT */
1580 pdcattr->ptlViewportOrg.x = 0;
1581 pdcattr->ptlViewportOrg.y = 0;
1582 pdcattr->ptlWindowOrg.x = 0;
1583 pdcattr->ptlWindowOrg.y = 0;
1584
1585 graphicsMode = pdcattr->iGraphicsMode;
1586 pdcattr->iGraphicsMode = GM_ADVANCED;
1588 pdcattr->iGraphicsMode = graphicsMode;
1589
1590 /* Paint the region */
1591 IntGdiFillRgn(dc, Rgn, pbrFill);
1592 REGION_Delete(Rgn);
1593 /* Restore the old mapping mode */
1594 IntGdiSetMapMode(dc, mapMode);
1595 pdcattr->szlViewportExt = ptViewportExt;
1596 pdcattr->ptlViewportOrg = ptViewportOrg;
1597 pdcattr->szlWindowExt = ptWindowExt;
1598 pdcattr->ptlWindowOrg = ptWindowOrg;
1599
1600 /* Go to GM_ADVANCED temporarily to restore the world transform */
1601 graphicsMode = pdcattr->iGraphicsMode;
1602 pdcattr->iGraphicsMode = GM_ADVANCED;
1604 pdcattr->iGraphicsMode = graphicsMode;
1605 return TRUE;
1606}
#define MatrixS2XForm(x, m)
Definition: coord.h:200
int APIENTRY IntGdiSetMapMode(PDC dc, int MapMode)
Definition: coord.c:828
BOOL NTAPI GreModifyWorldTransform(PDC pdc, const XFORML *pxform, DWORD dwMode)
Definition: coord.c:461
#define MWT_SET
Definition: ntgdityp.h:180
SIZEL szlViewportExt
Definition: ntgdihdl.h:344
INT iMapMode
Definition: ntgdihdl.h:338
POINTL ptlViewportOrg
Definition: ntgdihdl.h:343
POINTL ptlWindowOrg
Definition: ntgdihdl.h:341
SIZEL szlWindowExt
Definition: ntgdihdl.h:342
BOOL IntGdiFillRgn(_In_ PDC pdc, _In_ PREGION prgn, _In_opt_ PBRUSH pbrFill)
Definition: bitblt.c:1190
PREGION FASTCALL IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
Definition: region.c:2407
#define GM_ADVANCED
Definition: wingdi.h:865
#define MM_TEXT
Definition: wingdi.h:873
#define MWT_IDENTITY
Definition: wingdi.h:944

Referenced by PATH_FillPath(), and PATH_StrokePath().

◆ PATH_FlattenPath()

PPATH FASTCALL PATH_FlattenPath ( PPATH  pPath)

Definition at line 1420 of file path.c.

1421{
1422 PPATH newPath;
1423 INT srcpt;
1424 TRACE("PATH_FlattenPath\n");
1425 if (!(newPath = PATH_CreatePath(pPath->numEntriesUsed))) return NULL;
1426
1427 for (srcpt = 0; srcpt < pPath->numEntriesUsed; srcpt++)
1428 {
1429 switch(pPath->pFlags[srcpt] & ~PT_CLOSEFIGURE)
1430 {
1431 case PT_MOVETO:
1432 case PT_LINETO:
1433 if (!PATH_AddEntry(newPath, &pPath->pPoints[srcpt], pPath->pFlags[srcpt]))
1434 {
1435 PATH_UnlockPath(newPath);
1436 PATH_Delete(newPath->BaseObject.hHmgr);
1437 return NULL;
1438 }
1439 break;
1440 case PT_BEZIERTO:
1441 if(!PATH_AddFlatBezier(newPath, &pPath->pPoints[srcpt - 1], pPath->pFlags[srcpt + 2] & PT_CLOSEFIGURE))
1442 {
1443 PATH_UnlockPath(newPath);
1444 PATH_Delete(newPath->BaseObject.hHmgr);
1445 return NULL;
1446 }
1447 srcpt += 2;
1448 break;
1449 }
1450 }
1451 TRACE("PATH_FlattenPath good\n");
1452 newPath->state = pPath->state;
1453 return newPath;
1454}
BOOL FASTCALL PATH_AddFlatBezier(PPATH pPath, POINT *pt, BOOL closed)
Definition: path.c:1391

Referenced by IntGdiWidenPath(), NtGdiFillPath(), NtGdiFlattenPath(), NtGdiPathToRegion(), NtGdiSelectClipPath(), NtGdiStrokeAndFillPath(), and NtGdiStrokePath().

◆ PATH_InitGdiPath()

VOID FASTCALL PATH_InitGdiPath ( PPATH  pPath)

Definition at line 142 of file path.c.

144{
145 ASSERT(pPath != NULL);
146
147 pPath->state = PATH_Null;
148 pPath->pPoints = NULL;
149 pPath->pFlags = NULL;
150 pPath->numEntriesUsed = 0;
151 pPath->numEntriesAllocated = 0;
152}

Referenced by IntGdiWidenPath().

◆ PATH_LineTo()

BOOL FASTCALL PATH_LineTo ( PDC  dc,
INT  x,
INT  y 
)

Definition at line 593 of file path.c.

597{
598 BOOL Ret;
599 PPATH pPath;
600 POINT point, pointCurPos;
601
602 pPath = PATH_LockPath(dc->dclevel.hPath);
603 if (!pPath) return FALSE;
604
605 point.x = x;
606 point.y = y;
607
608 // Coalesce a MoveTo point.
609 if ( !PATH_MoveTo(dc, pPath) )
610 {
611 /* Add a PT_MOVETO if necessary */
612 if (pPath->newStroke)
613 {
614 TRACE("Line To : New Stroke\n");
615 pPath->newStroke = FALSE;
616 IntGetCurrentPositionEx(dc, &pointCurPos);
617 CoordLPtoDP(dc, &pointCurPos);
618 if (!PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO))
619 {
620 PATH_UnlockPath(pPath);
621 return FALSE;
622 }
623 }
624 }
625 Ret = add_log_points_new_stroke(dc, pPath, &point, 1, PT_LINETO , FALSE);
626 PATH_UnlockPath(pPath);
627 return Ret;
628}
static BOOL add_log_points_new_stroke(DC *dc, PPATH path, const POINT *points, DWORD count, BYTE type, BOOL bExtraPt)
Definition: path.c:543
BOOL FASTCALL PATH_MoveTo(PDC dc, PPATH pPath)
Definition: path.c:564

Referenced by IntGdiLineTo(), IntGdiPolygon(), IntGdiPolyline(), and IntRectangle().

◆ PATH_MoveTo()

BOOL FASTCALL PATH_MoveTo ( PDC  dc,
PPATH  pPath 
)

Definition at line 564 of file path.c.

567{
568 if (!pPath) return FALSE;
569
570 // GDI32 : Signal from user space of a change in position.
571 if (dc->pdcattr->ulDirty_ & DIRTY_STYLESTATE)
572 {
573 TRACE("MoveTo has changed\n");
574 pPath->newStroke = TRUE;
575 // Set position and clear the signal flag.
577 IntLPtoDP( dc, &pPath->pos, 1 );
578 return TRUE;
579 }
580
581 return FALSE;
582}
#define DIRTY_STYLESTATE
Definition: ntgdihdl.h:133

Referenced by IntGdiLineTo(), IntGdiPolygon(), IntGdiPolyline(), IntRectangle(), and PATH_LineTo().

◆ PATH_NormalizePoint()

static VOID PATH_NormalizePoint ( POINTL  corners[],
const POINTL pPoint,
FLOATL pX,
FLOATL pY 
)
static

Definition at line 401 of file path.c.

406{
407 FLOATOBJ tmp;
408
409 ASSERT(corners);
410 ASSERT(pPoint);
411 ASSERT(pX);
412 ASSERT(pY);
413
414 /* *pX = (float)(pPoint->x - corners[0].x) / (float)(corners[1].x - corners[0].x) * 2.0 - 1.0; */
415 FLOATOBJ_SetLong(&tmp, (pPoint->x - corners[0].x) * 2);
416 FLOATOBJ_DivLong(&tmp, corners[1].x - corners[0].x);
417 FLOATOBJ_Sub(&tmp, (PFLOATOBJ)&gef1);
418 *pX = FLOATOBJ_GetFloat(&tmp);
419
420 /* *pY = (float)(pPoint->y - corners[0].y) / (float)(corners[1].y - corners[0].y) * 2.0 - 1.0; */
421 FLOATOBJ_SetLong(&tmp, (pPoint->y - corners[0].y) * 2);
422 FLOATOBJ_DivLong(&tmp, corners[1].y - corners[0].y);
423 FLOATOBJ_Sub(&tmp, (PFLOATOBJ)&gef1);
424 *pY = FLOATOBJ_GetFloat(&tmp);
425}
static const FLOATOBJ gef1
Definition: floatobj.h:114
#define FLOATOBJ_DivLong(pf, l)
Definition: winddi.h:2829
FLOAT * PFLOATOBJ
Definition: winddi.h:677
#define FLOATOBJ_Sub(pf, pf1)
Definition: winddi.h:2821
FLOAT FLOATOBJ
Definition: winddi.h:677
#define FLOATOBJ_GetFloat(pf)
Definition: winddi.h:2816
#define FLOATOBJ_SetLong(pf, l)
Definition: winddi.h:2815

Referenced by PATH_Arc().

◆ PATH_PathToRegion()

BOOL FASTCALL PATH_PathToRegion ( PPATH  pPath,
INT  Mode,
PREGION  Rgn 
)

Definition at line 1463 of file path.c.

1467{
1468 int i, pos, polygons;
1469 PULONG counts;
1470 int Ret;
1471
1472 if (!pPath->numEntriesUsed) return FALSE;
1473
1474 counts = ExAllocatePoolWithTag(PagedPool, (pPath->numEntriesUsed / 2) * sizeof(*counts), TAG_PATH);
1475 if (!counts)
1476 {
1477 ERR("Failed to allocate %lu strokes\n", (pPath->numEntriesUsed / 2) * sizeof(*counts));
1479 return FALSE;
1480 }
1481
1482 pos = polygons = 0;
1483 ASSERT( pPath->pFlags[0] == PT_MOVETO );
1484 for (i = 1; i < pPath->numEntriesUsed; i++)
1485 {
1486 if (pPath->pFlags[i] != PT_MOVETO) continue;
1487 counts[polygons++] = i - pos;
1488 pos = i;
1489 }
1490 if (i > pos + 1) counts[polygons++] = i - pos;
1491
1492 ASSERT( polygons <= pPath->numEntriesUsed / 2 );
1493
1494 /* Fill the region with the strokes */
1495 Ret = REGION_SetPolyPolygonRgn(Rgn,
1496 pPath->pPoints,
1497 counts,
1498 polygons,
1499 Mode);
1500 if (!Ret)
1501 {
1502 ERR("REGION_SetPolyPolygonRgn failed\n");
1503 }
1504
1505 ExFreePoolWithTag(counts, TAG_PATH);
1506
1507 /* Success! */
1508 return Ret;
1509}
_In_ ULONG Mode
Definition: hubbusif.h:303
uint32_t * PULONG
Definition: typedefs.h:59
BOOL FASTCALL REGION_SetPolyPolygonRgn(_Inout_ PREGION prgn, _In_ const POINT *ppt, _In_ const ULONG *pcPoints, _In_ ULONG cPolygons, _In_ INT iMode)
Definition: region.c:3254

Referenced by NtGdiPathToRegion(), NtGdiSelectClipPath(), and PATH_FillPathEx().

◆ PATH_PolyBezier()

BOOL FASTCALL PATH_PolyBezier ( PDC  dc,
const POINT pts,
DWORD  cbPoints 
)

Definition at line 1164 of file path.c.

1168{
1169 PPATH pPath;
1170 BYTE *type;
1171
1172 ASSERT(dc);
1173 ASSERT(pts);
1174 ASSERT(cbPoints);
1175
1176 pPath = PATH_LockPath(dc->dclevel.hPath);
1177 if (!pPath) return FALSE;
1178
1179 type = add_log_points(dc, pPath, pts, cbPoints, PT_BEZIERTO, FALSE);
1180 if (!type) return FALSE;
1181
1182 type[0] = PT_MOVETO;
1183
1184 PATH_UnlockPath(pPath);
1185 return TRUE;
1186}

Referenced by IntGdiPolyBezier().

◆ PATH_PolyBezierTo()

BOOL FASTCALL PATH_PolyBezierTo ( PDC  dc,
const POINT pts,
DWORD  cbPoints 
)

Definition at line 1141 of file path.c.

1145{
1146 PPATH pPath;
1147 BOOL ret;
1148
1149 ASSERT(dc);
1150 ASSERT(pts);
1151 ASSERT(cbPoints);
1152
1153 pPath = PATH_LockPath(dc->dclevel.hPath);
1154 if (!pPath) return FALSE;
1155
1156 ret = add_log_points_new_stroke(dc, pPath, pts, cbPoints, PT_BEZIERTO , TRUE);
1157
1158 PATH_UnlockPath(pPath);
1159 return ret;
1160}

Referenced by IntGdiPolyBezierTo().

◆ PATH_PolyDraw()

BOOL FASTCALL PATH_PolyDraw ( PDC  dc,
const POINT pts,
const BYTE types,
DWORD  cbPoints 
)

Definition at line 1190 of file path.c.

1195{
1196 PPATH pPath;
1197 POINT orig_pos, cur_pos;
1198 ULONG i, lastmove = 0;
1199
1200 pPath = PATH_LockPath(dc->dclevel.hPath);
1201 if (!pPath) return FALSE;
1202
1203 if (pPath->state != PATH_Open)
1204 {
1205 PATH_UnlockPath(pPath);
1206 return FALSE;
1207 }
1208
1209 for (i = 0; i < pPath->numEntriesUsed; i++) if (pPath->pFlags[i] == PT_MOVETO) lastmove = i;
1210 orig_pos = pPath->pos;
1211
1212 IntGetCurrentPositionEx(dc, &cur_pos);
1213
1214 TRACE("PPD : Current pos X %d Y %d\n",pPath->pos.x, pPath->pos.y);
1215 TRACE("PPD : last %d pos X %d Y %d\n",lastmove, pPath->pPoints[lastmove].x, pPath->pPoints[lastmove].y);
1216
1217
1218 for(i = 0; i < cbPoints; i++)
1219 {
1220 switch (types[i])
1221 {
1222 case PT_MOVETO:
1223 pPath->newStroke = TRUE;
1224 pPath->pos = pts[i];
1225 IntLPtoDP( dc, &pPath->pos, 1);
1226 lastmove = pPath->numEntriesUsed;
1227 break;
1228 case PT_LINETO:
1230 if (!add_log_points_new_stroke(dc, pPath, &pts[i], 1, PT_LINETO , FALSE))
1231 {
1232 PATH_UnlockPath(pPath);
1233 return FALSE;
1234 }
1235 break;
1236 case PT_BEZIERTO:
1237 if ((i + 2 < cbPoints) && (types[i + 1] == PT_BEZIERTO) &&
1238 (types[i + 2] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
1239 {
1240 if (!add_log_points_new_stroke(dc, pPath, &pts[i], 3, PT_BEZIERTO , FALSE))
1241 {
1242 PATH_UnlockPath(pPath);
1243 return FALSE;
1244 }
1245 i += 2;
1246 break;
1247 }
1248 /* fall through */
1249 default:
1250 /* restore original position */
1251 pPath->pos = orig_pos;
1252
1253 TRACE("PPD Bad : pos X %d Y %d\n",pPath->pos.x, pPath->pos.y);
1254
1255 IntGdiMoveToEx(dc, cur_pos.x, cur_pos.y, NULL);
1256
1257 PATH_UnlockPath(pPath);
1258 return FALSE;
1259 }
1260
1261 if (types[i] & PT_CLOSEFIGURE)
1262 {
1263 close_figure( pPath );
1264 pPath->pos = pPath->pPoints[lastmove];
1265 TRACE("PPD close : pos X %d Y %d\n",pPath->pos.x, pPath->pos.y);
1266 }
1267 }
1268 PATH_UnlockPath(pPath);
1269 return TRUE;
1270}
Definition: cmds.c:130
static void close_figure(PPATH path)
Definition: path.c:536

Referenced by GdiPolyDraw().

◆ PATH_PolylineTo()

BOOL FASTCALL PATH_PolylineTo ( PDC  dc,
const POINT pts,
DWORD  cbPoints 
)

Definition at line 1274 of file path.c.

1278{
1279 PPATH pPath;
1280 BOOL ret;
1281
1282 ASSERT(dc);
1283 ASSERT(pts);
1284 ASSERT(cbPoints);
1285
1286 if (cbPoints < 1) return FALSE;
1287
1288 pPath = PATH_LockPath(dc->dclevel.hPath);
1289 if (!pPath) return FALSE;
1290
1291 if (pPath->newStroke)
1292 cbPoints--;
1293
1294 ret = add_log_points_new_stroke(dc, pPath, pts, cbPoints, PT_LINETO , TRUE);
1295 PATH_UnlockPath(pPath);
1296 return ret;
1297}

Referenced by IntGdiPolylineTo().

◆ PATH_PolyPolygon()

BOOL FASTCALL PATH_PolyPolygon ( PDC  dc,
const POINT pts,
const INT counts,
UINT  polygons 
)

Definition at line 1301 of file path.c.

1306{
1307 UINT poly, count;
1308 BYTE *type;
1309 PPATH pPath;
1310
1311 ASSERT(dc);
1312 ASSERT(pts);
1313 ASSERT(counts);
1314 ASSERT(polygons);
1315
1316 if (!polygons) return FALSE;
1317
1318 pPath = PATH_LockPath(dc->dclevel.hPath);
1319 if (!pPath) return FALSE;
1320
1321
1322 for (poly = count = 0; poly < polygons; poly++)
1323 {
1324 if (counts[poly] < 2)
1325 {
1326 PATH_UnlockPath(pPath);
1327 return FALSE;
1328 }
1329 count += counts[poly];
1330 }
1331
1332 type = add_log_points(dc, pPath, pts, count, PT_LINETO, FALSE);
1333 if (!type)
1334 {
1335 PATH_UnlockPath(pPath);
1336 return FALSE;
1337 }
1338
1339 /* make the first point of each polyline a PT_MOVETO, and close the last one */
1340 for (poly = 0; poly < polygons; type += counts[poly++])
1341 {
1342 type[0] = PT_MOVETO;
1343 type[counts[poly] - 1] = PT_LINETO | PT_CLOSEFIGURE;
1344 }
1345 PATH_UnlockPath(pPath);
1346 return TRUE;
1347}
unsigned int UINT
Definition: ndis.h:50

Referenced by IntGdiPolyPolygon().

◆ PATH_PolyPolyline()

BOOL FASTCALL PATH_PolyPolyline ( PDC  dc,
const POINT pts,
const DWORD counts,
DWORD  polylines 
)

Definition at line 1351 of file path.c.

1356{
1357 POINT pt;
1358 ULONG poly, point, i;
1359 PPATH pPath;
1360
1361 ASSERT(dc);
1362 ASSERT(pts);
1363 ASSERT(counts);
1364 ASSERT(polylines);
1365
1366 pPath = PATH_LockPath(dc->dclevel.hPath);
1367 if (!pPath)
1368 {
1369 return FALSE;
1370 }
1371
1372 for (i = 0, poly = 0; poly < polylines; poly++)
1373 {
1374 for (point = 0; point < counts[poly]; point++, i++)
1375 {
1376 pt = pts[i];
1377 CoordLPtoDP(dc, &pt);
1378 PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO);
1379 }
1380 }
1381 TRACE("PATH_PolyPolyline end count %d\n",pPath->numEntriesUsed);
1382 PATH_UnlockPath(pPath);
1383 return TRUE;
1384}

Referenced by IntGdiPolyPolyline().

◆ PATH_Rectangle()

BOOL FASTCALL PATH_Rectangle ( PDC  dc,
INT  x1,
INT  y1,
INT  x2,
INT  y2 
)

Definition at line 637 of file path.c.

643{
644 PPATH pPath;
645 RECTL rect;
646 POINTL points[4];
647 BYTE *type;
648
649 pPath = PATH_LockPath(dc->dclevel.hPath);
650 if (!pPath) return FALSE;
651
652 if (!PATH_CheckRect(dc, &rect, x1, y1, x2, y2))
653 {
654 PATH_UnlockPath(pPath);
655 return TRUE;
656 }
657
658 points[0].x = rect.right; points[0].y = rect.top;
659 points[1].x = rect.left; points[1].y = rect.top;
660 points[2].x = rect.left; points[2].y = rect.bottom;
661 points[3].x = rect.right; points[3].y = rect.bottom;
662
663 if (dc->dclevel.flPath & DCPATH_CLOCKWISE) reverse_points(points, 4 );
664
665 if (!(type = add_points( pPath, points, 4, PT_LINETO )))
666 {
667 PATH_UnlockPath(pPath);
668 return FALSE;
669 }
670 type[0] = PT_MOVETO;
671
672 /* Close the rectangle figure */
673 IntGdiCloseFigure(pPath) ;
674 PATH_UnlockPath(pPath);
675 return TRUE;
676}

Referenced by IntRectangle(), and PATH_RoundRect().

◆ PATH_ReserveEntries()

BOOL FASTCALL PATH_ReserveEntries ( PPATH  pPath,
INT  numEntries 
)

Definition at line 296 of file path.c.

299{
300 INT numEntriesToAllocate;
301 POINT *pPointsNew;
302 BYTE *pFlagsNew;
303
304 ASSERT(pPath != NULL);
305 ASSERT(numEntries >= 0);
306
307 /* Do we have to allocate more memory? */
308 if (numEntries > pPath->numEntriesAllocated)
309 {
310 /* Find number of entries to allocate. We let the size of the array
311 * grow exponentially, since that will guarantee linear time
312 * complexity. */
313 if (pPath->numEntriesAllocated)
314 {
315 numEntriesToAllocate = pPath->numEntriesAllocated;
316 while (numEntriesToAllocate < numEntries)
317 numEntriesToAllocate = numEntriesToAllocate * GROW_FACTOR_NUMER / GROW_FACTOR_DENOM;
318 }
319 else
320 numEntriesToAllocate = numEntries;
321
322 /* Allocate new arrays */
323 pPointsNew = (POINT *)ExAllocatePoolWithTag(PagedPool, numEntriesToAllocate * sizeof(POINT), TAG_PATH);
324 if (!pPointsNew)
325 return FALSE;
326
327 pFlagsNew = (BYTE *)ExAllocatePoolWithTag(PagedPool, numEntriesToAllocate * sizeof(BYTE), TAG_PATH);
328 if (!pFlagsNew)
329 {
330 ExFreePoolWithTag(pPointsNew, TAG_PATH);
331 return FALSE;
332 }
333
334 /* Copy old arrays to new arrays and discard old arrays */
335 if (pPath->pPoints)
336 {
337 ASSERT(pPath->pFlags);
338
339 memcpy(pPointsNew, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed);
340 memcpy(pFlagsNew, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
341
344 }
345
346 pPath->pPoints = pPointsNew;
347 pPath->pFlags = pFlagsNew;
348 pPath->numEntriesAllocated = numEntriesToAllocate;
349 }
350
351 return TRUE;
352}
#define GROW_FACTOR_DENOM
Definition: path.c:24
#define GROW_FACTOR_NUMER
Definition: path.c:23

Referenced by add_log_points(), add_points(), PATH_AddEntry(), and PATH_AssignGdiPath().

◆ PATH_RestorePath()

BOOL PATH_RestorePath ( DC dst,
DC src 
)

Definition at line 209 of file path.c.

210{
211 TRACE("PATH_RestorePath\n");
212
213 if (dst->dclevel.hPath == NULL)
214 {
215 PPATH pdstPath, psrcPath = PATH_LockPath(src->dclevel.hPath);
216 TRACE("PATH_RestorePath 1\n");
217 pdstPath = PATH_CreatePath(psrcPath->numEntriesAllocated);
218 dst->dclevel.flPath = src->dclevel.flPath;
219 dst->dclevel.hPath = pdstPath->BaseObject.hHmgr;
220
221 PATH_AssignGdiPath(pdstPath, psrcPath);
222
223 PATH_UnlockPath(pdstPath);
224 PATH_UnlockPath(psrcPath);
225 }
226 else
227 {
228 PPATH pdstPath, psrcPath = PATH_LockPath(src->dclevel.hPath);
229 pdstPath = PATH_LockPath(dst->dclevel.hPath);
230 TRACE("PATH_RestorePath 2\n");
231 dst->dclevel.flPath = src->dclevel.flPath & (DCPATH_CLOCKWISE|DCPATH_ACTIVE);
232 PATH_AssignGdiPath(pdstPath, psrcPath);
233
234 PATH_UnlockPath(pdstPath);
235 PATH_UnlockPath(psrcPath);
236 }
237 return TRUE;
238}
GLenum src
Definition: glext.h:6340
GLenum GLenum dst
Definition: glext.h:6340
BOOL FASTCALL PATH_AssignGdiPath(PPATH pPathDest, const PPATH pPathSrc)
Definition: path.c:166

Referenced by DC_vRestoreDC().

◆ PATH_RoundRect()

BOOL PATH_RoundRect ( DC dc,
INT  x1,
INT  y1,
INT  x2,
INT  y2,
INT  ell_width,
INT  ell_height 
)

Definition at line 685 of file path.c.

693{
694 PPATH pPath;
695 RECTL rect, ellipse;
696 POINT points[16];
697 BYTE *type;
699
700 if (!ell_width || !ell_height) return PATH_Rectangle( dc, x1, y1, x2, y2 );
701
702 pPath = PATH_LockPath(dc->dclevel.hPath);
703 if (!pPath) return FALSE;
704
705 if (!PATH_CheckRect(dc, &rect, x1, y1, x2, y2))
706 {
707 PATH_UnlockPath(pPath);
708 return TRUE;
709 }
710
711 RECTL_vSetRect(&ellipse, 0, 0, ell_width, ell_height);
712 IntLPtoDP( dc, (PPOINT)&ellipse, 2 );
713 RECTL_vMakeWellOrdered(&ellipse);
714 ell_width = min(RECTL_lGetWidth(&ellipse), RECTL_lGetWidth(&rect));
715 ell_height = min(RECTL_lGetHeight(&ellipse), RECTL_lGetHeight(&rect));
716
717 /*
718 * See here to understand what's happening
719 * https://stackoverflow.com/questions/1734745/how-to-create-circle-with-b%C3%A9zier-curves
720 */
721 xOffset = EngMulDiv(ell_width, 44771525, 200000000); /* w * (1 - 0.5522847) / 2 */
722 yOffset = EngMulDiv(ell_height, 44771525, 200000000); /* h * (1 - 0.5522847) / 2 */
723 TRACE("xOffset %d, yOffset %d, Rect WxH: %dx%d.\n",
725
726 /*
727 * Get half width & height.
728 * Do not use integer division, we need the rounding made by EngMulDiv.
729 */
730 ell_width = EngMulDiv(ell_width, 1, 2);
731 ell_height = EngMulDiv(ell_height, 1, 2);
732
733 /* starting point */
734 points[0].x = rect.right;
735 points[0].y = rect.top + ell_height;
736 /* first curve */
737 points[1].x = rect.right;
738 points[1].y = rect.top + yOffset;
739 points[2].x = rect.right - xOffset;
740 points[2].y = rect.top;
741 points[3].x = rect.right - ell_width;
742 points[3].y = rect.top;
743 /* horizontal line */
744 points[4].x = rect.left + ell_width;
745 points[4].y = rect.top;
746 /* second curve */
747 points[5].x = rect.left + xOffset;
748 points[5].y = rect.top;
749 points[6].x = rect.left;
750 points[6].y = rect.top + yOffset;
751 points[7].x = rect.left;
752 points[7].y = rect.top + ell_height;
753 /* vertical line */
754 points[8].x = rect.left;
755 points[8].y = rect.bottom - ell_height;
756 /* third curve */
757 points[9].x = rect.left;
758 points[9].y = rect.bottom - yOffset;
759 points[10].x = rect.left + xOffset;
760 points[10].y = rect.bottom;
761 points[11].x = rect.left + ell_width;
762 points[11].y = rect.bottom;
763 /* horizontal line */
764 points[12].x = rect.right - ell_width;
765 points[12].y = rect.bottom;
766 /* fourth curve */
767 points[13].x = rect.right - xOffset;
768 points[13].y = rect.bottom;
769 points[14].x = rect.right;
770 points[14].y = rect.bottom - yOffset;
771 points[15].x = rect.right;
772 points[15].y = rect.bottom - ell_height;
773
774 if (dc->dclevel.flPath & DCPATH_CLOCKWISE) reverse_points( points, 16 );
775 if (!(type = add_points( pPath, points, 16, PT_BEZIERTO )))
776 {
777 PATH_UnlockPath(pPath);
778 return FALSE;
779 }
780 type[0] = PT_MOVETO;
781 type[4] = type[8] = type[12] = PT_LINETO;
782
783 IntGdiCloseFigure(pPath);
784 PATH_UnlockPath(pPath);
785 return TRUE;
786}
#define min(a, b)
Definition: monoChain.cc:55
BOOL FASTCALL PATH_Rectangle(PDC dc, INT x1, INT y1, INT x2, INT y2)
Definition: path.c:637

Referenced by IntRoundRect().

◆ PATH_SavePath()

BOOL PATH_SavePath ( DC dst,
DC src 
)

Definition at line 187 of file path.c.

188{
189 PPATH pdstPath, psrcPath = PATH_LockPath(src->dclevel.hPath);
190 TRACE("PATH_SavePath\n");
191 if (psrcPath)
192 {
193 TRACE("PATH_SavePath 1\n");
194
195 pdstPath = PATH_CreatePath(psrcPath->numEntriesAllocated);
196
197 dst->dclevel.flPath = src->dclevel.flPath;
198
199 dst->dclevel.hPath = pdstPath->BaseObject.hHmgr;
200
201 PATH_AssignGdiPath(pdstPath, psrcPath);
202
203 PATH_UnlockPath(pdstPath);
204 PATH_UnlockPath(psrcPath);
205 }
206 return TRUE;
207}

Referenced by NtGdiSaveDC().

◆ PATH_ScaleNormalizedPoint()

static BOOLEAN PATH_ScaleNormalizedPoint ( POINT  corners[],
FLOATL  x,
FLOATL  y,
POINT pPoint 
)
static

Definition at line 363 of file path.c.

368{
369 FLOATOBJ tmp;
370
371 ASSERT(corners);
372 ASSERT(pPoint);
373
374 /* pPoint->x = (double)corners[0].x + (double)(corners[1].x - corners[0].x) * 0.5 * (x + 1.0); */
375 FLOATOBJ_SetFloat(&tmp, x);
376 FLOATOBJ_Add(&tmp, (FLOATOBJ*)&gef1);
377 FLOATOBJ_Div(&tmp, (FLOATOBJ*)&gef2);
378 FLOATOBJ_MulLong(&tmp, corners[1].x - corners[0].x);
379 FLOATOBJ_AddLong(&tmp, corners[0].x);
380 if (!FLOATOBJ_bConvertToLong(&tmp, &pPoint->x))
381 return FALSE;
382
383 /* pPoint->y = (double)corners[0].y + (double)(corners[1].y - corners[0].y) * 0.5 * (y + 1.0); */
384 FLOATOBJ_SetFloat(&tmp, y);
385 FLOATOBJ_Add(&tmp, (FLOATOBJ*)&gef1);
386 FLOATOBJ_Div(&tmp, (FLOATOBJ*)&gef2);
387 FLOATOBJ_MulLong(&tmp, corners[1].y - corners[0].y);
388 FLOATOBJ_AddLong(&tmp, corners[0].y);
389 if (!FLOATOBJ_bConvertToLong(&tmp, &pPoint->y))
390 return FALSE;
391 return TRUE;
392}
static const FLOATOBJ gef2
Definition: floatobj.h:115
#define FLOATOBJ_bConvertToLong(pf, pl)
Definition: floatobj.h:102
#define FLOATOBJ_Div(pf, pf1)
Definition: winddi.h:2827
#define FLOATOBJ_Add(pf, pf1)
Definition: winddi.h:2818
#define FLOATOBJ_MulLong(pf, l)
Definition: winddi.h:2826
#define FLOATOBJ_SetFloat(pf, f)
Definition: winddi.h:2814
#define FLOATOBJ_AddLong(pf, l)
Definition: winddi.h:2820

Referenced by PATH_DoArcPart().

◆ PATH_StrokePath()

BOOL FASTCALL PATH_StrokePath ( DC dc,
PPATH  pPath 
)

Definition at line 1610 of file path.c.

1613{
1614 BOOL ret = FALSE;
1615 INT nLinePts, nAlloc, jOldFillMode, i = 0;
1616 POINT *pLinePts = NULL;
1617 POINT ptViewportOrg, ptWindowOrg;
1618 SIZE szViewportExt, szWindowExt;
1619 DWORD mapMode, graphicsMode;
1620 XFORM xform;
1621 PDC_ATTR pdcattr = dc->pdcattr;
1622 PBRUSH pbrLine;
1623 PPATH pNewPath;
1624
1625 TRACE("Enter %s\n", __FUNCTION__);
1626
1627 pbrLine = dc->dclevel.pbrLine;
1628 if (IntIsEffectiveWidePen(pbrLine))
1629 {
1630 pNewPath = PATH_WidenPathEx(dc, pPath);
1631 if (pNewPath)
1632 {
1633 /* Fill the path with the WINDING fill mode */
1634 jOldFillMode = pdcattr->jFillMode;
1635 pdcattr->jFillMode = WINDING;
1636 PATH_FillPathEx(dc, pNewPath, pbrLine);
1637 pdcattr->jFillMode = jOldFillMode;
1638
1639 PATH_Delete(pNewPath->BaseObject.hHmgr);
1640 return TRUE;
1641 }
1642 }
1643
1644 /* Save the mapping mode info */
1645 mapMode = pdcattr->iMapMode;
1646
1647 szViewportExt = *DC_pszlViewportExt(dc);
1648 ptViewportOrg = dc->pdcattr->ptlViewportOrg;
1649 szWindowExt = dc->pdcattr->szlWindowExt;
1650 ptWindowOrg = dc->pdcattr->ptlWindowOrg;
1651
1652 MatrixS2XForm(&xform, &dc->pdcattr->mxWorldToPage);
1653
1654 /* Set MM_TEXT */
1655 pdcattr->iMapMode = MM_TEXT;
1656 pdcattr->ptlViewportOrg.x = 0;
1657 pdcattr->ptlViewportOrg.y = 0;
1658 pdcattr->ptlWindowOrg.x = 0;
1659 pdcattr->ptlWindowOrg.y = 0;
1660 graphicsMode = pdcattr->iGraphicsMode;
1661 pdcattr->iGraphicsMode = GM_ADVANCED;
1663 pdcattr->iGraphicsMode = graphicsMode;
1664
1665 /* Allocate enough memory for the worst case without beziers (one PT_MOVETO
1666 * and the rest PT_LINETO with PT_CLOSEFIGURE at the end) plus some buffer
1667 * space in case we get one to keep the number of reallocations small. */
1668 nAlloc = pPath->numEntriesUsed + 1 + 300;
1669 pLinePts = ExAllocatePoolWithTag(PagedPool, nAlloc * sizeof(POINT), TAG_PATH);
1670 if (!pLinePts)
1671 {
1672 ERR("Can't allocate pool!\n");
1674 goto end;
1675 }
1676 nLinePts = 0;
1677
1678 for (i = 0; i < pPath->numEntriesUsed; i++)
1679 {
1680 if ((i == 0 || (pPath->pFlags[i - 1] & PT_CLOSEFIGURE))
1681 && (pPath->pFlags[i] != PT_MOVETO))
1682 {
1683 ERR("Expected PT_MOVETO %s, got path flag %d\n",
1684 i == 0 ? "as first point" : "after PT_CLOSEFIGURE",
1685 (INT)pPath->pFlags[i]);
1686 goto end;
1687 }
1688
1689 switch(pPath->pFlags[i])
1690 {
1691 case PT_MOVETO:
1692 TRACE("Got PT_MOVETO (%ld, %ld)\n",
1693 pPath->pPoints[i].x, pPath->pPoints[i].y);
1694 if (nLinePts >= 2) IntGdiPolyline(dc, pLinePts, nLinePts);
1695 nLinePts = 0;
1696 pLinePts[nLinePts++] = pPath->pPoints[i];
1697 break;
1698 case PT_LINETO:
1699 case (PT_LINETO | PT_CLOSEFIGURE):
1700 TRACE("Got PT_LINETO (%ld, %ld)\n",
1701 pPath->pPoints[i].x, pPath->pPoints[i].y);
1702 pLinePts[nLinePts++] = pPath->pPoints[i];
1703 break;
1704 case PT_BEZIERTO:
1705 TRACE("Got PT_BEZIERTO\n");
1706 if (pPath->pFlags[i + 1] != PT_BEZIERTO ||
1707 (pPath->pFlags[i + 2] & ~PT_CLOSEFIGURE) != PT_BEZIERTO)
1708 {
1709 ERR("Path didn't contain 3 successive PT_BEZIERTOs\n");
1710 ret = FALSE;
1711 goto end;
1712 }
1713 else
1714 {
1715 INT nBzrPts, nMinAlloc;
1716 POINT *pBzrPts = GDI_Bezier(&pPath->pPoints[i - 1], 4, &nBzrPts);
1717 /* Make sure we have allocated enough memory for the lines of
1718 * this bezier and the rest of the path, assuming we won't get
1719 * another one (since we won't reallocate again then). */
1720 nMinAlloc = nLinePts + (pPath->numEntriesUsed - i) + nBzrPts;
1721 if (nAlloc < nMinAlloc)
1722 {
1723 // Reallocate memory
1724
1725 POINT *Realloc = NULL;
1726 nAlloc = nMinAlloc * 2;
1727
1729 nAlloc * sizeof(POINT),
1730 TAG_PATH);
1731
1732 if (!Realloc)
1733 {
1734 ERR("Can't allocate pool!\n");
1735 ExFreePoolWithTag(pBzrPts, TAG_BEZIER);
1736 goto end;
1737 }
1738
1739 memcpy(Realloc, pLinePts, nLinePts * sizeof(POINT));
1740 ExFreePoolWithTag(pLinePts, TAG_PATH);
1741 pLinePts = Realloc;
1742 }
1743 memcpy(&pLinePts[nLinePts], &pBzrPts[1], (nBzrPts - 1) * sizeof(POINT));
1744 nLinePts += nBzrPts - 1;
1745 ExFreePoolWithTag(pBzrPts, TAG_BEZIER);
1746 i += 2;
1747 }
1748 break;
1749 default:
1750 ERR("Got path flag %d (not supported)\n", (INT)pPath->pFlags[i]);
1751 goto end;
1752 }
1753
1754 if (pPath->pFlags[i] & PT_CLOSEFIGURE)
1755 {
1756 pLinePts[nLinePts++] = pLinePts[0];
1757 }
1758 }
1759 if (nLinePts >= 2)
1760 IntGdiPolyline(dc, pLinePts, nLinePts);
1761
1762 ret = TRUE;
1763
1764end:
1765 if (pLinePts) ExFreePoolWithTag(pLinePts, TAG_PATH);
1766
1767 /* Restore the old mapping mode */
1768 pdcattr->iMapMode = mapMode;
1769 pdcattr->szlWindowExt.cx = szWindowExt.cx;
1770 pdcattr->szlWindowExt.cy = szWindowExt.cy;
1771 pdcattr->ptlWindowOrg.x = ptWindowOrg.x;
1772 pdcattr->ptlWindowOrg.y = ptWindowOrg.y;
1773
1774 pdcattr->szlViewportExt.cx = szViewportExt.cx;
1775 pdcattr->szlViewportExt.cy = szViewportExt.cy;
1776 pdcattr->ptlViewportOrg.x = ptViewportOrg.x;
1777 pdcattr->ptlViewportOrg.y = ptViewportOrg.y;
1778
1779 /* Restore the world transform */
1780 XForm2MatrixS(&dc->pdcattr->mxWorldToPage, &xform);
1781
1782 /* If we've moved the current point then get its new position
1783 which will be in device (MM_TEXT) co-ords, convert it to
1784 logical co-ords and re-set it. This basically updates
1785 dc->CurPosX|Y so that their values are in the correct mapping
1786 mode.
1787 */
1788 if (i > 0)
1789 {
1790 POINT pt;
1792 IntDPtoLP(dc, &pt, 1);
1793 IntGdiMoveToEx(dc, pt.x, pt.y, NULL);
1794 }
1795 TRACE("Leave %s, ret=%d\n", __FUNCTION__, ret);
1796 return ret;
1797}
#define WINDING
Definition: constants.h:279
#define XForm2MatrixS(m, x)
Definition: coord.h:199
FORCEINLINE PSIZEL DC_pszlViewportExt(PDC pdc)
Definition: coord.h:111
static BOOLEAN IntDPtoLP(DC *pdc, PPOINTL ppt, UINT count)
Definition: coord.h:192
BOOL FASTCALL IntGdiPolyline(DC *dc, LPPOINT pt, int Count)
Definition: line.c:327
void * Realloc(void *, size_t)
#define IntIsEffectiveWidePen(pbrLine)
Definition: pen.h:33
Definition: types.h:101
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
PPATH FASTCALL PATH_WidenPathEx(DC *dc, PPATH pPath)
Definition: path.c:2151

Referenced by IntGdiLineTo(), IntGdiPolygon(), IntGdiPolyline(), IntRectangle(), NtGdiStrokeAndFillPath(), and NtGdiStrokePath().

◆ PATH_WidenPath()

static PPATH FASTCALL PATH_WidenPath ( DC dc)
static

Definition at line 2133 of file path.c.

2134{
2135 PPATH pPath, pNewPath;
2136
2137 pPath = PATH_LockPath(dc->dclevel.hPath);
2138 if (!pPath)
2139 {
2141 return NULL;
2142 }
2143
2144 pNewPath = PATH_WidenPathEx(dc, pPath);
2145 PATH_UnlockPath(pPath);
2146 return pNewPath;
2147}

Referenced by NtGdiWidenPath().

◆ PATH_WidenPathEx()

PPATH FASTCALL PATH_WidenPathEx ( DC dc,
PPATH  pPath 
)

Definition at line 2151 of file path.c.

2152{
2153 INT size;
2154 UINT penWidth, penStyle;
2155 DWORD obj_type;
2156 LPEXTLOGPEN elp;
2157 PDC_ATTR pdcattr = dc->pdcattr;
2158
2159 if (pPath->state != PATH_Closed)
2160 {
2161 TRACE("PWP 1\n");
2163 return NULL;
2164 }
2165
2166 size = GreGetObject(pdcattr->hpen, 0, NULL);
2167 if (!size)
2168 {
2169 TRACE("PWP 2\n");
2171 return NULL;
2172 }
2173
2175 if (elp == NULL)
2176 {
2177 TRACE("PWP 3\n");
2179 return NULL;
2180 }
2181
2182 GreGetObject(pdcattr->hpen, size, elp);
2183
2184 obj_type = GDI_HANDLE_GET_TYPE(pdcattr->hpen);
2185 if (obj_type == GDI_OBJECT_TYPE_PEN)
2186 {
2187 penStyle = ((LOGPEN*)elp)->lopnStyle;
2188 }
2189 else if (obj_type == GDI_OBJECT_TYPE_EXTPEN)
2190 {
2191 penStyle = elp->elpPenStyle;
2192 }
2193 else
2194 {
2195 TRACE("PWP 4\n");
2198 return NULL;
2199 }
2200
2201 penWidth = elp->elpWidth;
2203
2204 /* The function cannot apply to cosmetic pens */
2205 if (obj_type == GDI_OBJECT_TYPE_EXTPEN &&
2206 (PS_TYPE_MASK & penStyle) == PS_COSMETIC)
2207 {
2208 TRACE("PWP 5\n");
2210 return FALSE;
2211 }
2212
2213 return IntGdiWidenPath(pPath, penWidth, penStyle, dc->dclevel.laPath.eMiterLimit);
2214}
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define GDI_HANDLE_GET_TYPE(h)
Definition: gdi.h:31
#define GDI_OBJECT_TYPE_EXTPEN
Definition: gdi.h:55
#define GDI_OBJECT_TYPE_PEN
Definition: gdi.h:54
HANDLE hpen
Definition: ntgdihdl.h:296
DWORD elpWidth
Definition: wingdi.h:2389
DWORD elpPenStyle
Definition: wingdi.h:2388
INT NTAPI GreGetObject(IN HGDIOBJ hobj, IN INT cbCount, OUT PVOID pvBuffer)
Definition: gdiobj.c:1277
PPATH FASTCALL IntGdiWidenPath(PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit)
Definition: path.c:1802
#define PS_COSMETIC
Definition: wingdi.h:584
#define PS_TYPE_MASK
Definition: wingdi.h:603

Referenced by PATH_StrokePath(), and PATH_WidenPath().

◆ reverse_points()

static void reverse_points ( POINT points,
UINT  count 
)
static

Definition at line 504 of file path.c.

505{
506 UINT i;
507 for (i = 0; i < count / 2; i++)
508 {
509 POINT pt = points[i];
510 points[i] = points[count - i - 1];
511 points[count - i - 1] = pt;
512 }
513}

Referenced by IntGdiWidenPath(), PATH_Ellipse(), PATH_Rectangle(), and PATH_RoundRect().

◆ start_new_stroke()

static BOOL start_new_stroke ( PPATH  path)
static

Definition at line 516 of file path.c.

517{
518 if (!path->newStroke && path->numEntriesUsed &&
519 !(path->pFlags[path->numEntriesUsed - 1] & PT_CLOSEFIGURE) &&
520 path->pPoints[path->numEntriesUsed - 1].x == path->pos.x &&
521 path->pPoints[path->numEntriesUsed - 1].y == path->pos.y)
522 return TRUE;
523
524 path->newStroke = FALSE;
525 return add_points( path, &path->pos, 1, PT_MOVETO ) != NULL;
526}

Referenced by add_log_points_new_stroke().

◆ update_current_pos()

static void update_current_pos ( PPATH  path)
static

Definition at line 529 of file path.c.

530{
531 ASSERT(path->numEntriesUsed);
532 path->pos = path->pPoints[path->numEntriesUsed - 1];
533}

Referenced by add_log_points_new_stroke(), and PATH_Arc().