diff --git a/Makefile.in b/Makefile.in index 654fd372e88b..3d372fd0500f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -219,21 +219,21 @@ DONE_msg = $(B)src/components/msg/libmsg.dummy DEPS_msg = $(CRATE_msg) $(SRC_msg) $(DONE_SUBMODULES) -RFLAGS_gfx = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/msg +RFLAGS_gfx = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/style -L $(B)src/components/net -L $(B)src/components/msg SRC_gfx = $(call rwildcard,$(S)src/components/gfx/,*.rs) CRATE_gfx = $(S)src/components/gfx/gfx.rc DONE_gfx = $(B)src/components/gfx/libgfx.dummy -DEPS_gfx = $(CRATE_gfx) $(SRC_gfx) $(DONE_SUBMODULES) $(DONE_util) $(DONE_net) $(DONE_msg) +DEPS_gfx = $(CRATE_gfx) $(SRC_gfx) $(DONE_SUBMODULES) $(DONE_util) $(DONE_style) $(DONE_net) $(DONE_msg) -RFLAGS_script = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/gfx -L $(B)src/components/msg +RFLAGS_script = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/style -L $(B)src/components/net -L $(B)src/components/gfx -L $(B)src/components/msg WEBIDL_script = $(call rwildcard,$(S)src/components/script/,*.webidl) AUTOGEN_SRC_script = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_script)) SRC_script = $(call rwildcard,$(S)src/components/script/,*.rs) $(AUTOGEN_SRC_script) CRATE_script = $(S)src/components/script/script.rc DONE_script = $(B)src/components/script/libscript.dummy -DEPS_script = $(CRATE_script) $(SRC_script) $(DONE_SUBMODULES) $(DONE_util) $(DONE_net) $(DONE_gfx) $(DONE_msg) +DEPS_script = $(CRATE_script) $(SRC_script) $(DONE_SUBMODULES) $(DONE_util) $(DONE_style) $(DONE_net) $(DONE_gfx) $(DONE_msg) RFLAGS_style = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util MAKO_ZIP = $(S)src/components/style/Mako-0.8.1.zip diff --git a/src/components/gfx/color.rs b/src/components/gfx/color.rs index ef0f7871f7ec..ffd5b5ed2b21 100644 --- a/src/components/gfx/color.rs +++ b/src/components/gfx/color.rs @@ -8,15 +8,14 @@ use AzColor = azure::azure_hl::Color; pub type Color = AzColor; pub fn rgb(r: u8, g: u8, b: u8) -> AzColor { - rgba(r, g, b, 1.0) -} - -pub fn rgba(r: u8, g: u8, b: u8, a: f64) -> AzColor { AzColor { r: (r as AzFloat) / (255.0 as AzFloat), g: (g as AzFloat) / (255.0 as AzFloat), b: (b as AzFloat) / (255.0 as AzFloat), - a: a as AzFloat + a: 1.0 as AzFloat } } +pub fn rgba(r: AzFloat, g: AzFloat, b: AzFloat, a: AzFloat) -> AzColor { + AzColor { r: r, g: g, b: b, a: a } +} diff --git a/src/components/gfx/display_list.rs b/src/components/gfx/display_list.rs index caebdc470b89..812773383fbc 100644 --- a/src/components/gfx/display_list.rs +++ b/src/components/gfx/display_list.rs @@ -16,7 +16,7 @@ use color::Color; use servo_util::geometry::Au; -use newcss::values::CSSBorderStyle; +use style::computed_values::border_style; use render_context::RenderContext; use text::SendableTextRun; @@ -26,8 +26,6 @@ use servo_net::image::base::Image; use servo_util::range::Range; use extra::arc::Arc; -use newcss::values::{CSSTextDecorationUnderline, CSSTextDecorationOverline, CSSTextDecorationLineThrough}; - /// A list of rendering operations to be performed. pub struct DisplayList { list: ~[DisplayItem] @@ -110,7 +108,7 @@ pub struct BorderDisplayItem { color: SideOffsets2D, /// The border styles. - style: SideOffsets2D + style: SideOffsets2D } impl DisplayItem { @@ -143,25 +141,22 @@ impl DisplayItem { let strikeout_size = font.metrics.strikeout_size; let strikeout_offset = font.metrics.strikeout_offset; - match new_run.decoration { - CSSTextDecorationUnderline => { - let underline_y = baseline_origin.y - underline_offset; - let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y), - Size2D(width, underline_size)); - render_context.draw_solid_color(&underline_bounds, text.color); - }, - CSSTextDecorationOverline => { - let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y), - Size2D(width, underline_size)); - render_context.draw_solid_color(&overline_bounds, text.color); - }, - CSSTextDecorationLineThrough => { - let strikeout_y = baseline_origin.y - strikeout_offset; - let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y), - Size2D(width, strikeout_size)); - render_context.draw_solid_color(&strikeout_bounds, text.color); - }, - _ => () + if new_run.decoration.underline { + let underline_y = baseline_origin.y - underline_offset; + let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y), + Size2D(width, underline_size)); + render_context.draw_solid_color(&underline_bounds, text.color); + } + if new_run.decoration.overline { + let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y), + Size2D(width, underline_size)); + render_context.draw_solid_color(&overline_bounds, text.color); + } + if new_run.decoration.line_through { + let strikeout_y = baseline_origin.y - strikeout_offset; + let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y), + Size2D(width, strikeout_size)); + render_context.draw_solid_color(&strikeout_bounds, text.color); } } diff --git a/src/components/gfx/font.rs b/src/components/gfx/font.rs index f5d71a843e8b..7ec40f290716 100644 --- a/src/components/gfx/font.rs +++ b/src/components/gfx/font.rs @@ -28,7 +28,7 @@ use servo_util::time; use servo_util::time::profile; use servo_util::time::ProfilerChan; -use newcss::values::CSSTextDecoration; +use style::computed_values::text_decoration; // FontHandle encapsulates access to the platform's font API, // e.g. quartz, FreeType. It provides access to metrics and tables @@ -195,7 +195,7 @@ impl FontGroup { self.fonts = ~[]; } - pub fn create_textrun(&self, text: ~str, decoration: CSSTextDecoration) -> TextRun { + pub fn create_textrun(&self, text: ~str, decoration: text_decoration::T) -> TextRun { assert!(self.fonts.len() > 0); // TODO(Issue #177): Actually fall back through the FontGroup when a font is unsuitable. diff --git a/src/components/gfx/gfx.rc b/src/components/gfx/gfx.rc index 3a35c44b34d2..f21b70d5cea5 100644 --- a/src/components/gfx/gfx.rc +++ b/src/components/gfx/gfx.rc @@ -17,6 +17,7 @@ extern mod stb_image; extern mod extra; extern mod servo_net (name = "net"); extern mod servo_util (name = "util"); +extern mod style; extern mod servo_msg (name = "msg"); // Eventually we would like the shaper to be pluggable, as many operating systems have their own diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index d1f3f6fbd020..024737b32964 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -5,8 +5,7 @@ use servo_msg::compositor_msg::LayerBuffer; use servo_util::geometry::Au; use font_context::FontContext; -use newcss::values::CSSBorderStyle; -use newcss::values::{CSSBorderStyleNone, CSSBorderStyleHidden, CSSBorderStyleDotted, CSSBorderStyleDashed, CSSBorderStyleSolid, CSSBorderStyleDouble, CSSBorderStyleGroove, CSSBorderStyleRidge, CSSBorderStyleInset, CSSBorderStyleOutset}; +use style::computed_values::border_style; use opts::Opts; use azure::azure_hl::{B8G8R8A8, Color, ColorPattern, DrawOptions}; @@ -44,7 +43,7 @@ impl<'self> RenderContext<'self> { bounds: &Rect, border: SideOffsets2D, color: SideOffsets2D, - style: SideOffsets2D) { + style: SideOffsets2D) { let draw_opts = DrawOptions(1 as AzFloat, 0 as uint16_t); let rect = bounds.to_azure_rect(); let border = border.to_float_px(); @@ -113,14 +112,14 @@ impl<'self> RenderContext<'self> { self.canvas.draw_target.fill_rect(&rect, &pattern); } - fn apply_border_style(style: CSSBorderStyle, border_width: AzFloat, dash: &mut [AzFloat], stroke_opts: &mut StrokeOptions){ + fn apply_border_style(style: border_style::T, border_width: AzFloat, dash: &mut [AzFloat], stroke_opts: &mut StrokeOptions){ match style{ - CSSBorderStyleNone => { + border_style::none => { } - CSSBorderStyleHidden => { + border_style::hidden => { } //FIXME(sammykim): This doesn't work with dash_pattern and cap_style well. I referred firefox code. - CSSBorderStyleDotted => { + border_style::dotted => { stroke_opts.line_width = border_width; if border_width > 2.0 { @@ -135,7 +134,7 @@ impl<'self> RenderContext<'self> { stroke_opts.mDashPattern = vec::raw::to_ptr(dash); stroke_opts.mDashLength = dash.len() as size_t; } - CSSBorderStyleDashed => { + border_style::dashed => { stroke_opts.set_cap_style(AZ_CAP_BUTT as u8); stroke_opts.line_width = border_width; dash[0] = border_width*3 as AzFloat; @@ -144,28 +143,14 @@ impl<'self> RenderContext<'self> { stroke_opts.mDashLength = dash.len() as size_t; } //FIXME(sammykim): BorderStyleSolid doesn't show proper join-style with comparing firefox. - CSSBorderStyleSolid => { + border_style::solid => { stroke_opts.set_cap_style(AZ_CAP_BUTT as u8); stroke_opts.set_join_style(AZ_JOIN_BEVEL as u8); stroke_opts.line_width = border_width; stroke_opts.mDashLength = 0 as size_t; } //FIXME(sammykim): Five more styles should be implemented. - CSSBorderStyleDouble => { - - } - CSSBorderStyleGroove => { - - } - CSSBorderStyleRidge => { - - } - CSSBorderStyleInset => { - - } - CSSBorderStyleOutset => { - - } + //double, groove, ridge, inset, outset } } } diff --git a/src/components/gfx/text/text_run.rs b/src/components/gfx/text/text_run.rs index bc195005bf20..bcc8d3c876ec 100644 --- a/src/components/gfx/text/text_run.rs +++ b/src/components/gfx/text/text_run.rs @@ -10,13 +10,13 @@ use text::glyph::GlyphStore; use font::{Font, FontDescriptor, RunMetrics}; use servo_util::range::Range; use extra::arc::Arc; -use newcss::values::CSSTextDecoration; +use style::computed_values::text_decoration; /// A text run. pub struct TextRun { text: ~str, font: @mut Font, - decoration: CSSTextDecoration, + decoration: text_decoration::T, glyphs: ~[Arc], } @@ -24,7 +24,7 @@ pub struct TextRun { pub struct SendableTextRun { text: ~str, font: FontDescriptor, - decoration: CSSTextDecoration, + decoration: text_decoration::T, priv glyphs: ~[Arc], } @@ -117,7 +117,7 @@ impl<'self> Iterator for LineIterator<'self> { } impl<'self> TextRun { - pub fn new(font: @mut Font, text: ~str, decoration: CSSTextDecoration) -> TextRun { + pub fn new(font: @mut Font, text: ~str, decoration: text_decoration::T) -> TextRun { let glyphs = TextRun::break_and_shape(font, text); let run = TextRun { diff --git a/src/components/main/css/matching.rs b/src/components/main/css/matching.rs index f78f8c51ecd3..099b2bc600ef 100644 --- a/src/components/main/css/matching.rs +++ b/src/components/main/css/matching.rs @@ -4,72 +4,66 @@ // High-level interface to CSS selector matching. -use css::node_util::NodeUtil; -use css::select_handler::NodeSelectHandler; -use layout::incremental; +use std::cell::Cell; +use css::node_style::StyledNode; use script::dom::node::{AbstractNode, LayoutView}; -use newcss::complete::CompleteSelectResults; -use newcss::select::{SelectCtx, SelectResults}; +use style::Stylist; +use style::cascade; use servo_util::tree::TreeNodeRef; pub trait MatchMethods { - fn restyle_subtree(&self, select_ctx: &SelectCtx); + fn match_node(&self, stylist: &Stylist); + fn match_subtree(&self, stylist: &Stylist); + + fn cascade_node(&self, parent: Option>); + fn cascade_subtree(&self, parent: Option>); } impl MatchMethods for AbstractNode { - /** - * Performs CSS selector matching on a subtree. - * - * This is, importantly, the function that updates the layout data for - * the node (the reader-auxiliary box in the COW model) with the - * computed style. - */ - fn restyle_subtree(&self, select_ctx: &SelectCtx) { - // Only elements have styles - if self.is_element() { - do self.with_imm_element |elem| { - let inline_style = match elem.style_attribute { - None => None, - Some(ref sheet) => Some(sheet), - }; - let select_handler = NodeSelectHandler { node: *self }; - let incomplete_results = select_ctx.select_style(self, inline_style, &select_handler); - // Combine this node's results with its parent's to resolve all inherited values - let complete_results = compose_results(*self, incomplete_results); - - // If there was an existing style, compute the damage that - // incremental layout will need to fix. - if self.have_css_select_results() { - let damage = incremental::compute_damage(self, self.get_css_select_results(), &complete_results); - self.set_restyle_damage(damage); - } - self.set_css_select_results(complete_results); + fn match_node(&self, stylist: &Stylist) { + let applicable_declarations = do self.with_imm_element |element| { + let style_attribute = match element.style_attribute { + None => None, + Some(ref style_attribute) => Some(style_attribute) }; + stylist.get_applicable_declarations(self, style_attribute, None) + }; + let cell = Cell::new(applicable_declarations); + do self.write_layout_data |data| { + data.applicable_declarations = cell.take(); } + } + fn match_subtree(&self, stylist: &Stylist) { + self.match_node(stylist); for kid in self.children() { - kid.restyle_subtree(select_ctx); + if kid.is_element() { + kid.match_subtree(stylist); + } } } -} -fn compose_results(node: AbstractNode, results: SelectResults) - -> CompleteSelectResults { - match find_parent_element_node(node) { - None => CompleteSelectResults::new_root(results), - Some(parent_node) => { - let parent_results = parent_node.get_css_select_results(); - CompleteSelectResults::new_from_parent(parent_results, results) + fn cascade_node(&self, parent: Option>) { + let parent_style = match parent { + Some(parent) => Some(parent.style()), + None => None + }; + let computed_values = do self.read_layout_data |data| { + cascade(data.applicable_declarations, parent_style) + }; + let cell = Cell::new(computed_values); + do self.write_layout_data |data| { + data.style = Some(cell.take()); } - } -} + } + fn cascade_subtree(&self, parent: Option>) { + self.cascade_node(parent); -fn find_parent_element_node(node: AbstractNode) -> Option> { - match node.parent_node() { - Some(parent) if parent.is_element() => Some(parent), - Some(parent) => find_parent_element_node(parent), - None => None, + for kid in self.children() { + if kid.is_element() { + kid.cascade_subtree(Some(*self)); + } + } } } - diff --git a/src/components/main/css/node_style.rs b/src/components/main/css/node_style.rs index c4f38fb566c4..49ab10710e8b 100644 --- a/src/components/main/css/node_style.rs +++ b/src/components/main/css/node_style.rs @@ -7,22 +7,22 @@ use css::node_util::NodeUtil; use layout::incremental::RestyleDamage; -use newcss::complete::CompleteStyle; +use style::ComputedValues; use script::dom::node::{AbstractNode, LayoutView}; use servo_util::tree::TreeNodeRef; /// Node mixin providing `style` method that returns a `NodeStyle` pub trait StyledNode { - fn style(&self) -> CompleteStyle; + fn style(&self) -> &ComputedValues; fn restyle_damage(&self) -> RestyleDamage; } impl StyledNode for AbstractNode { - fn style(&self) -> CompleteStyle { + fn style(&self) -> &ComputedValues { assert!(self.is_element()); // Only elements can have styles let results = self.get_css_select_results(); - results.computed_style() + results } fn restyle_damage(&self) -> RestyleDamage { diff --git a/src/components/main/css/node_util.rs b/src/components/main/css/node_util.rs index f6b36a66f167..2d670129b8f7 100644 --- a/src/components/main/css/node_util.rs +++ b/src/components/main/css/node_util.rs @@ -6,14 +6,14 @@ use layout::incremental::RestyleDamage; use std::cast; use std::cell::Cell; -use newcss::complete::CompleteSelectResults; +use style::ComputedValues; use script::dom::node::{AbstractNode, LayoutView}; use servo_util::tree::TreeNodeRef; pub trait NodeUtil<'self> { - fn get_css_select_results(self) -> &'self CompleteSelectResults; - fn set_css_select_results(self, decl: CompleteSelectResults); + fn get_css_select_results(self) -> &'self ComputedValues; + fn set_css_select_results(self, decl: ComputedValues); fn have_css_select_results(self) -> bool; fn get_restyle_damage(self) -> RestyleDamage; @@ -28,7 +28,7 @@ impl<'self> NodeUtil<'self> for AbstractNode { * FIXME: This isn't completely memory safe since the style is * stored in a box that can be overwritten */ - fn get_css_select_results(self) -> &'self CompleteSelectResults { + fn get_css_select_results(self) -> &'self ComputedValues { do self.read_layout_data |layout_data| { match layout_data.style { None => fail!(~"style() called on node without a style!"), @@ -43,7 +43,7 @@ impl<'self> NodeUtil<'self> for AbstractNode { } /// Update the computed style of an HTML element with a style specified by CSS. - fn set_css_select_results(self, decl: CompleteSelectResults) { + fn set_css_select_results(self, decl: ComputedValues) { let cell = Cell::new(decl); self.write_layout_data(|data| data.style = Some(cell.take())); } diff --git a/src/components/main/css/select.rs b/src/components/main/css/select.rs index eadfee5688c3..b63a8a8ac6f0 100644 --- a/src/components/main/css/select.rs +++ b/src/components/main/css/select.rs @@ -4,26 +4,24 @@ use extra::url::Url; use std::cell::Cell; -use newcss::stylesheet::Stylesheet; -use newcss::select::SelectCtx; -use newcss::types::OriginUA; +use style::Stylesheet; +use style::Stylist; +use style::selector_matching::UserAgentOrigin; use newcss::util::DataStream; -pub fn new_css_select_ctx() -> SelectCtx { - let mut ctx = SelectCtx::new(); - ctx.append_sheet(html4_default_style(), OriginUA); - ctx.append_sheet(servo_default_style(), OriginUA); - return ctx; +pub fn new_stylist() -> Stylist { + let mut stylist = Stylist::new(); + stylist.add_stylesheet(html4_default_style(), UserAgentOrigin); + stylist.add_stylesheet(servo_default_style(), UserAgentOrigin); + stylist } fn html4_default_style() -> Stylesheet { - Stylesheet::new(default_url("html4_style"), - style_stream(html4_default_style_str())) + Stylesheet::from_str(html4_default_style_str()) } fn servo_default_style() -> Stylesheet { - Stylesheet::new(default_url("servo_style"), - style_stream(servo_default_style_str())) + Stylesheet::from_str(servo_default_style_str()) } fn default_url(name: &str) -> Url { diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index 88bb1e9369ee..45044caa341f 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -199,17 +199,15 @@ impl BlockFlowData { let available_width = remaining_width - model.noncontent_width(); // Top and bottom margins for blocks are 0 if auto. - let margin_top = MaybeAuto::from_margin(style.margin_top(), - remaining_width, - style.font_size()).specified_or_zero(); - let margin_bottom = MaybeAuto::from_margin(style.margin_bottom(), - remaining_width, - style.font_size()).specified_or_zero(); + let margin_top = MaybeAuto::from_style(style.Margin.margin_top, + remaining_width).specified_or_zero(); + let margin_bottom = MaybeAuto::from_style(style.Margin.margin_bottom, + remaining_width).specified_or_zero(); let (width, margin_left, margin_right) = - (MaybeAuto::from_width(style.width(), remaining_width, style.font_size()), - MaybeAuto::from_margin(style.margin_left(), remaining_width, style.font_size()), - MaybeAuto::from_margin(style.margin_right(), remaining_width, style.font_size())); + (MaybeAuto::from_style(style.Box.width, remaining_width), + MaybeAuto::from_style(style.Margin.margin_left, remaining_width), + MaybeAuto::from_style(style.Margin.margin_right, remaining_width)); let (width, margin_left, margin_right) = self.compute_horiz(width, margin_left, @@ -403,7 +401,7 @@ impl BlockFlowData { for &box in self.box.iter() { let style = box.style(); - let maybe_height = MaybeAuto::from_height(style.height(), Au(0), style.font_size()); + let maybe_height = MaybeAuto::from_style(style.Box.height, Au(0)); let maybe_height = maybe_height.specified_or_zero(); height = geometry::max(height, maybe_height); } diff --git a/src/components/main/layout/box.rs b/src/components/main/layout/box.rs index 3ee83d4407c7..012fd5b681fe 100644 --- a/src/components/main/layout/box.rs +++ b/src/components/main/layout/box.rs @@ -23,17 +23,18 @@ use gfx::display_list::{TextDisplayItemClass}; use gfx::font::{FontStyle, FontWeight300}; use servo_util::geometry::Au; use gfx::text::text_run::TextRun; -use newcss::color::rgb; -use newcss::complete::CompleteStyle; -use newcss::units::{Em, Px}; -use newcss::units::{Cursive, Fantasy, Monospace, SansSerif, Serif}; -use newcss::values::{CSSBorderStyleDashed, CSSBorderStyleSolid}; -use newcss::values::{CSSClearNone, CSSClearLeft, CSSClearRight, CSSClearBoth}; -use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily}; -use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal}; -use newcss::values::{CSSFontStyleOblique, CSSTextAlign, CSSTextDecoration, CSSLineHeight, CSSVerticalAlign}; -use newcss::values::{CSSTextDecorationNone, CSSFloatNone, CSSPositionStatic}; -use newcss::values::{CSSDisplayInlineBlock, CSSDisplayInlineTable}; +use gfx::color::rgb; +use style::ComputedValues; +use style::computed_values::border_style; +use style::computed_values::clear; +use style::computed_values::float; +use style::properties::longhands::font_family::FamilyName; +use style::computed_values::font_style; +use style::computed_values::line_height; +use style::computed_values::position; +use style::computed_values::text_align; +use style::computed_values::text_decoration; +use style::computed_values::vertical_align; use script::dom::node::{AbstractNode, LayoutView}; use servo_net::image::holder::ImageHolder; use servo_net::local_image_cache::LocalImageCache; @@ -119,7 +120,7 @@ pub struct UnscannedTextRenderBox { // Cache font-style and text-decoration to check whether // this box can merge with another render box. font_style: Option, - text_decoration: Option, + text_decoration: Option, } impl UnscannedTextRenderBox { @@ -394,26 +395,18 @@ impl RenderBox { Au(0) } else { let style = self.style(); - let font_size = style.font_size(); - let width = MaybeAuto::from_width(style.width(), - Au(0), - font_size).specified_or_zero(); - let margin_left = MaybeAuto::from_margin(style.margin_left(), - Au(0), - font_size).specified_or_zero(); - let margin_right = MaybeAuto::from_margin(style.margin_right(), - Au(0), - font_size).specified_or_zero(); - let padding_left = base.model.compute_padding_length(style.padding_left(), - Au(0), - font_size); - let padding_right = base.model.compute_padding_length(style.padding_right(), - Au(0), - font_size); - let border_left = base.model.compute_border_width(style.border_left_width(), - font_size); - let border_right = base.model.compute_border_width(style.border_right_width(), - font_size); + let width = MaybeAuto::from_style(style.Box.width, + Au(0)).specified_or_zero(); + let margin_left = MaybeAuto::from_style(style.Margin.margin_left, + Au(0)).specified_or_zero(); + let margin_right = MaybeAuto::from_style(style.Margin.margin_right, + Au(0)).specified_or_zero(); + let padding_left = base.model.compute_padding_length(style.Padding.padding_left, + Au(0)); + let padding_right = base.model.compute_padding_length(style.Padding.padding_right, + Au(0)); + let border_left = style.Border.border_left_width; + let border_right = style.Border.border_right_width; width + margin_left + margin_right + padding_left + padding_right + border_left + border_right @@ -593,7 +586,7 @@ impl RenderBox { /// A convenience function to access the computed style of the DOM node that this render box /// represents. - pub fn style(&self) -> CompleteStyle { + pub fn style(&self) -> &ComputedValues { self.with_base(|base| base.node.style()) } @@ -663,7 +656,7 @@ impl RenderBox { self.paint_background_if_applicable(list, &absolute_box_bounds); let nearest_ancestor_element = self.nearest_ancestor_element(); - let color = nearest_ancestor_element.style().color().to_gfx_color(); + let color = nearest_ancestor_element.style().Color.color.to_gfx_color(); // Create the text box. do list.with_mut_ref |list| { @@ -696,8 +689,8 @@ impl RenderBox { extra: ExtraDisplayListData::new(*self), }, border: debug_border, - color: SideOffsets2D::new_all_same(rgb(0, 0, 200).to_gfx_color()), - style: SideOffsets2D::new_all_same(CSSBorderStyleSolid) + color: SideOffsets2D::new_all_same(rgb(0, 0, 200)), + style: SideOffsets2D::new_all_same(border_style::solid) }; list.append_item(BorderDisplayItemClass(border_display_item)) @@ -718,8 +711,8 @@ impl RenderBox { extra: ExtraDisplayListData::new(*self), }, border: debug_border, - color: SideOffsets2D::new_all_same(rgb(0, 200, 0).to_gfx_color()), - style: SideOffsets2D::new_all_same(CSSBorderStyleDashed) + color: SideOffsets2D::new_all_same(rgb(0, 200, 0)), + style: SideOffsets2D::new_all_same(border_style::dashed) }; list.append_item(BorderDisplayItemClass(border_display_item)) @@ -745,8 +738,8 @@ impl RenderBox { extra: ExtraDisplayListData::new(*self), }, border: debug_border, - color: SideOffsets2D::new_all_same(rgb(0, 0, 200).to_gfx_color()), - style: SideOffsets2D::new_all_same(CSSBorderStyleSolid) + color: SideOffsets2D::new_all_same(rgb(0, 0, 200)), + style: SideOffsets2D::new_all_same(border_style::solid) }; list.append_item(BorderDisplayItemClass(border_display_item)) @@ -804,7 +797,8 @@ impl RenderBox { // doesn't have a render box". let nearest_ancestor_element = self.nearest_ancestor_element(); - let background_color = nearest_ancestor_element.style().background_color(); + let style = nearest_ancestor_element.style(); + let background_color = style.resolve_color(style.Background.background_color); if !background_color.alpha.approx_eq(&0.0) { do list.with_mut_ref |list| { let solid_color_display_item = ~SolidColorDisplayItem { @@ -822,11 +816,11 @@ impl RenderBox { pub fn clear(&self) -> Option { let style = self.style(); - match style.clear() { - CSSClearNone => None, - CSSClearLeft => Some(ClearLeft), - CSSClearRight => Some(ClearRight), - CSSClearBoth => Some(ClearBoth) + match style.Box.clear { + clear::none => None, + clear::left => Some(ClearLeft), + clear::right => Some(ClearRight), + clear::both => Some(ClearBoth) } } @@ -838,31 +832,21 @@ impl RenderBox { debug!("(font style) start: %?", element.type_id()); // FIXME: Too much allocation here. - let font_families = do my_style.font_family().map |family| { + let font_families = do my_style.Font.font_family.map |family| { match *family { - CSSFontFamilyFamilyName(ref family_str) => (*family_str).clone(), - CSSFontFamilyGenericFamily(Serif) => ~"serif", - CSSFontFamilyGenericFamily(SansSerif) => ~"sans-serif", - CSSFontFamilyGenericFamily(Cursive) => ~"cursive", - CSSFontFamilyGenericFamily(Fantasy) => ~"fantasy", - CSSFontFamilyGenericFamily(Monospace) => ~"monospace", + FamilyName(ref name) => (*name).clone() } }; let font_families = font_families.connect(", "); debug!("(font style) font families: `%s`", font_families); - let font_size = match my_style.font_size() { - CSSFontSizeLength(Px(length)) => length as f64, - // todo: this is based on a hard coded font size, should be the parent element's font size - CSSFontSizeLength(Em(length)) => (length as f64) * 16f64, - _ => 16f64 // px units - }; + let font_size = my_style.Font.font_size.to_f64().unwrap() / 60.0; debug!("(font style) font size: `%fpx`", font_size); - let (italic, oblique) = match my_style.font_style() { - CSSFontStyleNormal => (false, false), - CSSFontStyleItalic => (true, false), - CSSFontStyleOblique => (false, true), + let (italic, oblique) = match my_style.Font.font_style { + font_style::normal => (false, false), + font_style::italic => (true, false), + font_style::oblique => (false, true), }; FontStyle { @@ -900,48 +884,45 @@ impl RenderBox { /// Returns the text alignment of the computed style of the nearest ancestor-or-self `Element` /// node. - pub fn text_align(&self) -> CSSTextAlign { - self.nearest_ancestor_element().style().text_align() + pub fn text_align(&self) -> text_align::T { + self.nearest_ancestor_element().style().Text.text_align } - pub fn line_height(&self) -> CSSLineHeight { - self.nearest_ancestor_element().style().line_height() + pub fn line_height(&self) -> line_height::T { + self.nearest_ancestor_element().style().Box.line_height } - pub fn vertical_align(&self) -> CSSVerticalAlign { - self.nearest_ancestor_element().style().vertical_align() + pub fn vertical_align(&self) -> vertical_align::T { + self.nearest_ancestor_element().style().Box.vertical_align } /// Returns the text decoration of the computed style of the nearest `Element` node - pub fn text_decoration(&self) -> CSSTextDecoration { + pub fn text_decoration(&self) -> text_decoration::T { /// Computes the propagated value of text-decoration, as specified in CSS 2.1 ยง 16.3.1 /// TODO: make sure this works with anonymous box generation. - fn get_propagated_text_decoration(element: AbstractNode) -> CSSTextDecoration { + fn get_propagated_text_decoration(element: AbstractNode) -> text_decoration::T { //Skip over non-element nodes in the DOM if(!element.is_element()){ return match element.parent_node() { - None => CSSTextDecorationNone, + None => text_decoration::none, Some(parent) => get_propagated_text_decoration(parent), }; } - //FIXME: is the root param on display() important? - let display_in_flow = match element.style().display(false) { - CSSDisplayInlineTable | CSSDisplayInlineBlock => false, - _ => true, - }; + //FIXME: Implement correctly + let display_in_flow = true; - let position = element.style().position(); - let float = element.style().float(); + let position = element.style().Box.position; + let float = element.style().Box.float; - let in_flow = (position == CSSPositionStatic) && (float == CSSFloatNone) && + let in_flow = (position == position::static_) && (float == float::none) && display_in_flow; - let text_decoration = element.style().text_decoration(); + let text_decoration = element.style().Text.text_decoration; - if(text_decoration == CSSTextDecorationNone && in_flow){ + if text_decoration == text_decoration::none && in_flow { match element.parent_node() { - None => CSSTextDecorationNone, + None => text_decoration::none, Some(parent) => get_propagated_text_decoration(parent), } } @@ -1024,8 +1005,15 @@ impl RenderBox { return } - let (top_color, right_color, bottom_color, left_color) = (self.style().border_top_color(), self.style().border_right_color(), self.style().border_bottom_color(), self.style().border_left_color()); - let (top_style, right_style, bottom_style, left_style) = (self.style().border_top_style(), self.style().border_right_style(), self.style().border_bottom_style(), self.style().border_left_style()); + let style = self.style(); + let top_color = style.resolve_color(style.Border.border_top_color); + let right_color = style.resolve_color(style.Border.border_right_color); + let bottom_color = style.resolve_color(style.Border.border_bottom_color); + let left_color = style.resolve_color(style.Border.border_left_color); + let top_style = style.Border.border_top_style; + let right_style = style.Border.border_right_style; + let bottom_style = style.Border.border_bottom_style; + let left_style = style.Border.border_left_style; // Append the border to the display list. do list.with_mut_ref |list| { let border_display_item = ~BorderDisplayItem { diff --git a/src/components/main/layout/box_builder.rs b/src/components/main/layout/box_builder.rs index e0c821fc9451..9686ddcb6cb9 100644 --- a/src/components/main/layout/box_builder.rs +++ b/src/components/main/layout/box_builder.rs @@ -17,13 +17,8 @@ use layout::inline::{InlineFlowData, InlineLayout}; use layout::text::TextRunScanner; use css::node_style::StyledNode; -use newcss::values::{CSSDisplayBlock, CSSDisplayInline, CSSDisplayInlineBlock}; -use newcss::values::{CSSDisplayTable, CSSDisplayInlineTable, CSSDisplayListItem}; -use newcss::values::{CSSDisplayTableRowGroup, CSSDisplayTableHeaderGroup, CSSDisplayTableFooterGroup}; -use newcss::values::{CSSDisplayTableRow, CSSDisplayTableColumnGroup, CSSDisplayTableColumn}; -use newcss::values::{CSSDisplayTableCell, CSSDisplayTableCaption}; -use newcss::values::{CSSDisplayNone}; -use newcss::values::{CSSFloatNone, CSSFloatLeft, CSSFloatRight}; +use style::computed_values::display; +use style::computed_values::float; use layout::float_context::{FloatLeft, FloatRight}; use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId}; use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId}; @@ -374,31 +369,26 @@ impl LayoutTreeBuilder { parent_generator: &mut BoxGenerator<'a>, mut sibling_generator: Option<&mut BoxGenerator<'a>>) -> BoxGenResult<'a> { - let display = if node.is_element() { - match node.style().display(node.is_root()) { - CSSDisplayNone => return NoGenerator, // tree ends here if 'display: none' - // TODO(eatkinson) these are hacks so that the code doesn't crash - // when unsupported display values are used. They should be deleted - // as they are implemented. - CSSDisplayListItem => CSSDisplayBlock, - CSSDisplayTable => CSSDisplayBlock, - CSSDisplayInlineTable => CSSDisplayInlineBlock, - CSSDisplayTableRowGroup => CSSDisplayBlock, - CSSDisplayTableHeaderGroup => CSSDisplayBlock, - CSSDisplayTableFooterGroup => CSSDisplayBlock, - CSSDisplayTableRow => CSSDisplayBlock, - CSSDisplayTableColumnGroup => return NoGenerator, - CSSDisplayTableColumn => return NoGenerator, - CSSDisplayTableCell => CSSDisplayBlock, - CSSDisplayTableCaption => CSSDisplayBlock, - v => v + let display = node.style().Box.display; + if node.is_root() { + match display { + display::none => return NoGenerator, + display::inline => display::block, + display::list_item => display::block, + v => v + } + } else { + match display { + display::none => return NoGenerator, + display::list_item => display::block, + v => v + } } } else { match node.type_id() { - - ElementNodeTypeId(_) => CSSDisplayInline, - TextNodeTypeId => CSSDisplayInline, + ElementNodeTypeId(_) => display::inline, + TextNodeTypeId => display::inline, DoctypeNodeTypeId | DocumentFragmentNodeTypeId | CommentNodeTypeId => return NoGenerator, @@ -407,13 +397,11 @@ impl LayoutTreeBuilder { let sibling_flow: Option<&mut FlowContext> = sibling_generator.as_mut().map(|gen| &mut *gen.flow); - // TODO(eatkinson): use the value of the float property to - // determine whether to float left or right. let is_float = if (node.is_element()) { - match node.style().float() { - CSSFloatNone => None, - CSSFloatLeft => Some(FloatLeft), - CSSFloatRight => Some(FloatRight) + match node.style().Box.float { + float::none => None, + float::left => Some(FloatLeft), + float::right => Some(FloatRight) } } else { None @@ -422,14 +410,14 @@ impl LayoutTreeBuilder { let new_generator = match (display, &mut parent_generator.flow, sibling_flow) { // Floats - (CSSDisplayBlock, & &BlockFlow(_), _) | - (CSSDisplayBlock, & &FloatFlow(_), _) if is_float.is_some() => { + (display::block, & &BlockFlow(_), _) | + (display::block, & &FloatFlow(_), _) if is_float.is_some() => { self.create_child_generator(node, parent_generator, Flow_Float(is_float.unwrap())) } // If we're placing a float after an inline, append the float to the inline flow, // then continue building from the inline flow in case there are more inlines // afterward. - (CSSDisplayBlock, _, Some(&InlineFlow(_))) if is_float.is_some() => { + (display::block, _, Some(&InlineFlow(_))) if is_float.is_some() => { let float_generator = self.create_child_generator(node, sibling_generator.unwrap(), Flow_Float(is_float.unwrap())); @@ -438,11 +426,11 @@ impl LayoutTreeBuilder { // This is a catch-all case for when: // a) sibling_flow is None // b) sibling_flow is a BlockFlow - (CSSDisplayBlock, & &InlineFlow(_), _) if is_float.is_some() => { + (display::block, & &InlineFlow(_), _) if is_float.is_some() => { self.create_child_generator(node, parent_generator, Flow_Float(is_float.unwrap())) } - (CSSDisplayBlock, & &BlockFlow(ref info), _) => match (info.is_root, node.parent_node().is_some()) { + (display::block, & &BlockFlow(ref info), _) => match (info.is_root, node.parent_node().is_some()) { // If this is the root node, then use the root flow's // context. Otherwise, make a child block context. (true, true) => self.create_child_generator(node, parent_generator, Flow_Block), @@ -452,34 +440,34 @@ impl LayoutTreeBuilder { } }, - (CSSDisplayBlock, & &FloatFlow(*), _) => { + (display::block, & &FloatFlow(*), _) => { self.create_child_generator(node, parent_generator, Flow_Block) } // Inlines that are children of inlines are part of the same flow - (CSSDisplayInline, & &InlineFlow(*), _) => return ParentGenerator, - (CSSDisplayInlineBlock, & &InlineFlow(*), _) => return ParentGenerator, + (display::inline, & &InlineFlow(*), _) => return ParentGenerator, + (display::inline_block, & &InlineFlow(*), _) => return ParentGenerator, // Inlines that are children of blocks create new flows if their // previous sibling was a block. - (CSSDisplayInline, & &BlockFlow(*), Some(&BlockFlow(*))) | - (CSSDisplayInlineBlock, & &BlockFlow(*), Some(&BlockFlow(*))) => { + (display::inline, & &BlockFlow(*), Some(&BlockFlow(*))) | + (display::inline_block, & &BlockFlow(*), Some(&BlockFlow(*))) => { self.create_child_generator(node, parent_generator, Flow_Inline) } // The first two cases should only be hit when a FloatFlow // is the first child of a BlockFlow. Other times, we will - (CSSDisplayInline, _, Some(&FloatFlow(*))) | - (CSSDisplayInlineBlock, _, Some(&FloatFlow(*))) | - (CSSDisplayInline, & &FloatFlow(*), _) | - (CSSDisplayInlineBlock, & &FloatFlow(*), _) => { + (display::inline, _, Some(&FloatFlow(*))) | + (display::inline_block, _, Some(&FloatFlow(*))) | + (display::inline, & &FloatFlow(*), _) | + (display::inline_block, & &FloatFlow(*), _) => { self.create_child_generator(node, parent_generator, Flow_Inline) } // Inlines whose previous sibling was not a block try to use their // sibling's flow context. - (CSSDisplayInline, & &BlockFlow(*), _) | - (CSSDisplayInlineBlock, & &BlockFlow(*), _) => { + (display::inline, & &BlockFlow(*), _) | + (display::inline_block, & &BlockFlow(*), _) => { return match sibling_generator { None => NewGenerator(self.create_child_generator(node, parent_generator, @@ -490,7 +478,7 @@ impl LayoutTreeBuilder { // blocks that are children of inlines need to split their parent // flows. - (CSSDisplayBlock, & &InlineFlow(*), _) => { + (display::block, & &InlineFlow(*), _) => { match grandparent_generator { None => fail!("expected to have a grandparent block flow"), Some(grandparent_gen) => { diff --git a/src/components/main/layout/display_list_builder.rs b/src/components/main/layout/display_list_builder.rs index 6d175cf6a9a6..5dc6a7ebec2b 100644 --- a/src/components/main/layout/display_list_builder.rs +++ b/src/components/main/layout/display_list_builder.rs @@ -10,7 +10,7 @@ use std::cast::transmute; use script::dom::node::AbstractNode; use gfx; -use newcss; +use style; /// Display list data is usually an AbstractNode with view () to indicate /// that nodes in this view shoud not really be touched. The idea is to @@ -61,9 +61,9 @@ pub trait ToGfxColor { fn to_gfx_color(&self) -> gfx::color::Color; } -impl ToGfxColor for newcss::color::Color { +impl ToGfxColor for style::properties::RGBA { fn to_gfx_color(&self) -> gfx::color::Color { - gfx::color::rgba(self.red, self.green, self.blue, self.alpha as f64) + gfx::color::rgba(self.red, self.green, self.blue, self.alpha) } } diff --git a/src/components/main/layout/float.rs b/src/components/main/layout/float.rs index 588a0dabff9b..857f03dc4c5f 100644 --- a/src/components/main/layout/float.rs +++ b/src/components/main/layout/float.rs @@ -113,18 +113,14 @@ impl FloatFlowData { model.compute_padding(style, remaining_width); // Margins for floats are 0 if auto. - let margin_top = MaybeAuto::from_margin(style.margin_top(), - remaining_width, - style.font_size()).specified_or_zero(); - let margin_bottom = MaybeAuto::from_margin(style.margin_bottom(), - remaining_width, - style.font_size()).specified_or_zero(); - let margin_left = MaybeAuto::from_margin(style.margin_left(), - remaining_width, - style.font_size()).specified_or_zero(); - let margin_right = MaybeAuto::from_margin(style.margin_right(), - remaining_width, - style.font_size()).specified_or_zero(); + let margin_top = MaybeAuto::from_style(style.Margin.margin_top, + remaining_width).specified_or_zero(); + let margin_bottom = MaybeAuto::from_style(style.Margin.margin_bottom, + remaining_width).specified_or_zero(); + let margin_left = MaybeAuto::from_style(style.Margin.margin_left, + remaining_width).specified_or_zero(); + let margin_right = MaybeAuto::from_style(style.Margin.margin_right, + remaining_width).specified_or_zero(); @@ -133,9 +129,8 @@ impl FloatFlowData { remaining_width)); - let width = MaybeAuto::from_width(style.width(), - remaining_width, - style.font_size()).specified_or_default(shrink_to_fit); + let width = MaybeAuto::from_style(style.Box.width, + remaining_width).specified_or_default(shrink_to_fit); debug!("assign_widths_float -- width: %?", width); model.margin.top = margin_top; @@ -274,9 +269,8 @@ impl FloatFlowData { //TODO(eatkinson): compute heights properly using the 'height' property. for &box in self.box.iter() { let height_prop = - MaybeAuto::from_height(box.style().height(), - Au(0), - box.style().font_size()).specified_or_zero(); + MaybeAuto::from_style(box.style().Box.height, + Au(0)).specified_or_zero(); height = geometry::max(height, height_prop) + noncontent_height; debug!("assign_height_float -- height: %?", height); diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs index b19bc15a11f0..cad2ec09a2f5 100644 --- a/src/components/main/layout/inline.rs +++ b/src/components/main/layout/inline.rs @@ -18,13 +18,9 @@ use std::util; use geom::{Point2D, Rect, Size2D}; use gfx::display_list::DisplayList; use servo_util::geometry::Au; -use newcss::units::{Em, Px}; -use newcss::values::{CSSFontSizeLength}; -use newcss::values::{CSSTextAlignLeft, CSSTextAlignCenter, CSSTextAlignRight, CSSTextAlignJustify}; -use newcss::values::{CSSLineHeightNormal, CSSLineHeightNumber, CSSLineHeightLength, CSSLineHeightPercentage}; -use newcss::values::{CSSVerticalAlignBaseline, CSSVerticalAlignMiddle, CSSVerticalAlignSub, CSSVerticalAlignSuper, - CSSVerticalAlignTextTop, CSSVerticalAlignTextBottom, CSSVerticalAlignTop, CSSVerticalAlignBottom, - CSSVerticalAlignLength, CSSVerticalAlignPercentage}; +use style::computed_values::line_height; +use style::computed_values::text_align; +use style::computed_values::vertical_align; use servo_util::range::Range; use servo_util::tree::TreeNodeRef; use extra::container::Deque; @@ -171,11 +167,9 @@ impl LineboxScanner { fn calculate_line_height(&self, box: RenderBox, font_size: Au) -> Au { match box.line_height() { - CSSLineHeightNormal => font_size.scale_by(1.14f64), - CSSLineHeightNumber(l) => font_size.scale_by(l as f64), - CSSLineHeightLength(Em(l)) => font_size.scale_by(l as f64), - CSSLineHeightLength(Px(l)) => Au::from_frac_px(l as f64), - CSSLineHeightPercentage(p) => font_size.scale_by(p as f64 / 100.0f64) + line_height::Normal => font_size.scale_by(1.14), + line_height::Number(l) => font_size.scale_by(l), + line_height::Length(l) => l } } @@ -628,7 +622,7 @@ impl InlineFlowData { linebox_align = first_box.text_align(); } else { // Nothing to lay out, so assume left alignment. - linebox_align = CSSTextAlignLeft; + linebox_align = text_align::left; } // Set the box x positions @@ -636,7 +630,7 @@ impl InlineFlowData { match linebox_align { // So sorry, but justified text is more complicated than shuffling linebox coordinates. // TODO(Issue #213): implement `text-align: justify` - CSSTextAlignLeft | CSSTextAlignJustify => { + text_align::left | text_align::justify => { for i in line.range.eachi() { do self.boxes[i].with_mut_base |base| { base.position.origin.x = offset_x; @@ -644,8 +638,8 @@ impl InlineFlowData { } } } - CSSTextAlignCenter => { - offset_x = offset_x + slack_width.scale_by(0.5f64); + text_align::center => { + offset_x = offset_x + slack_width.scale_by(0.5); for i in line.range.eachi() { do self.boxes[i].with_mut_base |base| { base.position.origin.x = offset_x; @@ -653,7 +647,7 @@ impl InlineFlowData { } } } - CSSTextAlignRight => { + text_align::right => { offset_x = offset_x + slack_width; for i in line.range.eachi() { do self.boxes[i].with_mut_base |base| { @@ -715,7 +709,7 @@ impl InlineFlowData { let text_ascent = text_box.run.font.metrics.ascent; // Offset from the top of the box is 1/2 of the leading + ascent - let text_offset = text_ascent + (line_height - em_size).scale_by(0.5f64); + let text_offset = text_ascent + (line_height - em_size).scale_by(0.5); text_bounds.translate(&Point2D(text_box.base.position.origin.x, Au(0))); (text_offset, line_height - text_offset, text_ascent) @@ -751,14 +745,8 @@ impl InlineFlowData { Some(parent) => parent, }; - // TODO: When the calculation of font-size style is supported, it should be updated. - let font_size = match parent.style().font_size() { - CSSFontSizeLength(Px(length)) => length as f64, - // todo: this is based on a hard coded font size, should be the parent element's font size - CSSFontSizeLength(Em(length)) => length as f64 * 16f64, - _ => 16f64 // px units - }; - parent_text_top = Au::from_frac_px(font_size); + let font_size = parent.style().Font.font_size; + parent_text_top = font_size; } // This flag decides whether topmost and bottommost are updated or not. @@ -766,41 +754,41 @@ impl InlineFlowData { let mut no_update_flag = false; // Calculate a relative offset from baseline. let offset = match cur_box.vertical_align() { - CSSVerticalAlignBaseline => { + vertical_align::baseline => { -ascent }, - CSSVerticalAlignMiddle => { + vertical_align::middle => { // TODO: x-height value should be used from font info. let xheight = Au(0); -(xheight + scanner.box_height(cur_box)).scale_by(0.5) }, - CSSVerticalAlignSub => { + vertical_align::sub => { // TODO: The proper position for subscripts should be used. // Lower the baseline to the proper position for subscripts let sub_offset = Au(0); (sub_offset - ascent) }, - CSSVerticalAlignSuper => { + vertical_align::super_ => { // TODO: The proper position for superscripts should be used. // Raise the baseline to the proper position for superscripts let super_offset = Au(0); (-super_offset - ascent) }, - CSSVerticalAlignTextTop => { + vertical_align::text_top => { let box_height = top_from_base + bottom_from_base; let prev_bottom_from_base = bottom_from_base; top_from_base = parent_text_top; bottom_from_base = box_height - top_from_base; (bottom_from_base - prev_bottom_from_base - ascent) }, - CSSVerticalAlignTextBottom => { + vertical_align::text_bottom => { let box_height = top_from_base + bottom_from_base; let prev_bottom_from_base = bottom_from_base; bottom_from_base = parent_text_bottom; top_from_base = box_height - bottom_from_base; (bottom_from_base - prev_bottom_from_base - ascent) }, - CSSVerticalAlignTop => { + vertical_align::top => { if biggest_top < (top_from_base + bottom_from_base) { biggest_top = top_from_base + bottom_from_base; } @@ -808,7 +796,7 @@ impl InlineFlowData { no_update_flag = true; offset_top }, - CSSVerticalAlignBottom => { + vertical_align::bottom => { if biggest_bottom < (top_from_base + bottom_from_base) { biggest_bottom = top_from_base + bottom_from_base; } @@ -816,17 +804,13 @@ impl InlineFlowData { no_update_flag = true; offset_bottom }, - CSSVerticalAlignLength(length) => { - let length_offset = match length { - Em(l) => Au::from_frac_px(cur_box.font_style().pt_size * l as f64), - Px(l) => Au::from_frac_px(l as f64), - }; - -(length_offset + ascent) + vertical_align::Length(length) => { + -(length + ascent) }, - CSSVerticalAlignPercentage(p) => { + vertical_align::Percentage(p) => { let pt_size = cur_box.font_style().pt_size; let line_height = scanner.calculate_line_height(cur_box, Au::from_pt(pt_size)); - let percent_offset = line_height.scale_by(p as f64 / 100.0f64); + let percent_offset = line_height.scale_by(p); -(percent_offset + ascent) } }; @@ -866,10 +850,10 @@ impl InlineFlowData { for box_i in line.range.eachi() { let cur_box = self.boxes[box_i]; let adjust_offset = match cur_box.vertical_align() { - CSSVerticalAlignTop => { + vertical_align::top => { Au(0) }, - CSSVerticalAlignBottom => { + vertical_align::bottom => { baseline_offset + bottommost }, _ => { diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index 056b9477b19e..07a638a2604b 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -6,7 +6,7 @@ /// rendered. use css::matching::MatchMethods; -use css::select::new_css_select_ctx; +use css::select::new_stylist; use layout::aux::LayoutAuxMethods; use layout::box_builder::LayoutTreeBuilder; use layout::context::LayoutContext; @@ -28,9 +28,9 @@ use servo_util::geometry::Au; use gfx::opts::Opts; use gfx::render_task::{RenderMsg, RenderChan, RenderLayer}; use gfx::render_task; -use newcss::select::SelectCtx; -use newcss::stylesheet::Stylesheet; -use newcss::types::OriginAuthor; +use style::Stylist; +use style::Stylesheet; +use style::selector_matching::AuthorOrigin; use script::dom::event::ReflowEvent; use script::dom::node::{AbstractNode, LayoutView}; use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery}; @@ -63,7 +63,7 @@ struct LayoutTask { display_list: Option>>>, - css_select_ctx: @mut SelectCtx, + stylist: Stylist, profiler_chan: ProfilerChan, } @@ -115,7 +115,7 @@ impl LayoutTask { display_list: None, - css_select_ctx: @mut new_css_select_ctx(), + stylist: new_stylist(), profiler_chan: profiler_chan, } } @@ -167,9 +167,8 @@ impl LayoutTask { true } - fn handle_add_stylesheet(&self, sheet: Stylesheet) { - let sheet = Cell::new(sheet); - self.css_select_ctx.append_sheet(sheet.take(), OriginAuthor); + fn handle_add_stylesheet(&mut self, sheet: Stylesheet) { + self.stylist.add_stylesheet(sheet, AuthorOrigin); } /// The high-level routine that performs layout tasks. @@ -212,7 +211,8 @@ impl LayoutTask { ReflowDocumentDamage => {} MatchSelectorsDocumentDamage => { do profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone()) { - node.restyle_subtree(self.css_select_ctx); + node.match_subtree(&self.stylist); + node.cascade_subtree(None); } } } diff --git a/src/components/main/layout/model.rs b/src/components/main/layout/model.rs index c4d6e453ec55..9225c8408fda 100644 --- a/src/components/main/layout/model.rs +++ b/src/components/main/layout/model.rs @@ -7,14 +7,9 @@ use std::num::Zero; use geom::side_offsets::SideOffsets2D; use servo_util::geometry::Au; -use newcss::complete::CompleteStyle; -use newcss::units::{Length, Em, Px}; -use newcss::values::{CSSBorderWidth, CSSBorderWidthLength, CSSBorderWidthMedium}; -use newcss::values::{CSSBorderWidthThick, CSSBorderWidthThin, CSSFontSize, CSSFontSizeLength}; -use newcss::values::{CSSWidth, CSSWidthLength, CSSWidthPercentage, CSSWidthAuto}; -use newcss::values::{CSSHeight, CSSHeightLength, CSSHeightPercentage, CSSHeightAuto}; -use newcss::values::{CSSMargin, CSSMarginLength, CSSMarginPercentage, CSSMarginAuto}; -use newcss::values::{CSSPadding, CSSPaddingLength, CSSPaddingPercentage}; +use style::ComputedValues; +use style::properties::common_types::computed; + /// Encapsulates the borders, padding, and margins, which we collectively call the "box model". pub struct BoxModel { border: SideOffsets2D, @@ -24,18 +19,6 @@ pub struct BoxModel { content_box_width: Au, } -fn from_length(length: Length, font_size: CSSFontSize) -> Au { - match length { - Px(v) => Au::from_frac_px(v as f64), - Em(em) => { - match font_size { - CSSFontSizeLength(Px(v)) => Au::from_frac_px((em * v) as f64), - _ => fail!("expected non-relative font size") - } - } - } -} - /// Useful helper data type when computing values for blocks and positioned elements. pub enum MaybeAuto { Auto, @@ -43,27 +26,11 @@ pub enum MaybeAuto { } impl MaybeAuto { - pub fn from_margin(margin: CSSMargin, containing_width: Au, font_size: CSSFontSize) -> MaybeAuto { - match margin { - CSSMarginAuto => Auto, - CSSMarginPercentage(percent) => Specified(containing_width.scale_by(percent as f64 / 100.0f64)), - CSSMarginLength(length) => Specified(from_length(length, font_size)) - } - } - - pub fn from_width(width: CSSWidth, containing_width: Au, font_size: CSSFontSize) -> MaybeAuto { - match width { - CSSWidthAuto => Auto, - CSSWidthPercentage(percent) => Specified(containing_width.scale_by(percent as f64 / 100.0f64)), - CSSWidthLength(length) => Specified(from_length(length, font_size)) - } - } - - pub fn from_height(height: CSSHeight, cb_height: Au, font_size: CSSFontSize) -> MaybeAuto { - match height { - CSSHeightAuto => Auto, - CSSHeightPercentage(percent) => Specified(cb_height.scale_by(percent as f64 / 100.0f64)), - CSSHeightLength(length) => Specified(from_length(length, font_size)) + pub fn from_style(length: computed::LengthOrPercentageOrAuto, containing_length: Au) -> MaybeAuto { + match length { + computed::LPA_Auto => Auto, + computed::LPA_Percentage(percent) => Specified(containing_length.scale_by(percent)), + computed::LPA_Length(length) => Specified(length) } } @@ -96,19 +63,19 @@ impl Zero for BoxModel { impl BoxModel { /// Populates the box model parameters from the given computed style. - pub fn compute_borders(&mut self, style: CompleteStyle) { + pub fn compute_borders(&mut self, style: &ComputedValues) { // Compute the borders. - self.border.top = self.compute_border_width(style.border_top_width(), style.font_size()); - self.border.right = self.compute_border_width(style.border_right_width(), style.font_size()); - self.border.bottom = self.compute_border_width(style.border_bottom_width(), style.font_size()); - self.border.left = self.compute_border_width(style.border_left_width(), style.font_size()); + self.border.top = style.Border.border_top_width; + self.border.right = style.Border.border_right_width; + self.border.bottom = style.Border.border_bottom_width; + self.border.left = style.Border.border_left_width; } - pub fn compute_padding(&mut self, style: CompleteStyle, containing_width: Au) { - self.padding.top = self.compute_padding_length(style.padding_top(), containing_width, style.font_size()); - self.padding.right = self.compute_padding_length(style.padding_right(), containing_width, style.font_size()); - self.padding.bottom = self.compute_padding_length(style.padding_bottom(), containing_width, style.font_size()); - self.padding.left = self.compute_padding_length(style.padding_left(), containing_width, style.font_size()); + pub fn compute_padding(&mut self, style: &ComputedValues, containing_width: Au) { + self.padding.top = self.compute_padding_length(style.Padding.padding_top, containing_width); + self.padding.right = self.compute_padding_length(style.Padding.padding_right, containing_width); + self.padding.bottom = self.compute_padding_length(style.Padding.padding_bottom, containing_width); + self.padding.left = self.compute_padding_length(style.Padding.padding_left, containing_width); } pub fn noncontent_width(&self) -> Au { @@ -127,20 +94,10 @@ impl BoxModel { self.margin.left + self.border.left + self.padding.left } - /// Helper function to compute the border width in app units from the CSS border width. - pub fn compute_border_width(&self, width: CSSBorderWidth, font_size: CSSFontSize) -> Au { - match width { - CSSBorderWidthLength(length) => from_length(length, font_size), - CSSBorderWidthThin => Au::from_px(1), - CSSBorderWidthMedium => Au::from_px(5), - CSSBorderWidthThick => Au::from_px(10), - } - } - - pub fn compute_padding_length(&self, padding: CSSPadding, content_box_width: Au, font_size: CSSFontSize) -> Au { + pub fn compute_padding_length(&self, padding: computed::LengthOrPercentage, content_box_width: Au) -> Au { match padding { - CSSPaddingLength(length) => from_length(length, font_size), - CSSPaddingPercentage(p) => content_box_width.scale_by(p as f64 / 100.0f64) + computed::LP_Length(length) => length, + computed::LP_Percentage(p) => content_box_width.scale_by(p) } } } diff --git a/src/components/main/servo.rc b/src/components/main/servo.rc index 3eb4119c8c8a..2d08f88567e8 100755 --- a/src/components/main/servo.rc +++ b/src/components/main/servo.rc @@ -31,6 +31,7 @@ extern mod script; extern mod servo_net (name = "net"); extern mod servo_msg (name = "msg"); extern mod servo_util (name = "util"); +extern mod style; extern mod sharegl; extern mod stb_image; extern mod extra; diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 2babf101e6b0..0a2442d6aa26 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -13,7 +13,7 @@ use dom::document::AbstractDocument; use dom::node::{ElementNodeTypeId, Node, ScriptView, AbstractNode}; use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery}; use layout_interface::{ContentBoxesResponse}; -use newcss::stylesheet::Stylesheet; +use style; use servo_util::tree::{TreeNodeRef, ElementLike}; use js::jsapi::{JSContext, JSObject}; @@ -27,7 +27,7 @@ pub struct Element { tag_name: ~str, // TODO: This should be an atom, not a ~str. attrs: HashMap<~str, ~str>, attrs_list: ~[~str], // store an order of attributes. - style_attribute: Option, + style_attribute: Option, } impl Reflectable for Element { @@ -173,10 +173,8 @@ impl<'self> Element { }); if "style" == name { - self.style_attribute = Some( - Stylesheet::from_attribute( - FromStr::from_str("http://www.example.com/").unwrap(), - null_str_as_empty_ref(raw_value))); + self.style_attribute = Some(style::parse_style_attribute( + null_str_as_empty_ref(raw_value))); } // TODO: update owner document's id hashmap for `document.getElementById()` diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 913812fa5949..58ecc873a4e8 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -25,7 +25,8 @@ use std::unstable::raw::Box; use extra::arc::Arc; use js::jsapi::{JSObject, JSContext}; use netsurfcss::util::VoidPtrLike; -use newcss::complete::CompleteSelectResults; +use style::ComputedValues; +use style::properties::PropertyDeclaration; use servo_util::tree::{TreeNode, TreeNodeRef, TreeNodeRefAsElement}; use servo_util::range::Range; use gfx::display_list::DisplayList; @@ -904,8 +905,11 @@ pub struct DisplayBoxes { /// Data that layout associates with a node. pub struct LayoutData { + /// The results of CSS matching for this node. + applicable_declarations: ~[@[PropertyDeclaration]], + /// The results of CSS styling for this node. - style: Option, + style: Option, /// Description of how to account for recent style changes. restyle_damage: Option, @@ -919,6 +923,7 @@ impl LayoutData { /// Creates new layout data. pub fn new() -> LayoutData { LayoutData { + applicable_declarations: ~[], style: None, restyle_damage: None, boxes: DisplayBoxes { display_list: None, range: None }, diff --git a/src/components/script/html/cssparse.rs b/src/components/script/html/cssparse.rs index e6383599d395..bfe1d984171e 100644 --- a/src/components/script/html/cssparse.rs +++ b/src/components/script/html/cssparse.rs @@ -8,9 +8,8 @@ use std::cell::Cell; use std::comm; use std::comm::Port; use std::task; -use newcss::stylesheet::Stylesheet; -use newcss::util::DataStream; -use servo_net::resource_task::{Load, LoadResponse, Payload, Done, ResourceTask, ProgressMsg}; +use style::Stylesheet; +use servo_net::resource_task::{Load, ProgressMsg, Payload, Done, ResourceTask}; use extra::url::Url; /// Where a style sheet comes from. @@ -26,73 +25,42 @@ pub fn spawn_css_parser(provenance: StylesheetProvenance, let provenance_cell = Cell::new(provenance); do task::spawn { - let url = do provenance_cell.with_ref |p| { + // TODO: CSS parsing should take a base URL. + let _url = do provenance_cell.with_ref |p| { match *p { UrlProvenance(ref the_url) => (*the_url).clone(), InlineProvenance(ref the_url, _) => (*the_url).clone() } }; - let sheet = Stylesheet::new(url, data_stream(provenance_cell.take(), - resource_task.clone())); + let sheet = match provenance_cell.take() { + UrlProvenance(url) => { + debug!("cssparse: loading style sheet at %s", url.to_str()); + let (input_port, input_chan) = comm::stream(); + resource_task.send(Load(url, input_chan)); + Stylesheet::from_iter(ProgressMsgPortIterator { + progress_port: input_port.recv().progress_port + }) + } + InlineProvenance(_, data) => { + Stylesheet::from_str(data) + } + }; result_chan.send(sheet); } return result_port; } -fn data_stream(provenance: StylesheetProvenance, resource_task: ResourceTask) -> @mut DataStream { - match provenance { - UrlProvenance(url) => { - debug!("cssparse: loading style sheet at %s", url.to_str()); - let (input_port, input_chan) = comm::stream(); - resource_task.send(Load(url, input_chan)); - resource_port_to_data_stream(input_port) - } - InlineProvenance(_, data) => { - data_to_data_stream(data) - } - } +struct ProgressMsgPortIterator { + progress_port: Port } -fn resource_port_to_data_stream(input_port: Port) -> @mut DataStream { - let progress_port = input_port.recv().progress_port; - struct ResourcePortDataStream { - progress_port: Port, - }; - impl DataStream for ResourcePortDataStream { - fn read(&mut self) -> Option<~[u8]> { - match self.progress_port.recv() { - Payload(data) => Some(data), - Done(*) => None - } +impl Iterator<~[u8]> for ProgressMsgPortIterator { + fn next(&mut self) -> Option<~[u8]> { + match self.progress_port.recv() { + Payload(data) => Some(data), + Done(*) => None } } - let stream = @mut ResourcePortDataStream { - progress_port: progress_port, - }; - stream as @mut DataStream } - -fn data_to_data_stream(data: ~str) -> @mut DataStream { - let data_cell = Cell::new(data); - struct DataDataStream { - data_cell: Cell<~str>, - }; - impl DataStream for DataDataStream { - fn read(&mut self) -> Option<~[u8]> { - if self.data_cell.is_empty() { - None - } else { - // FIXME: Blech, a copy. - let data = self.data_cell.take(); - Some(data.as_bytes().to_owned()) - } - } - } - let stream = @mut DataDataStream { - data_cell: data_cell, - }; - stream as @mut DataStream -} - diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index 66d85e0dfac0..c6dca22ee214 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -12,7 +12,7 @@ use dom::node::{AbstractNode, ElementNodeTypeId, Node, ScriptView}; use dom::types::*; use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser}; use js::jsapi::JSContext; -use newcss::stylesheet::Stylesheet; +use style::Stylesheet; use script_task::page_from_context; use std::cast; diff --git a/src/components/script/layout_interface.rs b/src/components/script/layout_interface.rs index 2349611ebaf7..348594ca1629 100644 --- a/src/components/script/layout_interface.rs +++ b/src/components/script/layout_interface.rs @@ -13,7 +13,7 @@ use geom::rect::Rect; use geom::size::Size2D; use geom::point::Point2D; use servo_util::geometry::Au; -use newcss::stylesheet::Stylesheet; +use style::Stylesheet; use extra::url::Url; /// Asynchronous messages that script can send to layout. diff --git a/src/components/script/script.rc b/src/components/script/script.rc index 9aa5f2f3a760..13f98daf71aa 100644 --- a/src/components/script/script.rc +++ b/src/components/script/script.rc @@ -21,6 +21,7 @@ extern mod netsurfcss; extern mod newcss (name = "css"); extern mod servo_net (name = "net"); extern mod servo_util (name = "util"); +extern mod style; extern mod servo_msg (name = "msg"); extern mod extra; diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index e507ee132a76..5585e0ba764f 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -371,7 +371,7 @@ pub mod longhands { <%self:longhand name="font-family" inherited="True"> pub use to_computed_value = super::computed_as_specified; #[deriving(Eq, Clone)] - enum FontFamily { + pub enum FontFamily { FamilyName(~str), // Generic // Serif, @@ -563,9 +563,10 @@ pub mod longhands { } pub mod computed_value { pub type T = super::SpecifiedValue; + pub static none: T = super::SpecifiedValue { underline: false, overline: false, line_through: false }; } #[inline] pub fn get_initial_value() -> computed_value::T { - SpecifiedValue { underline: false, overline: false, line_through: false } // none + none } /// none | [ underline || overline || line-through || blink ] pub fn parse(input: &[ComponentValue]) -> Option { @@ -978,7 +979,7 @@ fn get_initial_values() -> ComputedValues { // Most specific/important declarations last -pub fn cascade(applicable_declarations: &[~[PropertyDeclaration]], +pub fn cascade(applicable_declarations: &[@[PropertyDeclaration]], parent_style: Option< &ComputedValues>) -> ComputedValues { let initial_keep_alive; diff --git a/src/components/style/selectors.rs b/src/components/style/selectors.rs index 11077d8d0290..b055baa0cdbb 100644 --- a/src/components/style/selectors.rs +++ b/src/components/style/selectors.rs @@ -90,7 +90,9 @@ pub fn parse_selector_list(input: ~[ComponentValue], namespaces: &NamespaceMap) skip_whitespace(iter); match iter.peek() { None => break, // EOF - Some(&Comma) => (), + Some(&Comma) => { + iter.next(); + } _ => return None, } match parse_selector(iter, namespaces) { @@ -116,6 +118,7 @@ fn parse_selector(iter: &mut Iter, namespaces: &NamespaceMap) let any_whitespace = skip_whitespace(iter); let combinator = match iter.peek() { None => break, // EOF + Some(&Comma) => break, Some(&Delim('>')) => { iter.next(); Child }, Some(&Delim('+')) => { iter.next(); NextSibling }, Some(&Delim('~')) => { iter.next(); LaterSibling }, @@ -356,6 +359,7 @@ fn parse_qualified_name(iter: &mut Iter, allow_universal: bool, namespaces: &Nam } }, Some(&Delim('|')) => explicit_namespace(iter, allow_universal, Some(~"")), + Some(&IDHash(*)) => default_namespace(namespaces, None), _ => return None, } }