gdi32: Add a helper function for drawing a wide line segment.
This commit is contained in:
parent
8b1bab524b
commit
a59c53b312
|
@ -1326,6 +1326,132 @@ static void add_join( dibdrv_physdev *pdev, HRGN region, HRGN round_cap, const P
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wide_line_segment( dibdrv_physdev *pdev, HRGN total,
|
||||||
|
const POINT *pt_1, const POINT *pt_2, int dx, int dy,
|
||||||
|
BOOL need_cap_1, BOOL need_cap_2, struct face *face_1, struct face *face_2 )
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
BOOL sq_cap_1 = need_cap_1 && (pdev->pen_endcap == PS_ENDCAP_SQUARE);
|
||||||
|
BOOL sq_cap_2 = need_cap_2 && (pdev->pen_endcap == PS_ENDCAP_SQUARE);
|
||||||
|
|
||||||
|
if (dx == 0 && dy == 0) return;
|
||||||
|
|
||||||
|
if (dy == 0)
|
||||||
|
{
|
||||||
|
rect.left = min( pt_1->x, pt_2->x );
|
||||||
|
rect.right = max( pt_1->x, pt_2->x );
|
||||||
|
rect.top = pt_1->y - pdev->pen_width / 2;
|
||||||
|
rect.bottom = rect.top + pdev->pen_width;
|
||||||
|
if ((sq_cap_1 && dx > 0) || (sq_cap_2 && dx < 0)) rect.left -= pdev->pen_width / 2;
|
||||||
|
if ((sq_cap_2 && dx > 0) || (sq_cap_1 && dx < 0)) rect.right += pdev->pen_width / 2;
|
||||||
|
add_rect_to_region( total, &rect );
|
||||||
|
if (dx > 0)
|
||||||
|
{
|
||||||
|
face_1->start.x = face_1->end.x = rect.left;
|
||||||
|
face_1->start.y = face_2->end.y = rect.bottom;
|
||||||
|
face_1->end.y = face_2->start.y = rect.top;
|
||||||
|
face_2->start.x = face_2->end.x = rect.right - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
face_1->start.x = face_1->end.x = rect.right;
|
||||||
|
face_1->start.y = face_2->end.y = rect.top;
|
||||||
|
face_1->end.y = face_2->start.y = rect.bottom;
|
||||||
|
face_2->start.x = face_2->end.x = rect.left + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dx == 0)
|
||||||
|
{
|
||||||
|
rect.top = min( pt_1->y, pt_2->y );
|
||||||
|
rect.bottom = max( pt_1->y, pt_2->y );
|
||||||
|
rect.left = pt_1->x - pdev->pen_width / 2;
|
||||||
|
rect.right = rect.left + pdev->pen_width;
|
||||||
|
if ((sq_cap_1 && dy > 0) || (sq_cap_2 && dy < 0)) rect.top -= pdev->pen_width / 2;
|
||||||
|
if ((sq_cap_2 && dy > 0) || (sq_cap_1 && dy < 0)) rect.bottom += pdev->pen_width / 2;
|
||||||
|
add_rect_to_region( total, &rect );
|
||||||
|
if (dy > 0)
|
||||||
|
{
|
||||||
|
face_1->start.x = face_2->end.x = rect.left;
|
||||||
|
face_1->start.y = face_1->end.y = rect.top;
|
||||||
|
face_1->end.x = face_2->start.x = rect.right;
|
||||||
|
face_2->start.y = face_2->end.y = rect.bottom - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
face_1->start.x = face_2->end.x = rect.right;
|
||||||
|
face_1->start.y = face_1->end.y = rect.bottom;
|
||||||
|
face_1->end.x = face_2->start.x = rect.left;
|
||||||
|
face_2->start.y = face_2->end.y = rect.top + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double len = hypot( dx, dy );
|
||||||
|
double width_x, width_y;
|
||||||
|
POINT seg_pts[4];
|
||||||
|
POINT wide_half, narrow_half;
|
||||||
|
HRGN segment;
|
||||||
|
|
||||||
|
width_x = pdev->pen_width * abs( dy ) / len;
|
||||||
|
width_y = pdev->pen_width * abs( dx ) / len;
|
||||||
|
|
||||||
|
narrow_half.x = round( width_x / 2 );
|
||||||
|
narrow_half.y = round( width_y / 2 );
|
||||||
|
wide_half.x = round( (width_x + 1) / 2 );
|
||||||
|
wide_half.y = round( (width_y + 1) / 2 );
|
||||||
|
|
||||||
|
if (dx < 0)
|
||||||
|
{
|
||||||
|
wide_half.y = -wide_half.y;
|
||||||
|
narrow_half.y = -narrow_half.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dy < 0)
|
||||||
|
{
|
||||||
|
POINT tmp = narrow_half; narrow_half = wide_half; wide_half = tmp;
|
||||||
|
wide_half.x = -wide_half.x;
|
||||||
|
narrow_half.x = -narrow_half.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
seg_pts[0].x = pt_1->x - narrow_half.x;
|
||||||
|
seg_pts[0].y = pt_1->y + narrow_half.y;
|
||||||
|
seg_pts[1].x = pt_1->x + wide_half.x;
|
||||||
|
seg_pts[1].y = pt_1->y - wide_half.y;
|
||||||
|
seg_pts[2].x = pt_2->x + wide_half.x;
|
||||||
|
seg_pts[2].y = pt_2->y - wide_half.y;
|
||||||
|
seg_pts[3].x = pt_2->x - narrow_half.x;
|
||||||
|
seg_pts[3].y = pt_2->y + narrow_half.y;
|
||||||
|
|
||||||
|
if (sq_cap_1)
|
||||||
|
{
|
||||||
|
seg_pts[0].x -= narrow_half.y;
|
||||||
|
seg_pts[1].x -= narrow_half.y;
|
||||||
|
seg_pts[0].y -= narrow_half.x;
|
||||||
|
seg_pts[1].y -= narrow_half.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sq_cap_2)
|
||||||
|
{
|
||||||
|
seg_pts[2].x += wide_half.y;
|
||||||
|
seg_pts[3].x += wide_half.y;
|
||||||
|
seg_pts[2].y += wide_half.x;
|
||||||
|
seg_pts[3].y += wide_half.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
segment = CreatePolygonRgn( seg_pts, 4, ALTERNATE );
|
||||||
|
CombineRgn( total, total, segment, RGN_OR );
|
||||||
|
DeleteObject( segment );
|
||||||
|
|
||||||
|
face_1->start = seg_pts[0];
|
||||||
|
face_1->end = seg_pts[1];
|
||||||
|
face_2->start = seg_pts[2];
|
||||||
|
face_2->end = seg_pts[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
face_1->dx = face_2->dx = dx;
|
||||||
|
face_1->dy = face_2->dy = dy;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL wide_pen_lines(dibdrv_physdev *pdev, int num, POINT *pts, BOOL close, HRGN total)
|
static BOOL wide_pen_lines(dibdrv_physdev *pdev, int num, POINT *pts, BOOL close, HRGN total)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1349,133 +1475,15 @@ static BOOL wide_pen_lines(dibdrv_physdev *pdev, int num, POINT *pts, BOOL close
|
||||||
const POINT *pt_2 = pts + ((close && i == num - 1) ? 0 : i + 1);
|
const POINT *pt_2 = pts + ((close && i == num - 1) ? 0 : i + 1);
|
||||||
int dx = pt_2->x - pt_1->x;
|
int dx = pt_2->x - pt_1->x;
|
||||||
int dy = pt_2->y - pt_1->y;
|
int dy = pt_2->y - pt_1->y;
|
||||||
RECT rect;
|
|
||||||
struct face face_1, face_2, prev_face, first_face;
|
struct face face_1, face_2, prev_face, first_face;
|
||||||
BOOL need_cap_1 = !close && (i == 0);
|
BOOL need_cap_1 = !close && (i == 0);
|
||||||
BOOL need_cap_2 = !close && (i == num - 1);
|
BOOL need_cap_2 = !close && (i == num - 1);
|
||||||
BOOL sq_cap_1 = need_cap_1 && (pdev->pen_endcap == PS_ENDCAP_SQUARE);
|
|
||||||
BOOL sq_cap_2 = need_cap_2 && (pdev->pen_endcap == PS_ENDCAP_SQUARE);
|
|
||||||
|
|
||||||
if (dx == 0 && dy == 0) continue;
|
wide_line_segment( pdev, total, pt_1, pt_2, dx, dy, need_cap_1, need_cap_2, &face_1, &face_2 );
|
||||||
|
|
||||||
if (dy == 0)
|
|
||||||
{
|
|
||||||
rect.left = min( pt_1->x, pt_2->x );
|
|
||||||
rect.right = rect.left + abs( dx );
|
|
||||||
rect.top = pt_1->y - pdev->pen_width / 2;
|
|
||||||
rect.bottom = rect.top + pdev->pen_width;
|
|
||||||
if ((sq_cap_1 && dx > 0) || (sq_cap_2 && dx < 0)) rect.left -= pdev->pen_width / 2;
|
|
||||||
if ((sq_cap_2 && dx > 0) || (sq_cap_1 && dx < 0)) rect.right += pdev->pen_width / 2;
|
|
||||||
add_rect_to_region( total, &rect );
|
|
||||||
if (dx > 0)
|
|
||||||
{
|
|
||||||
face_1.start.x = face_1.end.x = rect.left;
|
|
||||||
face_1.start.y = face_2.end.y = rect.bottom;
|
|
||||||
face_1.end.y = face_2.start.y = rect.top;
|
|
||||||
face_2.start.x = face_2.end.x = rect.right - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
face_1.start.x = face_1.end.x = rect.right;
|
|
||||||
face_1.start.y = face_2.end.y = rect.top;
|
|
||||||
face_1.end.y = face_2.start.y = rect.bottom;
|
|
||||||
face_2.start.x = face_2.end.x = rect.left + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (dx == 0)
|
|
||||||
{
|
|
||||||
rect.top = min( pt_1->y, pt_2->y );
|
|
||||||
rect.bottom = rect.top + abs( dy );
|
|
||||||
rect.left = pt_1->x - pdev->pen_width / 2;
|
|
||||||
rect.right = rect.left + pdev->pen_width;
|
|
||||||
if ((sq_cap_1 && dy > 0) || (sq_cap_2 && dy < 0)) rect.top -= pdev->pen_width / 2;
|
|
||||||
if ((sq_cap_2 && dy > 0) || (sq_cap_1 && dy < 0)) rect.bottom += pdev->pen_width / 2;
|
|
||||||
add_rect_to_region( total, &rect );
|
|
||||||
if (dy > 0)
|
|
||||||
{
|
|
||||||
face_1.start.x = face_2.end.x = rect.left;
|
|
||||||
face_1.start.y = face_1.end.y = rect.top;
|
|
||||||
face_1.end.x = face_2.start.x = rect.right;
|
|
||||||
face_2.start.y = face_2.end.y = rect.bottom - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
face_1.start.x = face_2.end.x = rect.right;
|
|
||||||
face_1.start.y = face_1.end.y = rect.bottom;
|
|
||||||
face_1.end.x = face_2.start.x = rect.left;
|
|
||||||
face_2.start.y = face_2.end.y = rect.top + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double len = hypot( dx, dy );
|
|
||||||
double width_x, width_y;
|
|
||||||
POINT seg_pts[4];
|
|
||||||
POINT wide_half, narrow_half;
|
|
||||||
HRGN segment;
|
|
||||||
|
|
||||||
width_x = pdev->pen_width * abs( dy ) / len;
|
|
||||||
width_y = pdev->pen_width * abs( dx ) / len;
|
|
||||||
|
|
||||||
narrow_half.x = round( width_x / 2 );
|
|
||||||
narrow_half.y = round( width_y / 2 );
|
|
||||||
wide_half.x = round( (width_x + 1) / 2 );
|
|
||||||
wide_half.y = round( (width_y + 1) / 2 );
|
|
||||||
|
|
||||||
if (dx < 0)
|
|
||||||
{
|
|
||||||
wide_half.y = -wide_half.y;
|
|
||||||
narrow_half.y = -narrow_half.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dy < 0)
|
|
||||||
{
|
|
||||||
POINT tmp = narrow_half; narrow_half = wide_half; wide_half = tmp;
|
|
||||||
wide_half.x = -wide_half.x;
|
|
||||||
narrow_half.x = -narrow_half.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
seg_pts[0].x = pt_1->x - narrow_half.x;
|
|
||||||
seg_pts[0].y = pt_1->y + narrow_half.y;
|
|
||||||
seg_pts[1].x = pt_1->x + wide_half.x;
|
|
||||||
seg_pts[1].y = pt_1->y - wide_half.y;
|
|
||||||
seg_pts[2].x = pt_2->x + wide_half.x;
|
|
||||||
seg_pts[2].y = pt_2->y - wide_half.y;
|
|
||||||
seg_pts[3].x = pt_2->x - narrow_half.x;
|
|
||||||
seg_pts[3].y = pt_2->y + narrow_half.y;
|
|
||||||
|
|
||||||
if (sq_cap_1)
|
|
||||||
{
|
|
||||||
seg_pts[0].x -= narrow_half.y;
|
|
||||||
seg_pts[1].x -= narrow_half.y;
|
|
||||||
seg_pts[0].y -= narrow_half.x;
|
|
||||||
seg_pts[1].y -= narrow_half.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sq_cap_2)
|
|
||||||
{
|
|
||||||
seg_pts[2].x += wide_half.y;
|
|
||||||
seg_pts[3].x += wide_half.y;
|
|
||||||
seg_pts[2].y += wide_half.x;
|
|
||||||
seg_pts[3].y += wide_half.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
segment = CreatePolygonRgn( seg_pts, 4, ALTERNATE );
|
|
||||||
CombineRgn( total, total, segment, RGN_OR );
|
|
||||||
DeleteObject( segment );
|
|
||||||
|
|
||||||
face_1.start = seg_pts[0];
|
|
||||||
face_1.end = seg_pts[1];
|
|
||||||
face_2.start = seg_pts[2];
|
|
||||||
face_2.end = seg_pts[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_cap_1) add_cap( pdev, total, round_cap, pt_1 );
|
if (need_cap_1) add_cap( pdev, total, round_cap, pt_1 );
|
||||||
if (need_cap_2) add_cap( pdev, total, round_cap, pt_2 );
|
if (need_cap_2) add_cap( pdev, total, round_cap, pt_2 );
|
||||||
|
|
||||||
face_1.dx = face_2.dx = dx;
|
|
||||||
face_1.dy = face_2.dy = dy;
|
|
||||||
|
|
||||||
if (i == 0) first_face = face_1;
|
if (i == 0) first_face = face_1;
|
||||||
else add_join( pdev, total, round_cap, pt_1, &prev_face, &face_1 );
|
else add_join( pdev, total, round_cap, pt_1, &prev_face, &face_1 );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue