gdi32: Add support for drawing horizontal patterned lines.

oldstable
Huw Davies 2011-05-06 11:48:34 +01:00 committed by Alexandre Julliard
parent 54397f1552
commit 6976cee425
5 changed files with 170 additions and 4 deletions

View File

@ -47,6 +47,7 @@ extern const primitive_funcs funcs_null DECLSPEC_HIDDEN;
extern void calc_and_xor_masks(INT rop, DWORD color, DWORD *and, DWORD *xor) DECLSPEC_HIDDEN;
extern void update_brush_rop( dibdrv_physdev *pdev, INT rop ) DECLSPEC_HIDDEN;
extern void reset_dash_origin(dibdrv_physdev *pdev) DECLSPEC_HIDDEN;
static inline BOOL defer_pen(dibdrv_physdev *pdev)
{

View File

@ -71,6 +71,8 @@ BOOL CDECL dibdrv_LineTo( PHYSDEV dev, INT x, INT y )
LPtoDP(dev->hdc, pts, 2);
reset_dash_origin(pdev);
if(defer_pen(pdev) || !pdev->pen_line(pdev, pts, pts + 1))
return next->funcs->pLineTo( next, x, y );

View File

@ -544,9 +544,139 @@ static BOOL solid_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end)
return TRUE;
}
void reset_dash_origin(dibdrv_physdev *pdev)
{
pdev->dash_pos.cur_dash = 0;
pdev->dash_pos.left_in_dash = pdev->pen_pattern.dashes[0];
pdev->dash_pos.mark = TRUE;
}
static inline void skip_dash(dibdrv_physdev *pdev, unsigned int skip)
{
skip %= pdev->pen_pattern.total_len;
while(skip)
{
if(pdev->dash_pos.left_in_dash > skip)
{
pdev->dash_pos.left_in_dash -= skip;
return;
}
skip -= pdev->dash_pos.left_in_dash;
pdev->dash_pos.cur_dash++;
if(pdev->dash_pos.cur_dash == pdev->pen_pattern.count) pdev->dash_pos.cur_dash = 0;
pdev->dash_pos.left_in_dash = pdev->pen_pattern.dashes[pdev->dash_pos.cur_dash];
pdev->dash_pos.mark = !pdev->dash_pos.mark;
}
}
static inline void get_dash_colors(const dibdrv_physdev *pdev, DWORD *and, DWORD *xor)
{
if(pdev->dash_pos.mark)
{
*and = pdev->pen_and;
*xor = pdev->pen_xor;
}
else /* space */
{
*and = pdev->bkgnd_and;
*xor = pdev->bkgnd_xor;
}
}
static BOOL dashed_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end)
{
return FALSE;
const WINEREGION *clip = get_wine_region(pdev->clip);
DWORD and, xor;
int i, dash_len;
RECT rect;
const dash_pos start_pos = pdev->dash_pos;
BOOL ret = TRUE;
if(start->y == end->y) /* hline */
{
BOOL l_to_r;
INT left, right, cur_x;
rect.top = start->y;
rect.bottom = start->y + 1;
if(start->x <= end->x)
{
left = start->x;
right = end->x - 1;
l_to_r = TRUE;
}
else
{
left = end->x + 1;
right = start->x;
l_to_r = FALSE;
}
for(i = 0; i < clip->numRects; i++)
{
if(clip->rects[i].top > start->y) break;
if(clip->rects[i].bottom <= start->y) continue;
if(clip->rects[i].right > left && clip->rects[i].left <= right)
{
int clipped_left = max(clip->rects[i].left, left);
int clipped_right = min(clip->rects[i].right - 1, right);
pdev->dash_pos = start_pos;
if(l_to_r)
{
cur_x = clipped_left;
if(cur_x != left)
skip_dash(pdev, clipped_left - left);
while(cur_x <= clipped_right)
{
get_dash_colors(pdev, &and, &xor);
dash_len = pdev->dash_pos.left_in_dash;
if(cur_x + dash_len > clipped_right + 1)
dash_len = clipped_right - cur_x + 1;
rect.left = cur_x;
rect.right = cur_x + dash_len;
pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor);
cur_x += dash_len;
skip_dash(pdev, dash_len);
}
}
else
{
cur_x = clipped_right;
if(cur_x != right)
skip_dash(pdev, right - clipped_right);
while(cur_x >= clipped_left)
{
get_dash_colors(pdev, &and, &xor);
dash_len = pdev->dash_pos.left_in_dash;
if(cur_x - dash_len < clipped_left - 1)
dash_len = cur_x - clipped_left + 1;
rect.left = cur_x - dash_len + 1;
rect.right = cur_x + 1;
pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor);
cur_x -= dash_len;
skip_dash(pdev, dash_len);
}
}
}
}
pdev->dash_pos = start_pos;
skip_dash(pdev, right - left + 1);
}
else
{
ret = FALSE;
}
release_wine_region(pdev->clip);
return ret;
}
static const dash_pattern dash_patterns[4] =

View File

@ -99,6 +99,13 @@ typedef struct
DWORD total_len; /* total length of the dashes, should be multiplied by 2 if there are an odd number of dash lengths */
} dash_pattern;
typedef struct
{
int left_in_dash;
int cur_dash;
BOOL mark;
} dash_pos;
typedef struct dibdrv_physdev
{
struct gdi_physdev dev;
@ -109,8 +116,9 @@ typedef struct dibdrv_physdev
/* pen */
DWORD pen_color, pen_and, pen_xor;
BOOL (* pen_line)(struct dibdrv_physdev *pdev, POINT *start, POINT *end);
dash_pattern pen_pattern;
dash_pos dash_pos;
BOOL (* pen_line)(struct dibdrv_physdev *pdev, POINT *start, POINT *end);
/* brush */
UINT brush_style;

View File

@ -84,6 +84,8 @@ static const char *sha1_graphics_a8r8g8b8[] =
"d51bd330cec510cdccf5394328bd8e5411901e9e",
"df4aebf98d91f11be560dd232123b3ae327303d7",
"f2af53dd073a09b1031d0032d28da35c82adc566",
"eb5a963a6f7b25533ddfb8915e70865d037bd156",
"c387917268455017aa0b28bed73aa6554044bbb3",
NULL
};
@ -237,7 +239,7 @@ static const RECT patblt_clips[] =
static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sha1)
{
DWORD dib_size = get_dib_size(bmi);
HPEN solid_pen, orig_pen;
HPEN solid_pen, dashed_pen, orig_pen;
HBRUSH solid_brush, orig_brush;
INT i, y;
HRGN hrgn, hrgn2;
@ -349,12 +351,35 @@ static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sh
patblt_clips[i].bottom - patblt_clips[i].top, PATCOPY);
}
compare_hash(bmi, bits, sha1, "clipped patblt");
memset(bits, 0xcc, dib_size);
/* clipped dashed lines */
dashed_pen = CreatePen(PS_DASH, 1, RGB(0xff, 0, 0));
SelectObject(hdc, dashed_pen);
SetBkMode(hdc, TRANSPARENT);
SetBkColor(hdc, RGB(0, 0xff, 0));
for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
{
MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL);
LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom);
}
compare_hash(bmi, bits, sha1, "clipped dashed hlines");
memset(bits, 0xcc, dib_size);
for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
{
MoveToEx(hdc, hline_clips[i].right - 1, hline_clips[i].bottom, NULL);
LineTo(hdc, hline_clips[i].left - 1, hline_clips[i].top);
}
compare_hash(bmi, bits, sha1, "clipped dashed hlines r -> l");
memset(bits, 0xcc, dib_size);
ExtSelectClipRgn(hdc, NULL, RGN_COPY);
SelectObject(hdc, orig_brush);
SelectObject(hdc, orig_pen);
DeleteObject(dashed_pen);
DeleteObject(solid_brush);
DeleteObject(solid_pen);
}