[NTGDI] Support the wide pen (#4137)

- Extend PATH_WidenPath function as PATH_WidenPathEx with the path argument.
- Use PATH_WidenPathEx and PATH_FillPathEx functions to implement wide pen drawing in PATH_StrokePath function.
- Add the code to IntGdiLineTo, IntRectangle, IntGdiPolygon, and IntGdiPolyline in order to stroke the path when the effective wide pen.
FIXME: Boundary rectangle.
CORE-2527, CORE-8366
This commit is contained in:
Katayama Hirofumi MZ 2021-12-06 20:44:06 +09:00 committed by GitHub
parent ff89651ed0
commit 6358c4ac9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 258 additions and 85 deletions

View file

@ -31,7 +31,7 @@ AddPenLinesBounds(PDC dc, int count, POINT *points)
bounds.left = bounds.top = INT_MAX;
bounds.right = bounds.bottom = INT_MIN;
if (((pbrLine->ulPenStyle & PS_TYPE_MASK) & PS_GEOMETRIC) || (pbrLine->lWidth > 1))
if (IntIsEffectiveWidePen(pbrLine))
{
/* Windows uses some heuristics to estimate the distance from the point that will be painted */
lWidth = pbrLine->lWidth + 2;
@ -152,9 +152,13 @@ IntGdiLineTo(DC *dc,
PBRUSH pbrLine;
RECTL Bounds;
POINT Points[2];
PDC_ATTR pdcattr = dc->pdcattr;
PDC_ATTR pdcattr;
PPATH pPath;
ASSERT_DC_PREPARED(dc);
pdcattr = dc->pdcattr;
if (PATH_IsPathOpen(dc->dclevel))
{
Ret = PATH_LineTo(dc, XEnd, YEnd);
@ -199,15 +203,47 @@ IntGdiLineTo(DC *dc,
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 (IntIsEffectiveWidePen(pbrLine))
{
/* Clear the path */
PATH_Delete(dc->dclevel.hPath);
dc->dclevel.hPath = NULL;
/* Begin a path */
pPath = PATH_CreatePath(2);
dc->dclevel.flPath |= DCPATH_ACTIVE;
dc->dclevel.hPath = pPath->BaseObject.hHmgr;
IntGetCurrentPositionEx(dc, &pPath->pos);
IntLPtoDP(dc, &pPath->pos, 1);
PATH_MoveTo(dc, pPath);
PATH_LineTo(dc, XEnd, YEnd);
/* Close the path */
pPath->state = PATH_Closed;
dc->dclevel.flPath &= ~DCPATH_ACTIVE;
/* Actually stroke a path */
Ret = PATH_StrokePath(dc, pPath);
/* Clear the path */
PATH_UnlockPath(pPath);
PATH_Delete(dc->dclevel.hPath);
dc->dclevel.hPath = NULL;
/* FIXME: Boundary */
}
else
{
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)
@ -298,6 +334,7 @@ IntGdiPolyline(DC *dc,
BOOL Ret = TRUE;
LONG i;
PDC_ATTR pdcattr = dc->pdcattr;
PPATH pPath;
if (!dc->dclevel.pSurface)
{
@ -331,13 +368,48 @@ IntGdiPolyline(DC *dc,
AddPenLinesBounds(dc, Count, Points);
}
Ret = IntEngPolyline(&psurf->SurfObj,
(CLIPOBJ *)&dc->co,
&dc->eboLine.BrushObject,
Points,
Count,
ROP2_TO_MIX(pdcattr->jROP2));
if (IntIsEffectiveWidePen(pbrLine))
{
/* Clear the path */
PATH_Delete(dc->dclevel.hPath);
dc->dclevel.hPath = NULL;
/* Begin a path */
pPath = PATH_CreatePath(Count);
dc->dclevel.flPath |= DCPATH_ACTIVE;
dc->dclevel.hPath = pPath->BaseObject.hHmgr;
pPath->pos = pt[0];
IntLPtoDP(dc, &pPath->pos, 1);
PATH_MoveTo(dc, pPath);
for (i = 1; i < Count; ++i)
{
PATH_LineTo(dc, pt[i].x, pt[i].y);
}
/* Close the path */
pPath->state = PATH_Closed;
dc->dclevel.flPath &= ~DCPATH_ACTIVE;
/* Actually stroke a path */
Ret = PATH_StrokePath(dc, pPath);
/* Clear the path */
PATH_UnlockPath(pPath);
PATH_Delete(dc->dclevel.hPath);
dc->dclevel.hPath = NULL;
/* FIXME: Boundary */
}
else
{
Ret = IntEngPolyline(&psurf->SurfObj,
(CLIPOBJ *)&dc->co,
&dc->eboLine.BrushObject,
Points,
Count,
ROP2_TO_MIX(pdcattr->jROP2));
}
EngFreeMem(Points);
}
else