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
5128e5dc
Commit
5128e5dc
authored
Jul 07, 2007
by
Evan Stade
Committed by
Alexandre Julliard
Jul 09, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gdiplus: Rendering of linecaps.
parent
0a6f6874
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
217 additions
and
8 deletions
+217
-8
graphics.c
dlls/gdiplus/graphics.c
+217
-3
pen.c
dlls/gdiplus/pen.c
+0
-5
No files found.
dlls/gdiplus/graphics.c
View file @
5128e5dc
...
...
@@ -27,8 +27,11 @@
#include "gdiplus_private.h"
#include "wine/debug.h"
/* looks-right constant */
WINE_DEFAULT_DEBUG_CHANNEL
(
gdiplus
);
/* looks-right constants */
#define TENSION_CONST (0.3)
#define ANCHOR_WIDTH (2.0)
static
inline
INT
roundr
(
REAL
x
)
{
...
...
@@ -108,6 +111,212 @@ static void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
*
y
=
roundr
(
tension
*
(
yadj
-
yend
)
+
yend
);
}
/* Draws the linecap the specified color and size on the hdc. The linecap is in
* direction of the line from x1, y1 to x2, y2 and is anchored on x2, y2. */
static
void
draw_cap
(
HDC
hdc
,
COLORREF
color
,
GpLineCap
cap
,
REAL
size
,
REAL
x1
,
REAL
y1
,
REAL
x2
,
REAL
y2
)
{
HGDIOBJ
oldbrush
,
oldpen
;
HBRUSH
brush
;
HPEN
pen
;
POINT
pt
[
4
];
REAL
theta
,
dsmall
,
dbig
,
dx
,
dy
,
invert
;
if
(
x2
!=
x1
)
theta
=
atan
((
y2
-
y1
)
/
(
x2
-
x1
));
else
if
(
y2
!=
y1
){
theta
=
M_PI_2
*
(
y2
>
y1
?
1
.
0
:
-
1
.
0
);
}
else
return
;
invert
=
((
x2
-
x1
)
>=
0
.
0
?
1
.
0
:
-
1
.
0
);
brush
=
CreateSolidBrush
(
color
);
pen
=
CreatePen
(
PS_SOLID
,
1
,
color
);
oldbrush
=
SelectObject
(
hdc
,
brush
);
oldpen
=
SelectObject
(
hdc
,
pen
);
switch
(
cap
){
case
LineCapFlat
:
break
;
case
LineCapSquare
:
case
LineCapSquareAnchor
:
case
LineCapDiamondAnchor
:
size
=
size
*
(
cap
&
LineCapNoAnchor
?
ANCHOR_WIDTH
:
1
.
0
)
/
2
.
0
;
if
(
cap
==
LineCapDiamondAnchor
){
dsmall
=
cos
(
theta
+
M_PI_2
)
*
size
;
dbig
=
sin
(
theta
+
M_PI_2
)
*
size
;
}
else
{
dsmall
=
cos
(
theta
+
M_PI_4
)
*
size
;
dbig
=
sin
(
theta
+
M_PI_4
)
*
size
;
}
/* calculating the latter points from the earlier points makes them
* look a little better because of rounding issues */
pt
[
0
].
x
=
roundr
(
x2
-
dsmall
);
pt
[
1
].
x
=
roundr
(((
REAL
)
pt
[
0
].
x
)
+
dbig
+
dsmall
);
pt
[
0
].
y
=
roundr
(
y2
-
dbig
);
pt
[
3
].
y
=
roundr
(((
REAL
)
pt
[
0
].
y
)
+
dsmall
+
dbig
);
pt
[
1
].
y
=
roundr
(
y2
-
dsmall
);
pt
[
2
].
y
=
roundr
(
dbig
+
dsmall
+
((
REAL
)
pt
[
1
].
y
));
pt
[
3
].
x
=
roundr
(
x2
-
dbig
);
pt
[
2
].
x
=
roundr
(((
REAL
)
pt
[
3
].
x
)
+
dsmall
+
dbig
);
Polygon
(
hdc
,
pt
,
4
);
break
;
case
LineCapArrowAnchor
:
size
=
size
*
4
.
0
/
sqrt
(
3
.
0
);
dx
=
cos
(
M_PI
/
6
.
0
+
theta
)
*
size
*
invert
;
dy
=
sin
(
M_PI
/
6
.
0
+
theta
)
*
size
*
invert
;
pt
[
0
].
x
=
roundr
(
x2
-
dx
);
pt
[
0
].
y
=
roundr
(
y2
-
dy
);
dx
=
cos
(
-
M_PI
/
6
.
0
+
theta
)
*
size
*
invert
;
dy
=
sin
(
-
M_PI
/
6
.
0
+
theta
)
*
size
*
invert
;
pt
[
1
].
x
=
roundr
(
x2
-
dx
);
pt
[
1
].
y
=
roundr
(
y2
-
dy
);
pt
[
2
].
x
=
roundr
(
x2
);
pt
[
2
].
y
=
roundr
(
y2
);
Polygon
(
hdc
,
pt
,
3
);
break
;
case
LineCapRoundAnchor
:
dx
=
dy
=
ANCHOR_WIDTH
*
size
/
2
.
0
;
x2
=
(
REAL
)
roundr
(
x2
-
dx
);
y2
=
(
REAL
)
roundr
(
y2
-
dy
);
Ellipse
(
hdc
,
(
INT
)
x2
,
(
INT
)
y2
,
roundr
(
x2
+
2
.
0
*
dx
),
roundr
(
y2
+
2
.
0
*
dy
));
break
;
case
LineCapTriangle
:
size
=
size
/
2
.
0
;
dx
=
cos
(
M_PI_2
+
theta
)
*
size
;
dy
=
sin
(
M_PI_2
+
theta
)
*
size
;
/* Using roundr here can make the triangle float off the end of the
* line. */
pt
[
0
].
x
=
((
x2
-
x1
)
>=
0
?
floor
(
x2
-
dx
)
:
ceil
(
x2
-
dx
));
pt
[
0
].
y
=
((
y2
-
y1
)
>=
0
?
floor
(
y2
-
dy
)
:
ceil
(
y2
-
dy
));
pt
[
1
].
x
=
roundr
(
pt
[
0
].
x
+
2
.
0
*
dx
);
pt
[
1
].
y
=
roundr
(
pt
[
0
].
y
+
2
.
0
*
dy
);
dx
=
cos
(
theta
)
*
size
*
invert
;
dy
=
sin
(
theta
)
*
size
*
invert
;
pt
[
2
].
x
=
roundr
(
x2
+
dx
);
pt
[
2
].
y
=
roundr
(
y2
+
dy
);
Polygon
(
hdc
,
pt
,
3
);
break
;
case
LineCapRound
:
dx
=
-
cos
(
M_PI_2
+
theta
)
*
size
*
invert
;
dy
=
-
sin
(
M_PI_2
+
theta
)
*
size
*
invert
;
pt
[
0
].
x
=
((
x2
-
x1
)
>=
0
?
floor
(
x2
-
dx
)
:
ceil
(
x2
-
dx
));
pt
[
0
].
y
=
((
y2
-
y1
)
>=
0
?
floor
(
y2
-
dy
)
:
ceil
(
y2
-
dy
));
pt
[
1
].
x
=
roundr
(
pt
[
0
].
x
+
2
.
0
*
dx
);
pt
[
1
].
y
=
roundr
(
pt
[
0
].
y
+
2
.
0
*
dy
);
dx
=
dy
=
size
/
2
.
0
;
x2
=
(
REAL
)
roundr
(
x2
-
dx
);
y2
=
(
REAL
)
roundr
(
y2
-
dy
);
Pie
(
hdc
,
(
INT
)
x2
,
(
INT
)
y2
,
roundr
(
x2
+
2
.
0
*
dx
),
roundr
(
y2
+
2
.
0
*
dy
),
pt
[
0
].
x
,
pt
[
0
].
y
,
pt
[
1
].
x
,
pt
[
1
].
y
);
break
;
case
LineCapCustom
:
FIXME
(
"line cap not implemented
\n
"
);
default:
break
;
}
SelectObject
(
hdc
,
oldbrush
);
SelectObject
(
hdc
,
oldpen
);
DeleteObject
(
brush
);
DeleteObject
(
pen
);
}
/* Shortens the line by the given percent by changing x2, y2.
* If percent is > 1.0 then the line will change direction. */
static
void
shorten_line_percent
(
REAL
x1
,
REAL
y1
,
REAL
*
x2
,
REAL
*
y2
,
REAL
percent
)
{
REAL
dist
,
theta
,
dx
,
dy
;
if
((
y1
==
*
y2
)
&&
(
x1
==
*
x2
))
return
;
dist
=
sqrt
((
*
x2
-
x1
)
*
(
*
x2
-
x1
)
+
(
*
y2
-
y1
)
*
(
*
y2
-
y1
))
*
percent
;
theta
=
(
*
x2
==
x1
?
M_PI_2
:
atan
((
*
y2
-
y1
)
/
(
*
x2
-
x1
)));
dx
=
cos
(
theta
)
*
dist
;
dy
=
sin
(
theta
)
*
dist
;
*
x2
=
*
x2
+
fabs
(
dx
)
*
(
*
x2
>
x1
?
-
1
.
0
:
1
.
0
);
*
y2
=
*
y2
+
fabs
(
dy
)
*
(
*
y2
>
y1
?
-
1
.
0
:
1
.
0
);
}
/* Shortens the line by the given amount by changing x2, y2.
* If the amount is greater than the distance, the line will become length 0. */
static
void
shorten_line_amt
(
REAL
x1
,
REAL
y1
,
REAL
*
x2
,
REAL
*
y2
,
REAL
amt
)
{
REAL
dx
,
dy
,
percent
;
dx
=
*
x2
-
x1
;
dy
=
*
y2
-
y1
;
if
(
dx
==
0
&&
dy
==
0
)
return
;
percent
=
amt
/
sqrt
(
dx
*
dx
+
dy
*
dy
);
if
(
percent
>=
1
.
0
){
*
x2
=
x1
;
*
y2
=
y1
;
return
;
}
shorten_line_percent
(
x1
,
y1
,
x2
,
y2
,
percent
);
}
/* Draws lines between the given points, and if caps is true then draws an endcap
* at the end of the last line. FIXME: Startcaps not implemented. */
static
void
draw_polyline
(
HDC
hdc
,
GpPen
*
pen
,
GDIPCONST
GpPointF
*
pt
,
INT
count
,
BOOL
caps
)
{
POINT
*
pti
=
GdipAlloc
(
count
*
sizeof
(
POINT
));
REAL
x
=
pt
[
count
-
1
].
X
,
y
=
pt
[
count
-
1
].
Y
;
INT
i
;
if
(
caps
){
if
(
pen
->
endcap
==
LineCapArrowAnchor
)
shorten_line_amt
(
pt
[
count
-
2
].
X
,
pt
[
count
-
2
].
Y
,
&
x
,
&
y
,
pen
->
width
);
draw_cap
(
hdc
,
pen
->
color
,
pen
->
endcap
,
pen
->
width
,
pt
[
count
-
2
].
X
,
pt
[
count
-
2
].
Y
,
pt
[
count
-
1
].
X
,
pt
[
count
-
1
].
Y
);
}
for
(
i
=
0
;
i
<
count
-
1
;
i
++
){
pti
[
i
].
x
=
roundr
(
pt
[
i
].
X
);
pti
[
i
].
y
=
roundr
(
pt
[
i
].
Y
);
}
pti
[
i
].
x
=
roundr
(
x
);
pti
[
i
].
y
=
roundr
(
y
);
Polyline
(
hdc
,
pti
,
count
);
GdipFree
(
pti
);
}
GpStatus
WINGDIPAPI
GdipCreateFromHDC
(
HDC
hdc
,
GpGraphics
**
graphics
)
{
if
(
hdc
==
NULL
)
...
...
@@ -248,16 +457,21 @@ GpStatus WINGDIPAPI GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1,
INT
y1
,
INT
x2
,
INT
y2
)
{
INT
save_state
;
GpPointF
pt
[
2
];
if
(
!
pen
||
!
graphics
)
return
InvalidParameter
;
pt
[
0
].
X
=
(
REAL
)
x1
;
pt
[
0
].
Y
=
(
REAL
)
y1
;
pt
[
1
].
X
=
(
REAL
)
x2
;
pt
[
1
].
Y
=
(
REAL
)
y2
;
save_state
=
SaveDC
(
graphics
->
hdc
);
EndPath
(
graphics
->
hdc
);
SelectObject
(
graphics
->
hdc
,
pen
->
gdipen
);
MoveToEx
(
graphics
->
hdc
,
x1
,
y1
,
NULL
);
LineTo
(
graphics
->
hdc
,
x2
,
y2
);
draw_polyline
(
graphics
->
hdc
,
pen
,
pt
,
2
,
TRUE
);
RestoreDC
(
graphics
->
hdc
,
save_state
);
...
...
dlls/gdiplus/pen.c
View file @
5128e5dc
...
...
@@ -77,11 +77,6 @@ GpStatus WINGDIPAPI GdipSetPenEndCap(GpPen *pen, GpLineCap cap)
{
if
(
!
pen
)
return
InvalidParameter
;
if
(
cap
!=
LineCapFlat
){
FIXME
(
"Not implemented for non-flat EndCap
\n
"
);
return
NotImplemented
;
}
pen
->
endcap
=
cap
;
return
Ok
;
...
...
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