Skip to content

Commit ac8243f

Browse files
Merge pull request #62 from iShape-Rust/fix/outline_crush
Fix/outline crush
2 parents 1eb9054 + ce3706a commit ac8243f

File tree

22 files changed

+460
-184
lines changed

22 files changed

+460
-184
lines changed

examples/overlay_editor/Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ log = "0.4.22"
2626
console_log = "^1.0.0"
2727
console_error_panic_hook = "^0"
2828

29-
i_mesh = "^0.3.0"
30-
i_triangle = { version = "^0.35.0", features = ["serde"] }
29+
#i_mesh = "^0.4.0"
30+
#i_triangle = { version = "^0.35.0", features = ["serde"] }
3131

32-
#i_triangle = { path = "../../../../iShape/iTriangle/iTriangle", default-features = true, features = ["serde"] }
33-
#i_mesh = { path = "../../../../iShape/iMesh/iMesh" }
32+
i_triangle = { path = "../../../../iShape/iTriangle/iTriangle", default-features = true, features = ["serde"] }
33+
i_mesh = { path = "../../../../iShape/iMesh/iMesh" }
3434

3535
#ICED_BACKEND=wgpu cargo r -r

examples/overlay_editor/src/app/boolean/content.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub(crate) enum BooleanMessage {
3939
}
4040

4141
impl EditorApp {
42-
fn boolean_sidebar(&self) -> Column<AppMessage> {
42+
fn boolean_sidebar(&self) -> Column<'_, AppMessage> {
4343
let count = self.app_resource.boolean.count;
4444
let mut column = Column::new().push(
4545
Space::new()

examples/overlay_editor/src/app/main.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::app::string::content::StringMessage;
66
use crate::app::string::content::StringState;
77
use crate::app::stroke::content::StrokeMessage;
88
use crate::app::stroke::content::StrokeState;
9-
use iced::event::Event as MainEvent;
109
use iced::keyboard::key::Named;
1110
use iced::keyboard::Key;
1211
use iced::widget::{rule, Space};
@@ -64,7 +63,6 @@ pub(crate) enum AppMessage {
6463
String(StringMessage),
6564
Stroke(StrokeMessage),
6665
Outline(OutlineMessage),
67-
EventOccurred(MainEvent),
6866
NextTest,
6967
PrevTest,
7068
}
@@ -111,7 +109,6 @@ impl EditorApp {
111109
MainAction::Stroke => self.stroke_prev_test(),
112110
MainAction::Outline => self.outline_prev_test(),
113111
}
114-
_ => {}
115112
}
116113

117114
Task::none()

examples/overlay_editor/src/app/stroke/content.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use i_triangle::i_overlay::i_float::int::rect::IntRect;
1313
use iced::widget::{scrollable, Button, Column, Container, Row, Space, Text};
1414
use iced::{Alignment, Length, Padding, Size, Vector};
1515
use std::collections::HashMap;
16+
use std::rc::Rc;
1617

1718
pub(crate) struct StrokeState {
1819
pub(crate) test: usize,
@@ -307,7 +308,7 @@ impl StrokeState {
307308
[ 3.0, 0.0],
308309
[-1.0, 2.0],
309310
];
310-
style = style.start_cap(LineCap::Custom(points))
311+
style = style.start_cap(LineCap::Custom(Rc::from(points)))
311312
}
312313
}
313314

@@ -326,7 +327,7 @@ impl StrokeState {
326327
[ 3.0, 0.0],
327328
[-1.0, 2.0],
328329
];
329-
style = style.end_cap(LineCap::Custom(points))
330+
style = style.end_cap(LineCap::Custom(Rc::from(points)))
330331
}
331332
}
332333

examples/overlay_editor/src/draw/shape.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl ShapeWidget {
7171
let validation = Validation::with_fill_rule(fill_rule.unwrap_or_default());
7272
let triangulation =
7373
IntTriangulator::new(shapes.points_count(), validation, Default::default())
74-
.triangulate_shapes(shapes, false);
74+
.triangulate_shapes(shapes);
7575

7676
Self::fill_mesh_for_triangulation(triangulation, camera, offset, color)
7777
}
@@ -91,7 +91,7 @@ impl ShapeWidget {
9191
let validation = Validation::with_fill_rule(fill_rule.unwrap_or_default());
9292
let triangulation =
9393
IntTriangulator::new(paths.points_count(), validation, Default::default())
94-
.triangulate_shape(paths, false);
94+
.triangulate_shape(paths);
9595

9696
// let triangulation = paths.triangulate().into_triangulation();
9797

iOverlay/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ allow_multithreading = ["dep:rayon"]
3434
[dev-dependencies]
3535
serde = { version = "^1.0", features = ["derive"] }
3636
serde_json = "^1.0"
37-
rand = { version = "~0.9", features = ["alloc"] }
37+
rand = { version = "~0.10", features = ["alloc"] }
3838
#i_float = { path = "../../iFloat", features = ["serde"] }
3939
#i_shape = { path = "../../iShape", features = ["serde"] }
4040
i_float = { version = "~1.16.0", features = ["serde"] }

iOverlay/src/build/boolean.rs

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -274,19 +274,6 @@ impl BooleanFillFilter for SegmentFill {
274274
}
275275

276276
impl OverlayLinkFilter for [OverlayLink] {
277-
#[inline]
278-
fn filter_by_overlay(&self, overlay_rule: OverlayRule) -> Vec<VisitState> {
279-
match overlay_rule {
280-
OverlayRule::Subject => filter_subject(self),
281-
OverlayRule::Clip => filter_clip(self),
282-
OverlayRule::Intersect => filter_intersect(self),
283-
OverlayRule::Union => filter_union(self),
284-
OverlayRule::Difference => filter_difference(self),
285-
OverlayRule::Xor => filter_xor(self),
286-
OverlayRule::InverseDifference => filter_inverse_difference(self),
287-
}
288-
}
289-
290277
#[inline]
291278
fn filter_by_overlay_into(&self, overlay_rule: OverlayRule, buffer: &mut Vec<VisitState>) {
292279
match overlay_rule {
@@ -301,62 +288,6 @@ impl OverlayLinkFilter for [OverlayLink] {
301288
}
302289
}
303290

304-
#[inline]
305-
fn filter_subject(links: &[OverlayLink]) -> Vec<VisitState> {
306-
links
307-
.iter()
308-
.map(|link| VisitState::new(!link.fill.is_subject()))
309-
.collect()
310-
}
311-
312-
#[inline]
313-
fn filter_clip(links: &[OverlayLink]) -> Vec<VisitState> {
314-
links
315-
.iter()
316-
.map(|link| VisitState::new(!link.fill.is_clip()))
317-
.collect()
318-
}
319-
320-
#[inline]
321-
fn filter_intersect(links: &[OverlayLink]) -> Vec<VisitState> {
322-
links
323-
.iter()
324-
.map(|link| VisitState::new(!link.fill.is_intersect()))
325-
.collect()
326-
}
327-
328-
#[inline]
329-
fn filter_union(links: &[OverlayLink]) -> Vec<VisitState> {
330-
links
331-
.iter()
332-
.map(|link| VisitState::new(!link.fill.is_union()))
333-
.collect()
334-
}
335-
336-
#[inline]
337-
fn filter_difference(links: &[OverlayLink]) -> Vec<VisitState> {
338-
links
339-
.iter()
340-
.map(|link| VisitState::new(!link.fill.is_difference()))
341-
.collect()
342-
}
343-
344-
#[inline]
345-
fn filter_inverse_difference(links: &[OverlayLink]) -> Vec<VisitState> {
346-
links
347-
.iter()
348-
.map(|link| VisitState::new(!link.fill.is_inverse_difference()))
349-
.collect()
350-
}
351-
352-
#[inline]
353-
fn filter_xor(links: &[OverlayLink]) -> Vec<VisitState> {
354-
links
355-
.iter()
356-
.map(|link| VisitState::new(!link.fill.is_xor()))
357-
.collect()
358-
}
359-
360291
#[inline]
361292
fn filter_subject_into(links: &[OverlayLink], buffer: &mut Vec<VisitState>) {
362293
buffer.clear();

iOverlay/src/build/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pub(crate) mod boolean;
22
pub(crate) mod builder;
33
mod graph;
4-
mod offset;
4+
pub(crate) mod offset;
55
pub(crate) mod string;
66
pub(crate) mod sweep;
77
mod util;

iOverlay/src/build/offset.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ use crate::segm::segment::{Segment, SegmentFill};
99

1010
impl GraphBuilder<ShapeCountOffset, OverlayNode> {
1111
#[inline]
12-
pub(crate) fn build_offset(
12+
pub(crate) fn build_offset<F: FillStrategy<ShapeCountOffset>>(
1313
&mut self,
1414
solver: &Solver,
1515
segments: &[Segment<ShapeCountOffset>],
1616
) -> OffsetGraph<'_> {
17-
self.build_fills_with_strategy::<SubjectOffsetStrategy>(solver, segments);
17+
self.build_fills_with_strategy::<F>(solver, segments);
1818
self.build_links_all(segments);
1919
self.offset_graph(solver)
2020
}
@@ -29,10 +29,11 @@ impl GraphBuilder<ShapeCountOffset, OverlayNode> {
2929
}
3030
}
3131

32-
struct SubjectOffsetStrategy;
32+
pub(crate) struct PositiveSubjectOffsetStrategy;
33+
pub(crate) struct NegativeSubjectOffsetStrategy;
3334
const BOLD_BIT: usize = 2;
3435

35-
impl FillStrategy<ShapeCountOffset> for SubjectOffsetStrategy {
36+
impl FillStrategy<ShapeCountOffset> for PositiveSubjectOffsetStrategy {
3637
#[inline(always)]
3738
fn add_and_fill(this: ShapeCountOffset, bot: ShapeCountOffset) -> (ShapeCountOffset, SegmentFill) {
3839
let top_subj = bot.subj + this.subj;
@@ -53,6 +54,27 @@ impl FillStrategy<ShapeCountOffset> for SubjectOffsetStrategy {
5354
}
5455
}
5556

57+
impl FillStrategy<ShapeCountOffset> for NegativeSubjectOffsetStrategy {
58+
#[inline(always)]
59+
fn add_and_fill(this: ShapeCountOffset, bot: ShapeCountOffset) -> (ShapeCountOffset, SegmentFill) {
60+
let top_subj = bot.subj + this.subj;
61+
let bot_subj = bot.subj;
62+
63+
let subj_top = (top_subj < 0) as SegmentFill;
64+
let subj_bot = (bot_subj < 0) as SegmentFill;
65+
66+
let bold = this.bold as SegmentFill;
67+
68+
let fill = subj_top | (subj_bot << 1) | (bold << BOLD_BIT);
69+
let top = ShapeCountOffset {
70+
subj: top_subj,
71+
bold: false,
72+
}; // bold not need
73+
74+
(top, fill)
75+
}
76+
}
77+
5678
impl OverlayLink {
5779
#[inline(always)]
5880
pub(crate) fn is_bold(&self) -> bool {

iOverlay/src/core/extract.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl OverlayGraph<'_> {
183183
start_data: &StartPathData,
184184
clockwise: bool,
185185
visited_state: VisitState,
186-
visited: &mut Vec<VisitState>,
186+
visited: &mut [VisitState],
187187
points: &mut Vec<IntPoint>,
188188
) {
189189
let mut link_id = start_data.link_id;
@@ -196,7 +196,7 @@ impl OverlayGraph<'_> {
196196

197197
// Find a closed tour
198198
while node_id != last_node_id {
199-
link_id = GraphUtil::next_link(self.links, self.nodes, link_id, node_id, clockwise, &visited);
199+
link_id = GraphUtil::next_link(self.links, self.nodes, link_id, node_id, clockwise, visited);
200200

201201
let link = unsafe {
202202
// Safety: `link_id` is always derived from a previous in-bounds index or

0 commit comments

Comments
 (0)