Add groove and ridge border support.

This commit is contained in:
Bryan Bell 2014-05-20 02:20:26 -07:00
parent 90a0bcfa78
commit 792666ec87
3 changed files with 315 additions and 5 deletions

View file

@ -43,6 +43,15 @@ enum DashSize {
DashedBorder = 3
}
enum ShortEnd {
TopShort,
LeftShort,
RightShort,
BottomShort,
NoneShort,
AllShort,
}
impl<'a> RenderContext<'a> {
pub fn get_draw_target(&self) -> &'a DrawTarget {
self.draw_target
@ -159,8 +168,14 @@ impl<'a> RenderContext<'a> {
border_style::solid => {
self.draw_solid_border_segment(direction,bounds,border,color_select);
}
border_style::groove => {
self.draw_groove_border_segment(direction, bounds, border, color_select);
}
border_style::ridge => {
self.draw_ridge_border_segment(direction, bounds, border, color_select);
}
//FIXME(sammykim): Five more styles should be implemented.
//double, groove, ridge, inset, outset
//double, inset, outset
}
}
@ -178,8 +193,14 @@ impl<'a> RenderContext<'a> {
border_style::solid => {
self.draw_solid_border_segment(Right,bounds,border,color);
}
border_style::groove => {
self.draw_groove_border_segment(Right, bounds, border, color);
}
border_style::ridge => {
self.draw_ridge_border_segment(Right, bounds, border, color);
}
//FIXME(sankha93): Five more styles should be implemented.
//double, groove, ridge, inset, outset
//double, inset, outset
}
}
@ -283,6 +304,284 @@ impl<'a> RenderContext<'a> {
let path = path_builder.finish();
self.draw_target.fill(&path, &ColorPattern(color), &draw_opts);
}
fn get_scaled_bounds(&self,
bounds : &Rect<Au>,
border : SideOffsets2D<f32>,
shrink_factor : f32) -> (Point2D<f32>, Point2D<f32>, Point2D<f32>, Point2D<f32>) {
let rect = bounds.to_azure_rect();
let scaled_border = SideOffsets2D::new(shrink_factor * border.top,
shrink_factor * border.right,
shrink_factor * border.bottom,
shrink_factor * border.left);
let left_top = Point2D(rect.origin.x, rect.origin.y);
let right_top = Point2D(rect.origin.x + rect.size.width, rect.origin.y);
let left_bottom = Point2D(rect.origin.x, rect.origin.y + rect.size.height);
let right_bottom = Point2D(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
let scaled_left_top = left_top + Point2D(scaled_border.left,
scaled_border.top);
let scaled_right_top = right_top + Point2D(-scaled_border.right,
scaled_border.top);
let scaled_left_bottom = left_bottom + Point2D(scaled_border.left,
-scaled_border.bottom);
let scaled_right_bottom = right_bottom + Point2D(-scaled_border.right,
-scaled_border.bottom);
return (scaled_left_top, scaled_right_top, scaled_left_bottom, scaled_right_bottom);
}
fn draw_groove_border_segment(&self,
direction : Direction,
bounds : &Rect<Au>,
border : SideOffsets2D<f32>,
color : Color) {
let rect = bounds.to_azure_rect();
let left_top = Point2D(rect.origin.x, rect.origin.y);
let right_top = Point2D(rect.origin.x + rect.size.width, rect.origin.y);
let left_bottom = Point2D(rect.origin.x, rect.origin.y + rect.size.height);
let right_bottom = Point2D(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
// shrink the bounds by 2/3 of the border, leaving the innermost 1/3 of the border
let (inner_left_top, inner_right_top, inner_left_bottom, inner_right_bottom) =
self.get_scaled_bounds(bounds, border, 2.0/3.0);
// shrink the bounds by 1/3 of the border, leaving the innermost 2/3 of the border
let (middle_left_top, middle_right_top, middle_left_bottom, middle_right_bottom) =
self.get_scaled_bounds(bounds, border, 1.0/3.0);
let scaled_border = SideOffsets2D::new((1.0/3.0) * border.top,
(1.0/3.0) * border.right,
(1.0/3.0) * border.bottom,
(1.0/3.0) * border.left);
let darker_color = Color(color.r * 1.0/3.0, color.g * 1.0/3.0, color.b * 1.0/3.0, color.a);
match direction {
Top => {
// outer portion of the border
self.draw_short_ended_path(left_top, right_top, left_bottom, right_bottom,
direction, scaled_border, darker_color, LeftShort);
// middle portion of the border
self.draw_short_ended_path(middle_left_top, middle_right_top, middle_left_bottom,
middle_right_bottom, direction, scaled_border, darker_color,
LeftShort);
// inner portion of the border
self.draw_short_ended_path(inner_left_top, inner_right_top, inner_left_bottom,
inner_right_bottom, direction, scaled_border, color,
LeftShort);
}
Left => {
// outer portion of the border
self.draw_short_ended_path(left_top, right_top, left_bottom, right_bottom,
direction, scaled_border, darker_color, NoneShort);
// middle portion of the border
self.draw_short_ended_path(middle_left_top, middle_right_top, middle_left_bottom,
middle_right_bottom, direction, scaled_border, darker_color,
NoneShort);
// inner portion of the border
self.draw_short_ended_path(inner_left_top, inner_right_top, inner_left_bottom,
inner_right_bottom, direction, scaled_border, color,
NoneShort);
}
Right => {
// outer portion of the border
self.draw_short_ended_path(left_top, right_top, left_bottom, right_bottom,
direction, scaled_border, color, AllShort);
// middle portion of the border
self.draw_short_ended_path(middle_left_top, middle_right_top, middle_left_bottom,
middle_right_bottom, direction, scaled_border, darker_color,
AllShort);
// inner portion of the border
self.draw_short_ended_path(inner_left_top, inner_right_top, inner_left_bottom,
inner_right_bottom, direction, scaled_border, darker_color,
AllShort);
}
Bottom => {
// outer portion of the border
self.draw_short_ended_path(left_top, right_top, left_bottom, right_bottom,
direction, scaled_border, color, LeftShort);
// middle portion of the border
self.draw_short_ended_path(middle_left_top, middle_right_top, middle_left_bottom,
middle_right_bottom, direction, scaled_border, darker_color,
LeftShort);
// inner portion of the border
self.draw_short_ended_path(inner_left_top, inner_right_top, inner_left_bottom,
inner_right_bottom, direction, scaled_border, darker_color,
LeftShort);
}
}
}
fn draw_ridge_border_segment(&self,
direction : Direction,
bounds : &Rect<Au>,
border : SideOffsets2D<f32>,
color : Color) {
let rect = bounds.to_azure_rect();
let left_top = Point2D(rect.origin.x, rect.origin.y);
let right_top = Point2D(rect.origin.x + rect.size.width, rect.origin.y);
let left_bottom = Point2D(rect.origin.x, rect.origin.y + rect.size.height);
let right_bottom = Point2D(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
// shrink the bounds by 2/3 of the border, leaving the innermost 1/3 of the border
let (inner_left_top, inner_right_top, inner_left_bottom, inner_right_bottom) =
self.get_scaled_bounds(bounds, border, 2.0/3.0);
// shrink the bounds by 1/3 of the border, leaving the innermost 2/3 of the border
let (middle_left_top, middle_right_top, middle_left_bottom, middle_right_bottom) =
self.get_scaled_bounds(bounds, border, 1.0/3.0);
let scaled_border = SideOffsets2D::new((1.0/3.0) * border.top,
(1.0/3.0) * border.right,
(1.0/3.0) * border.bottom,
(1.0/3.0) * border.left);
let darker_color = Color(color.r * 2.0/3.0, color.g * 2.0/3.0, color.b * 2.0/3.0, color.a);
match direction {
Top => {
// outer portion of the border
self.draw_short_ended_path(left_top, right_top, left_bottom, right_bottom,
direction, scaled_border, color, LeftShort);
// middle portion of the border
self.draw_short_ended_path(middle_left_top, middle_right_top, middle_left_bottom,
middle_right_bottom, direction, scaled_border, color,
LeftShort);
// inner portion of the border
self.draw_short_ended_path(inner_left_top, inner_right_top, inner_left_bottom,
inner_right_bottom, direction, scaled_border, darker_color,
LeftShort);
}
Left => {
// outer portion of the border
self.draw_short_ended_path(left_top, right_top, left_bottom, right_bottom,
direction, scaled_border, color, NoneShort);
// middle portion of the border
self.draw_short_ended_path(middle_left_top, middle_right_top, middle_left_bottom,
middle_right_bottom, direction, scaled_border, color,
NoneShort);
// inner portion of the border
self.draw_short_ended_path(inner_left_top, inner_right_top, inner_left_bottom,
inner_right_bottom, direction, scaled_border, darker_color,
NoneShort);
}
Right => {
// outer portion of the border
self.draw_short_ended_path(left_top, right_top, left_bottom, right_bottom,
direction, scaled_border, darker_color, AllShort);
// middle portion of the border
self.draw_short_ended_path(middle_left_top, middle_right_top, middle_left_bottom,
middle_right_bottom, direction, scaled_border, color,
AllShort);
// inner portion of the border
self.draw_short_ended_path(inner_left_top, inner_right_top, inner_left_bottom,
inner_right_bottom, direction, scaled_border, color,
AllShort);
}
Bottom => {
// outer portion of the border
self.draw_short_ended_path(left_top, right_top, left_bottom, right_bottom,
direction, scaled_border, darker_color, LeftShort);
// middle portion of the border
self.draw_short_ended_path(middle_left_top, middle_right_top, middle_left_bottom,
middle_right_bottom, direction, scaled_border, color,
LeftShort);
// inner portion of the border
self.draw_short_ended_path(inner_left_top, inner_right_top, inner_left_bottom,
inner_right_bottom, direction, scaled_border, color,
LeftShort);
}
}
}
fn draw_square_border_path(&self,
left_top : Point2D<f32>,
right_top : Point2D<f32>,
left_bottom : Point2D<f32>,
right_bottom : Point2D<f32>,
direction : Direction,
border : SideOffsets2D<f32>,
color : Color) {
let draw_opts = DrawOptions(1.0 , 0);
let path_builder = self.draw_target.create_path_builder();
match direction {
Top => {
path_builder.move_to(left_top);
path_builder.line_to(right_top);
path_builder.line_to(right_top + Point2D(0.0, border.top));
path_builder.line_to(left_top + Point2D(0.0, border.top));
}
Left => {
path_builder.move_to(left_top);
path_builder.line_to(left_top + Point2D(border.left, 0.0));
path_builder.line_to(left_bottom + Point2D(border.left, 0.0));
path_builder.line_to(left_bottom);
}
Right => {
path_builder.move_to(right_top);
path_builder.line_to(right_bottom);
path_builder.line_to(right_bottom + Point2D(-border.right, 0.0));
path_builder.line_to(right_top + Point2D(-border.right, 0.0));
}
Bottom => {
path_builder.move_to(left_bottom);
path_builder.line_to(left_bottom + Point2D(0.0, -border.bottom));
path_builder.line_to(right_bottom + Point2D(0.0, -border.bottom));
path_builder.line_to(right_bottom);
}
}
let path = path_builder.finish();
self.draw_target.fill(&path, &ColorPattern(color), &draw_opts);
}
fn draw_short_ended_path(&self,
left_top : Point2D<f32>,
right_top : Point2D<f32>,
left_bottom : Point2D<f32>,
right_bottom : Point2D<f32>,
direction : Direction,
border : SideOffsets2D<f32>,
color : Color,
short_end : ShortEnd) {
match direction {
Top | Bottom => {
let left_border_short = match short_end { LeftShort | AllShort => { border.left }
_ => { 0.0 }};
let right_border_short = match short_end { RightShort | AllShort => { border.right }
_ => { 0.0 }};
self.draw_square_border_path(left_top + Point2D(left_border_short, 0.0),
right_top + Point2D(-right_border_short, 0.0),
left_bottom + Point2D(left_border_short, 0.0),
right_bottom + Point2D(-right_border_short, 0.0),
direction,
SideOffsets2D::new(border.top,
border.right - right_border_short,
border.bottom,
border.left - left_border_short),
color);
}
Left | Right => {
let top_border_short = match short_end { TopShort | AllShort => { border.top }
_ => { 0.0 }};
let bottom_border_short = match short_end { BottomShort | AllShort => { border.bottom }
_ => { 0.0 }};
self.draw_square_border_path(left_top + Point2D(0.0, top_border_short),
right_top + Point2D(0.0, top_border_short),
left_bottom + Point2D(0.0, -bottom_border_short),
right_bottom + Point2D(0.0, -bottom_border_short),
direction,
SideOffsets2D::new(border.top - top_border_short,
border.right,
border.bottom - bottom_border_short,
border.left),
color);
}
}
}
}
trait ToAzureRect {

View file

@ -221,8 +221,8 @@ pub mod longhands {
${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")}
% endfor
// double groove ridge insed outset
${single_keyword("border-top-style", values="none solid dotted dashed hidden")}
// double insed outset
${single_keyword("border-top-style", values="none solid dotted dashed hidden groove ridge")}
% for side in ["right", "bottom", "left"]:
<%self:longhand name="border-${side}-style", no_super="True">

View file

@ -26,6 +26,16 @@
border-width: 10px;
border-color: green red yellow black;
}
#groove{
border-style: groove;
border-width: 10px;
border-color: green red yellow black;
}
#ridge{
border-style: ridge;
border-width: 10px;
border-color: green red yellow black;
}
#diamond1{
width: 0;
height: 0;
@ -47,8 +57,9 @@
<div id="hidden"> hidden test.</div>
<div id="solid"> solid test</div>
<div id="dashed"> dashed test</div>
<!-- It doesn't show anything yet. -->
<div id="dotted"> dotted test</div>
<div id="groove"> groove test</div>
<div id="ridge"> ridge test</div>
<!-- It's a Diamond -->
<div id="diamond1"></div>
<div id="diamond2"></div>