Huw Davies : gdi32: Draw single pixel wide, horizontal or vertical lines with the dib driver.
Alexandre Julliard
julliard at winehq.org
Thu Apr 7 11:16:42 CDT 2011
Module: wine
Branch: master
Commit: 1e27c9512527e5382599a7ecc91ca607b9ccaaeb
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1e27c9512527e5382599a7ecc91ca607b9ccaaeb
Author: Huw Davies <huw at codeweavers.com>
Date: Thu Apr 7 13:49:33 2011 +0100
gdi32: Draw single pixel wide, horizontal or vertical lines with the dib driver.
---
dlls/gdi32/Makefile.in | 1 +
dlls/gdi32/clipping.c | 13 -----------
dlls/gdi32/dibdrv/dc.c | 2 +-
dlls/gdi32/dibdrv/dibdrv.h | 6 +++++
dlls/gdi32/dibdrv/graphics.c | 47 ++++++++++++++++++++++++++++++++++++++++
dlls/gdi32/dibdrv/objects.c | 49 ++++++++++++++++++++++++++++++++++++++++++
dlls/gdi32/gdi_private.h | 9 +++++++
7 files changed, 113 insertions(+), 14 deletions(-)
diff --git a/dlls/gdi32/Makefile.in b/dlls/gdi32/Makefile.in
index 4b070ac..6a04742 100644
--- a/dlls/gdi32/Makefile.in
+++ b/dlls/gdi32/Makefile.in
@@ -15,6 +15,7 @@ C_SRCS = \
dc.c \
dib.c \
dibdrv/dc.c \
+ dibdrv/graphics.c \
dibdrv/objects.c \
dibdrv/primitives.c \
driver.c \
diff --git a/dlls/gdi32/clipping.c b/dlls/gdi32/clipping.c
index 9d529ac..86b19f1 100644
--- a/dlls/gdi32/clipping.c
+++ b/dlls/gdi32/clipping.c
@@ -30,19 +30,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(clipping);
/***********************************************************************
- * get_clip_region
- *
- * Return the total clip region (if any).
- */
-static inline HRGN get_clip_region( DC * dc )
-{
- if (dc->hMetaClipRgn) return dc->hMetaClipRgn;
- if (dc->hMetaRgn) return dc->hMetaRgn;
- return dc->hClipRgn;
-}
-
-
-/***********************************************************************
* get_clip_rect
*
* Compute a clip rectangle from its logical coordinates.
diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c
index 1a16260..78248dd 100644
--- a/dlls/gdi32/dibdrv/dc.c
+++ b/dlls/gdi32/dibdrv/dc.c
@@ -192,7 +192,7 @@ const DC_FUNCTIONS dib_driver =
NULL, /* pGetTextMetrics */
NULL, /* pIntersectClipRect */
NULL, /* pInvertRgn */
- NULL, /* pLineTo */
+ dibdrv_LineTo, /* pLineTo */
NULL, /* pModifyWorldTransform */
NULL, /* pMoveTo */
NULL, /* pOffsetClipRgn */
diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h
index 2620e38..b7408ac 100644
--- a/dlls/gdi32/dibdrv/dibdrv.h
+++ b/dlls/gdi32/dibdrv/dibdrv.h
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+extern BOOL CDECL dibdrv_LineTo( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN;
extern HPEN CDECL dibdrv_SelectPen( PHYSDEV dev, HPEN hpen ) DECLSPEC_HIDDEN;
extern COLORREF CDECL dibdrv_SetDCPenColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
@@ -26,6 +27,11 @@ static inline dibdrv_physdev *get_dibdrv_pdev( PHYSDEV dev )
return (dibdrv_physdev *)dev;
}
+static inline DC *get_dibdrv_dc( PHYSDEV dev )
+{
+ return CONTAINING_RECORD( dev, DC, dibdrv );
+}
+
typedef struct primitive_funcs
{
void (* solid_rects)(const dib_info *dib, int num, RECT *rc, DWORD and, DWORD xor);
diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c
new file mode 100644
index 0000000..1e0de2f
--- /dev/null
+++ b/dlls/gdi32/dibdrv/graphics.c
@@ -0,0 +1,47 @@
+/*
+ * DIB driver graphics operations.
+ *
+ * Copyright 2011 Huw Davies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "gdi_private.h"
+#include "dibdrv.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dib);
+
+/***********************************************************************
+ * dibdrv_LineTo
+ */
+BOOL CDECL dibdrv_LineTo( PHYSDEV dev, INT x, INT y )
+{
+ PHYSDEV next = GET_NEXT_PHYSDEV( dev, pLineTo );
+ dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
+ POINT pts[2];
+
+ GetCurrentPositionEx(dev->hdc, pts);
+ pts[1].x = x;
+ pts[1].y = y;
+
+ LPtoDP(dev->hdc, pts, 2);
+
+ if(pdev->defer || !pdev->pen_line(pdev, pts, pts + 1))
+ return next->funcs->pLineTo( next, x, y );
+
+ return TRUE;
+}
diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c
index 88c9581..a26785a 100644
--- a/dlls/gdi32/dibdrv/objects.c
+++ b/dlls/gdi32/dibdrv/objects.c
@@ -89,6 +89,54 @@ void calc_and_xor_masks(INT rop, DWORD color, DWORD *and, DWORD *xor)
*xor = (color & rop2_xor_array[rop-1][0]) | ((~color) & rop2_xor_array[rop-1][1]);
}
+static inline void order_end_points(int *s, int *e)
+{
+ if(*s > *e)
+ {
+ int tmp;
+ tmp = *s + 1;
+ *s = *e + 1;
+ *e = tmp;
+ }
+}
+
+static inline BOOL pt_in_rect( const RECT *rect, POINT pt )
+{
+ return ((pt.x >= rect->left) && (pt.x < rect->right) &&
+ (pt.y >= rect->top) && (pt.y < rect->bottom));
+}
+
+static BOOL solid_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end)
+{
+ RECT rc;
+ DC *dc = get_dibdrv_dc( &pdev->dev );
+
+ if(get_clip_region(dc) || !pt_in_rect(&dc->vis_rect, *start) || !pt_in_rect(&dc->vis_rect, *end))
+ return FALSE;
+
+ rc.left = start->x;
+ rc.top = start->y;
+ rc.right = end->x;
+ rc.bottom = end->y;
+
+ if(rc.top == rc.bottom)
+ {
+ order_end_points(&rc.left, &rc.right);
+ rc.bottom++;
+ pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rc, pdev->pen_and, pdev->pen_xor);
+ return TRUE;
+ }
+ else if(rc.left == rc.right)
+ {
+ order_end_points(&rc.top, &rc.bottom);
+ rc.right++;
+ pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rc, pdev->pen_and, pdev->pen_xor);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/***********************************************************************
* dibdrv_SelectPen
*/
@@ -133,6 +181,7 @@ HPEN CDECL dibdrv_SelectPen( PHYSDEV dev, HPEN hpen )
case PS_SOLID:
if(logpen.lopnStyle & PS_GEOMETRIC) break;
if(logpen.lopnWidth.x > 1) break;
+ pdev->pen_line = solid_pen_line;
pdev->defer &= ~DEFER_PEN;
break;
default:
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 9a81afd..fc86b32 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -101,6 +101,7 @@ typedef struct dibdrv_physdev
/* pen */
DWORD pen_color, pen_and, pen_xor;
+ BOOL (* pen_line)(struct dibdrv_physdev *pdev, POINT *start, POINT *end);
} dibdrv_physdev;
#define DEFER_FORMAT 1
@@ -399,6 +400,14 @@ extern INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp ) DECLSPEC_HIDDEN;
/* clipping.c */
extern void CLIPPING_UpdateGCRegion( DC * dc ) DECLSPEC_HIDDEN;
+/* Return the total clip region (if any) */
+static inline HRGN get_clip_region( DC * dc )
+{
+ if (dc->hMetaClipRgn) return dc->hMetaClipRgn;
+ if (dc->hMetaRgn) return dc->hMetaRgn;
+ return dc->hClipRgn;
+}
+
/* dc.c */
extern DC *alloc_dc_ptr( WORD magic ) DECLSPEC_HIDDEN;
extern void free_dc_ptr( DC *dc ) DECLSPEC_HIDDEN;
More information about the wine-cvs
mailing list