gdi32: Add support for drawing horizontal patterned lines.
This commit is contained in:
parent
54397f1552
commit
6976cee425
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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] =
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue