+++ /dev/null
-/*
- * PROJECT: ReactOS Win32k Subsystem
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: win32ss/gdi/ntgdi/line.c
- * PURPOSE: Line functions
- * PROGRAMMERS: ...
- */
-
-#include <win32k.h>
-
-#define NDEBUG
-#include <debug.h>
-
-// Some code from the WINE project source (www.winehq.com)
-
-VOID FASTCALL
-AddPenLinesBounds(PDC dc, int count, POINT *points)
-{
- DWORD join, endcap;
- RECTL bounds, rect;
- LONG lWidth;
- PBRUSH pbrLine;
-
- /* Get BRUSH from current pen. */
- pbrLine = dc->dclevel.pbrLine;
- ASSERT(pbrLine);
-
- lWidth = pbrLine->lWidth;
-
- // Setup bounds
- bounds.left = bounds.top = INT_MAX;
- bounds.right = bounds.bottom = INT_MIN;
-
- if (((pbrLine->ulPenStyle & PS_TYPE_MASK) & PS_GEOMETRIC) || lWidth > 1)
- {
- /* Windows uses some heuristics to estimate the distance from the point that will be painted */
- lWidth = lWidth + 2;
- endcap = (PS_ENDCAP_MASK & pbrLine->ulPenStyle);
- join = (PS_JOIN_MASK & pbrLine->ulPenStyle);
- if (join == PS_JOIN_MITER)
- {
- lWidth *= 5;
- if (endcap == PS_ENDCAP_SQUARE) lWidth = (lWidth * 3 + 1) / 2;
- }
- else
- {
- if (endcap == PS_ENDCAP_SQUARE) lWidth -= lWidth / 4;
- else lWidth = (lWidth + 1) / 2;
- }
- }
-
- while (count-- > 0)
- {
- rect.left = points->x - lWidth;
- rect.top = points->y - lWidth;
- rect.right = points->x + lWidth + 1;
- rect.bottom = points->y + lWidth + 1;
- RECTL_bUnionRect(&bounds, &bounds, &rect);
- points++;
- }
-
- DPRINT("APLB dc %p l %d t %d\n",dc,rect.left,rect.top);
- DPRINT(" r %d b %d\n",rect.right,rect.bottom);
-
- {
- RECTL rcRgn;
- if (dc->fs & DC_FLAG_DIRTY_RAO) CLIPPING_UpdateGCRegion(dc);
- if (REGION_GetRgnBox(dc->prgnRao, &rcRgn))
- {
- if (RECTL_bIntersectRect( &rcRgn, &rcRgn, &bounds )) IntUpdateBoundsRect(dc, &rcRgn);
- }
- else
- IntUpdateBoundsRect(dc, &bounds);
- }
-}
-
-// Should use Fx in Point
-//
-BOOL FASTCALL
-IntGdiMoveToEx(DC *dc,
- int X,
- int Y,
- LPPOINT Point)
-{
- PDC_ATTR pdcattr = dc->pdcattr;
- if ( Point )
- {
- if ( pdcattr->ulDirty_ & DIRTY_PTLCURRENT ) // Double hit!
- {
- Point->x = pdcattr->ptfxCurrent.x; // ret prev before change.
- Point->y = pdcattr->ptfxCurrent.y;
- IntDPtoLP ( dc, Point, 1); // Reconvert back.
- }
- else
- {
- Point->x = pdcattr->ptlCurrent.x;
- Point->y = pdcattr->ptlCurrent.y;
- }
- }
- pdcattr->ptlCurrent.x = X;
- pdcattr->ptlCurrent.y = Y;
- pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
- CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
- pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
-
- return TRUE;
-}
-
-BOOL FASTCALL
-GreMoveTo( HDC hdc,
- INT x,
- INT y,
- LPPOINT pptOut)
-{
- BOOL Ret;
- PDC dc;
- if (!(dc = DC_LockDc(hdc)))
- {
- EngSetLastError(ERROR_INVALID_HANDLE);
- return FALSE;
- }
- Ret = IntGdiMoveToEx(dc, x, y, pptOut);
- DC_UnlockDc(dc);
- return Ret;
-}
-
-// Should use Fx in pt
-//
-VOID FASTCALL
-IntGetCurrentPositionEx(PDC dc, LPPOINT pt)
-{
- PDC_ATTR pdcattr = dc->pdcattr;
-
- if ( pt )
- {
- if (pdcattr->ulDirty_ & DIRTY_PTFXCURRENT)
- {
- pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
- CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
- pdcattr->ulDirty_ &= ~(DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
- }
- pt->x = pdcattr->ptlCurrent.x;
- pt->y = pdcattr->ptlCurrent.y;
- }
-}
-
-BOOL FASTCALL
-IntGdiLineTo(DC *dc,
- int XEnd,
- int YEnd)
-{
- SURFACE *psurf;
- BOOL Ret = TRUE;
- PBRUSH pbrLine;
- RECTL Bounds;
- POINT Points[2];
- PDC_ATTR pdcattr = dc->pdcattr;
- ASSERT_DC_PREPARED(dc);
-
- if (PATH_IsPathOpen(dc->dclevel))
- {
- Ret = PATH_LineTo(dc, XEnd, YEnd);
- }
- else
- {
- psurf = dc->dclevel.pSurface;
- if (NULL == psurf)
- {
- EngSetLastError(ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- Points[0].x = pdcattr->ptlCurrent.x;
- Points[0].y = pdcattr->ptlCurrent.y;
- Points[1].x = XEnd;
- Points[1].y = YEnd;
-
- IntLPtoDP(dc, Points, 2);
-
- /* The DCOrg is in device coordinates */
- Points[0].x += dc->ptlDCOrig.x;
- Points[0].y += dc->ptlDCOrig.y;
- Points[1].x += dc->ptlDCOrig.x;
- Points[1].y += dc->ptlDCOrig.y;
-
- Bounds.left = min(Points[0].x, Points[1].x);
- Bounds.top = min(Points[0].y, Points[1].y);
- Bounds.right = max(Points[0].x, Points[1].x);
- Bounds.bottom = max(Points[0].y, Points[1].y);
-
- /* Get BRUSH from current pen. */
- pbrLine = dc->dclevel.pbrLine;
- ASSERT(pbrLine);
-
- if (dc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
- {
- DPRINT("Bounds dc %p l %d t %d\n",dc,Bounds.left,Bounds.top);
- DPRINT(" r %d b %d\n",Bounds.right,Bounds.bottom);
- AddPenLinesBounds(dc, 2, Points);
- }
-
- if (!(pbrLine->flAttrs & BR_IS_NULL))
- {
- Ret = IntEngLineTo(&psurf->SurfObj,
- (CLIPOBJ *)&dc->co,
- &dc->eboLine.BrushObject,
- Points[0].x, Points[0].y,
- Points[1].x, Points[1].y,
- &Bounds,
- ROP2_TO_MIX(pdcattr->jROP2));
- }
-
- }
-
- if (Ret)
- {
- pdcattr->ptlCurrent.x = XEnd;
- pdcattr->ptlCurrent.y = YEnd;
- pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
- CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
- pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
- }
-
- return Ret;
-}
-
-BOOL FASTCALL
-IntGdiPolyBezier(DC *dc,
- LPPOINT pt,
- DWORD Count)
-{
- BOOL ret = FALSE; // Default to FAILURE
-
- if ( PATH_IsPathOpen(dc->dclevel) )
- {
- return PATH_PolyBezier ( dc, pt, Count );
- }
-
- /* We'll convert it into line segments and draw them using Polyline */
- {
- POINT *Pts;
- INT nOut;
-
- Pts = GDI_Bezier ( pt, Count, &nOut );
- if ( Pts )
- {
- ret = IntGdiPolyline(dc, Pts, nOut);
- ExFreePoolWithTag(Pts, TAG_BEZIER);
- }
- }
-
- return ret;
-}
-
-BOOL FASTCALL
-IntGdiPolyBezierTo(DC *dc,
- LPPOINT pt,
- DWORD Count)
-{
- BOOL ret = FALSE; // Default to failure
- PDC_ATTR pdcattr = dc->pdcattr;
-
- if ( PATH_IsPathOpen(dc->dclevel) )
- ret = PATH_PolyBezierTo ( dc, pt, Count );
- else /* We'll do it using PolyBezier */
- {
- POINT *npt;
- npt = ExAllocatePoolWithTag(PagedPool,
- sizeof(POINT) * (Count + 1),
- TAG_BEZIER);
- if ( npt )
- {
- npt[0].x = pdcattr->ptlCurrent.x;
- npt[0].y = pdcattr->ptlCurrent.y;
- memcpy(npt + 1, pt, sizeof(POINT) * Count);
- ret = IntGdiPolyBezier(dc, npt, Count+1);
- ExFreePoolWithTag(npt, TAG_BEZIER);
- }
- }
- if ( ret )
- {
- pdcattr->ptlCurrent.x = pt[Count-1].x;
- pdcattr->ptlCurrent.y = pt[Count-1].y;
- pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
- CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
- pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
- }
-
- return ret;
-}
-
-BOOL FASTCALL
-IntGdiPolyline(DC *dc,
- LPPOINT pt,
- int Count)
-{
- SURFACE *psurf;
- BRUSH *pbrLine;
- LPPOINT Points;
- BOOL Ret = TRUE;
- LONG i;
- PDC_ATTR pdcattr = dc->pdcattr;
-
- if (!dc->dclevel.pSurface)
- {
- return TRUE;
- }
-
- DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL);
- psurf = dc->dclevel.pSurface;
-
- /* Get BRUSHOBJ from current pen. */
- pbrLine = dc->dclevel.pbrLine;
- ASSERT(pbrLine);
-
- if (!(pbrLine->flAttrs & BR_IS_NULL))
- {
- Points = EngAllocMem(0, Count * sizeof(POINT), GDITAG_TEMP);
- if (Points != NULL)
- {
- RtlCopyMemory(Points, pt, Count * sizeof(POINT));
- IntLPtoDP(dc, Points, Count);
-
- /* Offset the array of points by the DC origin */
- for (i = 0; i < Count; i++)
- {
- Points[i].x += dc->ptlDCOrig.x;
- Points[i].y += dc->ptlDCOrig.y;
- }
-
- if (dc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
- {
- AddPenLinesBounds(dc, Count, Points);
- }
-
- Ret = IntEngPolyline(&psurf->SurfObj,
- (CLIPOBJ *)&dc->co,
- &dc->eboLine.BrushObject,
- Points,
- Count,
- ROP2_TO_MIX(pdcattr->jROP2));
-
- EngFreeMem(Points);
- }
- else
- {
- Ret = FALSE;
- }
- }
-
- DC_vFinishBlit(dc, NULL);
-
- return Ret;
-}
-
-BOOL FASTCALL
-IntGdiPolylineTo(DC *dc,
- LPPOINT pt,
- DWORD Count)
-{
- BOOL ret = FALSE; // Default to failure
- PDC_ATTR pdcattr = dc->pdcattr;
-
- if (PATH_IsPathOpen(dc->dclevel))
- {
- ret = PATH_PolylineTo(dc, pt, Count);
- }
- else /* Do it using Polyline */
- {
- POINT *pts = ExAllocatePoolWithTag(PagedPool,
- sizeof(POINT) * (Count + 1),
- TAG_SHAPE);
- if ( pts )
- {
- pts[0].x = pdcattr->ptlCurrent.x;
- pts[0].y = pdcattr->ptlCurrent.y;
- memcpy( pts + 1, pt, sizeof(POINT) * Count);
- ret = IntGdiPolyline(dc, pts, Count + 1);
- ExFreePoolWithTag(pts, TAG_SHAPE);
- }
- }
- if ( ret )
- {
- pdcattr->ptlCurrent.x = pt[Count-1].x;
- pdcattr->ptlCurrent.y = pt[Count-1].y;
- pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
- CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
- pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
- }
-
- return ret;
-}
-
-
-BOOL FASTCALL
-IntGdiPolyPolyline(DC *dc,
- LPPOINT pt,
- PULONG PolyPoints,
- DWORD Count)
-{
- ULONG i;
- LPPOINT pts;
- PULONG pc;
- BOOL ret = FALSE; // Default to failure
- pts = pt;
- pc = PolyPoints;
-
- if (PATH_IsPathOpen(dc->dclevel))
- {
- return PATH_PolyPolyline( dc, pt, PolyPoints, Count );
- }
- for (i = 0; i < Count; i++)
- {
- ret = IntGdiPolyline ( dc, pts, *pc );
- if (ret == FALSE)
- {
- return ret;
- }
- pts+=*pc++;
- }
-
- return ret;
-}
-
-/******************************************************************************/
-
-BOOL
-APIENTRY
-NtGdiLineTo(HDC hDC,
- int XEnd,
- int YEnd)
-{
- DC *dc;
- BOOL Ret;
- RECT rcLockRect ;
-
- dc = DC_LockDc(hDC);
- if (!dc)
- {
- EngSetLastError(ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- rcLockRect.left = dc->pdcattr->ptlCurrent.x;
- rcLockRect.top = dc->pdcattr->ptlCurrent.y;
- rcLockRect.right = XEnd;
- rcLockRect.bottom = YEnd;
-
- IntLPtoDP(dc, &rcLockRect, 2);
-
- /* The DCOrg is in device coordinates */
- rcLockRect.left += dc->ptlDCOrig.x;
- rcLockRect.top += dc->ptlDCOrig.y;
- rcLockRect.right += dc->ptlDCOrig.x;
- rcLockRect.bottom += dc->ptlDCOrig.y;
-
- DC_vPrepareDCsForBlit(dc, &rcLockRect, NULL, NULL);
-
- Ret = IntGdiLineTo(dc, XEnd, YEnd);
-
- DC_vFinishBlit(dc, NULL);
-
- DC_UnlockDc(dc);
- return Ret;
-}
-
-// FIXME: This function is completely broken
-BOOL
-APIENTRY
-NtGdiPolyDraw(
- IN HDC hdc,
- IN LPPOINT lppt,
- IN LPBYTE lpbTypes,
- IN ULONG cCount)
-{
- PDC dc;
- PDC_ATTR pdcattr;
- POINT bzr[4];
- volatile PPOINT line_pts, line_pts_old, bzr_pts;
- INT num_pts, num_bzr_pts, space, space_old, size;
- ULONG i;
- BOOL result = FALSE;
-
- dc = DC_LockDc(hdc);
- if (!dc) return FALSE;
- pdcattr = dc->pdcattr;
-
- if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
- DC_vUpdateFillBrush(dc);
-
- if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
- DC_vUpdateLineBrush(dc);
-
- if (!cCount)
- {
- DC_UnlockDc(dc);
- return TRUE;
- }
-
- line_pts = NULL;
- line_pts_old = NULL;
- bzr_pts = NULL;
-
- _SEH2_TRY
- {
- ProbeArrayForRead(lppt, sizeof(POINT), cCount, sizeof(LONG));
- ProbeArrayForRead(lpbTypes, sizeof(BYTE), cCount, sizeof(BYTE));
-
- if (PATH_IsPathOpen(dc->dclevel))
- {
- result = PATH_PolyDraw(dc, (const POINT *)lppt, (const BYTE *)lpbTypes, cCount);
- _SEH2_LEAVE;
- }
-
- /* Check for valid point types */
- for (i = 0; i < cCount; i++)
- {
- switch (lpbTypes[i])
- {
- case PT_MOVETO:
- case PT_LINETO | PT_CLOSEFIGURE:
- case PT_LINETO:
- break;
- case PT_BEZIERTO:
- if((i + 2 < cCount) && (lpbTypes[i + 1] == PT_BEZIERTO) &&
- ((lpbTypes[i + 2] & ~PT_CLOSEFIGURE) == PT_BEZIERTO))
- {
- i += 2;
- break;
- }
- default:
- _SEH2_LEAVE;
- }
- }
-
- space = cCount + 300;
- line_pts = ExAllocatePoolWithTag(PagedPool, space * sizeof(POINT), TAG_SHAPE);
- if (line_pts == NULL)
- {
- result = FALSE;
- _SEH2_LEAVE;
- }
-
- num_pts = 1;
-
- line_pts[0].x = pdcattr->ptlCurrent.x;
- line_pts[0].y = pdcattr->ptlCurrent.y;
-
- for ( i = 0; i < cCount; i++ )
- {
- switch (lpbTypes[i])
- {
- case PT_MOVETO:
- if (num_pts >= 2) IntGdiPolyline( dc, line_pts, num_pts );
- num_pts = 0;
- line_pts[num_pts++] = lppt[i];
- break;
- case PT_LINETO:
- case (PT_LINETO | PT_CLOSEFIGURE):
- line_pts[num_pts++] = lppt[i];
- break;
- case PT_BEZIERTO:
- bzr[0].x = line_pts[num_pts - 1].x;
- bzr[0].y = line_pts[num_pts - 1].y;
- RtlCopyMemory( &bzr[1], &lppt[i], 3 * sizeof(POINT) );
-
- if ((bzr_pts = GDI_Bezier( bzr, 4, &num_bzr_pts )))
- {
- size = num_pts + (cCount - i) + num_bzr_pts;
- if (space < size)
- {
- space_old = space;
- space = size * 2;
- line_pts_old = line_pts;
- line_pts = ExAllocatePoolWithTag(PagedPool, space * sizeof(POINT), TAG_SHAPE);
- if (!line_pts) _SEH2_LEAVE;
- RtlCopyMemory(line_pts, line_pts_old, space_old * sizeof(POINT));
- ExFreePoolWithTag(line_pts_old, TAG_SHAPE);
- line_pts_old = NULL;
- }
- RtlCopyMemory( &line_pts[num_pts], &bzr_pts[1], (num_bzr_pts - 1) * sizeof(POINT) );
- num_pts += num_bzr_pts - 1;
- ExFreePoolWithTag(bzr_pts, TAG_BEZIER);
- bzr_pts = NULL;
- }
- i += 2;
- break;
- }
- if (lpbTypes[i] & PT_CLOSEFIGURE) line_pts[num_pts++] = line_pts[0];
- }
-
- if (num_pts >= 2) IntGdiPolyline( dc, line_pts, num_pts );
- IntGdiMoveToEx( dc, line_pts[num_pts - 1].x, line_pts[num_pts - 1].y, NULL );
- result = TRUE;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- SetLastNtError(_SEH2_GetExceptionCode());
- }
- _SEH2_END;
-
- if (line_pts != NULL)
- {
- ExFreePoolWithTag(line_pts, TAG_SHAPE);
- }
-
- if ((line_pts_old != NULL) && (line_pts_old != line_pts))
- {
- ExFreePoolWithTag(line_pts_old, TAG_SHAPE);
- }
-
- if (bzr_pts != NULL)
- {
- ExFreePoolWithTag(bzr_pts, TAG_BEZIER);
- }
-
- DC_UnlockDc(dc);
-
- return result;
-}
-
-/*
- * @implemented
- */
-_Success_(return != FALSE)
-BOOL
-APIENTRY
-NtGdiMoveTo(
- IN HDC hdc,
- IN INT x,
- IN INT y,
- OUT OPTIONAL LPPOINT pptOut)
-{
- PDC pdc;
- BOOL Ret;
- POINT Point;
-
- pdc = DC_LockDc(hdc);
- if (!pdc) return FALSE;
-
- Ret = IntGdiMoveToEx(pdc, x, y, &Point);
-
- if (Ret && pptOut)
- {
- _SEH2_TRY
- {
- ProbeForWrite(pptOut, sizeof(POINT), 1);
- RtlCopyMemory(pptOut, &Point, sizeof(POINT));
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- SetLastNtError(_SEH2_GetExceptionCode());
- Ret = FALSE; // CHECKME: is this correct?
- }
- _SEH2_END;
- }
-
- DC_UnlockDc(pdc);
-
- return Ret;
-}
-
-/* EOF */