Skip to content

Commit bbd5d85

Browse files
authored
Add stroke-line-join for Path (#9912)
* Add `stroke-line-join` for `Path` * Add `LineJoin` enum * Add `stroke-line-join` property for `Path` * Set line_join in Skia and FemtoVG renders * Set pen_join_style in Qt backend * Add example test case * Docs: Add `stroke-line-join` property for `Path`
1 parent 0bdb99d commit bbd5d85

File tree

8 files changed

+95
-4
lines changed

8 files changed

+95
-4
lines changed

docs/astro/src/content/docs/reference/elements/path.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ The width of the outline.
4747
The appearance of the ends of the path's outline.
4848
</SlintProperty>
4949

50+
### stroke-line-join
51+
<SlintProperty propName="stroke-line-join" typeName="enum" enumName="LineJoin" defaultValue='miter'>
52+
The appearance of the joins between segments of stroked paths.
53+
</SlintProperty>
54+
5055
### width
5156
<SlintProperty propName="width" typeName="length">
5257
If non-zero, the path will be scaled to fit into the specified width.

internal/backends/qt/qt_window.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use i_slint_core::item_rendering::{
2020
use i_slint_core::item_tree::ParentItemTraversalMode;
2121
use i_slint_core::item_tree::{ItemTreeRc, ItemTreeRef, ItemTreeWeak};
2222
use i_slint_core::items::{
23-
self, ColorScheme, FillRule, ImageRendering, ItemRc, ItemRef, Layer, LineCap, MouseCursor,
24-
Opacity, PointerEventButton, RenderingResult, TextWrap,
23+
self, ColorScheme, FillRule, ImageRendering, ItemRc, ItemRef, Layer, LineCap, LineJoin,
24+
MouseCursor, Opacity, PointerEventButton, RenderingResult, TextWrap,
2525
};
2626
use i_slint_core::layout::Orientation;
2727
use i_slint_core::lengths::{
@@ -716,6 +716,12 @@ impl ItemRenderer for QtItemRenderer<'_> {
716716
LineCap::Round => 0x20,
717717
LineCap::Square => 0x10,
718718
};
719+
let stroke_pen_join_style: i32 = match path.stroke_line_join() {
720+
LineJoin::Miter => 0x00,
721+
LineJoin::Round => 0x80,
722+
LineJoin::Bevel => 0x40,
723+
};
724+
719725
let pos = qttypes::QPoint { x: offset.x as _, y: offset.y as _ };
720726
let mut painter_path = QPainterPath::default();
721727

@@ -762,11 +768,12 @@ impl ItemRenderer for QtItemRenderer<'_> {
762768
stroke_brush as "QBrush",
763769
stroke_width as "float",
764770
stroke_pen_cap_style as "int",
771+
stroke_pen_join_style as "int",
765772
anti_alias as "bool"] {
766773
(*painter)->save();
767774
auto cleanup = qScopeGuard([&] { (*painter)->restore(); });
768775
(*painter)->translate(pos);
769-
(*painter)->setPen(stroke_width > 0 ? QPen(stroke_brush, stroke_width, Qt::SolidLine, Qt::PenCapStyle(stroke_pen_cap_style)) : Qt::NoPen);
776+
(*painter)->setPen(stroke_width > 0 ? QPen(stroke_brush, stroke_width, Qt::SolidLine, Qt::PenCapStyle(stroke_pen_cap_style), Qt::PenJoinStyle(stroke_pen_join_style)) : Qt::NoPen);
770777
(*painter)->setBrush(fill_brush);
771778
(*painter)->setRenderHint(QPainter::Antialiasing, anti_alias);
772779
(*painter)->drawPath(painter_path);

internal/common/enums.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,16 @@ macro_rules! for_each_enums {
480480
Square,
481481
}
482482

483+
/// This enum describes the appearance of the joins between segments of stroked paths.
484+
enum LineJoin {
485+
/// The stroke joins with a sharp corner or a clipped corner, depending on the miter limit.
486+
Miter,
487+
/// The stroke joins with a smooth, rounded corner.
488+
Round,
489+
/// The stroke joins with a beveled (flattened) corner.
490+
Bevel,
491+
}
492+
483493
/// This enum describes the detected operating system types.
484494
#[non_exhaustive]
485495
enum OperatingSystemType {

internal/compiler/builtins.slint

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ export component Path {
501501
in property <brush> stroke;
502502
in property <length> stroke-width;
503503
in property <LineCap> stroke-line-cap;
504+
in property <LineJoin> stroke-line-join;
504505
in property <string> commands; // 'fake' hardcoded in typeregister.rs
505506
in property <float> viewbox-x;
506507
in property <float> viewbox-y;

internal/core/items/path.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ When adding an item or a property, it needs to be kept in sync with different pl
88
Lookup the [`crate::items`] module documentation.
99
*/
1010

11-
use super::{FillRule, Item, ItemConsts, ItemRc, ItemRendererRef, LineCap, RenderingResult};
11+
use super::{
12+
FillRule, Item, ItemConsts, ItemRc, ItemRendererRef, LineCap, LineJoin, RenderingResult,
13+
};
1214
use crate::graphics::{Brush, PathData, PathDataIterator};
1315
use crate::input::{
1416
FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, KeyEvent,
@@ -41,6 +43,7 @@ pub struct Path {
4143
pub stroke: Property<Brush>,
4244
pub stroke_width: Property<LogicalLength>,
4345
pub stroke_line_cap: Property<LineCap>,
46+
pub stroke_line_join: Property<LineJoin>,
4447
pub viewbox_x: Property<f32>,
4548
pub viewbox_y: Property<f32>,
4649
pub viewbox_width: Property<f32>,

internal/renderers/femtovg/itemrenderer.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,11 @@ impl<'a, R: femtovg::Renderer + TextureImporter> ItemRenderer for GLItemRenderer
461461
items::LineCap::Round => femtovg::LineCap::Round,
462462
items::LineCap::Square => femtovg::LineCap::Square,
463463
});
464+
paint.set_line_join(match path.stroke_line_join() {
465+
items::LineJoin::Miter => femtovg::LineJoin::Miter,
466+
items::LineJoin::Round => femtovg::LineJoin::Round,
467+
items::LineJoin::Bevel => femtovg::LineJoin::Bevel,
468+
});
464469
paint.set_anti_alias(anti_alias);
465470
paint
466471
});

internal/renderers/skia/itemrenderer.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,11 @@ impl ItemRenderer for SkiaItemRenderer<'_> {
656656
i_slint_core::items::LineCap::Round => skia_safe::PaintCap::Round,
657657
i_slint_core::items::LineCap::Square => skia_safe::PaintCap::Square,
658658
});
659+
border_paint.set_stroke_join(match path.stroke_line_join() {
660+
i_slint_core::items::LineJoin::Miter => skia_safe::PaintJoin::Miter,
661+
i_slint_core::items::LineJoin::Round => skia_safe::PaintJoin::Round,
662+
i_slint_core::items::LineJoin::Bevel => skia_safe::PaintJoin::Bevel,
663+
});
659664
border_paint.set_stroke(true);
660665
self.canvas.draw_path(&skpath, &border_paint);
661666
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright © SixtyFPS GmbH <[email protected]>
2+
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3+
4+
PathLineJoin := Window {
5+
GridLayout {
6+
Row {
7+
Text {
8+
text: "The path to the right should have rounded corners (line-join: round)";
9+
}
10+
Path {
11+
commands: "M10.5 15.5 9 17l-1.5-1.5";
12+
fill: transparent;
13+
stroke: white;
14+
stroke-width: 10px;
15+
stroke-line-join: round;
16+
}
17+
}
18+
Row {
19+
Text {
20+
text: "The path to the right should have sharp pointed corners (line-join: miter)";
21+
}
22+
Path {
23+
commands: "M10.5 15.5 9 17l-1.5-1.5";
24+
fill: transparent;
25+
stroke: white;
26+
stroke-width: 10px;
27+
stroke-line-join: miter;
28+
}
29+
}
30+
Row {
31+
Text {
32+
text: "The path to the right should have beveled/flat corners (line-join: bevel)";
33+
}
34+
Path {
35+
commands: "M10.5 15.5 9 17l-1.5-1.5";
36+
fill: transparent;
37+
stroke: white;
38+
stroke-width: 10px;
39+
stroke-line-join: bevel;
40+
}
41+
}
42+
Row {
43+
Text {
44+
text: "Zigzag pattern with round joins - should show smooth rounded corners";
45+
}
46+
Path {
47+
commands: "m15 17-1.5-1.5L12 17l-1.5-1.5L9 17l-1.5-1.5";
48+
fill: transparent;
49+
stroke: white;
50+
stroke-width: 10px;
51+
stroke-line-join: round;
52+
}
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)