Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
7c235156
Commit
7c235156
authored
Dec 22, 2011
by
Huw Davies
Committed by
Alexandre Julliard
Dec 22, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gdi32: Add support for geometric solid pens.
parent
0c1574bd
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
155 additions
and
18 deletions
+155
-18
objects.c
dlls/gdi32/dibdrv/objects.c
+155
-18
No files found.
dlls/gdi32/dibdrv/objects.c
View file @
7c235156
...
...
@@ -999,18 +999,27 @@ static BOOL null_pen_lines(dibdrv_physdev *pdev, int num, POINT *pts, BOOL close
return
TRUE
;
}
struct
face
{
POINT
start
,
end
;
int
dx
,
dy
;
};
static
void
add_cap
(
dibdrv_physdev
*
pdev
,
HRGN
region
,
const
POINT
*
pt
)
{
HRGN
cap
;
switch
(
pdev
->
pen_endcap
)
{
default:
FIXME
(
"Unknown end cap %x
\n
"
,
pdev
->
pen_endcap
);
/* fall through */
case
PS_ENDCAP_ROUND
:
cap
=
CreateEllipticRgn
(
pt
->
x
-
pdev
->
pen_width
/
2
,
pt
->
y
-
pdev
->
pen_width
/
2
,
pt
->
x
+
(
pdev
->
pen_width
+
1
)
/
2
,
pt
->
y
+
(
pdev
->
pen_width
+
1
)
/
2
);
break
;
default:
/* only supporting cosmetic pens so far, so always PS_ENDCAP_ROUND */
case
PS_ENDCAP_SQUARE
:
/* already been handled */
case
PS_ENDCAP_FLAT
:
return
;
}
...
...
@@ -1019,19 +1028,92 @@ static void add_cap( dibdrv_physdev *pdev, HRGN region, const POINT *pt )
return
;
}
static
void
add_join
(
dibdrv_physdev
*
pdev
,
HRGN
region
,
const
POINT
*
pt
)
#define round( f ) (((f) > 0) ? (f) + 0.5 : (f) - 0.5)
/*******************************************************************************
* create_miter_region
*
* We need to calculate the intersection of two lines. We know a point
* on each line (a face start and the other face end point) and
* the direction vector of each line eg. (dx_1, dy_1).
*
* (x, y) = (x_1, y_1) + u * (dx_1, dy_1) = (x_2, y_2) + v * (dx_2, dy_2)
* solving (eg using Cramer's rule) gives:
* u = ((x_2 - x_1) dy_2 - (y_2 - y_1) dx_2) / det
* with det = dx_1 dy_2 - dx_2 dy_1
* substituting back in and simplifying gives
* (x, y) = a (dx_1, dy_1) - b (dx_2, dy_2)
* with a = (x_2 dy_2 - y_2 dx_2) / det
* and b = (x_1 dy_1 - y_1 dx_1) / det
*/
static
HRGN
create_miter_region
(
dibdrv_physdev
*
pdev
,
const
POINT
*
pt
,
const
struct
face
*
face_1
,
const
struct
face
*
face_2
)
{
int
det
=
face_1
->
dx
*
face_2
->
dy
-
face_1
->
dy
*
face_2
->
dx
;
POINT
pt_1
,
pt_2
,
pts
[
5
];
double
a
,
b
,
x
,
y
;
FLOAT
limit
;
if
(
det
==
0
)
return
0
;
if
(
det
<
0
)
{
const
struct
face
*
tmp
=
face_1
;
face_1
=
face_2
;
face_2
=
tmp
;
det
=
-
det
;
}
pt_1
=
face_1
->
start
;
pt_2
=
face_2
->
end
;
a
=
(
double
)((
pt_2
.
x
*
face_2
->
dy
-
pt_2
.
y
*
face_2
->
dx
))
/
det
;
b
=
(
double
)((
pt_1
.
x
*
face_1
->
dy
-
pt_1
.
y
*
face_1
->
dx
))
/
det
;
x
=
a
*
face_1
->
dx
-
b
*
face_2
->
dx
;
y
=
a
*
face_1
->
dy
-
b
*
face_2
->
dy
;
GetMiterLimit
(
pdev
->
dev
.
hdc
,
&
limit
);
if
(((
x
-
pt
->
x
)
*
(
x
-
pt
->
x
)
+
(
y
-
pt
->
y
)
*
(
y
-
pt
->
y
))
*
4
>
limit
*
limit
*
pdev
->
pen_width
*
pdev
->
pen_width
)
return
0
;
pts
[
0
]
=
face_2
->
start
;
pts
[
1
]
=
face_1
->
start
;
pts
[
2
].
x
=
round
(
x
);
pts
[
2
].
y
=
round
(
y
);
pts
[
3
]
=
face_2
->
end
;
pts
[
4
]
=
face_1
->
end
;
return
CreatePolygonRgn
(
pts
,
5
,
ALTERNATE
);
}
static
void
add_join
(
dibdrv_physdev
*
pdev
,
HRGN
region
,
const
POINT
*
pt
,
const
struct
face
*
face_1
,
const
struct
face
*
face_2
)
{
HRGN
join
;
POINT
pts
[
4
];
switch
(
pdev
->
pen_join
)
{
default:
FIXME
(
"Unknown line join %x
\n
"
,
pdev
->
pen_join
);
/* fall through */
case
PS_JOIN_ROUND
:
join
=
CreateEllipticRgn
(
pt
->
x
-
pdev
->
pen_width
/
2
,
pt
->
y
-
pdev
->
pen_width
/
2
,
pt
->
x
+
(
pdev
->
pen_width
+
1
)
/
2
,
pt
->
y
+
(
pdev
->
pen_width
+
1
)
/
2
);
break
;
default:
/* only supporting cosmetic pens so far, so always PS_JOIN_ROUND */
return
;
case
PS_JOIN_MITER
:
join
=
create_miter_region
(
pdev
,
pt
,
face_1
,
face_2
);
if
(
join
)
break
;
/* fall through */
case
PS_JOIN_BEVEL
:
pts
[
0
]
=
face_1
->
start
;
pts
[
1
]
=
face_2
->
end
;
pts
[
2
]
=
face_1
->
end
;
pts
[
3
]
=
face_2
->
start
;
join
=
CreatePolygonRgn
(
pts
,
4
,
ALTERNATE
);
break
;
}
CombineRgn
(
region
,
region
,
join
,
RGN_OR
);
...
...
@@ -1039,8 +1121,6 @@ static void add_join( dibdrv_physdev *pdev, HRGN region, const POINT *pt )
return
;
}
#define round( f ) (((f) > 0) ? (f) + 0.5 : (f) - 0.5)
static
HRGN
get_wide_lines_region
(
dibdrv_physdev
*
pdev
,
int
num
,
POINT
*
pts
,
BOOL
close
)
{
int
i
;
...
...
@@ -1058,6 +1138,11 @@ static HRGN get_wide_lines_region( dibdrv_physdev *pdev, int num, POINT *pts, BO
int
dx
=
pt_2
->
x
-
pt_1
->
x
;
int
dy
=
pt_2
->
y
-
pt_1
->
y
;
RECT
rect
;
struct
face
face_1
,
face_2
,
prev_face
,
first_face
;
BOOL
need_cap_1
=
!
close
&&
(
i
==
0
);
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
;
...
...
@@ -1067,7 +1152,23 @@ static HRGN get_wide_lines_region( dibdrv_physdev *pdev, int num, POINT *pts, BO
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
;
segment
=
CreateRectRgnIndirect
(
&
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
)
{
...
...
@@ -1075,7 +1176,23 @@ static HRGN get_wide_lines_region( dibdrv_physdev *pdev, int num, POINT *pts, BO
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
;
segment
=
CreateRectRgnIndirect
(
&
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
{
...
...
@@ -1114,25 +1231,46 @@ static HRGN get_wide_lines_region( dibdrv_physdev *pdev, int num, POINT *pts, BO
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
);
face_1
.
start
=
seg_pts
[
0
];
face_1
.
end
=
seg_pts
[
1
];
face_2
.
start
=
seg_pts
[
2
];
face_2
.
end
=
seg_pts
[
3
];
}
CombineRgn
(
total
,
total
,
segment
,
RGN_OR
);
DeleteObject
(
segment
);
if
(
i
==
0
)
{
if
(
!
close
)
add_cap
(
pdev
,
total
,
pt_1
);
}
else
add_join
(
pdev
,
total
,
pt_1
);
if
(
need_cap_1
)
add_cap
(
pdev
,
total
,
pt_1
);
if
(
need_cap_2
)
add_cap
(
pdev
,
total
,
pt_2
);
if
(
i
==
num
-
1
)
{
if
(
close
)
add_join
(
pdev
,
total
,
pt_2
);
else
add_cap
(
pdev
,
total
,
pt_2
);
}
face_1
.
dx
=
face_2
.
dx
=
dx
;
face_1
.
dy
=
face_2
.
dy
=
dy
;
if
(
i
==
0
)
first_face
=
face_1
;
else
add_join
(
pdev
,
total
,
pt_1
,
&
prev_face
,
&
face_1
);
if
(
i
==
num
-
1
&&
close
)
add_join
(
pdev
,
total
,
pt_2
,
&
face_2
,
&
first_face
);
prev_face
=
face_2
;
}
return
total
;
}
...
...
@@ -1235,7 +1373,6 @@ HPEN dibdrv_SelectPen( PHYSDEV dev, HPEN hpen )
switch
(
style
)
{
case
PS_SOLID
:
if
(
logpen
.
lopnStyle
&
PS_GEOMETRIC
)
break
;
if
(
pdev
->
pen_width
<=
1
)
pdev
->
pen_lines
=
solid_pen_lines
;
else
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment