mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +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
|
DashedBorder = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ShortEnd {
|
||||||
|
TopShort,
|
||||||
|
LeftShort,
|
||||||
|
RightShort,
|
||||||
|
BottomShort,
|
||||||
|
NoneShort,
|
||||||
|
AllShort,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> RenderContext<'a> {
|
impl<'a> RenderContext<'a> {
|
||||||
pub fn get_draw_target(&self) -> &'a DrawTarget {
|
pub fn get_draw_target(&self) -> &'a DrawTarget {
|
||||||
self.draw_target
|
self.draw_target
|
||||||
|
@ -159,8 +168,14 @@ impl<'a> RenderContext<'a> {
|
||||||
border_style::solid => {
|
border_style::solid => {
|
||||||
self.draw_solid_border_segment(direction,bounds,border,color_select);
|
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.
|
//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 => {
|
border_style::solid => {
|
||||||
self.draw_solid_border_segment(Right,bounds,border,color);
|
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.
|
//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();
|
let path = path_builder.finish();
|
||||||
self.draw_target.fill(&path, &ColorPattern(color), &draw_opts);
|
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 {
|
trait ToAzureRect {
|
||||||
|
|
|
@ -221,8 +221,8 @@ pub mod longhands {
|
||||||
${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")}
|
${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")}
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
// double groove ridge insed outset
|
// double insed outset
|
||||||
${single_keyword("border-top-style", values="none solid dotted dashed hidden")}
|
${single_keyword("border-top-style", values="none solid dotted dashed hidden groove ridge")}
|
||||||
|
|
||||||
% for side in ["right", "bottom", "left"]:
|
% for side in ["right", "bottom", "left"]:
|
||||||
<%self:longhand name="border-${side}-style", no_super="True">
|
<%self:longhand name="border-${side}-style", no_super="True">
|
||||||
|
|
|
@ -26,6 +26,16 @@
|
||||||
border-width: 10px;
|
border-width: 10px;
|
||||||
border-color: green red yellow black;
|
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{
|
#diamond1{
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
@ -47,8 +57,9 @@
|
||||||
<div id="hidden"> hidden test.</div>
|
<div id="hidden"> hidden test.</div>
|
||||||
<div id="solid"> solid test</div>
|
<div id="solid"> solid test</div>
|
||||||
<div id="dashed"> dashed test</div>
|
<div id="dashed"> dashed test</div>
|
||||||
<!-- It doesn't show anything yet. -->
|
|
||||||
<div id="dotted"> dotted test</div>
|
<div id="dotted"> dotted test</div>
|
||||||
|
<div id="groove"> groove test</div>
|
||||||
|
<div id="ridge"> ridge test</div>
|
||||||
<!-- It's a Diamond -->
|
<!-- It's a Diamond -->
|
||||||
<div id="diamond1"></div>
|
<div id="diamond1"></div>
|
||||||
<div id="diamond2"></div>
|
<div id="diamond2"></div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue