[2/2] gdiplus: save GDI path in GdipDrawLineI

Evan Stade estade at gmail.com
Mon Jul 2 17:13:09 CDT 2007


Hi,

GDI+ must save/restore the GDI path  before and after drawing on a DC.

Changelog:
*add functions to save and restore any open GDI path
*used them in GdipDrawLineI

 dlls/gdiplus/graphics.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 76 insertions(+), 0 deletions(-)

-- 
Evan Stade
-------------- next part --------------
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 453cbe5..6e3b280 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -30,6 +30,13 @@ #include "wine/debug.h"
 /* looks-right constant */
 #define TENSION_CONST (0.3)
 
+typedef struct path_state{
+    INT count;
+    LPPOINT points;
+    LPBYTE types;
+    BOOL open;
+} path_state;
+
 static inline INT roundr(REAL x)
 {
     return (INT) floor(x+0.5);
@@ -108,6 +115,72 @@ static void calc_curve_bezier_endp(REAL 
     *y = roundr(tension * (yadj - yend) + yend);
 }
 
+/* Sets open to true if the path was open before it was saved.
+ * Saves the path (whether or not it was open) in points, types, count. */
+static void save_gdi_path(HDC hdc, path_state * state)
+{
+    state->open = EndPath(hdc);
+    state->count = GetPath(hdc, NULL, NULL, 0);
+
+    if(state->count > 0){
+        state->points = GdipAlloc(state->count * sizeof(POINT));
+        state->types = GdipAlloc(state->count);
+        GetPath(hdc, state->points, state->types, state->count);
+    }
+}
+
+/* Assumes there is no open path in the hdc. Restores the path given by
+ * points, types, count. */
+static void restore_gdi_path(HDC hdc, path_state * state)
+{
+    INT num_bezier, i, count = state->count;
+    LPPOINT points = state->points;
+    LPBYTE types = state->types;
+    BOOL open = state->open;
+
+    BeginPath(hdc);
+
+    for(i = 0; i < count; i++){
+        switch(types[i] & ~PT_CLOSEFIGURE){
+            case PT_LINETO:
+
+                LineTo(hdc, points[i].x,  points[i].y);
+
+                break;
+
+            case PT_MOVETO:
+
+                MoveToEx(hdc, points[i].x,  points[i].y, NULL);
+
+                break;
+
+            case PT_BEZIERTO:
+
+                /* count number of consecutive bezier points */
+                for(num_bezier = 1; i + num_bezier < count; num_bezier++){
+                    if(((types[i + num_bezier] & ~PT_CLOSEFIGURE) != PT_BEZIERTO)
+                       || (types[i + num_bezier - 1] & PT_CLOSEFIGURE))
+                        break;
+                }
+
+                PolyBezierTo(hdc, &(points[i]), num_bezier);
+
+                i += num_bezier - 1;
+
+                break;
+        }
+        if(types[i] & PT_CLOSEFIGURE){
+            CloseFigure(hdc);
+        }
+    }
+
+    GdipFree(points);
+    GdipFree(types);
+
+    if(!open)
+        EndPath(hdc);
+}
+
 GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
 {
     if(hdc == NULL)
@@ -247,11 +320,13 @@ GpStatus WINGDIPAPI GdipDrawCurve2(GpGra
 GpStatus WINGDIPAPI GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1,
     INT y1, INT x2, INT y2)
 {
+    path_state path = {0, NULL, NULL, 0};
     INT save_state;
 
     if(!pen || !graphics)
         return InvalidParameter;
 
+    save_gdi_path(graphics->hdc, &path);
     save_state = SaveDC(graphics->hdc);
     SelectObject(graphics->hdc, pen->gdipen);
 
@@ -259,6 +334,7 @@ GpStatus WINGDIPAPI GdipDrawLineI(GpGrap
     LineTo(graphics->hdc, x2, y2);
 
     RestoreDC(graphics->hdc, save_state);
+    restore_gdi_path(graphics->hdc, &path);
 
     return Ok;
 }
-- 
1.4.1


More information about the wine-patches mailing list