resend : gdi32:WidenPath partial implementation

Laurent Vromman laurent at vromman.org
Sun Feb 18 13:07:04 CST 2007


Changelog :
- Add a partial implementation for the function gd32:WidenPath

It is the second time I send this patch. It seems it was forgotten the 
previous time. I am sorry for that.


If this patch needs to be improved, please let me know, I'll try to do it.

Laurent Vromman



-------------- next part --------------
diff --git a/dlls/gdi32/path.c b/dlls/gdi32/path.c
index 306ed37..d9ccbb3 100644
--- a/dlls/gdi32/path.c
+++ b/dlls/gdi32/path.c
@@ -1823,6 +1823,14 @@ BOOL WINAPI StrokePath(HDC hdc)
 /*******************************************************************
  *      WidenPath [GDI32.@]
  *
+ *   Redefines the current path as the area that would be painted if the path were stroked using the pen currently selected into the given device context.
+ *
+ *   PARAMS
+ *    hdc    [I] Handle to a device context that contains a closed path.
+ *
+ *   RETURNS
+ *     Success: TRUE. The path is updated with the new computed path.
+ *     Failure: FALSE.
  *
  */
 BOOL WINAPI WidenPath(HDC hdc)
@@ -1833,9 +1841,188 @@ BOOL WINAPI WidenPath(HDC hdc)
    if(!dc) return FALSE;
 
    if(dc->funcs->pWidenPath)
-     ret = dc->funcs->pWidenPath(dc->physDev);
-
-   FIXME("stub\n");
+      ret = dc->funcs->pWidenPath(dc->physDev);
+   else {
+      ret = PATH_WidenPath(hdc);
+   }
    GDI_ReleaseObj( hdc );
+   FIXME("partially implemented\n");
    return ret;
 }
+
+static BOOL PATH_WidenPath(HDC hdc) 
+{
+    INT i, j, numStrokes, nLinePts, penWidth, penWidthIn, penWidthOut, size;
+    DC *dc;
+    BOOL ret = FALSE;
+    GdiPath *pPath, *pNewPath, **pStrokes, *pUpPath, *pDownPath;
+    HPEN hPen;
+    EXTLOGPEN *elp;
+    FLOAT fCos, fSin, nPente;
+
+    dc = DC_GetDCPtr( hdc );
+    pPath = &dc->path;
+
+    PATH_FlattenPath(pPath);
+
+    if(pPath->state != PATH_Closed) {
+       ERR("Path Closed\n");
+       return FALSE;
+    }
+
+    hPen = SelectObject(hdc, GetStockObject(DC_PEN));
+
+    size = GetObjectW( hPen, 0, NULL );
+
+    if (!size) return FALSE;
+
+    elp = HeapAlloc( GetProcessHeap(), 0, size );
+
+    GetObjectW( hPen, size, elp );
+    /* FIXME: add support for user style pens */
+    penWidth = elp->elpWidth;
+    HeapFree( GetProcessHeap(), 0, elp );
+
+    /* FIXME : If extPen, use the shape on corners */
+    penWidthIn = penWidth / 2;
+    penWidthOut = penWidth / 2;
+    if(penWidthIn + penWidthOut < penWidth)
+        penWidthOut++;
+
+    numStrokes = 0;
+    nLinePts = 0;
+
+    pStrokes = HeapAlloc(GetProcessHeap(), 0, numStrokes * sizeof(GdiPath*));
+    pStrokes[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(GdiPath));
+    PATH_InitGdiPath(pStrokes[0]);
+    pStrokes[0]->pFlags = HeapAlloc(GetProcessHeap(), 0, pPath->numEntriesUsed * sizeof(INT));
+    pStrokes[0]->pPoints = HeapAlloc(GetProcessHeap(), 0, pPath->numEntriesUsed * sizeof(POINT));
+    pStrokes[0]->numEntriesUsed = 0;
+
+    for(i = 0, j = 0; i < pPath->numEntriesUsed; i++, j++) {
+        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:
+                numStrokes++;
+                j = 0;
+                pStrokes = HeapReAlloc(GetProcessHeap(), 0, pStrokes, numStrokes * sizeof(GdiPath*));
+                pStrokes[numStrokes - 1] = HeapAlloc(GetProcessHeap(), 0, sizeof(GdiPath));
+                PATH_InitGdiPath(pStrokes[numStrokes - 1]);
+                pStrokes[numStrokes - 1]->pFlags = HeapAlloc(GetProcessHeap(), 0, pPath->numEntriesUsed * sizeof(INT));
+                pStrokes[numStrokes - 1]->pPoints = HeapAlloc(GetProcessHeap(), 0, pPath->numEntriesUsed * sizeof(POINT));
+                pStrokes[numStrokes - 1]->numEntriesUsed = 0;
+
+                pStrokes[numStrokes - 1]->pFlags[j] = pPath->pFlags[i];
+                pStrokes[numStrokes - 1]->pPoints[j].x = pPath->pPoints[i].x;
+                pStrokes[numStrokes - 1]->pPoints[j].y = pPath->pPoints[i].y;
+                pStrokes[numStrokes - 1]->numEntriesUsed++;
+
+                break;
+            case PT_LINETO:
+            case (PT_LINETO | PT_CLOSEFIGURE):
+                pStrokes[numStrokes - 1]->pFlags[j] = pPath->pFlags[i];
+                pStrokes[numStrokes - 1]->pPoints[j].x = pPath->pPoints[i].x;
+                pStrokes[numStrokes - 1]->pPoints[j].y = pPath->pPoints[i].y;
+                pStrokes[numStrokes - 1]->numEntriesUsed++;
+                break;
+            case PT_BEZIERTO:
+                // should never happen because of the FlattenPath call
+                ERR("Should never happen \n");
+                break;
+            default:
+                ERR("Got path flag %d\n", (INT)pPath->pFlags[i]);
+                ret = FALSE;
+                goto end;
+        }
+    }
+
+    pNewPath = HeapAlloc(GetProcessHeap(), 0, sizeof(GdiPath));
+    PATH_InitGdiPath(pNewPath);
+    pNewPath->pFlags = HeapAlloc(GetProcessHeap(), 0, 4 * pPath->numEntriesUsed * sizeof(INT));
+    pNewPath->pPoints = HeapAlloc(GetProcessHeap(), 0, 4 * pPath->numEntriesUsed * sizeof(POINT));
+    pNewPath->numEntriesUsed = 0;
+    pNewPath->numEntriesAllocated = 4 * pPath->numEntriesUsed;
+
+    for(i = 0; i < numStrokes; i++) {
+        pUpPath = HeapAlloc(GetProcessHeap(), 0, sizeof(GdiPath));
+        PATH_InitGdiPath(pUpPath);
+        pUpPath->pFlags = HeapAlloc(GetProcessHeap(), 0, 2 * pStrokes[i]->numEntriesUsed * sizeof(INT));
+        pUpPath->pPoints = HeapAlloc(GetProcessHeap(), 0, 2 * pStrokes[i]->numEntriesUsed * sizeof(POINT));
+        pUpPath->numEntriesUsed = 0;
+        pDownPath = HeapAlloc(GetProcessHeap(), 0, sizeof(GdiPath));
+        PATH_InitGdiPath(pDownPath);
+        pDownPath->pFlags = HeapAlloc(GetProcessHeap(), 0, 2 * pStrokes[i]->numEntriesUsed * sizeof(INT));
+        pDownPath->pPoints = HeapAlloc(GetProcessHeap(), 0, 2 * pStrokes[i]->numEntriesUsed * sizeof(POINT));
+        pDownPath->numEntriesUsed = 0;
+        for(j = 0; j < pStrokes[i]->numEntriesUsed - 1; j++) {
+            if(pStrokes[i]->pPoints[j+1].x != pStrokes[i]->pPoints[j].x) {
+                nPente = (pStrokes[i]->pPoints[j+1].y - pStrokes[i]->pPoints[j].y) / (pStrokes[i]->pPoints[j+1].x - pStrokes[i]->pPoints[j].x);
+                fCos = cos(atan(nPente));
+                fSin = sin(atan(nPente));
+            }
+            else {
+                fCos = 0;
+                fSin = 1;
+            }
+
+            // FIXME : Improve corners
+            pUpPath->pPoints[2 * j].x = pStrokes[i]->pPoints[j].x + penWidthOut * fSin;
+            pUpPath->pPoints[2 * j].y = pStrokes[i]->pPoints[j].y + penWidthOut * fCos;
+            pUpPath->pFlags[2 * j] = pStrokes[i]->pFlags[j];
+            pUpPath->pPoints[2 * j + 1] .x = pStrokes[i]->pPoints[j+1].x + penWidthOut * fSin;
+            pUpPath->pPoints[2 * j + 1] .y = pStrokes[i]->pPoints[j+1].y + penWidthOut * fCos;
+            pUpPath->pFlags[2 * j + 1] = PT_LINETO;
+            pUpPath->numEntriesUsed = pUpPath->numEntriesUsed + 2;
+
+            pDownPath->pPoints[2 * j].x = pStrokes[i]->pPoints[j].x - penWidthIn * fSin;
+            pDownPath->pPoints[2 * j].y = pStrokes[i]->pPoints[j].y - penWidthIn * fCos;
+            pDownPath->pFlags[2 * j] = PT_LINETO;
+            pDownPath->pPoints[2 * j + 1] .x = pStrokes[i]->pPoints[j+1].x - penWidthIn * fSin;
+            pDownPath->pPoints[2 * j + 1] .y = pStrokes[i]->pPoints[j+1].y - penWidthIn * fCos;
+            pDownPath->pFlags[2 * j + 1] = PT_LINETO;
+            pDownPath->numEntriesUsed = pUpPath->numEntriesUsed;
+        }
+
+        for(j = 0; j < pUpPath->numEntriesUsed; j++) {
+            pNewPath->pPoints[pNewPath->numEntriesUsed + j].x = pUpPath->pPoints[j].x;
+            pNewPath->pPoints[pNewPath->numEntriesUsed + j].y = pUpPath->pPoints[j].y;
+            pNewPath->pFlags[pNewPath->numEntriesUsed + j] = pUpPath->pFlags[j];
+            pNewPath->pPoints[pNewPath->numEntriesUsed + pUpPath->numEntriesUsed + j].x = pDownPath->pPoints[pUpPath->numEntriesUsed - j - 1].x;
+            pNewPath->pPoints[pNewPath->numEntriesUsed + pUpPath->numEntriesUsed + j].y = pDownPath->pPoints[pUpPath->numEntriesUsed - j - 1].y;
+            pNewPath->pFlags[pNewPath->numEntriesUsed + pUpPath->numEntriesUsed + j] = pDownPath->pFlags[pUpPath->numEntriesUsed - j - 1];
+        }
+        pNewPath->numEntriesUsed += 2 * pUpPath->numEntriesUsed;
+        pNewPath->pFlags[pNewPath->numEntriesUsed - 1] = PT_CLOSEFIGURE | PT_LINETO;
+
+        PATH_DestroyGdiPath(pStrokes[i]);
+        HeapFree(GetProcessHeap(), 0, pStrokes[i]);
+        PATH_DestroyGdiPath(pUpPath);
+        HeapFree(GetProcessHeap(), 0, pUpPath);
+        PATH_DestroyGdiPath(pDownPath);
+        HeapFree(GetProcessHeap(), 0, pDownPath);
+    }
+    HeapFree(GetProcessHeap(), 0, pStrokes);
+
+    pNewPath->state = PATH_Closed;
+    if(!PATH_AssignGdiPath(pPath, pNewPath)) {
+        ERR("Assign path failed\n");
+        ret = FALSE;
+        goto end;
+    }
+    PATH_DestroyGdiPath(pNewPath);
+    HeapFree(GetProcessHeap(), 0, pNewPath);
+
+    ret = TRUE;
+
+end :
+    GDI_ReleaseObj( hdc );
+    return ret;
+}
+


More information about the wine-patches mailing list