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
1271ae3e
Commit
1271ae3e
authored
Nov 07, 2022
by
Bartosz Kosiorek
Committed by
Alexandre Julliard
Nov 23, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gdiplus: Add support for widen path with GpCustomLineCap.
Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=45273
parent
a8e87307
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
90 additions
and
8 deletions
+90
-8
gdiplus_private.h
dlls/gdiplus/gdiplus_private.h
+2
-2
graphicspath.c
dlls/gdiplus/graphicspath.c
+75
-6
graphicspath.c
dlls/gdiplus/tests/graphicspath.c
+13
-0
No files found.
dlls/gdiplus/gdiplus_private.h
View file @
1271ae3e
...
@@ -352,8 +352,8 @@ struct GpCustomLineCap{
...
@@ -352,8 +352,8 @@ struct GpCustomLineCap{
GpPathData
pathdata
;
GpPathData
pathdata
;
BOOL
fill
;
/* TRUE for fill, FALSE for stroke */
BOOL
fill
;
/* TRUE for fill, FALSE for stroke */
GpLineCap
basecap
;
/* cap used together with customLineCap */
GpLineCap
basecap
;
/* cap used together with customLineCap */
REAL
inset
;
/* how much to adjust the end of the line
*/
REAL
inset
;
/* distance between line end and cap beginning
*/
GpLineJoin
join
;
GpLineJoin
join
;
/* joins used for drawing custom cap*/
REAL
scale
;
REAL
scale
;
};
};
...
...
dlls/gdiplus/graphicspath.c
View file @
1271ae3e
...
@@ -1982,9 +1982,17 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
...
@@ -1982,9 +1982,17 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
}
}
}
}
static
void
widen_open_figure
(
const
GpPointF
*
points
,
int
start
,
int
end
,
GpPen
*
pen
,
REAL
pen_width
,
GpLineCap
start_cap
,
GpLineCap
end_cap
,
path_list_node_t
**
last_point
);
static
void
widen_closed_figure
(
const
GpPointF
*
points
,
int
start
,
int
end
,
GpPen
*
pen
,
REAL
pen_width
,
path_list_node_t
**
last_point
);
static
void
add_anchor
(
const
GpPointF
*
endpoint
,
const
GpPointF
*
nextpoint
,
static
void
add_anchor
(
const
GpPointF
*
endpoint
,
const
GpPointF
*
nextpoint
,
REAL
pen_width
,
GpLineCap
cap
,
GpCustomLineCap
*
custom
,
path_list_node_t
**
last_point
)
GpPen
*
pen
,
GpLineCap
cap
,
GpCustomLineCap
*
custom
,
path_list_node_t
**
last_point
)
{
{
REAL
pen_width
=
max
(
pen
->
width
,
2
.
0
);
switch
(
cap
)
switch
(
cap
)
{
{
default:
default:
...
@@ -2091,6 +2099,68 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint,
...
@@ -2091,6 +2099,68 @@ static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint,
endpoint
->
Y
+
perp_dy
,
PathPointTypeLine
);
endpoint
->
Y
+
perp_dy
,
PathPointTypeLine
);
break
;
break
;
}
}
case
LineCapCustom
:
{
REAL
segment_dy
=
nextpoint
->
Y
-
endpoint
->
Y
;
REAL
segment_dx
=
nextpoint
->
X
-
endpoint
->
X
;
REAL
segment_length
=
sqrtf
(
segment_dy
*
segment_dy
+
segment_dx
*
segment_dx
);
REAL
posx
,
posy
;
REAL
perp_dx
,
perp_dy
;
REAL
sina
,
cosa
;
GpPointF
*
tmp_points
;
if
(
!
custom
)
break
;
if
(
custom
->
type
==
CustomLineCapTypeAdjustableArrow
)
{
GpAdjustableArrowCap
*
arrow
=
(
GpAdjustableArrowCap
*
)
custom
;
TRACE
(
"GpAdjustableArrowCap middle_inset: %f height: %f width: %f
\n
"
,
arrow
->
middle_inset
,
arrow
->
height
,
arrow
->
width
);
}
else
TRACE
(
"GpCustomLineCap fill: %d basecap: %d inset: %f join: %d scale: %f pen_width:%f
\n
"
,
custom
->
fill
,
custom
->
basecap
,
custom
->
inset
,
custom
->
join
,
custom
->
scale
,
pen_width
);
/* Coordination where cap needs to be drawn */
posx
=
endpoint
->
X
-
pen_width
*
segment_dx
/
segment_length
;
posy
=
endpoint
->
Y
-
pen_width
*
segment_dy
/
segment_length
;
sina
=
-
pen_width
*
custom
->
scale
*
segment_dx
/
segment_length
;
cosa
=
pen_width
*
custom
->
scale
*
segment_dy
/
segment_length
;
if
(
!
custom
->
fill
)
{
tmp_points
=
heap_alloc_zero
(
custom
->
pathdata
.
Count
*
sizeof
(
GpPoint
));
if
(
!
tmp_points
)
{
ERR
(
"Out of memory
\n
"
);
return
;
}
for
(
INT
i
=
0
;
i
<
custom
->
pathdata
.
Count
;
i
++
)
{
tmp_points
[
i
].
X
=
posx
+
custom
->
pathdata
.
Points
[
i
].
X
*
cosa
+
(
custom
->
pathdata
.
Points
[
i
].
Y
-
1
.
0
)
*
sina
;
tmp_points
[
i
].
Y
=
posy
+
custom
->
pathdata
.
Points
[
i
].
X
*
sina
-
(
custom
->
pathdata
.
Points
[
i
].
Y
-
1
.
0
)
*
cosa
;
}
if
((
custom
->
pathdata
.
Types
[
custom
->
pathdata
.
Count
-
1
]
&
PathPointTypeCloseSubpath
)
==
PathPointTypeCloseSubpath
)
widen_closed_figure
(
tmp_points
,
0
,
custom
->
pathdata
.
Count
-
1
,
pen
,
pen_width
,
last_point
);
else
widen_open_figure
(
tmp_points
,
0
,
custom
->
pathdata
.
Count
-
1
,
pen
,
pen_width
,
LineCapFlat
,
LineCapFlat
,
last_point
);
}
else
{
for
(
INT
i
=
0
;
i
<
custom
->
pathdata
.
Count
;
i
++
)
{
/* rotation of CustomCap according to line */
perp_dx
=
custom
->
pathdata
.
Points
[
i
].
X
*
cosa
+
(
custom
->
pathdata
.
Points
[
i
].
Y
-
1
.
0
)
*
sina
;
perp_dy
=
custom
->
pathdata
.
Points
[
i
].
X
*
sina
-
(
custom
->
pathdata
.
Points
[
i
].
Y
-
1
.
0
)
*
cosa
;
*
last_point
=
add_path_list_node
(
*
last_point
,
posx
+
perp_dx
,
posy
+
perp_dy
,
custom
->
pathdata
.
Types
[
i
]);
}
}
/* FIXME: The line should be adjusted by the inset value of the custom cap. */
break
;
}
}
}
(
*
last_point
)
->
type
|=
PathPointTypeCloseSubpath
;
(
*
last_point
)
->
type
|=
PathPointTypeCloseSubpath
;
...
@@ -2335,16 +2405,15 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
...
@@ -2335,16 +2405,15 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
if
(
status
==
Ok
)
if
(
status
==
Ok
)
{
{
REAL
anchor_pen_width
=
max
(
pen
->
width
,
2
.
0
);
REAL
pen_width
=
(
pen
->
unit
==
UnitWorld
)
?
max
(
pen
->
width
,
1
.
0
)
:
pen
->
width
;
REAL
pen_width
=
(
pen
->
unit
==
UnitWorld
)
?
max
(
pen
->
width
,
1
.
0
)
:
pen
->
width
;
BYTE
*
types
=
flat_path
->
pathdata
.
Types
;
BYTE
*
types
=
flat_path
->
pathdata
.
Types
;
last_point
=
points
;
last_point
=
points
;
if
(
pen
->
endcap
>
LineCapDiamondAnchor
)
if
(
pen
->
endcap
>
LineCapDiamondAnchor
&&
pen
->
endcap
!=
LineCapCustom
)
FIXME
(
"unimplemented end cap %x
\n
"
,
pen
->
endcap
);
FIXME
(
"unimplemented end cap %x
\n
"
,
pen
->
endcap
);
if
(
pen
->
startcap
>
LineCapDiamondAnchor
)
if
(
pen
->
startcap
>
LineCapDiamondAnchor
&&
pen
->
startcap
!=
LineCapCustom
)
FIXME
(
"unimplemented start cap %x
\n
"
,
pen
->
startcap
);
FIXME
(
"unimplemented start cap %x
\n
"
,
pen
->
startcap
);
if
(
pen
->
dashcap
!=
DashCapFlat
)
if
(
pen
->
dashcap
!=
DashCapFlat
)
...
@@ -2395,12 +2464,12 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
...
@@ -2395,12 +2464,12 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
if
(
pen
->
startcap
&
LineCapAnchorMask
)
if
(
pen
->
startcap
&
LineCapAnchorMask
)
add_anchor
(
&
flat_path
->
pathdata
.
Points
[
subpath_start
],
add_anchor
(
&
flat_path
->
pathdata
.
Points
[
subpath_start
],
&
flat_path
->
pathdata
.
Points
[
subpath_start
+
1
],
&
flat_path
->
pathdata
.
Points
[
subpath_start
+
1
],
anchor_pen_width
,
pen
->
startcap
,
pen
->
customstart
,
&
last_point
);
pen
,
pen
->
startcap
,
pen
->
customstart
,
&
last_point
);
if
(
pen
->
endcap
&
LineCapAnchorMask
)
if
(
pen
->
endcap
&
LineCapAnchorMask
)
add_anchor
(
&
flat_path
->
pathdata
.
Points
[
i
],
add_anchor
(
&
flat_path
->
pathdata
.
Points
[
i
],
&
flat_path
->
pathdata
.
Points
[
i
-
1
],
&
flat_path
->
pathdata
.
Points
[
i
-
1
],
anchor_pen_width
,
pen
->
endcap
,
pen
->
customend
,
&
last_point
);
pen
,
pen
->
endcap
,
pen
->
customend
,
&
last_point
);
}
}
}
}
...
...
dlls/gdiplus/tests/graphicspath.c
View file @
1271ae3e
...
@@ -1682,9 +1682,12 @@ static void test_widen_cap(void)
...
@@ -1682,9 +1682,12 @@ static void test_widen_cap(void)
{
LineCapSquareAnchor
,
10
.
0
,
widenline_capsquareanchor_dashed_path
,
{
LineCapSquareAnchor
,
10
.
0
,
widenline_capsquareanchor_dashed_path
,
ARRAY_SIZE
(
widenline_capsquareanchor_dashed_path
),
TRUE
},
ARRAY_SIZE
(
widenline_capsquareanchor_dashed_path
),
TRUE
},
};
};
GpAdjustableArrowCap
*
arrowcap
;
GpStatus
status
;
GpStatus
status
;
GpPath
*
path
;
GpPath
*
path
;
GpPen
*
pen
;
GpPen
*
pen
;
int
i
;
int
i
;
status
=
GdipCreatePath
(
FillModeAlternate
,
&
path
);
status
=
GdipCreatePath
(
FillModeAlternate
,
&
path
);
...
@@ -1749,6 +1752,16 @@ static void test_widen_cap(void)
...
@@ -1749,6 +1752,16 @@ static void test_widen_cap(void)
expect
(
Ok
,
status
);
expect
(
Ok
,
status
);
ok_path_fudge
(
path
,
widenline_capsquareanchor_multifigure_path
,
ok_path_fudge
(
path
,
widenline_capsquareanchor_multifigure_path
,
ARRAY_SIZE
(
widenline_capsquareanchor_multifigure_path
),
FALSE
,
0
.
000005
);
ARRAY_SIZE
(
widenline_capsquareanchor_multifigure_path
),
FALSE
,
0
.
000005
);
status
=
GdipCreateAdjustableArrowCap
(
4
.
0
,
4
.
0
,
TRUE
,
&
arrowcap
);
ok
(
status
==
Ok
,
"Failed to create adjustable cap, %d
\n
"
,
status
);
status
=
GdipSetAdjustableArrowCapMiddleInset
(
arrowcap
,
1
.
0
);
ok
(
status
==
Ok
,
"Failed to set middle inset inadjustable cap, %d
\n
"
,
status
);
status
=
GdipSetPenCustomEndCap
(
pen
,
(
GpCustomLineCap
*
)
arrowcap
);
ok
(
status
==
Ok
,
"Failed to create custom end cap, %d
\n
"
,
status
);
status
=
GdipWidenPath
(
path
,
pen
,
NULL
,
FlatnessDefault
);
expect
(
Ok
,
status
);
GdipDeletePen
(
pen
);
GdipDeletePen
(
pen
);
GdipDeletePath
(
path
);
GdipDeletePath
(
path
);
...
...
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