/*
* PROJECT: ReactOS Win32k Subsystem
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: win32k/objects/line.c
+ * FILE: win32ss/gdi/ntgdi/line.c
* PURPOSE: Line functions
* PROGRAMMERS: ...
*/
// 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,
- BOOL BypassPath)
+ LPPOINT Point)
{
- BOOL PathIsOpen;
PDC_ATTR pdcattr = dc->pdcattr;
if ( Point )
{
CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
- if (BypassPath) return TRUE;
-
- PathIsOpen = PATH_IsPathOpen(dc->dclevel);
-
- if ( PathIsOpen )
- return PATH_MoveTo ( dc );
-
return TRUE;
}
INT y,
LPPOINT pptOut)
{
+ BOOL Ret;
PDC dc;
if (!(dc = DC_LockDc(hdc)))
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
- return IntGdiMoveToEx(dc, x, y, pptOut, TRUE);
+ Ret = IntGdiMoveToEx(dc, x, y, pptOut);
+ DC_UnlockDc(dc);
+ return Ret;
}
// Should use Fx in pt
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);
- if (Ret)
- {
- // FIXME: PATH_LineTo should maybe do this? No
- 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;
}
else
{
pbrLine = dc->dclevel.pbrLine;
ASSERT(pbrLine);
+ if (dc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
+ {
+ DPRINT1("Bounds dc %p l %d t %d\n",dc,Bounds.left,Bounds.top);
+ DPRINT1(" r %d b %d\n",Bounds.right,Bounds.bottom);
+ AddPenLinesBounds(dc, 2, Points);
+ }
+
if (!(pbrLine->flAttrs & BR_IS_NULL))
{
Ret = IntEngLineTo(&psurf->SurfObj,
- dc->rosdc.CombinedClip,
+ &dc->co.ClipObj,
&dc->eboLine.BrushObject,
Points[0].x, Points[0].y,
Points[1].x, Points[1].y,
LONG i;
PDC_ATTR pdcattr = dc->pdcattr;
- psurf = dc->dclevel.pSurface;
- if (!psurf)
+ if (!dc->dclevel.pSurface)
{
return FALSE;
}
- if (PATH_IsPathOpen(dc->dclevel))
- return PATH_Polyline(dc, pt, Count);
-
DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL);
-
- if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
- DC_vUpdateFillBrush(dc);
-
- if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
- DC_vUpdateLineBrush(dc);
+ psurf = dc->dclevel.pSurface;
/* Get BRUSHOBJ from current pen. */
pbrLine = dc->dclevel.pbrLine;
Points[i].y += dc->ptlDCOrig.y;
}
+ if (dc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
+ {
+ AddPenLinesBounds(dc, Count, Points);
+ }
+
Ret = IntEngPolyline(&psurf->SurfObj,
- dc->rosdc.CombinedClip,
+ &dc->co.ClipObj,
&dc->eboLine.BrushObject,
Points,
Count,
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 );
DC_vPrepareDCsForBlit(dc, &rcLockRect, NULL, NULL);
- if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
- DC_vUpdateLineBrush(dc);
-
Ret = IntGdiLineTo(dc, XEnd, YEnd);
DC_vFinishBlit(dc, NULL);
}
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, TRUE );
+ IntGdiMoveToEx( dc, line_pts[num_pts - 1].x, line_pts[num_pts - 1].y, NULL );
result = TRUE;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
pdc = DC_LockDc(hdc);
if (!pdc) return FALSE;
- Ret = IntGdiMoveToEx(pdc, x, y, &Point, TRUE);
+ Ret = IntGdiMoveToEx(pdc, x, y, &Point);
if (Ret && pptOut)
{