[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