mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Add groove and ridge border support.
This commit is contained in:
parent
90a0bcfa78
commit
792666ec87
3 changed files with 315 additions and 5 deletions
|
@ -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 {
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue