[GDI] Use PolyLine in StrokePath

Felix Nawothnig felix.nawothnig at t-online.de
Sat May 14 01:14:08 CDT 2005


Each figure in a path has to be drawn as a single primitive (using 
PolyLine e.g.) by StrokePath so the joining points are recognized as 
such and properly rendered according to PS_JOIN_* by the graphics driver.

This fixes bug 11.

ChangeLog:
Draw each figure as a single primitive in StrokePath()
-------------- next part --------------
Index: path.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/path.c,v
retrieving revision 1.5
diff -u -r1.5 path.c
--- path.c	24 Mar 2005 21:01:38 -0000	1.5
+++ path.c	14 May 2005 06:11:47 -0000
@@ -1430,8 +1430,8 @@
 
 static BOOL PATH_StrokePath(DC *dc, GdiPath *pPath)
 {
-    INT i;
-    POINT ptLastMove = {0,0};
+    INT i, nLinePts, nAlloc;
+    POINT *pLinePts;
     POINT ptViewportOrg, ptWindowOrg;
     SIZE szViewportExt, szWindowExt;
     DWORD mapMode, graphicsMode;
@@ -1461,19 +1461,37 @@
     ModifyWorldTransform(dc->hSelf, &xform, MWT_IDENTITY);
     SetGraphicsMode(dc->hSelf, graphicsMode);
 
+    /* Allocate enough memory for the worst case without beziers (one PT_MOVETO
+     * and the rest PT_LINETO with PT_CLOSEFIGURE at the end) plus some buffer 
+     * space in case we get one to keep the number of reallocations small. */
+    nAlloc = pPath->numEntriesUsed + 1 + 300; 
+    pLinePts = HeapAlloc(GetProcessHeap(), 0, nAlloc * sizeof(POINT));
+    nLinePts = 0;
+    
     for(i = 0; i < pPath->numEntriesUsed; i++) {
+        if((i == 0 || (pPath->pFlags[i-1] & PT_CLOSEFIGURE)) &&
+	   (pPath->pFlags[i] != PT_MOVETO))
+	{
+	    ERR("Expected PT_MOVETO %s, got path flag %d\n", 
+	        i == 0 ? "as first point" : "after PT_CLOSEFIGURE",
+		(INT)pPath->pFlags[i]);
+	    ret = FALSE;
+	    goto end;
+	}
         switch(pPath->pFlags[i]) {
 	case PT_MOVETO:
 	    TRACE("Got PT_MOVETO (%ld, %ld)\n",
 		  pPath->pPoints[i].x, pPath->pPoints[i].y);
-	    MoveToEx(dc->hSelf, pPath->pPoints[i].x, pPath->pPoints[i].y, NULL);
-	    ptLastMove = pPath->pPoints[i];
+	    if(nLinePts >= 2)
+	        Polyline(dc->hSelf, pLinePts, nLinePts);
+	    nLinePts = 0;
+	    pLinePts[nLinePts++] = pPath->pPoints[i];
 	    break;
 	case PT_LINETO:
 	case (PT_LINETO | PT_CLOSEFIGURE):
 	    TRACE("Got PT_LINETO (%ld, %ld)\n",
 		  pPath->pPoints[i].x, pPath->pPoints[i].y);
-	    LineTo(dc->hSelf, pPath->pPoints[i].x, pPath->pPoints[i].y);
+	    pLinePts[nLinePts++] = pPath->pPoints[i];
 	    break;
 	case PT_BEZIERTO:
 	    TRACE("Got PT_BEZIERTO\n");
@@ -1482,9 +1500,25 @@
 	        ERR("Path didn't contain 3 successive PT_BEZIERTOs\n");
 		ret = FALSE;
 		goto end;
+	    } else {
+	        INT nBzrPts, nMinAlloc;
+	        POINT *pBzrPts = GDI_Bezier(&pPath->pPoints[i-1], 4, &nBzrPts);
+		/* Make sure we have allocated enough memory for the lines of 
+		 * this bezier and the rest of the path, assuming we won't get
+		 * another one (since we won't reallocate again then). */
+		nMinAlloc = nLinePts + (pPath->numEntriesUsed - i) + nBzrPts;
+		if(nAlloc < nMinAlloc)
+		{
+		    nAlloc = nMinAlloc * 2;
+		    pLinePts = HeapReAlloc(GetProcessHeap(), 0, pLinePts,
+		                           nAlloc * sizeof(POINT));
+		}
+		memcpy(&pLinePts[nLinePts], &pBzrPts[1],
+		       (nBzrPts - 1) * sizeof(POINT));
+		nLinePts += nBzrPts - 1;
+		HeapFree(GetProcessHeap(), 0, pBzrPts);
+		i += 2;
 	    }
-	    PolyBezierTo(dc->hSelf, &pPath->pPoints[i], 3);
-	    i += 2;
 	    break;
 	default:
 	    ERR("Got path flag %d\n", (INT)pPath->pFlags[i]);
@@ -1492,10 +1526,13 @@
 	    goto end;
 	}
 	if(pPath->pFlags[i] & PT_CLOSEFIGURE)
-	    LineTo(dc->hSelf, ptLastMove.x, ptLastMove.y);
+	    pLinePts[nLinePts++] = pLinePts[0];
     }
+    if(nLinePts >= 2)
+        Polyline(dc->hSelf, pLinePts, nLinePts);
 
  end:
+    HeapFree(GetProcessHeap(), 0, pLinePts);
 
     /* Restore the old mapping mode */
     SetMapMode(dc->hSelf, mapMode);


More information about the wine-patches mailing list