Skip to content

Commit faef685

Browse files
AustinMReppertAustin M. Reppert
andauthored
Draw borders with the same color in single bezpath. (#366)
* Draw adjacent borders with the same color in single bezpath. * Avoid unnecessary deref. * Avoid duplicate draw. * Handle wraparound case. * Handle non-adjacent edges touching. --------- Co-authored-by: Austin M. Reppert <austinmreppert@protonmail.com>
1 parent be765a5 commit faef685

1 file changed

Lines changed: 64 additions & 35 deletions

File tree

packages/blitz-paint/src/render.rs

Lines changed: 64 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use style::{
3535
},
3636
};
3737

38-
use kurbo::{self, Affine, Insets, Point, Rect, Stroke, Vec2};
38+
use kurbo::{self, Affine, BezPath, Insets, Point, Rect, Stroke, Vec2};
3939
use peniko::{self, Fill, ImageData, ImageSampler};
4040
use style::values::generics::color::{ColorOrAuto, GenericColor};
4141
use taffy::Layout;
@@ -806,8 +806,69 @@ impl ElementCx<'_> {
806806

807807
/// Draw all borders for a node
808808
fn draw_border(&self, scene: &mut impl PaintScene) {
809-
for edge in [Edge::Top, Edge::Right, Edge::Bottom, Edge::Left] {
810-
self.draw_border_edge(scene, edge);
809+
let style = &*self.style;
810+
let border = style.get_border();
811+
let current_color = style.clone_color();
812+
813+
let mut borders: [(Color, Option<BezPath>); 4] = [
814+
(Color::TRANSPARENT, None),
815+
(Color::TRANSPARENT, None),
816+
(Color::TRANSPARENT, None),
817+
(Color::TRANSPARENT, None),
818+
];
819+
let mut count = 0;
820+
821+
for &edge in &[Edge::Top, Edge::Right, Edge::Bottom, Edge::Left] {
822+
let color = match edge {
823+
Edge::Top => &border.border_top_color,
824+
Edge::Right => &border.border_right_color,
825+
Edge::Bottom => &border.border_bottom_color,
826+
Edge::Left => &border.border_left_color,
827+
}
828+
.resolve_to_absolute(&current_color)
829+
.as_srgb_color();
830+
831+
if color.components[3] > 0.0 {
832+
borders[count] = (color, Some(self.frame.border_edge_shape(edge)));
833+
count += 1;
834+
}
835+
}
836+
837+
if count == 0 {
838+
return;
839+
}
840+
841+
// Group together identical colors by sorting.
842+
let active_slice = &mut borders[0..count];
843+
active_slice.sort_unstable_by(|a, b| {
844+
a.0.components
845+
.partial_cmp(&b.0.components)
846+
.unwrap_or(std::cmp::Ordering::Equal)
847+
});
848+
849+
let mut start_border_index = 0;
850+
while start_border_index < count {
851+
let color = borders[start_border_index].0;
852+
let mut next_border_index = start_border_index + 1;
853+
let has_multiple_edges =
854+
next_border_index < count && borders[next_border_index].0 == color;
855+
if has_multiple_edges {
856+
let mut border_path = borders[start_border_index].1.take().unwrap();
857+
while next_border_index < count && borders[next_border_index].0 == color {
858+
border_path.extend(&borders[next_border_index].1.take().unwrap());
859+
next_border_index += 1;
860+
}
861+
scene.fill(Fill::NonZero, self.transform, color, None, &border_path);
862+
} else {
863+
scene.fill(
864+
Fill::NonZero,
865+
self.transform,
866+
color,
867+
None,
868+
borders[start_border_index].1.as_ref().unwrap(),
869+
);
870+
}
871+
start_border_index = next_border_index;
811872
}
812873
}
813874

@@ -900,38 +961,6 @@ impl ElementCx<'_> {
900961
}
901962
}
902963

903-
/// Draw a single border edge for a node
904-
fn draw_border_edge(&self, scene: &mut impl PaintScene, edge: Edge) {
905-
let style = &*self.style;
906-
let border = style.get_border();
907-
let path = self.frame.border_edge_shape(edge);
908-
909-
let current_color = style.clone_color();
910-
let color = match edge {
911-
Edge::Top => border
912-
.border_top_color
913-
.resolve_to_absolute(&current_color)
914-
.as_srgb_color(),
915-
Edge::Right => border
916-
.border_right_color
917-
.resolve_to_absolute(&current_color)
918-
.as_srgb_color(),
919-
Edge::Bottom => border
920-
.border_bottom_color
921-
.resolve_to_absolute(&current_color)
922-
.as_srgb_color(),
923-
Edge::Left => border
924-
.border_left_color
925-
.resolve_to_absolute(&current_color)
926-
.as_srgb_color(),
927-
};
928-
929-
let alpha = color.components[3];
930-
if alpha != 0.0 {
931-
scene.fill(Fill::NonZero, self.transform, color, None, &path);
932-
}
933-
}
934-
935964
/// ❌ dotted - Defines a dotted border
936965
/// ❌ dashed - Defines a dashed border
937966
/// ✅ solid - Defines a solid border

0 commit comments

Comments
 (0)