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
69a807c6
Commit
69a807c6
authored
Jul 06, 2007
by
Evan Stade
Committed by
Alexandre Julliard
Jul 09, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gdiplus: Added linecap rendering for GdipDrawBezier.
parent
5128e5dc
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
83 additions
and
6 deletions
+83
-6
graphics.c
dlls/gdiplus/graphics.c
+83
-6
No files found.
dlls/gdiplus/graphics.c
View file @
69a807c6
...
...
@@ -32,6 +32,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
/* looks-right constants */
#define TENSION_CONST (0.3)
#define ANCHOR_WIDTH (2.0)
#define MAX_ITERS (50)
static
inline
INT
roundr
(
REAL
x
)
{
...
...
@@ -317,6 +318,72 @@ static void draw_polyline(HDC hdc, GpPen *pen, GDIPCONST GpPointF * pt,
GdipFree
(
pti
);
}
/* Conducts a linear search to find the bezier points that will back off
* the endpoint of the curve by a distance of amt. Linear search works
* better than binary in this case because there are multiple solutions,
* and binary searches often find a bad one. I don't think this is what
* Windows does but short of rendering the bezier without GDI's help it's
* the best we can do. */
static
void
shorten_bezier_amt
(
GpPointF
*
pt
,
REAL
amt
)
{
GpPointF
origpt
[
4
];
REAL
percent
=
0
.
00
,
dx
,
dy
,
origx
=
pt
[
3
].
X
,
origy
=
pt
[
3
].
Y
,
diff
=
-
1
.
0
;
INT
i
;
memcpy
(
origpt
,
pt
,
sizeof
(
GpPointF
)
*
4
);
for
(
i
=
0
;
(
i
<
MAX_ITERS
)
&&
(
diff
<
amt
);
i
++
){
/* reset bezier points to original values */
memcpy
(
pt
,
origpt
,
sizeof
(
GpPointF
)
*
4
);
/* Perform magic on bezier points. Order is important here.*/
shorten_line_percent
(
pt
[
2
].
X
,
pt
[
2
].
Y
,
&
pt
[
3
].
X
,
&
pt
[
3
].
Y
,
percent
);
shorten_line_percent
(
pt
[
1
].
X
,
pt
[
1
].
Y
,
&
pt
[
2
].
X
,
&
pt
[
2
].
Y
,
percent
);
shorten_line_percent
(
pt
[
2
].
X
,
pt
[
2
].
Y
,
&
pt
[
3
].
X
,
&
pt
[
3
].
Y
,
percent
);
shorten_line_percent
(
pt
[
0
].
X
,
pt
[
0
].
Y
,
&
pt
[
1
].
X
,
&
pt
[
1
].
Y
,
percent
);
shorten_line_percent
(
pt
[
1
].
X
,
pt
[
1
].
Y
,
&
pt
[
2
].
X
,
&
pt
[
2
].
Y
,
percent
);
shorten_line_percent
(
pt
[
2
].
X
,
pt
[
2
].
Y
,
&
pt
[
3
].
X
,
&
pt
[
3
].
Y
,
percent
);
dx
=
pt
[
3
].
X
-
origx
;
dy
=
pt
[
3
].
Y
-
origy
;
diff
=
sqrt
(
dx
*
dx
+
dy
*
dy
);
percent
+=
0
.
0005
*
amt
;
}
}
/* Draws bezier curves between 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_polybezier
(
HDC
hdc
,
GpPen
*
pen
,
GDIPCONST
GpPointF
*
pt
,
INT
count
,
BOOL
caps
)
{
POINT
*
pti
=
GdipAlloc
(
count
*
sizeof
(
POINT
));
GpPointF
*
ptf
=
GdipAlloc
(
4
*
sizeof
(
GpPointF
));
INT
i
;
memcpy
(
ptf
,
&
pt
[
count
-
4
],
4
*
sizeof
(
GpPointF
));
if
(
caps
){
if
(
pen
->
endcap
==
LineCapArrowAnchor
)
shorten_bezier_amt
(
ptf
,
pen
->
width
);
draw_cap
(
hdc
,
pen
->
color
,
pen
->
endcap
,
pen
->
width
,
ptf
[
3
].
X
,
ptf
[
3
].
Y
,
pt
[
count
-
1
].
X
,
pt
[
count
-
1
].
Y
);
}
for
(
i
=
0
;
i
<
count
-
4
;
i
++
){
pti
[
i
].
x
=
roundr
(
pt
[
i
].
X
);
pti
[
i
].
y
=
roundr
(
pt
[
i
].
Y
);
}
for
(
i
=
0
;
i
<
4
;
i
++
){
pti
[
i
].
x
=
roundr
(
ptf
[
i
].
X
);
pti
[
i
].
y
=
roundr
(
ptf
[
i
].
Y
);
}
PolyBezier
(
hdc
,
pti
,
count
);
GdipFree
(
pti
);
GdipFree
(
ptf
);
}
GpStatus
WINGDIPAPI
GdipCreateFromHDC
(
HDC
hdc
,
GpGraphics
**
graphics
)
{
if
(
hdc
==
NULL
)
...
...
@@ -385,18 +452,28 @@ GpStatus WINGDIPAPI GdipDrawArc(GpGraphics *graphics, GpPen *pen, REAL x,
GpStatus
WINGDIPAPI
GdipDrawBezier
(
GpGraphics
*
graphics
,
GpPen
*
pen
,
REAL
x1
,
REAL
y1
,
REAL
x2
,
REAL
y2
,
REAL
x3
,
REAL
y3
,
REAL
x4
,
REAL
y4
)
{
HGDIOBJ
old_pen
;
POINT
pt
[
4
]
=
{{
roundr
(
x1
),
roundr
(
y1
)},
{
roundr
(
x2
),
roundr
(
y2
)},
{
roundr
(
x3
),
roundr
(
y3
)},
{
roundr
(
x4
),
roundr
(
y4
)}};
INT
save_state
;
GpPointF
pt
[
4
];
if
(
!
graphics
||
!
pen
)
return
InvalidParameter
;
old_pen
=
SelectObject
(
graphics
->
hdc
,
pen
->
gdipen
);
pt
[
0
].
X
=
x1
;
pt
[
0
].
Y
=
y1
;
pt
[
1
].
X
=
x2
;
pt
[
1
].
Y
=
y2
;
pt
[
2
].
X
=
x3
;
pt
[
2
].
Y
=
y3
;
pt
[
3
].
X
=
x4
;
pt
[
3
].
Y
=
y4
;
PolyBezier
(
graphics
->
hdc
,
pt
,
4
);
save_state
=
SaveDC
(
graphics
->
hdc
);
EndPath
(
graphics
->
hdc
);
SelectObject
(
graphics
->
hdc
,
pen
->
gdipen
);
SelectObject
(
graphics
->
hdc
,
old_pen
);
draw_polybezier
(
graphics
->
hdc
,
pen
,
pt
,
4
,
TRUE
);
RestoreDC
(
graphics
->
hdc
,
save_state
);
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