diff --git a/dlls/gdi32/Makefile.in b/dlls/gdi32/Makefile.in index 4b070ac8b57..6a047429e78 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 9d529ac111e..86b19f11f57 100644 --- a/dlls/gdi32/clipping.c +++ b/dlls/gdi32/clipping.c @@ -29,19 +29,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 * diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c index 1a162601f38..78248ddf8ac 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 2620e389e45..b7408ac7492 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 00000000000..1e0de2fa6a7 --- /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 88c9581274c..a26785a07ff 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 9a81afdfd45..fc86b322bbc 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;