diff options
-rw-r--r-- | components/gfx/paint_context.rs | 304 | ||||
-rw-r--r-- | tests/ref/basic.list | 1 | ||||
-rw-r--r-- | tests/ref/border_radius_asymmetric_sizes_a.html | 71 | ||||
-rw-r--r-- | tests/ref/border_radius_asymmetric_sizes_ref.html | 217 |
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> |