Implement the winding fill rule for real
This commit is contained in:
parent
e5f9b56a1d
commit
dbd83d17ef
|
@ -33,7 +33,7 @@ pub mod legalizer;
|
||||||
pub mod partitioner;
|
pub mod partitioner;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum FillRule {
|
pub enum FillRule {
|
||||||
EvenOdd = 0,
|
EvenOdd = 0,
|
||||||
Winding = 1,
|
Winding = 1,
|
||||||
|
|
|
@ -466,6 +466,14 @@ impl<'a> Partitioner<'a> {
|
||||||
active_edge_index > 0 && self.should_fill_below_active_edge(active_edge_index - 1)
|
active_edge_index > 0 && self.should_fill_below_active_edge(active_edge_index - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn winding_number_above_active_edge(&self, active_edge_index: u32) -> i32 {
|
||||||
|
if active_edge_index == 0 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
self.winding_number_below_active_edge(active_edge_index - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn winding_number_below_active_edge(&self, active_edge_index: u32) -> i32 {
|
fn winding_number_below_active_edge(&self, active_edge_index: u32) -> i32 {
|
||||||
let mut winding_number = 0;
|
let mut winding_number = 0;
|
||||||
for active_edge_index in 0..(active_edge_index as usize + 1) {
|
for active_edge_index in 0..(active_edge_index as usize + 1) {
|
||||||
|
@ -479,14 +487,44 @@ impl<'a> Partitioner<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_b_quad_below(&mut self, upper_active_edge_index: u32, right_x: f32) {
|
fn emit_b_quad_below(&mut self, upper_active_edge_index: u32, right_x: f32) {
|
||||||
self.emit_b_quad_above(upper_active_edge_index + 1, right_x)
|
let mut lower_active_edge_index = upper_active_edge_index + 1;
|
||||||
|
|
||||||
|
if self.fill_rule == FillRule::Winding {
|
||||||
|
let active_edge_count = self.active_edges.len() as u32;
|
||||||
|
let mut winding_number =
|
||||||
|
self.winding_number_below_active_edge(lower_active_edge_index);
|
||||||
|
while lower_active_edge_index + 1 < active_edge_count && winding_number != 0 {
|
||||||
|
lower_active_edge_index += 1;
|
||||||
|
if self.active_edges[lower_active_edge_index as usize].left_to_right {
|
||||||
|
winding_number += 1
|
||||||
|
} else {
|
||||||
|
winding_number -= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.emit_b_quad_above(lower_active_edge_index, right_x)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_b_quad_above(&mut self, lower_active_edge_index: u32, right_x: f32) {
|
fn emit_b_quad_above(&mut self, lower_active_edge_index: u32, right_x: f32) {
|
||||||
// TODO(pcwalton): Assert that the green X position is the same on both edges.
|
// TODO(pcwalton): Assert that the green X position is the same on both edges.
|
||||||
debug_assert!(lower_active_edge_index > 0,
|
debug_assert!(lower_active_edge_index > 0,
|
||||||
"Can't emit b_quads above the top active edge");
|
"Can't emit b_quads above the top active edge");
|
||||||
let upper_active_edge_index = lower_active_edge_index - 1;
|
|
||||||
|
let mut upper_active_edge_index = lower_active_edge_index - 1;
|
||||||
|
|
||||||
|
if self.fill_rule == FillRule::Winding {
|
||||||
|
let mut winding_number =
|
||||||
|
self.winding_number_above_active_edge(upper_active_edge_index);
|
||||||
|
while upper_active_edge_index > 0 && winding_number != 0 {
|
||||||
|
upper_active_edge_index -= 1;
|
||||||
|
if self.active_edges[upper_active_edge_index as usize].left_to_right {
|
||||||
|
winding_number -= 1
|
||||||
|
} else {
|
||||||
|
winding_number += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let upper_curve = self.subdivide_active_edge_at(upper_active_edge_index, right_x);
|
let upper_curve = self.subdivide_active_edge_at(upper_active_edge_index, right_x);
|
||||||
let lower_curve = self.subdivide_active_edge_at(lower_active_edge_index, right_x);
|
let lower_curve = self.subdivide_active_edge_at(lower_active_edge_index, right_x);
|
||||||
|
|
Loading…
Reference in New Issue