aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/gfx/paint_context.rs304
-rw-r--r--tests/ref/basic.list1
-rw-r--r--tests/ref/border_radius_asymmetric_sizes_a.html71
-rw-r--r--tests/ref/border_radius_asymmetric_sizes_ref.html217
4 files changed, 549 insertions, 44 deletions
diff --git a/components/gfx/paint_context.rs b/components/gfx/paint_context.rs
index a96d413cafc..9ebe86b1f38 100644
--- a/components/gfx/paint_context.rs
+++ b/components/gfx/paint_context.rs
@@ -72,6 +72,19 @@ enum DashSize {
DashedBorder = 3
}
+#[derive(Copy, Clone, Debug)]
+struct Ellipse {
+ origin: Point2D<f32>,
+ width: f32,
+ height: f32,
+}
+
+#[derive(Copy, Clone, Debug)]
+struct Line {
+ start: Point2D<f32>,
+ end: Point2D<f32>,
+}
+
impl<'a> PaintContext<'a> {
pub fn draw_target(&self) -> &DrawTarget {
&self.draw_target
@@ -355,6 +368,104 @@ impl<'a> PaintContext<'a> {
self.draw_target.push_clip(&path_builder.finish());
}
+ fn solve_quadratic(a: f32, b: f32, c: f32) -> (Option<f32>, Option<f32>) {
+ let discriminant = b * b - 4. * a * c;
+ if discriminant < 0. {
+ return (None, None);
+ }
+ let x1 = (-b + discriminant.sqrt())/(2. * a);
+ let x2 = (-b - discriminant.sqrt())/(2. * a);
+ if discriminant == 0. {
+ return (Some(x1), None);
+ }
+ return (Some(x1), Some(x2));
+ }
+
+ fn intersect_ellipse_line(e: Ellipse, l: Line) -> (Option<Point2D<f32>>, Option<Point2D<f32>>) {
+ debug_assert!(l.end.x - l.start.x > f32::EPSILON, "Error line segment end.x > start.x!!");
+ // shift the origin to center of the ellipse.
+ let line = Line { start: l.start - e.origin,
+ end: l.end - e.origin };
+
+ let a = (line.end.y - line.start.y)/(line.end.x - line.start.x);
+ let b = line.start.y - (a * line.start.x);
+ // given the equation of a line,
+ // y = a * x + b,
+ // and the equation of an ellipse,
+ // x^2/w^2 + y^2/h^2 = 1,
+ // substitute y = a * x + b, giving
+ // x^2/w^2 + (a^2x^2 + 2abx + b^2)/h^2 = 1
+ // then simplify to
+ // (h^2 + w^2a^2)x^2 + 2abw^2x + (b^2w^2 - w^2h^2) = 0
+ // finally solve for w using the quadratic equation.
+ let w = e.width;
+ let h = e.height;
+ let quad_a = h * h + w * w * a * a;
+ let quad_b = 2. * a * b * w * w;
+ let quad_c = b * b * w * w - w * w * h * h;
+ let intersections = PaintContext::solve_quadratic(quad_a, quad_b, quad_c);
+ match intersections {
+ (Some(x0), Some(x1)) => {
+ let mut p0 = Point2D::new(x0, a * x0 + b) + e.origin;
+ let mut p1 = Point2D::new(x1, a * x1 + b) + e.origin;
+ if x0 > x1 {
+ mem::swap(&mut p0, &mut p1);
+ }
+ (Some(p0), Some(p1))
+ },
+ (Some(x0), None) => {
+ let p = Point2D::new(x0, a * x0 + b) + e.origin;
+ (Some(p), None)
+ },
+ (None, Some(x1)) => {
+ let p = Point2D::new(x1, a * x1 + b) + e.origin;
+ (Some(p), None)
+ },
+ (None, None) => (None, None),
+ }
+ }
+
+ // Given an ellipse and line segment, the line segment may intersect the
+ // ellipse at 0, 1, or 2 points. We compute those intersection points.
+ // For each intersection point the angle of the point on the ellipse relative to
+ // the top|bottom of the ellipse is computed.
+ // Examples:
+ // - intersection at ellipse.center + (0, ellipse.height), the angle is 0 rad.
+ // - intersection at ellipse.center + (0, -ellipse.height), the angle is 0 rad.
+ // - intersection at ellipse.center + (+-ellipse.width, 0), the angle is pi/2.
+ fn ellipse_line_intersection_angles(e: Ellipse, l: Line)
+ -> (Option<(Point2D<f32>, f32)>, Option<(Point2D<f32>, f32)>) {
+ fn point_angle(e: Ellipse, intersect_point: Point2D<f32>) -> f32 {
+ ((intersect_point.y - e.origin.y).abs() / e.height).asin()
+ }
+
+ let intersection = PaintContext::intersect_ellipse_line(e, l);
+ match intersection {
+ (Some(p0), Some(p1)) => (Some((p0, point_angle(e, p0))), Some((p1, point_angle(e, p1)))),
+ (Some(p0), None) => (Some((p0, point_angle(e, p0))), None),
+ (None, Some(p1)) => (None, Some((p1, point_angle(e, p1)))),
+ (None, None) => (None, None),
+ }
+ }
+
+ fn ellipse_rightmost_line_intersection_angle(e: Ellipse, l: Line) -> Option<f32> {
+ match PaintContext::ellipse_line_intersection_angles(e, l) {
+ (Some((p0, angle0)), Some((p1, _))) if p0.x > p1.x => Some(angle0),
+ (_, Some((_, angle1))) => Some(angle1),
+ (Some((_, angle0)), None) => Some(angle0),
+ (None, None) => None,
+ }
+ }
+
+ fn ellipse_leftmost_line_intersection_angle(e: Ellipse, l: Line) -> Option<f32> {
+ match PaintContext::ellipse_line_intersection_angles(e, l) {
+ (Some((p0, angle0)), Some((p1, _))) if p0.x < p1.x => Some(angle0),
+ (_, Some((_, angle1))) => Some(angle1),
+ (Some((_, angle0)), None) => Some(angle0),
+ (None, None) => None,
+ }
+ }
+
// The following comment is wonderful, and stolen from
// gecko:gfx/thebes/gfxContext.cpp:RoundedRectangle for reference.
//
@@ -450,6 +561,11 @@ impl<'a> PaintContext<'a> {
let box_BL = box_TL + Point2D::new(0.0, bounds.size.height);
let box_BR = box_TL + Point2D::new(bounds.size.width, bounds.size.height);
+ let inner_TL = box_TL + Point2D::new(border.left, border.top);
+ let inner_TR = box_TR + Point2D::new(-border.right, border.top);
+ let inner_BR = box_BR + Point2D::new(-border.right, -border.bottom);
+ let inner_BL = box_BL + Point2D::new(border.left, -border.bottom);
+
let rad_R: AzFloat = 0.;
let rad_BR = rad_R + f32::consts::FRAC_PI_4;
let rad_B = rad_BR + f32::consts::FRAC_PI_4;
@@ -457,7 +573,6 @@ impl<'a> PaintContext<'a> {
let rad_L = rad_BL + f32::consts::FRAC_PI_4;
let rad_TL = rad_L + f32::consts::FRAC_PI_4;
let rad_T = rad_TL + f32::consts::FRAC_PI_4;
- let rad_TR = rad_T + f32::consts::FRAC_PI_4;
fn dx(x: AzFloat) -> Point2D<AzFloat> {
Point2D::new(x, 0.)
@@ -475,12 +590,41 @@ impl<'a> PaintContext<'a> {
Point2D::new(0., if cond { dy } else { 0. })
}
+ fn compatible_borders_corner(border1_width: f32, border2_width: f32) -> bool {
+ (border1_width - border2_width).abs() <= f32::EPSILON
+ }
+
+ let distance_to_elbow_TL =
+ if border.top == border.left {
+ (radius.top_left - border.top).max(0.)
+ } else {
+ 0.
+ };
+ let distance_to_elbow_TR =
+ if border.top == border.right {
+ (radius.top_right - border.top).max(0.)
+ } else {
+ 0.
+ };
+ let distance_to_elbow_BR =
+ if border.right == border.bottom {
+ (radius.bottom_right - border.bottom).max(0.)
+ } else {
+ 0.
+ };
+ let distance_to_elbow_BL =
+ if border.left == border.bottom {
+ (radius.bottom_left - border.bottom).max(0.)
+ } else {
+ 0.
+ };
+
match direction {
Direction::Top => {
let edge_TL = box_TL + dx(radius.top_left.max(border.left));
let edge_TR = box_TR + dx(-radius.top_right.max(border.right));
- let edge_BR = edge_TR + dy(border.top);
- let edge_BL = edge_TL + dy(border.top);
+ let edge_BR = box_TR + dx(-border.right - distance_to_elbow_TR) + dy(border.top);
+ let edge_BL = box_TL + dx(border.left + distance_to_elbow_TL) + dy(border.top);
let corner_TL = edge_TL + dx_if(radius.top_left == 0., -border.left);
let corner_TR = edge_TR + dx_if(radius.top_right == 0., border.right);
@@ -497,11 +641,18 @@ impl<'a> PaintContext<'a> {
// the origin is the center of the arcs we're about to draw.
let origin = edge_TR + Point2D::new((border.right - radius.top_right).max(0.),
radius.top_right);
- // the elbow is the inside of the border's curve.
- let distance_to_elbow = (radius.top_right - border.top).max(0.);
-
- path_builder.arc(origin, radius.top_right, rad_T, rad_TR, false);
- path_builder.arc(origin, distance_to_elbow, rad_TR, rad_T, true);
+ let angle = if compatible_borders_corner(border.top, border.right) {
+ f32::consts::FRAC_PI_4
+ } else {
+ let line = Line { start: inner_TR, end: box_TR };
+ let ellipse = Ellipse { origin: origin, width: radius.top_right, height: radius.top_right };
+ PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap()
+ };
+
+ path_builder.arc(origin, radius.top_right, rad_T, rad_R - angle, false);
+ if distance_to_elbow_TR != 0. {
+ path_builder.arc(origin, distance_to_elbow_TR, rad_R - angle, rad_T, true);
+ }
}
match mode {
@@ -514,18 +665,26 @@ impl<'a> PaintContext<'a> {
if radius.top_left != 0. {
let origin = edge_TL + Point2D::new(-(border.left - radius.top_left).max(0.),
- radius.top_left);
- let distance_to_elbow = (radius.top_left - border.top).max(0.);
+ radius.top_left);
+ let angle = if compatible_borders_corner(border.top, border.left) {
+ f32::consts::FRAC_PI_4
+ } else {
+ let line = Line { start: box_TL, end: inner_TL };
+ let ellipse = Ellipse { origin: origin, width: radius.top_left, height: radius.top_left };
+ PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap()
+ };
- path_builder.arc(origin, distance_to_elbow, rad_T, rad_TL, true);
- path_builder.arc(origin, radius.top_left, rad_TL, rad_T, false);
+ if distance_to_elbow_TL != 0. {
+ path_builder.arc(origin, distance_to_elbow_TL, rad_T, rad_L + angle, true);
+ }
+ path_builder.arc(origin, radius.top_left, rad_L + angle, rad_T, false);
}
}
Direction::Left => {
let edge_TL = box_TL + dy(radius.top_left.max(border.top));
let edge_BL = box_BL + dy(-radius.bottom_left.max(border.bottom));
- let edge_TR = edge_TL + dx(border.left);
- let edge_BR = edge_BL + dx(border.left);
+ let edge_TR = box_TL + dx(border.left) + dy(border.top + distance_to_elbow_TL);
+ let edge_BR = box_BL + dx(border.left) + dy(-border.bottom - distance_to_elbow_BL);
let corner_TL = edge_TL + dy_if(radius.top_left == 0., -border.top);
let corner_BL = edge_BL + dy_if(radius.bottom_left == 0., border.bottom);
@@ -540,11 +699,20 @@ impl<'a> PaintContext<'a> {
if radius.top_left != 0. {
let origin = edge_TL + Point2D::new(radius.top_left,
- -(border.top - radius.top_left).max(0.));
- let distance_to_elbow = (radius.top_left - border.left).max(0.);
+ -(border.top - radius.top_left).max(0.));
- path_builder.arc(origin, radius.top_left, rad_L, rad_TL, false);
- path_builder.arc(origin, distance_to_elbow, rad_TL, rad_L, true);
+ let angle = if compatible_borders_corner(border.top, border.left) {
+ f32::consts::FRAC_PI_4
+ } else {
+ let line = Line { start: box_TL, end: inner_TL };
+ let ellipse = Ellipse { origin: origin, width: radius.top_left, height: radius.top_left };
+ PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap()
+ };
+
+ path_builder.arc(origin, radius.top_left, rad_L, rad_L + angle, false);
+ if distance_to_elbow_TL != 0. {
+ path_builder.arc(origin, distance_to_elbow_TL, rad_L + angle, rad_L, true);
+ }
}
match mode {
@@ -558,18 +726,28 @@ impl<'a> PaintContext<'a> {
if radius.bottom_left != 0. {
let origin = edge_BL +
Point2D::new(radius.bottom_left,
- (border.bottom - radius.bottom_left).max(0.));
- let distance_to_elbow = (radius.bottom_left - border.left).max(0.);
-
- path_builder.arc(origin, distance_to_elbow, rad_L, rad_BL, true);
- path_builder.arc(origin, radius.bottom_left, rad_BL, rad_L, false);
+ (border.bottom - radius.bottom_left).max(0.));
+ let angle = if compatible_borders_corner(border.bottom, border.left) {
+ f32::consts::FRAC_PI_4
+ } else {
+ let line = Line { start: box_BL, end: inner_BL };
+ let ellipse = Ellipse { origin: origin,
+ width: radius.bottom_left,
+ height: radius.bottom_left };
+ PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap()
+ };
+
+ if distance_to_elbow_BL != 0. {
+ path_builder.arc(origin, distance_to_elbow_BL, rad_L, rad_L - angle, true);
+ }
+ path_builder.arc(origin, radius.bottom_left, rad_L - angle, rad_L, false);
}
}
Direction::Right => {
let edge_TR = box_TR + dy(radius.top_right.max(border.top));
let edge_BR = box_BR + dy(-radius.bottom_right.max(border.bottom));
- let edge_TL = edge_TR + dx(-border.right);
- let edge_BL = edge_BR + dx(-border.right);
+ let edge_TL = box_TR + dx(-border.right) + dy(border.top + distance_to_elbow_TR);
+ let edge_BL = box_BR + dx(-border.right) + dy(-border.bottom - distance_to_elbow_BR);
let corner_TR = edge_TR + dy_if(radius.top_right == 0., -border.top);
let corner_BR = edge_BR + dy_if(radius.bottom_right == 0., border.bottom);
@@ -585,10 +763,18 @@ impl<'a> PaintContext<'a> {
if radius.top_right != 0. {
let origin = edge_TR + Point2D::new(-radius.top_right,
-(border.top - radius.top_right).max(0.));
- let distance_to_elbow = (radius.top_right - border.right).max(0.);
+ let angle = if compatible_borders_corner(border.top, border.right) {
+ f32::consts::FRAC_PI_4
+ } else {
+ let line = Line { start: inner_TR, end: box_TR };
+ let ellipse = Ellipse { origin: origin, width: radius.top_right, height: radius.top_right };
+ PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap()
+ };
- path_builder.arc(origin, distance_to_elbow, rad_R, rad_TR, true);
- path_builder.arc(origin, radius.top_right, rad_TR, rad_R, false);
+ if distance_to_elbow_TR != 0. {
+ path_builder.arc(origin, distance_to_elbow_TR, rad_R, rad_R - angle, true);
+ }
+ path_builder.arc(origin, radius.top_right, rad_R - angle, rad_R, false);
}
match mode {
@@ -602,18 +788,28 @@ impl<'a> PaintContext<'a> {
if radius.bottom_right != 0. {
let origin = edge_BR +
Point2D::new(-radius.bottom_right,
- (border.bottom - radius.bottom_right).max(0.));
- let distance_to_elbow = (radius.bottom_right - border.right).max(0.);
-
- path_builder.arc(origin, radius.bottom_right, rad_R, rad_BR, false);
- path_builder.arc(origin, distance_to_elbow, rad_BR, rad_R, true);
+ (border.bottom - radius.bottom_right).max(0.));
+ let angle = if compatible_borders_corner(border.bottom, border.right) {
+ f32::consts::FRAC_PI_4
+ } else {
+ let line = Line { start: inner_BR, end: box_BR };
+ let ellipse = Ellipse { origin: origin,
+ width: radius.bottom_right,
+ height: radius.bottom_right };
+ PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap()
+ };
+
+ path_builder.arc(origin, radius.bottom_right, rad_R, rad_R + angle, false);
+ if distance_to_elbow_BR != 0. {
+ path_builder.arc(origin, distance_to_elbow_BR, rad_R + angle, rad_R, true);
+ }
}
}
Direction::Bottom => {
let edge_BL = box_BL + dx(radius.bottom_left.max(border.left));
let edge_BR = box_BR + dx(-radius.bottom_right.max(border.right));
- let edge_TL = edge_BL + dy(-border.bottom);
- let edge_TR = edge_BR + dy(-border.bottom);
+ let edge_TL = box_BL + dy(-border.bottom) + dx(border.left + distance_to_elbow_BL);
+ let edge_TR = box_BR + dy(-border.bottom) + dx(-border.right - distance_to_elbow_BR);
let corner_BR = edge_BR + dx_if(radius.bottom_right == 0., border.right);
let corner_BL = edge_BL + dx_if(radius.bottom_left == 0., -border.left);
@@ -629,10 +825,20 @@ impl<'a> PaintContext<'a> {
if radius.bottom_right != 0. {
let origin = edge_BR + Point2D::new((border.right - radius.bottom_right).max(0.),
-radius.bottom_right);
- let distance_to_elbow = (radius.bottom_right - border.bottom).max(0.);
-
- path_builder.arc(origin, distance_to_elbow, rad_B, rad_BR, true);
- path_builder.arc(origin, radius.bottom_right, rad_BR, rad_B, false);
+ let angle = if compatible_borders_corner(border.bottom, border.right) {
+ f32::consts::FRAC_PI_4
+ } else {
+ let line = Line { start: inner_BR, end: box_BR };
+ let ellipse = Ellipse { origin: origin,
+ width: radius.bottom_right,
+ height: radius.bottom_right };
+ PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap()
+ };
+
+ if distance_to_elbow_BR != 0. {
+ path_builder.arc(origin, distance_to_elbow_BR, rad_B, rad_R + angle, true);
+ }
+ path_builder.arc(origin, radius.bottom_right, rad_R + angle, rad_B, false);
}
match mode {
@@ -645,11 +851,21 @@ impl<'a> PaintContext<'a> {
if radius.bottom_left != 0. {
let origin = edge_BL - Point2D::new((border.left - radius.bottom_left).max(0.),
- radius.bottom_left);
- let distance_to_elbow = (radius.bottom_left - border.bottom).max(0.);
-
- path_builder.arc(origin, radius.bottom_left, rad_B, rad_BL, false);
- path_builder.arc(origin, distance_to_elbow, rad_BL, rad_B, true);
+ radius.bottom_left);
+ let angle = if compatible_borders_corner(border.bottom, border.left) {
+ f32::consts::FRAC_PI_4
+ } else {
+ let line = Line { start: box_BL, end: inner_BL };
+ let ellipse = Ellipse { origin: origin,
+ width: radius.bottom_left,
+ height: radius.bottom_left };
+ PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap()
+ };
+
+ path_builder.arc(origin, radius.bottom_left, rad_B, rad_L - angle, false);
+ if distance_to_elbow_BL != 0. {
+ path_builder.arc(origin, distance_to_elbow_BL, rad_L - angle, rad_B, true);
+ }
}
}
}
diff --git a/tests/ref/basic.list b/tests/ref/basic.list
index ed4e0d91a4b..a7e3d2154ba 100644
--- a/tests/ref/basic.list
+++ b/tests/ref/basic.list
@@ -61,6 +61,7 @@ flaky_cpu == append_style_a.html append_style_b.html
== border_code_tag.html border_code_tag_ref.html
== border_collapse_missing_cell_a.html border_collapse_missing_cell_ref.html
== border_collapse_simple_a.html border_collapse_simple_ref.html
+== border_radius_asymmetric_sizes_a.html border_radius_asymmetric_sizes_ref.html
== border_radius_clip_a.html border_radius_clip_ref.html
!= border_radius_dashed_a.html border_radius_dashed_ref.html
== border_radius_overlapping_a.html border_radius_overlapping_ref.html
diff --git a/tests/ref/border_radius_asymmetric_sizes_a.html b/tests/ref/border_radius_asymmetric_sizes_a.html
new file mode 100644
index 00000000000..94676b11941
--- /dev/null
+++ b/tests/ref/border_radius_asymmetric_sizes_a.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
+ <meta content="utf-8" http-equiv="encoding">
+ <style type="text/css">
+ div.box {
+ background: white;
+ border-width: 10px 10px 10px 10px;
+ border-color: yellow red green blue;
+ border-radius: 10px;
+ border-style: solid;
+ height: 190px;
+ width: 190px;
+ }
+ div.top {
+ border-top-width: 30px;
+ }
+ div.right {
+ border-right-width: 30px;
+ }
+ div.bottom {
+ border-bottom-width: 30px;
+ }
+ div.left {
+ border-left-width: 30px;
+ }
+ div.radius10px {
+ border-radius: 10px;
+ }
+ div.radius20px {
+ border-radius: 20px;
+ }
+ div.radius30px {
+ border-radius: 30px;
+ }
+ div.radius40px {
+ border-radius: 40px;
+ }
+
+ #box2, #box4, #box6, #box8, #box10, #box12, #box14 {
+ width: 170px;
+ }
+ </style>
+ </head>
+ <body>
+ <h2>Border Radius - 10px</h2>
+ Box#1<div id="box1" class="box top"></div><br>
+ Box#2<div id="box2" class="box right"></div><br>
+ Box#3<div id="box3" class="box bottom"></div><br>
+ Box#4<div id="box4" class="box left"></div><br>
+
+ <h2>Border Radius - 20px</h2>
+ Box#5<div id="box5" class="box top radius20px"></div><br>
+ Box#6<div id="box6" class="box right radius20px"></div><br>
+ Box#7<div id="box7" class="box bottom radius20px"></div><br>
+ Box#8<div id="box8" class="box left radius20px"></div><br>
+
+ <h2>Border Radius - 30px</h2>
+ Box#9<div id="box9" class="box top radius30px"></div><br>
+ Box#10<div id="box10" class="box right radius30px"></div><br>
+ Box#11<div id="box11" class="box bottom radius30px"></div><br>
+ Box#12<div id="box12" class="box left radius30px"></div><br>
+
+ <h2>Border Radius - 40px</h2>
+ Box#13<div id="box13" class="box top radius40px"></div><br>
+ Box#14<div id="box14" class="box right radius40px"></div><br>
+ Box#15<div id="box15" class="box bottom radius40px"></div><br>
+ Box#16<div id="box16" class="box left radius40px"></div><br>
+ </body>
+</html>
diff --git a/tests/ref/border_radius_asymmetric_sizes_ref.html b/tests/ref/border_radius_asymmetric_sizes_ref.html
new file mode 100644
index 00000000000..4993ae6fd7d
--- /dev/null
+++ b/tests/ref/border_radius_asymmetric_sizes_ref.html
@@ -0,0 +1,217 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
+ <meta content="utf-8" http-equiv="encoding">
+ <style type="text/css">
+ .box-top {
+ background: white;
+ width: 190px;
+ height: 0px;
+ margin: 0px;
+ border-style: solid;
+ border-color: yellow red green blue;
+ }
+ .box-middle {
+ background: white;
+ width: 190px;
+ height: 190px;
+ margin: 0px;
+ border-style: solid;
+ border-color: yellow red green blue;
+ }
+ .box-bottom {
+ background: white;
+ width: 190px;
+ height: 0px;
+ margin: 0px;
+ border-style: solid;
+ border-color: yellow red green blue;
+ }
+ .top-radius-10 {
+ border-top-left-radius: 10px;
+ border-top-right-radius: 10px;
+ }
+ .bottom-radius-10 {
+ border-bottom-left-radius: 10px;
+ border-bottom-right-radius: 10px;
+ }
+ .top-radius-20 {
+ border-top-left-radius: 20px;
+ border-top-right-radius: 20px;
+ }
+ .bottom-radius-20 {
+ border-bottom-left-radius: 20px;
+ border-bottom-right-radius: 20px;
+ }
+ .top-radius-30 {
+ border-top-left-radius: 30px;
+ border-top-right-radius: 30px;
+ }
+ .bottom-radius-30 {
+ border-bottom-left-radius: 30px;
+ border-bottom-right-radius: 30px;
+ }
+ .top-radius-40 {
+ border-top-left-radius: 40px;
+ border-top-right-radius: 40px;
+ }
+ .bottom-radius-40 {
+ border-bottom-left-radius: 40px;
+ border-bottom-right-radius: 40px;
+ }
+ .box1-top {
+ border-top-width: 30px;
+ border-right-width: 10px;
+ border-bottom-width: 0px;
+ border-left-width: 10px;
+ }
+ .box1-middle {
+ border-width: 0px 10px 0px 10px;
+ }
+ .box1-bottom {
+ border-width: 0px 10px 10px 10px;
+ }
+ .box2-top {
+ width: 170px;
+ border-width: 10px 30px 0px 10px;
+ }
+ .box2-middle {
+ width: 170px;
+ border-width: 0px 30px 0px 10px;
+ }
+ .box2-bottom {
+ width: 170px;
+ border-width: 0px 30px 10px 10px;
+ }
+ .box3-top {
+ border-width: 10px 10px 0px 10px;
+ }
+ .box3-middle {
+ border-width: 0px 10px 0px 10px;
+ }
+ .box3-bottom {
+ border-top-width: 0px;
+ border-left-width: 10px;
+ border-right-width: 10px;
+ border-bottom-width: 30px;
+ }
+ .box4-top {
+ width: 170px;
+ border-width: 10px 10px 0px 30px;
+ }
+ .box4-middle {
+ width: 170px;
+ border-width: 0px 10px 0px 30px;
+ }
+ .box4-bottom {
+ width: 170px;
+ border-top-width: 0px;
+ border-left-width: 30px;
+ border-right-width: 10px;
+ border-bottom-width: 10px;
+ }
+ </style>
+ </head>
+ <body>
+ <h2>Border Radius - 10px</h2>
+ Box#1
+ <div id="box1-top" class="box-top box1-top top-radius-10"></div>
+ <div id="box1-middle" class="box-middle box1-middle middle-radius-10"></div>
+ <div id="box1-bottom" class="box-bottom box1-bottom bottom-radius-10"></div>
+ <br>
+
+ Box#2
+ <div id="box2-top" class="box-top box2-top top-radius-10"></div>
+ <div id="box2-middle" class="box-middle box2-middle middle-radius-10"></div>
+ <div id="box2-bottom" class="box-bottom box2-bottom bottom-radius-10"></div>
+ <br>
+
+ Box#3
+ <div id="box3-top" class="box-top box3-top top-radius-10"></div>
+ <div id="box3-middle" class="box-middle box3-middle middle-radius-10"></div>
+ <div id="box3-bottom" class="box-bottom box3-bottom bottom-radius-10"></div>
+ <br>
+
+ Box#4
+ <div id="box4-top" class="box-top box4-top top-radius-10"></div>
+ <div id="box4-middle" class="box-middle box4-middle middle-radius-10"></div>
+ <div id="box4-bottom" class="box-bottom box4-bottom bottom-radius-10"></div>
+ <br>
+
+ <h2>Border Radius - 20px</h2>
+ Box#5
+ <div id="box5-top" class="box-top box1-top top-radius-20"></div>
+ <div id="box5-middle" class="box-middle box1-middle middle-radius-20"></div>
+ <div id="box5-bottom" class="box-bottom box1-bottom bottom-radius-20"></div>
+ <br>
+
+ Box#6
+ <div id="box6-top" class="box-top box2-top top-radius-20"></div>
+ <div id="box6-middle" class="box-middle box2-middle middle-radius-20"></div>
+ <div id="box6-bottom" class="box-bottom box2-bottom bottom-radius-20"></div>
+ <br>
+
+ Box#7
+ <div id="box7-top" class="box-top box3-top top-radius-20"></div>
+ <div id="box7-middle" class="box-middle box3-middle middle-radius-20"></div>
+ <div id="box7-bottom" class="box-bottom box3-bottom bottom-radius-20"></div>
+ <br>
+
+ Box#8
+ <div id="box8-top" class="box-top box4-top top-radius-20"></div>
+ <div id="box8-middle" class="box-middle box4-middle middle-radius-20"></div>
+ <div id="box8-bottom" class="box-bottom box4-bottom bottom-radius-20"></div>
+ <br>
+
+ <h2>Border Radius - 30px</h2>
+ Box#9
+ <div id="box9-top" class="box-top box1-top top-radius-30"></div>
+ <div id="box9-middle" class="box-middle box1-middle middle-radius-30"></div>
+ <div id="box9-bottom" class="box-bottom box1-bottom bottom-radius-30"></div>
+ <br>
+
+ Box#10
+ <div id="box10-top" class="box-top box2-top top-radius-30"></div>
+ <div id="box10-middle" class="box-middle box2-middle middle-radius-30"></div>
+ <div id="box10-bottom" class="box-bottom box2-bottom bottom-radius-30"></div>
+ <br>
+
+ Box#11
+ <div id="box11-top" class="box-top box3-top top-radius-30"></div>
+ <div id="box11-middle" class="box-middle box3-middle middle-radius-30"></div>
+ <div id="box11-bottom" class="box-bottom box3-bottom bottom-radius-30"></div>
+ <br>
+
+ Box#12
+ <div id="box12-top" class="box-top box4-top top-radius-30"></div>
+ <div id="box12-middle" class="box-middle box4-middle middle-radius-30"></div>
+ <div id="box12-bottom" class="box-bottom box4-bottom bottom-radius-30"></div>
+ <br>
+
+ <h2>Border Radius - 40px</h2>
+ Box#13
+ <div id="box13-top" class="box-top box1-top top-radius-40"></div>
+ <div id="box13-middle" class="box-middle box1-middle middle-radius-40"></div>
+ <div id="box13-bottom" class="box-bottom box1-bottom bottom-radius-40"></div>
+ <br>
+
+ Box#14
+ <div id="box14-top" class="box-top box2-top top-radius-40"></div>
+ <div id="box14-middle" class="box-middle box2-middle middle-radius-40"></div>
+ <div id="box14-bottom" class="box-bottom box2-bottom bottom-radius-40"></div>
+ <br>
+
+ Box#15
+ <div id="box15-top" class="box-top box3-top top-radius-40"></div>
+ <div id="box15-middle" class="box-middle box3-middle middle-radius-40"></div>
+ <div id="box15-bottom" class="box-bottom box3-bottom bottom-radius-40"></div>
+ <br>
+
+ Box#16
+ <div id="box16-top" class="box-top box4-top top-radius-40"></div>
+ <div id="box16-middle" class="box-middle box4-middle middle-radius-40"></div>
+ <div id="box16-bottom" class="box-bottom box4-bottom bottom-radius-40"></div>
+ <br>
+ </body>
+</html>