Skip to content

Commit

Permalink
add stroke_rounded_rectangle function
Browse files Browse the repository at this point in the history
  • Loading branch information
nivkner committed Jul 7, 2017
1 parent 8074c3d commit ac0746c
Showing 1 changed file with 117 additions and 4 deletions.
121 changes: 117 additions & 4 deletions tessellation/src/basic_shapes.rs
Expand Up @@ -611,11 +611,124 @@ fn stroke_border_radius<Output: GeometryBuilder<StrokeVertex>>(

/// Tessellate the stroke of an axis-aligned rounded rectangle.
pub fn stroke_rounded_rectangle<Output: GeometryBuilder<StrokeVertex>>(
_rect: &Rect,
_radii: &BorderRadii,
_output: &mut Output,
rect: &Rect,
radii: &BorderRadii,
tolerance: f32,
output: &mut Output,
) -> Count {
unimplemented!();
output.begin_geometry();

let w = rect.size.width;
let h = rect.size.height;
let x_min = rect.min_x();
let y_min = rect.min_y();
let x_max = rect.max_x();
let y_max = rect.max_y();
let min_wh = w.min(h);
let mut tl = radii.top_left.abs().min(min_wh);
let mut tr = radii.top_right.abs().min(min_wh);
let mut bl = radii.bottom_left.abs().min(min_wh);
let mut br = radii.bottom_right.abs().min(min_wh);

// clamp border radii if they don't fit in the rectangle.
if tl + tr > w {
let x = (tl + tr - w) * 0.5;
tl -= x;
tr -= x;
}
if bl + br > w {
let x = (bl + br - w) * 0.5;
bl -= x;
br -= x;
}
if tr + br > h {
let x = (tr + br - h) * 0.5;
tr -= x;
br -= x;
}
if tl + bl > h {
let x = (tl + bl - h) * 0.5;
tl -= x;
bl -= x;
}

// top
let p1 = point(x_min + tl, y_min);
let p2 = point(x_max - tr, y_min);

// bottom
let p6 = point(x_min + bl, y_max);
let p5 = point(x_max - br, y_max);

// left
let p0 = point(x_min, y_min + tl);
let p7 = point(x_min, y_max - bl);

// right
let p3 = point(x_max, y_min + tr);
let p4 = point(x_max, y_max - br);

let sides = &[
[p1, p2],
[p5, p6],
[p3, p4],
[p0, p7],
];

let radii = [tl, tr, br, bl];
let angles = [
(PI, 1.5 * PI),
(1.5* PI, 2.0 * PI),
(0.0, PI * 0.5),
(PI * 0.5, PI),
];

let centers = [
point(p1.x, p0.y),
point(p2.x, p3.y),
point(p5.x, p4.y),
point(p6.x, p7.y),
];

let mut nums = radii.iter().map(|&radius| {
if radius > 0.0 {

let arc_len = 0.5 * PI * radius;
let step = circle_flattening_step(radius, tolerance);
let num_segments = (arc_len / step).ceil();

num_segments.log2() as u32 - 1
} else {
0
}
});

let options = StrokeOptions::default();
{ // output borrow scope start
let mut builder = StrokeBuilder::new(&options, output);
builder.move_to(p1); // start manually so every argument is on the same index
builder.line_to(p2);
stroke_border_radius_build(
centers[0],
angles[0],
radii[0],
nums.next().unwrap(),
&mut builder,
);
for i in 1..4 {
builder.line_to(sides[i][0]);
builder.line_to(sides[i][1]);
stroke_border_radius_build(
centers[i],
angles[i],
radii[i],
nums.next().unwrap(),
&mut builder,
);
}
} // output borrow scope end

return output.end_geometry();
}

/// Tessellate a circle.
Expand Down

0 comments on commit ac0746c

Please sign in to comment.