From 792666ec87a1766fbd792eba1d7e3413aedc59d5 Mon Sep 17 00:00:00 2001 From: Bryan Bell Date: Tue, 20 May 2014 02:20:26 -0700 Subject: [PATCH 1/6] Add groove and ridge border support. --- src/components/gfx/render_context.rs | 303 +++++++++++++++++++++++- src/components/style/properties.rs.mako | 4 +- src/test/html/test_border.html | 13 +- 3 files changed, 315 insertions(+), 5 deletions(-) diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index 95b834c3d5d..46278b97ca3 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -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, + border : SideOffsets2D, + shrink_factor : f32) -> (Point2D, Point2D, Point2D, Point2D) { + + 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, + border : SideOffsets2D, + 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, + border : SideOffsets2D, + 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, + right_top : Point2D, + left_bottom : Point2D, + right_bottom : Point2D, + direction : Direction, + border : SideOffsets2D, + 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, + right_top : Point2D, + left_bottom : Point2D, + right_bottom : Point2D, + direction : Direction, + border : SideOffsets2D, + 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 { diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index 08d4c3f3968..c510e71924b 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -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"> diff --git a/src/test/html/test_border.html b/src/test/html/test_border.html index 7015102d726..1446598ad59 100755 --- a/src/test/html/test_border.html +++ b/src/test/html/test_border.html @@ -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 @@
hidden test.
solid test
dashed test
-
dotted test
+
groove test
+
ridge test
From afe0c0bfa69ebb742500a05ae756eea48f6517fe Mon Sep 17 00:00:00 2001 From: Bryan Bell Date: Tue, 20 May 2014 19:36:11 -0700 Subject: [PATCH 2/6] Add ref test for dashed, dotted, groove, and ridge borders. Don't line up :'s in render_context.rs (style) --- src/components/gfx/render_context.rs | 54 +++++++++++++-------------- src/test/ref/basic.list | 1 + src/test/ref/borders.png | Bin 0 -> 3075 bytes src/test/ref/borders_a.html | 50 +++++++++++++++++++++++++ src/test/ref/borders_b.html | 19 ++++++++++ 5 files changed, 97 insertions(+), 27 deletions(-) create mode 100644 src/test/ref/borders.png create mode 100644 src/test/ref/borders_a.html create mode 100644 src/test/ref/borders_b.html diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index 46278b97ca3..e58c318f5c5 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -306,9 +306,9 @@ impl<'a> RenderContext<'a> { } fn get_scaled_bounds(&self, - bounds : &Rect, - border : SideOffsets2D, - shrink_factor : f32) -> (Point2D, Point2D, Point2D, Point2D) { + bounds: &Rect, + border: SideOffsets2D, + shrink_factor: f32) -> (Point2D, Point2D, Point2D, Point2D) { let rect = bounds.to_azure_rect(); let scaled_border = SideOffsets2D::new(shrink_factor * border.top, @@ -334,10 +334,10 @@ impl<'a> RenderContext<'a> { } fn draw_groove_border_segment(&self, - direction : Direction, - bounds : &Rect, - border : SideOffsets2D, - color : Color) { + direction: Direction, + bounds: &Rect, + border: SideOffsets2D, + 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); @@ -414,10 +414,10 @@ impl<'a> RenderContext<'a> { } fn draw_ridge_border_segment(&self, - direction : Direction, - bounds : &Rect, - border : SideOffsets2D, - color : Color) { + direction: Direction, + bounds: &Rect, + border: SideOffsets2D, + 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); @@ -536,21 +536,21 @@ impl<'a> RenderContext<'a> { } fn draw_short_ended_path(&self, - left_top : Point2D, - right_top : Point2D, - left_bottom : Point2D, - right_bottom : Point2D, - direction : Direction, - border : SideOffsets2D, - color : Color, - short_end : ShortEnd) { + left_top: Point2D, + right_top: Point2D, + left_bottom: Point2D, + right_bottom: Point2D, + direction: Direction, + border: SideOffsets2D, + 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 }}; + 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), @@ -563,10 +563,10 @@ impl<'a> RenderContext<'a> { 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 }}; + 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), diff --git a/src/test/ref/basic.list b/src/test/ref/basic.list index 43def47ea67..566bb3b2024 100644 --- a/src/test/ref/basic.list +++ b/src/test/ref/basic.list @@ -16,6 +16,7 @@ == root_height_a.html root_height_b.html == png_rgba_colorspace_a.html png_rgba_colorspace_b.html == border_style_none_a.html border_style_none_b.html +== borders_a.html borders_b.html == acid1_a.html acid1_b.html # text_decoration_propagation_a.html text_decoration_propagation_b.html # inline_text_align_a.html inline_text_align_b.html diff --git a/src/test/ref/borders.png b/src/test/ref/borders.png new file mode 100644 index 0000000000000000000000000000000000000000..a0abba83ff6bbc71ea86fc0f4ef841d424a2fc52 GIT binary patch literal 3075 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i0*Z)=h^jL%aG&yYaSW-L^Y-q+z}o>L z4uMk^&ib;r%HXYo?Go8k=Q;CxRNV{SHdv-VWxV$zwfy<%pYx`r?qp_I@cC`MJ_AER zHj5a8gHHk@!x2ozyX$p^wtnJOr=LCyGS9zRneu$%T=z0LC?mf5`CDH9{oTSk3=K05 zFfnv+;%D60qNDwNj^FI>)7JUEt^NJByt4gj{q^1G#%|xTnP?MV`M$gS_}bj%rw?C? zU7dDzmTC62HIbXmjeakCzpb!|l|eu_f`P%X5kDh(|H<0V_b%BlH_Nx!dwZArRiF`I zv%Y;xn~ObQFoWvfL$&Ykuis{4cpw}ZcjpNoLxCt0H-o~q&!^|v>aj5F+w=7J$Eofu z3=H9l8yFapKyqdK-=FXIm*M{?$G{+ev*yOf<9;xyZJz}n>VNj$&Bk!xZ2`<58*BSH zp8s^pW?-nvNoKX3|1(-0*>@X1&p#OTb6N%igI_UR%jbTM<;S(xFfx4jsl&g#{v8X@ zUNw*{mp6Ud&$2wz>f`0ZuG1MAez45rTd)6YYF`mdD>&3{|CC&_xbpRM1_txA%71@< z{kW74)V$6G6e{QLKdHO)>B>5w*&B1~DqiU$T>oD1;VJc}j0|~qBOIU0iCY~+P8@Uh zpZt5WmxqC2`I*hL?=Ui~a{`$bCNIdu@WBjj2H26HP#R^71_C6%jHZOqlrWkSMsvYv hE*Q-P!!Z}wGcKEM>Z{YcrV7}&XYh3Oa{)GungEoejVJ&B literal 0 HcmV?d00001 diff --git a/src/test/ref/borders_a.html b/src/test/ref/borders_a.html new file mode 100644 index 00000000000..4bd08b11a2a --- /dev/null +++ b/src/test/ref/borders_a.html @@ -0,0 +1,50 @@ + + + + + + +
+
+
+
+
+
+ + diff --git a/src/test/ref/borders_b.html b/src/test/ref/borders_b.html new file mode 100644 index 00000000000..d7d6399ced6 --- /dev/null +++ b/src/test/ref/borders_b.html @@ -0,0 +1,19 @@ + + + + + + + From 2bb5c8bdf3f4a2a4a483760cdc198696cc54aabc Mon Sep 17 00:00:00 2001 From: Bryan Bell Date: Tue, 20 May 2014 23:22:28 -0700 Subject: [PATCH 3/6] Refactor groove & ridge border support, add inset & outset border support Significant cleanup of border support, adds inset & outset border code. Border rendering matches Chrome's border rendering. --- src/components/gfx/render_context.rs | 386 ++++++------------------ src/components/style/properties.rs.mako | 4 +- src/test/html/test_border.html | 13 + src/test/ref/borders.png | Bin 3075 -> 2993 bytes src/test/ref/borders_a.html | 27 +- 5 files changed, 137 insertions(+), 293 deletions(-) diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index e58c318f5c5..b632a628651 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -43,15 +43,6 @@ 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 @@ -154,28 +145,26 @@ impl<'a> RenderContext<'a> { }; match style_select{ - border_style::none => { + border_style::none => { } - border_style::hidden => { + border_style::hidden => { } //FIXME(sammykim): This doesn't work with dash_pattern and cap_style well. I referred firefox code. - border_style::dotted => { + border_style::dotted => { self.draw_dashed_border_segment(direction, bounds, border, color_select, DottedBorder); } - border_style::dashed => { + border_style::dashed => { self.draw_dashed_border_segment(direction, bounds, border, color_select, DashedBorder); } - border_style::solid => { + 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::groove | border_style::ridge => { + self.draw_groove_ridge_border_segment(direction, bounds, border, color_select, style_select); } - border_style::ridge => { - self.draw_ridge_border_segment(direction, bounds, border, color_select); + border_style::inset | border_style::outset => { + self.draw_inset_outset_border_segment(direction, bounds, border, style_select, color_select); } - //FIXME(sammykim): Five more styles should be implemented. - //double, inset, outset } } @@ -183,32 +172,30 @@ impl<'a> RenderContext<'a> { let border = SideOffsets2D::new_all_same(bounds.size.width).to_float_px(); match style{ - border_style::none | border_style::hidden => {} - border_style::dotted => { + border_style::none | border_style::hidden => {} + border_style::dotted => { self.draw_dashed_border_segment(Right, bounds, border, color, DottedBorder); } - border_style::dashed => { + border_style::dashed => { self.draw_dashed_border_segment(Right, bounds, border, color, DashedBorder); } - border_style::solid => { + 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::groove | border_style::ridge => { + self.draw_groove_ridge_border_segment(Right, bounds, border, color, style); } - border_style::ridge => { - self.draw_ridge_border_segment(Right, bounds, border, color); + border_style::inset | border_style::outset => { + self.draw_inset_outset_border_segment(Right, bounds, border, style, color); } - //FIXME(sankha93): Five more styles should be implemented. - //double, inset, outset } } - fn draw_dashed_border_segment(&self, - direction: Direction, - bounds: &Rect, - border: SideOffsets2D, - color: Color, + fn draw_dashed_border_segment(&self, + direction: Direction, + bounds: &Rect, + border: SideOffsets2D, + color: Color, dash_size: DashSize) { let rect = bounds.to_azure_rect(); let draw_opts = DrawOptions(1 as AzFloat, 0 as uint16_t); @@ -266,43 +253,11 @@ impl<'a> RenderContext<'a> { fn draw_solid_border_segment(&self, direction: Direction, bounds: &Rect, border: SideOffsets2D, color: Color) { let rect = bounds.to_azure_rect(); - let draw_opts = DrawOptions(1.0 , 0); - let path_builder = self.draw_target.create_path_builder(); - 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); - - match direction { - Top => { - path_builder.move_to(left_top); - path_builder.line_to(right_top); - path_builder.line_to(right_top + Point2D(-border.right, border.top)); - path_builder.line_to(left_top + Point2D(border.left, border.top)); - } - Left => { - path_builder.move_to(left_top); - path_builder.line_to(left_top + Point2D(border.left, border.top)); - path_builder.line_to(left_bottom + Point2D(border.left, -border.bottom)); - 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, -border.bottom)); - path_builder.line_to(right_top + Point2D(-border.right, border.top)); - } - Bottom => { - path_builder.move_to(left_bottom); - path_builder.line_to(left_bottom + Point2D(border.left, -border.bottom)); - path_builder.line_to(right_bottom + Point2D(-border.right, -border.bottom)); - path_builder.line_to(right_bottom); - } - } - - let path = path_builder.finish(); - self.draw_target.fill(&path, &ColorPattern(color), &draw_opts); + self.draw_border_path((left_top, right_top, left_bottom, right_bottom), direction, border, color); } fn get_scaled_bounds(&self, @@ -333,200 +288,99 @@ impl<'a> RenderContext<'a> { return (scaled_left_top, scaled_right_top, scaled_left_bottom, scaled_right_bottom); } - fn draw_groove_border_segment(&self, - direction: Direction, - bounds: &Rect, - border: SideOffsets2D, - 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); + fn draw_groove_ridge_border_segment(&self, + direction: Direction, + bounds: &Rect, + border: SideOffsets2D, + color: Color, + style: border_style::T) { + // original bounds as a 4 element tuple, with no scaling. + let original_bounds = self.get_scaled_bounds(bounds, border, 0.0); + // shrink the bounds by 1/2 of the border, leaving the innermost 1/2 of the border + let inner_scaled_bounds = self.get_scaled_bounds(bounds, border, 0.5); + let scaled_border = SideOffsets2D::new(0.5 * border.top, + 0.5 * border.right, + 0.5 * border.bottom, + 0.5 * border.left); + let is_groove = match style { + border_style::groove => true, + border_style::ridge => false, + _ => { assert!(false, "invalid border style"); false } + }; - // 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); + let darker_color = self.scale_color(color, if is_groove { 1.0/3.0 } else { 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, - border: SideOffsets2D, - 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); - } - } + let (outer_color, inner_color) = match direction { + Top => if is_groove { (darker_color, color) } else { (color, darker_color) }, + Left => if is_groove { (darker_color, color) } else { (color, darker_color) }, + Right => if is_groove { (color, darker_color) } else { (darker_color, color) }, + Bottom => if is_groove { (color, darker_color) } else { (darker_color, color) } + }; + // outer portion of the border + self.draw_border_path(original_bounds, direction, scaled_border, outer_color); + // inner portion of the border + self.draw_border_path(inner_scaled_bounds, direction, scaled_border, inner_color); } - fn draw_square_border_path(&self, - left_top : Point2D, - right_top : Point2D, - left_bottom : Point2D, - right_bottom : Point2D, - direction : Direction, - border : SideOffsets2D, - color : Color) { - let draw_opts = DrawOptions(1.0 , 0); - let path_builder = self.draw_target.create_path_builder(); + fn scale_color(&self, color: Color, scale_factor: f32) -> Color { + return Color(color.r * scale_factor, color.g * scale_factor, color.b * scale_factor, color.a); + } + + fn draw_inset_outset_border_segment(&self, + direction: Direction, + bounds: &Rect, + border: SideOffsets2D, + style: border_style::T, + color: Color) { + let is_inset = match style { + border_style::inset => true, + border_style::outset => false, + _ => { assert!(false, "invalid border style"); false } + }; + // original bounds as a 4 element tuple, with no scaling. + let original_bounds = self.get_scaled_bounds(bounds, border, 0.0); + // select and scale the color appropriately. + let scaled_color = match direction { + Top => self.scale_color(color, if is_inset { 2.0/3.0 } else { 1.0 }), + Left => self.scale_color(color, if is_inset { 1.0/6.0 } else { 0.5 }), + Right => self.scale_color(color, if is_inset { 1.0 } else { 2.0/3.0 }), + Bottom => self.scale_color(color, if is_inset { 1.0 } else { 2.0/3.0 }) + }; + self.draw_border_path(original_bounds, direction, border, scaled_color); + } + + fn draw_border_path(&self, + bounds: (Point2D, Point2D, Point2D, Point2D), + direction: Direction, + border: SideOffsets2D, + color: Color) { + let (left_top, right_top, left_bottom, right_bottom) = bounds; + 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)); + path_builder.line_to(right_top + Point2D(-border.right, border.top)); + path_builder.line_to(left_top + Point2D(border.left, 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_top + Point2D(border.left, border.top)); + path_builder.line_to(left_bottom + Point2D(border.left, -border.bottom)); 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)); + path_builder.line_to(right_bottom + Point2D(-border.right, -border.bottom)); + path_builder.line_to(right_top + Point2D(-border.right, border.top)); } 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(left_bottom + Point2D(border.left, -border.bottom)); + path_builder.line_to(right_bottom + Point2D(-border.right, -border.bottom)); path_builder.line_to(right_bottom); } } @@ -534,54 +388,6 @@ impl<'a> RenderContext<'a> { self.draw_target.fill(&path, &ColorPattern(color), &draw_opts); } - - fn draw_short_ended_path(&self, - left_top: Point2D, - right_top: Point2D, - left_bottom: Point2D, - right_bottom: Point2D, - direction: Direction, - border: SideOffsets2D, - 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 { diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index c510e71924b..184a0f58f0e 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -221,8 +221,8 @@ pub mod longhands { ${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")} % endfor - // double insed outset - ${single_keyword("border-top-style", values="none solid dotted dashed hidden groove ridge")} + // double + ${single_keyword("border-top-style", values="none solid dotted dashed hidden groove ridge inset outset")} % for side in ["right", "bottom", "left"]: <%self:longhand name="border-${side}-style", no_super="True"> diff --git a/src/test/html/test_border.html b/src/test/html/test_border.html index 1446598ad59..3b81f02982d 100755 --- a/src/test/html/test_border.html +++ b/src/test/html/test_border.html @@ -36,6 +36,17 @@ border-width: 10px; border-color: green red yellow black; } +#inset{ + border-style: inset; + border-width: 10px; + border-color: green red yellow black; +} +#outset{ + border-style: outset; + border-width: 10px; + border-color: green red yellow black; +} + #diamond1{ width: 0; height: 0; @@ -60,6 +71,8 @@
dotted test
groove test
ridge test
+
inset test
+
outset test
diff --git a/src/test/ref/borders.png b/src/test/ref/borders.png index a0abba83ff6bbc71ea86fc0f4ef841d424a2fc52..7de3f724b7c18f0bdd4bd05bdd21077e7196e122 100644 GIT binary patch literal 2993 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i0*Z)=h^jL%a94P`IEGZrd3*PuuZ*LB z!^O<(MT+us_;Re&Na_s+S{MoO|z_4%W{{8B&nphbGgd-Rj3>&G)xP9JEqJRCblRu62znFbI zx#ptz?Vl&kxtG~(`aE%N|C^eW=ZoKO`0Q?0a*&CkgHwm0Va5Ucj9yFsdzP}(-%p$8 z`}g(v`2VNW=lqMEpY~kYTK*=I$ziu{vT`#hsBK_iNMgdzDEl?(cSX$JN~`#F_o7U* zudRvPoOX6rY|1z1|F@43ZOFe#zn|`2TJIOTuV7c~-o;r^V@!A7Tf>bt^s&T8j(_=j z28In{;uzuZ_V)SR;S3BB-I!*5d;T4l)Ui3Z%ta4nA1*K7Iwt~CRL4$*ERCf$vy!JjWj!)G*n2o~O>iDWd9j3$!NTtJIl@J*Vx XT5$DBrI)~#3j>3vtDnm{r-UW|gJNOy literal 3075 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i0*Z)=h^jL%aG&yYaSW-L^Y-q+z}o>L z4uMk^&ib;r%HXYo?Go8k=Q;CxRNV{SHdv-VWxV$zwfy<%pYx`r?qp_I@cC`MJ_AER zHj5a8gHHk@!x2ozyX$p^wtnJOr=LCyGS9zRneu$%T=z0LC?mf5`CDH9{oTSk3=K05 zFfnv+;%D60qNDwNj^FI>)7JUEt^NJByt4gj{q^1G#%|xTnP?MV`M$gS_}bj%rw?C? zU7dDzmTC62HIbXmjeakCzpb!|l|eu_f`P%X5kDh(|H<0V_b%BlH_Nx!dwZArRiF`I zv%Y;xn~ObQFoWvfL$&Ykuis{4cpw}ZcjpNoLxCt0H-o~q&!^|v>aj5F+w=7J$Eofu z3=H9l8yFapKyqdK-=FXIm*M{?$G{+ev*yOf<9;xyZJz}n>VNj$&Bk!xZ2`<58*BSH zp8s^pW?-nvNoKX3|1(-0*>@X1&p#OTb6N%igI_UR%jbTM<;S(xFfx4jsl&g#{v8X@ zUNw*{mp6Ud&$2wz>f`0ZuG1MAez45rTd)6YYF`mdD>&3{|CC&_xbpRM1_txA%71@< z{kW74)V$6G6e{QLKdHO)>B>5w*&B1~DqiU$T>oD1;VJc}j0|~qBOIU0iCY~+P8@Uh zpZt5WmxqC2`I*hL?=Ui~a{`$bCNIdu@WBjj2H26HP#R^71_C6%jHZOqlrWkSMsvYv hE*Q-P!!Z}wGcKEM>Z{YcrV7}&XYh3Oa{)GungEoejVJ&B diff --git a/src/test/ref/borders_a.html b/src/test/ref/borders_a.html index 4bd08b11a2a..ee7bd78db7b 100644 --- a/src/test/ref/borders_a.html +++ b/src/test/ref/borders_a.html @@ -15,7 +15,7 @@ #solid{ border-style: solid; border-width: 10px; - border-color: yellow green red black; + border-color: yellow; } #dashed{ border-style: dashed; @@ -31,20 +31,45 @@ border-style: groove; border-width: 10px; border-color: green red yellow black; + position: relative; + left: -30px; + width:1024px; } #ridge{ border-style: ridge; border-width: 10px; border-color: green red yellow black; + position: relative; + left: -30px; + width:1024px; +} +#inset{ + border-style: inset; + border-width: 10px; + border-color: green red yellow black; + position: relative; + left: -30px; + width:1024px; +} +#outset{ + border-style: outset; + border-width: 10px; + border-color: green red yellow black; + position: relative; + left: -30px; + width:1024px; }
+
+
+
From 432b8cdb3bf2cb5aa784e7cb2d7406f92db9608f Mon Sep 17 00:00:00 2001 From: Bryan Bell Date: Tue, 20 May 2014 23:57:42 -0700 Subject: [PATCH 4/6] Cleanup whitespace Cleanup whitespace + move functions for easier reading. --- src/components/gfx/render_context.rs | 92 +++++++++++++--------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index b632a628651..494a9952302 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -191,6 +191,45 @@ impl<'a> RenderContext<'a> { } } + fn draw_border_path(&self, + bounds: (Point2D, Point2D, Point2D, Point2D), + direction: Direction, + border: SideOffsets2D, + color: Color) { + let (left_top, right_top, left_bottom, right_bottom) = bounds; + 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(-border.right, border.top)); + path_builder.line_to(left_top + Point2D(border.left, border.top)); + } + Left => { + path_builder.move_to(left_top); + path_builder.line_to(left_top + Point2D(border.left, border.top)); + path_builder.line_to(left_bottom + Point2D(border.left, -border.bottom)); + 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, -border.bottom)); + path_builder.line_to(right_top + Point2D(-border.right, border.top)); + } + Bottom => { + path_builder.move_to(left_bottom); + path_builder.line_to(left_bottom + Point2D(border.left, -border.bottom)); + path_builder.line_to(right_bottom + Point2D(-border.right, -border.bottom)); + path_builder.line_to(right_bottom); + } + } + let path = path_builder.finish(); + self.draw_target.fill(&path, &ColorPattern(color), &draw_opts); + + } + fn draw_dashed_border_segment(&self, direction: Direction, bounds: &Rect, @@ -264,7 +303,6 @@ impl<'a> RenderContext<'a> { bounds: &Rect, border: SideOffsets2D, shrink_factor: f32) -> (Point2D, Point2D, Point2D, Point2D) { - let rect = bounds.to_azure_rect(); let scaled_border = SideOffsets2D::new(shrink_factor * border.top, shrink_factor * border.right, @@ -284,10 +322,13 @@ impl<'a> RenderContext<'a> { -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 scale_color(&self, color: Color, scale_factor: f32) -> Color { + return Color(color.r * scale_factor, color.g * scale_factor, color.b * scale_factor, color.a); + } + fn draw_groove_ridge_border_segment(&self, direction: Direction, bounds: &Rect, @@ -307,9 +348,7 @@ impl<'a> RenderContext<'a> { border_style::ridge => false, _ => { assert!(false, "invalid border style"); false } }; - let darker_color = self.scale_color(color, if is_groove { 1.0/3.0 } else { 2.0/3.0 }); - let (outer_color, inner_color) = match direction { Top => if is_groove { (darker_color, color) } else { (color, darker_color) }, Left => if is_groove { (darker_color, color) } else { (color, darker_color) }, @@ -320,11 +359,6 @@ impl<'a> RenderContext<'a> { self.draw_border_path(original_bounds, direction, scaled_border, outer_color); // inner portion of the border self.draw_border_path(inner_scaled_bounds, direction, scaled_border, inner_color); - - } - - fn scale_color(&self, color: Color, scale_factor: f32) -> Color { - return Color(color.r * scale_factor, color.g * scale_factor, color.b * scale_factor, color.a); } fn draw_inset_outset_border_segment(&self, @@ -338,7 +372,7 @@ impl<'a> RenderContext<'a> { border_style::outset => false, _ => { assert!(false, "invalid border style"); false } }; - // original bounds as a 4 element tuple, with no scaling. + // original bounds as a 4 element tuple, with no scaling. let original_bounds = self.get_scaled_bounds(bounds, border, 0.0); // select and scale the color appropriately. let scaled_color = match direction { @@ -350,44 +384,6 @@ impl<'a> RenderContext<'a> { self.draw_border_path(original_bounds, direction, border, scaled_color); } - fn draw_border_path(&self, - bounds: (Point2D, Point2D, Point2D, Point2D), - direction: Direction, - border: SideOffsets2D, - color: Color) { - let (left_top, right_top, left_bottom, right_bottom) = bounds; - 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(-border.right, border.top)); - path_builder.line_to(left_top + Point2D(border.left, border.top)); - } - Left => { - path_builder.move_to(left_top); - path_builder.line_to(left_top + Point2D(border.left, border.top)); - path_builder.line_to(left_bottom + Point2D(border.left, -border.bottom)); - 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, -border.bottom)); - path_builder.line_to(right_top + Point2D(-border.right, border.top)); - } - Bottom => { - path_builder.move_to(left_bottom); - path_builder.line_to(left_bottom + Point2D(border.left, -border.bottom)); - path_builder.line_to(right_bottom + Point2D(-border.right, -border.bottom)); - path_builder.line_to(right_bottom); - } - } - let path = path_builder.finish(); - self.draw_target.fill(&path, &ColorPattern(color), &draw_opts); - - } } trait ToAzureRect { From 13bfaeb97d61a153d00c34f648ec260fb0632241 Mon Sep 17 00:00:00 2001 From: Bryan Bell Date: Wed, 21 May 2014 16:30:15 -0700 Subject: [PATCH 5/6] Double border support --- src/components/gfx/render_context.rs | 18 ++++++++++++++++++ src/components/style/properties.rs.mako | 3 +-- src/test/html/test_border.html | 6 ++++++ src/test/ref/borders.png | Bin 2993 -> 3027 bytes src/test/ref/borders_a.html | 6 ++++++ 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index 494a9952302..6d4d62d79bc 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -159,6 +159,9 @@ impl<'a> RenderContext<'a> { border_style::solid => { self.draw_solid_border_segment(direction,bounds,border,color_select); } + border_style::double => { + self.draw_double_border_segment(direction, bounds, border, color_select); + } border_style::groove | border_style::ridge => { self.draw_groove_ridge_border_segment(direction, bounds, border, color_select, style_select); } @@ -182,6 +185,9 @@ impl<'a> RenderContext<'a> { border_style::solid => { self.draw_solid_border_segment(Right,bounds,border,color); } + border_style::double => { + self.draw_double_border_segment(Right, bounds, border, color); + } border_style::groove | border_style::ridge => { self.draw_groove_ridge_border_segment(Right, bounds, border, color, style); } @@ -329,6 +335,18 @@ impl<'a> RenderContext<'a> { return Color(color.r * scale_factor, color.g * scale_factor, color.b * scale_factor, color.a); } + fn draw_double_border_segment(&self, direction: Direction, bounds: &Rect, border: SideOffsets2D, color: Color) { + 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 inner_scaled_bounds = self.get_scaled_bounds(bounds, border, 2.0/3.0); + // draw the outer portion of the double border. + self.draw_solid_border_segment(direction, bounds, scaled_border, color); + // draw the inner portion of the double border. + self.draw_border_path(inner_scaled_bounds, direction, scaled_border, color); + } + fn draw_groove_ridge_border_segment(&self, direction: Direction, bounds: &Rect, diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index 184a0f58f0e..2f928bfa812 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -221,8 +221,7 @@ pub mod longhands { ${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")} % endfor - // double - ${single_keyword("border-top-style", values="none solid dotted dashed hidden groove ridge inset outset")} + ${single_keyword("border-top-style", values="none solid double dotted dashed hidden groove ridge inset outset")} % for side in ["right", "bottom", "left"]: <%self:longhand name="border-${side}-style", no_super="True"> diff --git a/src/test/html/test_border.html b/src/test/html/test_border.html index 3b81f02982d..6e8d60f5d1a 100755 --- a/src/test/html/test_border.html +++ b/src/test/html/test_border.html @@ -16,6 +16,11 @@ border-width: 10px; border-color: yellow green red black; } +#double{ + border-style: double; + border-width: 10px; + border-color: yellow green red black; +} #dashed{ border-style: dashed; border-width: 10px; @@ -67,6 +72,7 @@
none test.
hidden test.
solid test
+
double test
dashed test
dotted test
groove test
diff --git a/src/test/ref/borders.png b/src/test/ref/borders.png index 7de3f724b7c18f0bdd4bd05bdd21077e7196e122..7d7ee68b35a18a8523764fe14dc807dcbe294682 100644 GIT binary patch literal 3027 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i0*Z)=h^jL%aL@8|aSW-L^Y-pRUl~UM zhl`onixuVP@J;CJY_GU=-SHEj&Y!Ox*Q&!~7S;S-6}$cToML8%1)pEPVP#+lQ{KS9 zki^8zprD4qDBJmO@yGw$7#My`{P%a>3T`n52cHB+h9fLAW9ZHQVf^`BGy}sQmB&Ah z>qRgy7&fvp2nYii8_(CUXTNXumtkZOD?PmZQY?mZ!5-NDPupqzE@pY6H?z!{&vXAxqo0aF!RhQk{{CVEo?{D^e7cTpE zstv9K}zk7Hplle*2>J zDu^j-A~(N2yNlTPJoc^N8!!!K7an9{=-||0Xqa&T%D9pGyB3$!(~oc8h%zu-d(;Gt zMR=$I1M8+X1H+o5DA5Ft!sKeZYF37ZtvfK>_GZ)GxqF!y4n$#k-RzkSE=`|)RpD~q z4Y~7ij0_37Bt$VTS7Qb{NW^U0^UdK53=!Q#$M~n`4{-z;JnT>z(#7XCmjkWnBGw8T z=V98F4x=X1wD27b-qGNtbp=0~#zxcF2ufpb^rx;7*&JG@Dhq6^GkCiCxvXi0*Z)=h^jL%a94P`IEGZrd3*PuuZ*LB z!^O<(MT+us_;Re&Na_s+S{MoO|z_4%W{{8B&nphbGgd-Rj3>&G)xP9JEqJRCblRu62znFbI zx#ptz?Vl&kxtG~(`aE%N|C^eW=ZoKO`0Q?0a*&CkgHwm0Va5Ucj9yFsdzP}(-%p$8 z`}g(v`2VNW=lqMEpY~kYTK*=I$ziu{vT`#hsBK_iNMgdzDEl?(cSX$JN~`#F_o7U* zudRvPoOX6rY|1z1|F@43ZOFe#zn|`2TJIOTuV7c~-o;r^V@!A7Tf>bt^s&T8j(_=j z28In{;uzuZ_V)SR;S3BB-I!*5d;T4l)Ui3Z%ta4nA1*K7Iwt~CRL4$*ERCf$vy!JjWj!)G*n2o~O>iDWd9j3$!NTtJIl@J*Vx XT5$DBrI)~#3j>3vtDnm{r-UW|gJNOy diff --git a/src/test/ref/borders_a.html b/src/test/ref/borders_a.html index ee7bd78db7b..42657346f47 100644 --- a/src/test/ref/borders_a.html +++ b/src/test/ref/borders_a.html @@ -12,6 +12,11 @@ border-width: 10px; border-color: green red yellow black; } +#double{ + border-style: double; + border-width: 10px; + border-color: yellow; +} #solid{ border-style: solid; border-width: 10px; @@ -65,6 +70,7 @@
+
From 172c3b8b1c2854bad14a2acdd7cb49a8509dc6f6 Mon Sep 17 00:00:00 2001 From: Bryan Bell Date: Wed, 21 May 2014 20:19:03 -0700 Subject: [PATCH 6/6] Replace tuple with Rect Also includes other minor code cleanup. --- src/components/gfx/render_context.rs | 80 ++++++++++++---------------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index 6d4d62d79bc..d5df16b45ca 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -198,13 +198,16 @@ impl<'a> RenderContext<'a> { } fn draw_border_path(&self, - bounds: (Point2D, Point2D, Point2D, Point2D), + bounds: Rect, direction: Direction, border: SideOffsets2D, color: Color) { - let (left_top, right_top, left_bottom, right_bottom) = bounds; - let draw_opts = DrawOptions(1.0 , 0); - let path_builder = self.draw_target.create_path_builder(); + let left_top = bounds.origin; + let right_top = left_top + Point2D(bounds.size.width, 0.0); + let left_bottom = left_top + Point2D(0.0, bounds.size.height); + let right_bottom = left_top + Point2D(bounds.size.width, bounds.size.height); + 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); @@ -298,37 +301,23 @@ impl<'a> RenderContext<'a> { fn draw_solid_border_segment(&self, direction: Direction, bounds: &Rect, border: SideOffsets2D, 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); - self.draw_border_path((left_top, right_top, left_bottom, right_bottom), direction, border, color); + self.draw_border_path(rect, direction, border, color); } fn get_scaled_bounds(&self, bounds: &Rect, border: SideOffsets2D, - shrink_factor: f32) -> (Point2D, Point2D, Point2D, Point2D) { - 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); + shrink_factor: f32) -> Rect { + 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 scaled_left_top = left_top + Point2D(scaled_border.left, + scaled_border.top); + return Rect(scaled_left_top, + Size2D(rect.size.width - 2.0 * scaled_border.right, rect.size.height - 2.0 * scaled_border.bottom)); } fn scale_color(&self, color: Color, scale_factor: f32) -> Color { @@ -353,30 +342,28 @@ impl<'a> RenderContext<'a> { border: SideOffsets2D, color: Color, style: border_style::T) { - // original bounds as a 4 element tuple, with no scaling. + // original bounds as a Rect, with no scaling. let original_bounds = self.get_scaled_bounds(bounds, border, 0.0); // shrink the bounds by 1/2 of the border, leaving the innermost 1/2 of the border let inner_scaled_bounds = self.get_scaled_bounds(bounds, border, 0.5); let scaled_border = SideOffsets2D::new(0.5 * border.top, - 0.5 * border.right, - 0.5 * border.bottom, - 0.5 * border.left); + 0.5 * border.right, + 0.5 * border.bottom, + 0.5 * border.left); let is_groove = match style { border_style::groove => true, border_style::ridge => false, - _ => { assert!(false, "invalid border style"); false } + _ => fail!("invalid border style") }; let darker_color = self.scale_color(color, if is_groove { 1.0/3.0 } else { 2.0/3.0 }); - let (outer_color, inner_color) = match direction { - Top => if is_groove { (darker_color, color) } else { (color, darker_color) }, - Left => if is_groove { (darker_color, color) } else { (color, darker_color) }, - Right => if is_groove { (color, darker_color) } else { (darker_color, color) }, - Bottom => if is_groove { (color, darker_color) } else { (darker_color, color) } + let (outer_color, inner_color) = match (direction, is_groove) { + (Top, true) | (Left, true) | (Right, false) | (Bottom, false) => (darker_color, color), + (Top, false) | (Left, false) | (Right, true) | (Bottom, true) => (color, darker_color) }; // outer portion of the border self.draw_border_path(original_bounds, direction, scaled_border, outer_color); // inner portion of the border - self.draw_border_path(inner_scaled_bounds, direction, scaled_border, inner_color); + self.draw_border_path(inner_scaled_bounds, direction, scaled_border, inner_color); } fn draw_inset_outset_border_segment(&self, @@ -388,16 +375,15 @@ impl<'a> RenderContext<'a> { let is_inset = match style { border_style::inset => true, border_style::outset => false, - _ => { assert!(false, "invalid border style"); false } + _ => fail!("invalid border style") }; - // original bounds as a 4 element tuple, with no scaling. + // original bounds as a Rect let original_bounds = self.get_scaled_bounds(bounds, border, 0.0); // select and scale the color appropriately. let scaled_color = match direction { - Top => self.scale_color(color, if is_inset { 2.0/3.0 } else { 1.0 }), - Left => self.scale_color(color, if is_inset { 1.0/6.0 } else { 0.5 }), - Right => self.scale_color(color, if is_inset { 1.0 } else { 2.0/3.0 }), - Bottom => self.scale_color(color, if is_inset { 1.0 } else { 2.0/3.0 }) + Top => self.scale_color(color, if is_inset { 2.0/3.0 } else { 1.0 }), + Left => self.scale_color(color, if is_inset { 1.0/6.0 } else { 0.5 }), + Right | Bottom => self.scale_color(color, if is_inset { 1.0 } else { 2.0/3.0 }) }; self.draw_border_path(original_bounds, direction, border, scaled_color); }