Use the new style system

Credits to:
    Deokjin Kim
    Ilyong Cho
    Jaeman Park
    Junyoung Cho
    Ryan Choi
    Sangeun Kim
    Yongjin Kim
    Youngmin Yoo
    Youngsoo Son
This commit is contained in:
Seo Sanghyeon 2013-10-21 22:56:44 +09:00
parent f3f6e62f7f
commit b2431912d3
28 changed files with 353 additions and 494 deletions

View file

@ -219,21 +219,21 @@ DONE_msg = $(B)src/components/msg/libmsg.dummy
DEPS_msg = $(CRATE_msg) $(SRC_msg) $(DONE_SUBMODULES) 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) SRC_gfx = $(call rwildcard,$(S)src/components/gfx/,*.rs)
CRATE_gfx = $(S)src/components/gfx/gfx.rc CRATE_gfx = $(S)src/components/gfx/gfx.rc
DONE_gfx = $(B)src/components/gfx/libgfx.dummy 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) WEBIDL_script = $(call rwildcard,$(S)src/components/script/,*.webidl)
AUTOGEN_SRC_script = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_script)) AUTOGEN_SRC_script = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_script))
SRC_script = $(call rwildcard,$(S)src/components/script/,*.rs) $(AUTOGEN_SRC_script) SRC_script = $(call rwildcard,$(S)src/components/script/,*.rs) $(AUTOGEN_SRC_script)
CRATE_script = $(S)src/components/script/script.rc CRATE_script = $(S)src/components/script/script.rc
DONE_script = $(B)src/components/script/libscript.dummy 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 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 MAKO_ZIP = $(S)src/components/style/Mako-0.8.1.zip

View file

@ -8,15 +8,14 @@ use AzColor = azure::azure_hl::Color;
pub type Color = AzColor; pub type Color = AzColor;
pub fn rgb(r: u8, g: u8, b: u8) -> 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 { AzColor {
r: (r as AzFloat) / (255.0 as AzFloat), r: (r as AzFloat) / (255.0 as AzFloat),
g: (g as AzFloat) / (255.0 as AzFloat), g: (g as AzFloat) / (255.0 as AzFloat),
b: (b 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 }
}

View file

@ -16,7 +16,7 @@
use color::Color; use color::Color;
use servo_util::geometry::Au; use servo_util::geometry::Au;
use newcss::values::CSSBorderStyle; use style::computed_values::border_style;
use render_context::RenderContext; use render_context::RenderContext;
use text::SendableTextRun; use text::SendableTextRun;
@ -26,8 +26,6 @@ use servo_net::image::base::Image;
use servo_util::range::Range; use servo_util::range::Range;
use extra::arc::Arc; use extra::arc::Arc;
use newcss::values::{CSSTextDecorationUnderline, CSSTextDecorationOverline, CSSTextDecorationLineThrough};
/// A list of rendering operations to be performed. /// A list of rendering operations to be performed.
pub struct DisplayList<E> { pub struct DisplayList<E> {
list: ~[DisplayItem<E>] list: ~[DisplayItem<E>]
@ -110,7 +108,7 @@ pub struct BorderDisplayItem<E> {
color: SideOffsets2D<Color>, color: SideOffsets2D<Color>,
/// The border styles. /// The border styles.
style: SideOffsets2D<CSSBorderStyle> style: SideOffsets2D<border_style::T>
} }
impl<E> DisplayItem<E> { impl<E> DisplayItem<E> {
@ -143,25 +141,22 @@ impl<E> DisplayItem<E> {
let strikeout_size = font.metrics.strikeout_size; let strikeout_size = font.metrics.strikeout_size;
let strikeout_offset = font.metrics.strikeout_offset; let strikeout_offset = font.metrics.strikeout_offset;
match new_run.decoration { if new_run.decoration.underline {
CSSTextDecorationUnderline => {
let underline_y = baseline_origin.y - underline_offset; let underline_y = baseline_origin.y - underline_offset;
let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y), let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y),
Size2D(width, underline_size)); Size2D(width, underline_size));
render_context.draw_solid_color(&underline_bounds, text.color); render_context.draw_solid_color(&underline_bounds, text.color);
}, }
CSSTextDecorationOverline => { if new_run.decoration.overline {
let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y), let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y),
Size2D(width, underline_size)); Size2D(width, underline_size));
render_context.draw_solid_color(&overline_bounds, text.color); render_context.draw_solid_color(&overline_bounds, text.color);
}, }
CSSTextDecorationLineThrough => { if new_run.decoration.line_through {
let strikeout_y = baseline_origin.y - strikeout_offset; let strikeout_y = baseline_origin.y - strikeout_offset;
let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y), let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y),
Size2D(width, strikeout_size)); Size2D(width, strikeout_size));
render_context.draw_solid_color(&strikeout_bounds, text.color); render_context.draw_solid_color(&strikeout_bounds, text.color);
},
_ => ()
} }
} }

View file

@ -28,7 +28,7 @@ use servo_util::time;
use servo_util::time::profile; use servo_util::time::profile;
use servo_util::time::ProfilerChan; use servo_util::time::ProfilerChan;
use newcss::values::CSSTextDecoration; use style::computed_values::text_decoration;
// FontHandle encapsulates access to the platform's font API, // FontHandle encapsulates access to the platform's font API,
// e.g. quartz, FreeType. It provides access to metrics and tables // e.g. quartz, FreeType. It provides access to metrics and tables
@ -195,7 +195,7 @@ impl FontGroup {
self.fonts = ~[]; 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); assert!(self.fonts.len() > 0);
// TODO(Issue #177): Actually fall back through the FontGroup when a font is unsuitable. // TODO(Issue #177): Actually fall back through the FontGroup when a font is unsuitable.

View file

@ -17,6 +17,7 @@ extern mod stb_image;
extern mod extra; extern mod extra;
extern mod servo_net (name = "net"); extern mod servo_net (name = "net");
extern mod servo_util (name = "util"); extern mod servo_util (name = "util");
extern mod style;
extern mod servo_msg (name = "msg"); extern mod servo_msg (name = "msg");
// Eventually we would like the shaper to be pluggable, as many operating systems have their own // Eventually we would like the shaper to be pluggable, as many operating systems have their own

View file

@ -5,8 +5,7 @@
use servo_msg::compositor_msg::LayerBuffer; use servo_msg::compositor_msg::LayerBuffer;
use servo_util::geometry::Au; use servo_util::geometry::Au;
use font_context::FontContext; use font_context::FontContext;
use newcss::values::CSSBorderStyle; use style::computed_values::border_style;
use newcss::values::{CSSBorderStyleNone, CSSBorderStyleHidden, CSSBorderStyleDotted, CSSBorderStyleDashed, CSSBorderStyleSolid, CSSBorderStyleDouble, CSSBorderStyleGroove, CSSBorderStyleRidge, CSSBorderStyleInset, CSSBorderStyleOutset};
use opts::Opts; use opts::Opts;
use azure::azure_hl::{B8G8R8A8, Color, ColorPattern, DrawOptions}; use azure::azure_hl::{B8G8R8A8, Color, ColorPattern, DrawOptions};
@ -44,7 +43,7 @@ impl<'self> RenderContext<'self> {
bounds: &Rect<Au>, bounds: &Rect<Au>,
border: SideOffsets2D<Au>, border: SideOffsets2D<Au>,
color: SideOffsets2D<Color>, color: SideOffsets2D<Color>,
style: SideOffsets2D<CSSBorderStyle>) { style: SideOffsets2D<border_style::T>) {
let draw_opts = DrawOptions(1 as AzFloat, 0 as uint16_t); let draw_opts = DrawOptions(1 as AzFloat, 0 as uint16_t);
let rect = bounds.to_azure_rect(); let rect = bounds.to_azure_rect();
let border = border.to_float_px(); let border = border.to_float_px();
@ -113,14 +112,14 @@ impl<'self> RenderContext<'self> {
self.canvas.draw_target.fill_rect(&rect, &pattern); 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{ 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. //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; stroke_opts.line_width = border_width;
if border_width > 2.0 { if border_width > 2.0 {
@ -135,7 +134,7 @@ impl<'self> RenderContext<'self> {
stroke_opts.mDashPattern = vec::raw::to_ptr(dash); stroke_opts.mDashPattern = vec::raw::to_ptr(dash);
stroke_opts.mDashLength = dash.len() as size_t; stroke_opts.mDashLength = dash.len() as size_t;
} }
CSSBorderStyleDashed => { border_style::dashed => {
stroke_opts.set_cap_style(AZ_CAP_BUTT as u8); stroke_opts.set_cap_style(AZ_CAP_BUTT as u8);
stroke_opts.line_width = border_width; stroke_opts.line_width = border_width;
dash[0] = border_width*3 as AzFloat; dash[0] = border_width*3 as AzFloat;
@ -144,28 +143,14 @@ impl<'self> RenderContext<'self> {
stroke_opts.mDashLength = dash.len() as size_t; stroke_opts.mDashLength = dash.len() as size_t;
} }
//FIXME(sammykim): BorderStyleSolid doesn't show proper join-style with comparing firefox. //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_cap_style(AZ_CAP_BUTT as u8);
stroke_opts.set_join_style(AZ_JOIN_BEVEL as u8); stroke_opts.set_join_style(AZ_JOIN_BEVEL as u8);
stroke_opts.line_width = border_width; stroke_opts.line_width = border_width;
stroke_opts.mDashLength = 0 as size_t; stroke_opts.mDashLength = 0 as size_t;
} }
//FIXME(sammykim): Five more styles should be implemented. //FIXME(sammykim): Five more styles should be implemented.
CSSBorderStyleDouble => { //double, groove, ridge, inset, outset
}
CSSBorderStyleGroove => {
}
CSSBorderStyleRidge => {
}
CSSBorderStyleInset => {
}
CSSBorderStyleOutset => {
}
} }
} }
} }

View file

@ -10,13 +10,13 @@ use text::glyph::GlyphStore;
use font::{Font, FontDescriptor, RunMetrics}; use font::{Font, FontDescriptor, RunMetrics};
use servo_util::range::Range; use servo_util::range::Range;
use extra::arc::Arc; use extra::arc::Arc;
use newcss::values::CSSTextDecoration; use style::computed_values::text_decoration;
/// A text run. /// A text run.
pub struct TextRun { pub struct TextRun {
text: ~str, text: ~str,
font: @mut Font, font: @mut Font,
decoration: CSSTextDecoration, decoration: text_decoration::T,
glyphs: ~[Arc<GlyphStore>], glyphs: ~[Arc<GlyphStore>],
} }
@ -24,7 +24,7 @@ pub struct TextRun {
pub struct SendableTextRun { pub struct SendableTextRun {
text: ~str, text: ~str,
font: FontDescriptor, font: FontDescriptor,
decoration: CSSTextDecoration, decoration: text_decoration::T,
priv glyphs: ~[Arc<GlyphStore>], priv glyphs: ~[Arc<GlyphStore>],
} }
@ -117,7 +117,7 @@ impl<'self> Iterator<Range> for LineIterator<'self> {
} }
impl<'self> TextRun { 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 glyphs = TextRun::break_and_shape(font, text);
let run = TextRun { let run = TextRun {

View file

@ -4,72 +4,66 @@
// High-level interface to CSS selector matching. // High-level interface to CSS selector matching.
use css::node_util::NodeUtil; use std::cell::Cell;
use css::select_handler::NodeSelectHandler; use css::node_style::StyledNode;
use layout::incremental;
use script::dom::node::{AbstractNode, LayoutView}; use script::dom::node::{AbstractNode, LayoutView};
use newcss::complete::CompleteSelectResults; use style::Stylist;
use newcss::select::{SelectCtx, SelectResults}; use style::cascade;
use servo_util::tree::TreeNodeRef; use servo_util::tree::TreeNodeRef;
pub trait MatchMethods { 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<AbstractNode<LayoutView>>);
fn cascade_subtree(&self, parent: Option<AbstractNode<LayoutView>>);
} }
impl MatchMethods for AbstractNode<LayoutView> { impl MatchMethods for AbstractNode<LayoutView> {
/** fn match_node(&self, stylist: &Stylist) {
* Performs CSS selector matching on a subtree. let applicable_declarations = do self.with_imm_element |element| {
* let style_attribute = match element.style_attribute {
* 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, None => None,
Some(ref sheet) => Some(sheet), Some(ref style_attribute) => Some(style_attribute)
}; };
let select_handler = NodeSelectHandler { node: *self }; stylist.get_applicable_declarations(self, style_attribute, None)
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);
}; };
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() { for kid in self.children() {
kid.restyle_subtree(select_ctx); if kid.is_element() {
kid.match_subtree(stylist);
}
}
}
fn cascade_node(&self, parent: Option<AbstractNode<LayoutView>>) {
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<AbstractNode<LayoutView>>) {
self.cascade_node(parent);
for kid in self.children() {
if kid.is_element() {
kid.cascade_subtree(Some(*self));
}
} }
} }
} }
fn compose_results(node: AbstractNode<LayoutView>, 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 find_parent_element_node(node: AbstractNode<LayoutView>) -> Option<AbstractNode<LayoutView>> {
match node.parent_node() {
Some(parent) if parent.is_element() => Some(parent),
Some(parent) => find_parent_element_node(parent),
None => None,
}
}

View file

@ -7,22 +7,22 @@
use css::node_util::NodeUtil; use css::node_util::NodeUtil;
use layout::incremental::RestyleDamage; use layout::incremental::RestyleDamage;
use newcss::complete::CompleteStyle; use style::ComputedValues;
use script::dom::node::{AbstractNode, LayoutView}; use script::dom::node::{AbstractNode, LayoutView};
use servo_util::tree::TreeNodeRef; use servo_util::tree::TreeNodeRef;
/// Node mixin providing `style` method that returns a `NodeStyle` /// Node mixin providing `style` method that returns a `NodeStyle`
pub trait StyledNode { pub trait StyledNode {
fn style(&self) -> CompleteStyle; fn style(&self) -> &ComputedValues;
fn restyle_damage(&self) -> RestyleDamage; fn restyle_damage(&self) -> RestyleDamage;
} }
impl StyledNode for AbstractNode<LayoutView> { impl StyledNode for AbstractNode<LayoutView> {
fn style(&self) -> CompleteStyle { fn style(&self) -> &ComputedValues {
assert!(self.is_element()); // Only elements can have styles assert!(self.is_element()); // Only elements can have styles
let results = self.get_css_select_results(); let results = self.get_css_select_results();
results.computed_style() results
} }
fn restyle_damage(&self) -> RestyleDamage { fn restyle_damage(&self) -> RestyleDamage {

View file

@ -6,14 +6,14 @@ use layout::incremental::RestyleDamage;
use std::cast; use std::cast;
use std::cell::Cell; use std::cell::Cell;
use newcss::complete::CompleteSelectResults; use style::ComputedValues;
use script::dom::node::{AbstractNode, LayoutView}; use script::dom::node::{AbstractNode, LayoutView};
use servo_util::tree::TreeNodeRef; use servo_util::tree::TreeNodeRef;
pub trait NodeUtil<'self> { pub trait NodeUtil<'self> {
fn get_css_select_results(self) -> &'self CompleteSelectResults; fn get_css_select_results(self) -> &'self ComputedValues;
fn set_css_select_results(self, decl: CompleteSelectResults); fn set_css_select_results(self, decl: ComputedValues);
fn have_css_select_results(self) -> bool; fn have_css_select_results(self) -> bool;
fn get_restyle_damage(self) -> RestyleDamage; fn get_restyle_damage(self) -> RestyleDamage;
@ -28,7 +28,7 @@ impl<'self> NodeUtil<'self> for AbstractNode<LayoutView> {
* FIXME: This isn't completely memory safe since the style is * FIXME: This isn't completely memory safe since the style is
* stored in a box that can be overwritten * 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| { do self.read_layout_data |layout_data| {
match layout_data.style { match layout_data.style {
None => fail!(~"style() called on node without a style!"), None => fail!(~"style() called on node without a style!"),
@ -43,7 +43,7 @@ impl<'self> NodeUtil<'self> for AbstractNode<LayoutView> {
} }
/// Update the computed style of an HTML element with a style specified by CSS. /// 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); let cell = Cell::new(decl);
self.write_layout_data(|data| data.style = Some(cell.take())); self.write_layout_data(|data| data.style = Some(cell.take()));
} }

View file

@ -4,26 +4,24 @@
use extra::url::Url; use extra::url::Url;
use std::cell::Cell; use std::cell::Cell;
use newcss::stylesheet::Stylesheet; use style::Stylesheet;
use newcss::select::SelectCtx; use style::Stylist;
use newcss::types::OriginUA; use style::selector_matching::UserAgentOrigin;
use newcss::util::DataStream; use newcss::util::DataStream;
pub fn new_css_select_ctx() -> SelectCtx { pub fn new_stylist() -> Stylist {
let mut ctx = SelectCtx::new(); let mut stylist = Stylist::new();
ctx.append_sheet(html4_default_style(), OriginUA); stylist.add_stylesheet(html4_default_style(), UserAgentOrigin);
ctx.append_sheet(servo_default_style(), OriginUA); stylist.add_stylesheet(servo_default_style(), UserAgentOrigin);
return ctx; stylist
} }
fn html4_default_style() -> Stylesheet { fn html4_default_style() -> Stylesheet {
Stylesheet::new(default_url("html4_style"), Stylesheet::from_str(html4_default_style_str())
style_stream(html4_default_style_str()))
} }
fn servo_default_style() -> Stylesheet { fn servo_default_style() -> Stylesheet {
Stylesheet::new(default_url("servo_style"), Stylesheet::from_str(servo_default_style_str())
style_stream(servo_default_style_str()))
} }
fn default_url(name: &str) -> Url { fn default_url(name: &str) -> Url {

View file

@ -199,17 +199,15 @@ impl BlockFlowData {
let available_width = remaining_width - model.noncontent_width(); let available_width = remaining_width - model.noncontent_width();
// Top and bottom margins for blocks are 0 if auto. // Top and bottom margins for blocks are 0 if auto.
let margin_top = MaybeAuto::from_margin(style.margin_top(), let margin_top = MaybeAuto::from_style(style.Margin.margin_top,
remaining_width, remaining_width).specified_or_zero();
style.font_size()).specified_or_zero(); let margin_bottom = MaybeAuto::from_style(style.Margin.margin_bottom,
let margin_bottom = MaybeAuto::from_margin(style.margin_bottom(), remaining_width).specified_or_zero();
remaining_width,
style.font_size()).specified_or_zero();
let (width, margin_left, margin_right) = let (width, margin_left, margin_right) =
(MaybeAuto::from_width(style.width(), remaining_width, style.font_size()), (MaybeAuto::from_style(style.Box.width, remaining_width),
MaybeAuto::from_margin(style.margin_left(), remaining_width, style.font_size()), MaybeAuto::from_style(style.Margin.margin_left, remaining_width),
MaybeAuto::from_margin(style.margin_right(), remaining_width, style.font_size())); MaybeAuto::from_style(style.Margin.margin_right, remaining_width));
let (width, margin_left, margin_right) = self.compute_horiz(width, let (width, margin_left, margin_right) = self.compute_horiz(width,
margin_left, margin_left,
@ -403,7 +401,7 @@ impl BlockFlowData {
for &box in self.box.iter() { for &box in self.box.iter() {
let style = box.style(); 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(); let maybe_height = maybe_height.specified_or_zero();
height = geometry::max(height, maybe_height); height = geometry::max(height, maybe_height);
} }

View file

@ -23,17 +23,18 @@ use gfx::display_list::{TextDisplayItemClass};
use gfx::font::{FontStyle, FontWeight300}; use gfx::font::{FontStyle, FontWeight300};
use servo_util::geometry::Au; use servo_util::geometry::Au;
use gfx::text::text_run::TextRun; use gfx::text::text_run::TextRun;
use newcss::color::rgb; use gfx::color::rgb;
use newcss::complete::CompleteStyle; use style::ComputedValues;
use newcss::units::{Em, Px}; use style::computed_values::border_style;
use newcss::units::{Cursive, Fantasy, Monospace, SansSerif, Serif}; use style::computed_values::clear;
use newcss::values::{CSSBorderStyleDashed, CSSBorderStyleSolid}; use style::computed_values::float;
use newcss::values::{CSSClearNone, CSSClearLeft, CSSClearRight, CSSClearBoth}; use style::properties::longhands::font_family::FamilyName;
use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily}; use style::computed_values::font_style;
use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal}; use style::computed_values::line_height;
use newcss::values::{CSSFontStyleOblique, CSSTextAlign, CSSTextDecoration, CSSLineHeight, CSSVerticalAlign}; use style::computed_values::position;
use newcss::values::{CSSTextDecorationNone, CSSFloatNone, CSSPositionStatic}; use style::computed_values::text_align;
use newcss::values::{CSSDisplayInlineBlock, CSSDisplayInlineTable}; use style::computed_values::text_decoration;
use style::computed_values::vertical_align;
use script::dom::node::{AbstractNode, LayoutView}; use script::dom::node::{AbstractNode, LayoutView};
use servo_net::image::holder::ImageHolder; use servo_net::image::holder::ImageHolder;
use servo_net::local_image_cache::LocalImageCache; use servo_net::local_image_cache::LocalImageCache;
@ -119,7 +120,7 @@ pub struct UnscannedTextRenderBox {
// Cache font-style and text-decoration to check whether // Cache font-style and text-decoration to check whether
// this box can merge with another render box. // this box can merge with another render box.
font_style: Option<FontStyle>, font_style: Option<FontStyle>,
text_decoration: Option<CSSTextDecoration>, text_decoration: Option<text_decoration::T>,
} }
impl UnscannedTextRenderBox { impl UnscannedTextRenderBox {
@ -394,26 +395,18 @@ impl RenderBox {
Au(0) Au(0)
} else { } else {
let style = self.style(); let style = self.style();
let font_size = style.font_size(); let width = MaybeAuto::from_style(style.Box.width,
let width = MaybeAuto::from_width(style.width(), Au(0)).specified_or_zero();
Au(0), let margin_left = MaybeAuto::from_style(style.Margin.margin_left,
font_size).specified_or_zero(); Au(0)).specified_or_zero();
let margin_left = MaybeAuto::from_margin(style.margin_left(), let margin_right = MaybeAuto::from_style(style.Margin.margin_right,
Au(0), Au(0)).specified_or_zero();
font_size).specified_or_zero(); let padding_left = base.model.compute_padding_length(style.Padding.padding_left,
let margin_right = MaybeAuto::from_margin(style.margin_right(), Au(0));
Au(0), let padding_right = base.model.compute_padding_length(style.Padding.padding_right,
font_size).specified_or_zero(); Au(0));
let padding_left = base.model.compute_padding_length(style.padding_left(), let border_left = style.Border.border_left_width;
Au(0), let border_right = style.Border.border_right_width;
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);
width + margin_left + margin_right + padding_left + padding_right + width + margin_left + margin_right + padding_left + padding_right +
border_left + border_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 /// A convenience function to access the computed style of the DOM node that this render box
/// represents. /// represents.
pub fn style(&self) -> CompleteStyle { pub fn style(&self) -> &ComputedValues {
self.with_base(|base| base.node.style()) self.with_base(|base| base.node.style())
} }
@ -663,7 +656,7 @@ impl RenderBox {
self.paint_background_if_applicable(list, &absolute_box_bounds); self.paint_background_if_applicable(list, &absolute_box_bounds);
let nearest_ancestor_element = self.nearest_ancestor_element(); 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. // Create the text box.
do list.with_mut_ref |list| { do list.with_mut_ref |list| {
@ -696,8 +689,8 @@ impl RenderBox {
extra: ExtraDisplayListData::new(*self), extra: ExtraDisplayListData::new(*self),
}, },
border: debug_border, border: debug_border,
color: SideOffsets2D::new_all_same(rgb(0, 0, 200).to_gfx_color()), color: SideOffsets2D::new_all_same(rgb(0, 0, 200)),
style: SideOffsets2D::new_all_same(CSSBorderStyleSolid) style: SideOffsets2D::new_all_same(border_style::solid)
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) list.append_item(BorderDisplayItemClass(border_display_item))
@ -718,8 +711,8 @@ impl RenderBox {
extra: ExtraDisplayListData::new(*self), extra: ExtraDisplayListData::new(*self),
}, },
border: debug_border, border: debug_border,
color: SideOffsets2D::new_all_same(rgb(0, 200, 0).to_gfx_color()), color: SideOffsets2D::new_all_same(rgb(0, 200, 0)),
style: SideOffsets2D::new_all_same(CSSBorderStyleDashed) style: SideOffsets2D::new_all_same(border_style::dashed)
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) list.append_item(BorderDisplayItemClass(border_display_item))
@ -745,8 +738,8 @@ impl RenderBox {
extra: ExtraDisplayListData::new(*self), extra: ExtraDisplayListData::new(*self),
}, },
border: debug_border, border: debug_border,
color: SideOffsets2D::new_all_same(rgb(0, 0, 200).to_gfx_color()), color: SideOffsets2D::new_all_same(rgb(0, 0, 200)),
style: SideOffsets2D::new_all_same(CSSBorderStyleSolid) style: SideOffsets2D::new_all_same(border_style::solid)
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) list.append_item(BorderDisplayItemClass(border_display_item))
@ -804,7 +797,8 @@ impl RenderBox {
// doesn't have a render box". // doesn't have a render box".
let nearest_ancestor_element = self.nearest_ancestor_element(); 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) { if !background_color.alpha.approx_eq(&0.0) {
do list.with_mut_ref |list| { do list.with_mut_ref |list| {
let solid_color_display_item = ~SolidColorDisplayItem { let solid_color_display_item = ~SolidColorDisplayItem {
@ -822,11 +816,11 @@ impl RenderBox {
pub fn clear(&self) -> Option<ClearType> { pub fn clear(&self) -> Option<ClearType> {
let style = self.style(); let style = self.style();
match style.clear() { match style.Box.clear {
CSSClearNone => None, clear::none => None,
CSSClearLeft => Some(ClearLeft), clear::left => Some(ClearLeft),
CSSClearRight => Some(ClearRight), clear::right => Some(ClearRight),
CSSClearBoth => Some(ClearBoth) clear::both => Some(ClearBoth)
} }
} }
@ -838,31 +832,21 @@ impl RenderBox {
debug!("(font style) start: %?", element.type_id()); debug!("(font style) start: %?", element.type_id());
// FIXME: Too much allocation here. // 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 { match *family {
CSSFontFamilyFamilyName(ref family_str) => (*family_str).clone(), FamilyName(ref name) => (*name).clone()
CSSFontFamilyGenericFamily(Serif) => ~"serif",
CSSFontFamilyGenericFamily(SansSerif) => ~"sans-serif",
CSSFontFamilyGenericFamily(Cursive) => ~"cursive",
CSSFontFamilyGenericFamily(Fantasy) => ~"fantasy",
CSSFontFamilyGenericFamily(Monospace) => ~"monospace",
} }
}; };
let font_families = font_families.connect(", "); let font_families = font_families.connect(", ");
debug!("(font style) font families: `%s`", font_families); debug!("(font style) font families: `%s`", font_families);
let font_size = match my_style.font_size() { let font_size = my_style.Font.font_size.to_f64().unwrap() / 60.0;
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
};
debug!("(font style) font size: `%fpx`", font_size); debug!("(font style) font size: `%fpx`", font_size);
let (italic, oblique) = match my_style.font_style() { let (italic, oblique) = match my_style.Font.font_style {
CSSFontStyleNormal => (false, false), font_style::normal => (false, false),
CSSFontStyleItalic => (true, false), font_style::italic => (true, false),
CSSFontStyleOblique => (false, true), font_style::oblique => (false, true),
}; };
FontStyle { FontStyle {
@ -900,48 +884,45 @@ impl RenderBox {
/// Returns the text alignment of the computed style of the nearest ancestor-or-self `Element` /// Returns the text alignment of the computed style of the nearest ancestor-or-self `Element`
/// node. /// node.
pub fn text_align(&self) -> CSSTextAlign { pub fn text_align(&self) -> text_align::T {
self.nearest_ancestor_element().style().text_align() self.nearest_ancestor_element().style().Text.text_align
} }
pub fn line_height(&self) -> CSSLineHeight { pub fn line_height(&self) -> line_height::T {
self.nearest_ancestor_element().style().line_height() self.nearest_ancestor_element().style().Box.line_height
} }
pub fn vertical_align(&self) -> CSSVerticalAlign { pub fn vertical_align(&self) -> vertical_align::T {
self.nearest_ancestor_element().style().vertical_align() self.nearest_ancestor_element().style().Box.vertical_align
} }
/// Returns the text decoration of the computed style of the nearest `Element` node /// 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 /// 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. /// TODO: make sure this works with anonymous box generation.
fn get_propagated_text_decoration(element: AbstractNode<LayoutView>) -> CSSTextDecoration { fn get_propagated_text_decoration(element: AbstractNode<LayoutView>) -> text_decoration::T {
//Skip over non-element nodes in the DOM //Skip over non-element nodes in the DOM
if(!element.is_element()){ if(!element.is_element()){
return match element.parent_node() { return match element.parent_node() {
None => CSSTextDecorationNone, None => text_decoration::none,
Some(parent) => get_propagated_text_decoration(parent), Some(parent) => get_propagated_text_decoration(parent),
}; };
} }
//FIXME: is the root param on display() important? //FIXME: Implement correctly
let display_in_flow = match element.style().display(false) { let display_in_flow = true;
CSSDisplayInlineTable | CSSDisplayInlineBlock => false,
_ => true,
};
let position = element.style().position(); let position = element.style().Box.position;
let float = element.style().float(); 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; 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() { match element.parent_node() {
None => CSSTextDecorationNone, None => text_decoration::none,
Some(parent) => get_propagated_text_decoration(parent), Some(parent) => get_propagated_text_decoration(parent),
} }
} }
@ -1024,8 +1005,15 @@ impl RenderBox {
return 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 style = self.style();
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 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. // Append the border to the display list.
do list.with_mut_ref |list| { do list.with_mut_ref |list| {
let border_display_item = ~BorderDisplayItem { let border_display_item = ~BorderDisplayItem {

View file

@ -17,13 +17,8 @@ use layout::inline::{InlineFlowData, InlineLayout};
use layout::text::TextRunScanner; use layout::text::TextRunScanner;
use css::node_style::StyledNode; use css::node_style::StyledNode;
use newcss::values::{CSSDisplayBlock, CSSDisplayInline, CSSDisplayInlineBlock}; use style::computed_values::display;
use newcss::values::{CSSDisplayTable, CSSDisplayInlineTable, CSSDisplayListItem}; use style::computed_values::float;
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 layout::float_context::{FloatLeft, FloatRight}; use layout::float_context::{FloatLeft, FloatRight};
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId}; use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId}; use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId};
@ -374,31 +369,26 @@ impl LayoutTreeBuilder {
parent_generator: &mut BoxGenerator<'a>, parent_generator: &mut BoxGenerator<'a>,
mut sibling_generator: Option<&mut BoxGenerator<'a>>) mut sibling_generator: Option<&mut BoxGenerator<'a>>)
-> BoxGenResult<'a> { -> BoxGenResult<'a> {
let display = if node.is_element() { let display = if node.is_element() {
match node.style().display(node.is_root()) { let display = node.style().Box.display;
CSSDisplayNone => return NoGenerator, // tree ends here if 'display: none' if node.is_root() {
// TODO(eatkinson) these are hacks so that the code doesn't crash match display {
// when unsupported display values are used. They should be deleted display::none => return NoGenerator,
// as they are implemented. display::inline => display::block,
CSSDisplayListItem => CSSDisplayBlock, display::list_item => display::block,
CSSDisplayTable => CSSDisplayBlock,
CSSDisplayInlineTable => CSSDisplayInlineBlock,
CSSDisplayTableRowGroup => CSSDisplayBlock,
CSSDisplayTableHeaderGroup => CSSDisplayBlock,
CSSDisplayTableFooterGroup => CSSDisplayBlock,
CSSDisplayTableRow => CSSDisplayBlock,
CSSDisplayTableColumnGroup => return NoGenerator,
CSSDisplayTableColumn => return NoGenerator,
CSSDisplayTableCell => CSSDisplayBlock,
CSSDisplayTableCaption => CSSDisplayBlock,
v => v v => v
} }
} else {
match display {
display::none => return NoGenerator,
display::list_item => display::block,
v => v
}
}
} else { } else {
match node.type_id() { match node.type_id() {
ElementNodeTypeId(_) => display::inline,
ElementNodeTypeId(_) => CSSDisplayInline, TextNodeTypeId => display::inline,
TextNodeTypeId => CSSDisplayInline,
DoctypeNodeTypeId | DoctypeNodeTypeId |
DocumentFragmentNodeTypeId | DocumentFragmentNodeTypeId |
CommentNodeTypeId => return NoGenerator, CommentNodeTypeId => return NoGenerator,
@ -407,13 +397,11 @@ impl LayoutTreeBuilder {
let sibling_flow: Option<&mut FlowContext> = sibling_generator.as_mut().map(|gen| &mut *gen.flow); 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()) { let is_float = if (node.is_element()) {
match node.style().float() { match node.style().Box.float {
CSSFloatNone => None, float::none => None,
CSSFloatLeft => Some(FloatLeft), float::left => Some(FloatLeft),
CSSFloatRight => Some(FloatRight) float::right => Some(FloatRight)
} }
} else { } else {
None None
@ -422,14 +410,14 @@ impl LayoutTreeBuilder {
let new_generator = match (display, &mut parent_generator.flow, sibling_flow) { let new_generator = match (display, &mut parent_generator.flow, sibling_flow) {
// Floats // Floats
(CSSDisplayBlock, & &BlockFlow(_), _) | (display::block, & &BlockFlow(_), _) |
(CSSDisplayBlock, & &FloatFlow(_), _) if is_float.is_some() => { (display::block, & &FloatFlow(_), _) if is_float.is_some() => {
self.create_child_generator(node, parent_generator, Flow_Float(is_float.unwrap())) 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, // 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 // then continue building from the inline flow in case there are more inlines
// afterward. // 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, let float_generator = self.create_child_generator(node,
sibling_generator.unwrap(), sibling_generator.unwrap(),
Flow_Float(is_float.unwrap())); Flow_Float(is_float.unwrap()));
@ -438,11 +426,11 @@ impl LayoutTreeBuilder {
// This is a catch-all case for when: // This is a catch-all case for when:
// a) sibling_flow is None // a) sibling_flow is None
// b) sibling_flow is a BlockFlow // 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())) 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 // If this is the root node, then use the root flow's
// context. Otherwise, make a child block context. // context. Otherwise, make a child block context.
(true, true) => self.create_child_generator(node, parent_generator, Flow_Block), (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) self.create_child_generator(node, parent_generator, Flow_Block)
} }
// Inlines that are children of inlines are part of the same flow // Inlines that are children of inlines are part of the same flow
(CSSDisplayInline, & &InlineFlow(*), _) => return ParentGenerator, (display::inline, & &InlineFlow(*), _) => return ParentGenerator,
(CSSDisplayInlineBlock, & &InlineFlow(*), _) => return ParentGenerator, (display::inline_block, & &InlineFlow(*), _) => return ParentGenerator,
// Inlines that are children of blocks create new flows if their // Inlines that are children of blocks create new flows if their
// previous sibling was a block. // previous sibling was a block.
(CSSDisplayInline, & &BlockFlow(*), Some(&BlockFlow(*))) | (display::inline, & &BlockFlow(*), Some(&BlockFlow(*))) |
(CSSDisplayInlineBlock, & &BlockFlow(*), Some(&BlockFlow(*))) => { (display::inline_block, & &BlockFlow(*), Some(&BlockFlow(*))) => {
self.create_child_generator(node, parent_generator, Flow_Inline) self.create_child_generator(node, parent_generator, Flow_Inline)
} }
// The first two cases should only be hit when a FloatFlow // The first two cases should only be hit when a FloatFlow
// is the first child of a BlockFlow. Other times, we will // is the first child of a BlockFlow. Other times, we will
(CSSDisplayInline, _, Some(&FloatFlow(*))) | (display::inline, _, Some(&FloatFlow(*))) |
(CSSDisplayInlineBlock, _, Some(&FloatFlow(*))) | (display::inline_block, _, Some(&FloatFlow(*))) |
(CSSDisplayInline, & &FloatFlow(*), _) | (display::inline, & &FloatFlow(*), _) |
(CSSDisplayInlineBlock, & &FloatFlow(*), _) => { (display::inline_block, & &FloatFlow(*), _) => {
self.create_child_generator(node, parent_generator, Flow_Inline) self.create_child_generator(node, parent_generator, Flow_Inline)
} }
// Inlines whose previous sibling was not a block try to use their // Inlines whose previous sibling was not a block try to use their
// sibling's flow context. // sibling's flow context.
(CSSDisplayInline, & &BlockFlow(*), _) | (display::inline, & &BlockFlow(*), _) |
(CSSDisplayInlineBlock, & &BlockFlow(*), _) => { (display::inline_block, & &BlockFlow(*), _) => {
return match sibling_generator { return match sibling_generator {
None => NewGenerator(self.create_child_generator(node, None => NewGenerator(self.create_child_generator(node,
parent_generator, parent_generator,
@ -490,7 +478,7 @@ impl LayoutTreeBuilder {
// blocks that are children of inlines need to split their parent // blocks that are children of inlines need to split their parent
// flows. // flows.
(CSSDisplayBlock, & &InlineFlow(*), _) => { (display::block, & &InlineFlow(*), _) => {
match grandparent_generator { match grandparent_generator {
None => fail!("expected to have a grandparent block flow"), None => fail!("expected to have a grandparent block flow"),
Some(grandparent_gen) => { Some(grandparent_gen) => {

View file

@ -10,7 +10,7 @@ use std::cast::transmute;
use script::dom::node::AbstractNode; use script::dom::node::AbstractNode;
use gfx; use gfx;
use newcss; use style;
/// Display list data is usually an AbstractNode with view () to indicate /// 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 /// 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; 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 { 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)
} }
} }

View file

@ -113,18 +113,14 @@ impl FloatFlowData {
model.compute_padding(style, remaining_width); model.compute_padding(style, remaining_width);
// Margins for floats are 0 if auto. // Margins for floats are 0 if auto.
let margin_top = MaybeAuto::from_margin(style.margin_top(), let margin_top = MaybeAuto::from_style(style.Margin.margin_top,
remaining_width, remaining_width).specified_or_zero();
style.font_size()).specified_or_zero(); let margin_bottom = MaybeAuto::from_style(style.Margin.margin_bottom,
let margin_bottom = MaybeAuto::from_margin(style.margin_bottom(), remaining_width).specified_or_zero();
remaining_width, let margin_left = MaybeAuto::from_style(style.Margin.margin_left,
style.font_size()).specified_or_zero(); remaining_width).specified_or_zero();
let margin_left = MaybeAuto::from_margin(style.margin_left(), let margin_right = MaybeAuto::from_style(style.Margin.margin_right,
remaining_width, remaining_width).specified_or_zero();
style.font_size()).specified_or_zero();
let margin_right = MaybeAuto::from_margin(style.margin_right(),
remaining_width,
style.font_size()).specified_or_zero();
@ -133,9 +129,8 @@ impl FloatFlowData {
remaining_width)); remaining_width));
let width = MaybeAuto::from_width(style.width(), let width = MaybeAuto::from_style(style.Box.width,
remaining_width, remaining_width).specified_or_default(shrink_to_fit);
style.font_size()).specified_or_default(shrink_to_fit);
debug!("assign_widths_float -- width: %?", width); debug!("assign_widths_float -- width: %?", width);
model.margin.top = margin_top; model.margin.top = margin_top;
@ -274,9 +269,8 @@ impl FloatFlowData {
//TODO(eatkinson): compute heights properly using the 'height' property. //TODO(eatkinson): compute heights properly using the 'height' property.
for &box in self.box.iter() { for &box in self.box.iter() {
let height_prop = let height_prop =
MaybeAuto::from_height(box.style().height(), MaybeAuto::from_style(box.style().Box.height,
Au(0), Au(0)).specified_or_zero();
box.style().font_size()).specified_or_zero();
height = geometry::max(height, height_prop) + noncontent_height; height = geometry::max(height, height_prop) + noncontent_height;
debug!("assign_height_float -- height: %?", height); debug!("assign_height_float -- height: %?", height);

View file

@ -18,13 +18,9 @@ use std::util;
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D};
use gfx::display_list::DisplayList; use gfx::display_list::DisplayList;
use servo_util::geometry::Au; use servo_util::geometry::Au;
use newcss::units::{Em, Px}; use style::computed_values::line_height;
use newcss::values::{CSSFontSizeLength}; use style::computed_values::text_align;
use newcss::values::{CSSTextAlignLeft, CSSTextAlignCenter, CSSTextAlignRight, CSSTextAlignJustify}; use style::computed_values::vertical_align;
use newcss::values::{CSSLineHeightNormal, CSSLineHeightNumber, CSSLineHeightLength, CSSLineHeightPercentage};
use newcss::values::{CSSVerticalAlignBaseline, CSSVerticalAlignMiddle, CSSVerticalAlignSub, CSSVerticalAlignSuper,
CSSVerticalAlignTextTop, CSSVerticalAlignTextBottom, CSSVerticalAlignTop, CSSVerticalAlignBottom,
CSSVerticalAlignLength, CSSVerticalAlignPercentage};
use servo_util::range::Range; use servo_util::range::Range;
use servo_util::tree::TreeNodeRef; use servo_util::tree::TreeNodeRef;
use extra::container::Deque; use extra::container::Deque;
@ -171,11 +167,9 @@ impl LineboxScanner {
fn calculate_line_height(&self, box: RenderBox, font_size: Au) -> Au { fn calculate_line_height(&self, box: RenderBox, font_size: Au) -> Au {
match box.line_height() { match box.line_height() {
CSSLineHeightNormal => font_size.scale_by(1.14f64), line_height::Normal => font_size.scale_by(1.14),
CSSLineHeightNumber(l) => font_size.scale_by(l as f64), line_height::Number(l) => font_size.scale_by(l),
CSSLineHeightLength(Em(l)) => font_size.scale_by(l as f64), line_height::Length(l) => l
CSSLineHeightLength(Px(l)) => Au::from_frac_px(l as f64),
CSSLineHeightPercentage(p) => font_size.scale_by(p as f64 / 100.0f64)
} }
} }
@ -628,7 +622,7 @@ impl InlineFlowData {
linebox_align = first_box.text_align(); linebox_align = first_box.text_align();
} else { } else {
// Nothing to lay out, so assume left alignment. // Nothing to lay out, so assume left alignment.
linebox_align = CSSTextAlignLeft; linebox_align = text_align::left;
} }
// Set the box x positions // Set the box x positions
@ -636,7 +630,7 @@ impl InlineFlowData {
match linebox_align { match linebox_align {
// So sorry, but justified text is more complicated than shuffling linebox coordinates. // So sorry, but justified text is more complicated than shuffling linebox coordinates.
// TODO(Issue #213): implement `text-align: justify` // TODO(Issue #213): implement `text-align: justify`
CSSTextAlignLeft | CSSTextAlignJustify => { text_align::left | text_align::justify => {
for i in line.range.eachi() { for i in line.range.eachi() {
do self.boxes[i].with_mut_base |base| { do self.boxes[i].with_mut_base |base| {
base.position.origin.x = offset_x; base.position.origin.x = offset_x;
@ -644,8 +638,8 @@ impl InlineFlowData {
} }
} }
} }
CSSTextAlignCenter => { text_align::center => {
offset_x = offset_x + slack_width.scale_by(0.5f64); offset_x = offset_x + slack_width.scale_by(0.5);
for i in line.range.eachi() { for i in line.range.eachi() {
do self.boxes[i].with_mut_base |base| { do self.boxes[i].with_mut_base |base| {
base.position.origin.x = offset_x; base.position.origin.x = offset_x;
@ -653,7 +647,7 @@ impl InlineFlowData {
} }
} }
} }
CSSTextAlignRight => { text_align::right => {
offset_x = offset_x + slack_width; offset_x = offset_x + slack_width;
for i in line.range.eachi() { for i in line.range.eachi() {
do self.boxes[i].with_mut_base |base| { do self.boxes[i].with_mut_base |base| {
@ -715,7 +709,7 @@ impl InlineFlowData {
let text_ascent = text_box.run.font.metrics.ascent; let text_ascent = text_box.run.font.metrics.ascent;
// Offset from the top of the box is 1/2 of the leading + 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_bounds.translate(&Point2D(text_box.base.position.origin.x, Au(0)));
(text_offset, line_height - text_offset, text_ascent) (text_offset, line_height - text_offset, text_ascent)
@ -751,14 +745,8 @@ impl InlineFlowData {
Some(parent) => parent, Some(parent) => parent,
}; };
// TODO: When the calculation of font-size style is supported, it should be updated. let font_size = parent.style().Font.font_size;
let font_size = match parent.style().font_size() { parent_text_top = 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);
} }
// This flag decides whether topmost and bottommost are updated or not. // This flag decides whether topmost and bottommost are updated or not.
@ -766,41 +754,41 @@ impl InlineFlowData {
let mut no_update_flag = false; let mut no_update_flag = false;
// Calculate a relative offset from baseline. // Calculate a relative offset from baseline.
let offset = match cur_box.vertical_align() { let offset = match cur_box.vertical_align() {
CSSVerticalAlignBaseline => { vertical_align::baseline => {
-ascent -ascent
}, },
CSSVerticalAlignMiddle => { vertical_align::middle => {
// TODO: x-height value should be used from font info. // TODO: x-height value should be used from font info.
let xheight = Au(0); let xheight = Au(0);
-(xheight + scanner.box_height(cur_box)).scale_by(0.5) -(xheight + scanner.box_height(cur_box)).scale_by(0.5)
}, },
CSSVerticalAlignSub => { vertical_align::sub => {
// TODO: The proper position for subscripts should be used. // TODO: The proper position for subscripts should be used.
// Lower the baseline to the proper position for subscripts // Lower the baseline to the proper position for subscripts
let sub_offset = Au(0); let sub_offset = Au(0);
(sub_offset - ascent) (sub_offset - ascent)
}, },
CSSVerticalAlignSuper => { vertical_align::super_ => {
// TODO: The proper position for superscripts should be used. // TODO: The proper position for superscripts should be used.
// Raise the baseline to the proper position for superscripts // Raise the baseline to the proper position for superscripts
let super_offset = Au(0); let super_offset = Au(0);
(-super_offset - ascent) (-super_offset - ascent)
}, },
CSSVerticalAlignTextTop => { vertical_align::text_top => {
let box_height = top_from_base + bottom_from_base; let box_height = top_from_base + bottom_from_base;
let prev_bottom_from_base = bottom_from_base; let prev_bottom_from_base = bottom_from_base;
top_from_base = parent_text_top; top_from_base = parent_text_top;
bottom_from_base = box_height - top_from_base; bottom_from_base = box_height - top_from_base;
(bottom_from_base - prev_bottom_from_base - ascent) (bottom_from_base - prev_bottom_from_base - ascent)
}, },
CSSVerticalAlignTextBottom => { vertical_align::text_bottom => {
let box_height = top_from_base + bottom_from_base; let box_height = top_from_base + bottom_from_base;
let prev_bottom_from_base = bottom_from_base; let prev_bottom_from_base = bottom_from_base;
bottom_from_base = parent_text_bottom; bottom_from_base = parent_text_bottom;
top_from_base = box_height - bottom_from_base; top_from_base = box_height - bottom_from_base;
(bottom_from_base - prev_bottom_from_base - ascent) (bottom_from_base - prev_bottom_from_base - ascent)
}, },
CSSVerticalAlignTop => { vertical_align::top => {
if biggest_top < (top_from_base + bottom_from_base) { if biggest_top < (top_from_base + bottom_from_base) {
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; no_update_flag = true;
offset_top offset_top
}, },
CSSVerticalAlignBottom => { vertical_align::bottom => {
if biggest_bottom < (top_from_base + bottom_from_base) { if biggest_bottom < (top_from_base + bottom_from_base) {
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; no_update_flag = true;
offset_bottom offset_bottom
}, },
CSSVerticalAlignLength(length) => { vertical_align::Length(length) => {
let length_offset = match length { -(length + ascent)
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)
}, },
CSSVerticalAlignPercentage(p) => { vertical_align::Percentage(p) => {
let pt_size = cur_box.font_style().pt_size; let pt_size = cur_box.font_style().pt_size;
let line_height = scanner.calculate_line_height(cur_box, Au::from_pt(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) -(percent_offset + ascent)
} }
}; };
@ -866,10 +850,10 @@ impl InlineFlowData {
for box_i in line.range.eachi() { for box_i in line.range.eachi() {
let cur_box = self.boxes[box_i]; let cur_box = self.boxes[box_i];
let adjust_offset = match cur_box.vertical_align() { let adjust_offset = match cur_box.vertical_align() {
CSSVerticalAlignTop => { vertical_align::top => {
Au(0) Au(0)
}, },
CSSVerticalAlignBottom => { vertical_align::bottom => {
baseline_offset + bottommost baseline_offset + bottommost
}, },
_ => { _ => {

View file

@ -6,7 +6,7 @@
/// rendered. /// rendered.
use css::matching::MatchMethods; use css::matching::MatchMethods;
use css::select::new_css_select_ctx; use css::select::new_stylist;
use layout::aux::LayoutAuxMethods; use layout::aux::LayoutAuxMethods;
use layout::box_builder::LayoutTreeBuilder; use layout::box_builder::LayoutTreeBuilder;
use layout::context::LayoutContext; use layout::context::LayoutContext;
@ -28,9 +28,9 @@ use servo_util::geometry::Au;
use gfx::opts::Opts; use gfx::opts::Opts;
use gfx::render_task::{RenderMsg, RenderChan, RenderLayer}; use gfx::render_task::{RenderMsg, RenderChan, RenderLayer};
use gfx::render_task; use gfx::render_task;
use newcss::select::SelectCtx; use style::Stylist;
use newcss::stylesheet::Stylesheet; use style::Stylesheet;
use newcss::types::OriginAuthor; use style::selector_matching::AuthorOrigin;
use script::dom::event::ReflowEvent; use script::dom::event::ReflowEvent;
use script::dom::node::{AbstractNode, LayoutView}; use script::dom::node::{AbstractNode, LayoutView};
use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery}; use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery};
@ -63,7 +63,7 @@ struct LayoutTask {
display_list: Option<Arc<DisplayList<AbstractNode<()>>>>, display_list: Option<Arc<DisplayList<AbstractNode<()>>>>,
css_select_ctx: @mut SelectCtx, stylist: Stylist,
profiler_chan: ProfilerChan, profiler_chan: ProfilerChan,
} }
@ -115,7 +115,7 @@ impl LayoutTask {
display_list: None, display_list: None,
css_select_ctx: @mut new_css_select_ctx(), stylist: new_stylist(),
profiler_chan: profiler_chan, profiler_chan: profiler_chan,
} }
} }
@ -167,9 +167,8 @@ impl LayoutTask {
true true
} }
fn handle_add_stylesheet(&self, sheet: Stylesheet) { fn handle_add_stylesheet(&mut self, sheet: Stylesheet) {
let sheet = Cell::new(sheet); self.stylist.add_stylesheet(sheet, AuthorOrigin);
self.css_select_ctx.append_sheet(sheet.take(), OriginAuthor);
} }
/// The high-level routine that performs layout tasks. /// The high-level routine that performs layout tasks.
@ -212,7 +211,8 @@ impl LayoutTask {
ReflowDocumentDamage => {} ReflowDocumentDamage => {}
MatchSelectorsDocumentDamage => { MatchSelectorsDocumentDamage => {
do profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone()) { do profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone()) {
node.restyle_subtree(self.css_select_ctx); node.match_subtree(&self.stylist);
node.cascade_subtree(None);
} }
} }
} }

View file

@ -7,14 +7,9 @@
use std::num::Zero; use std::num::Zero;
use geom::side_offsets::SideOffsets2D; use geom::side_offsets::SideOffsets2D;
use servo_util::geometry::Au; use servo_util::geometry::Au;
use newcss::complete::CompleteStyle; use style::ComputedValues;
use newcss::units::{Length, Em, Px}; use style::properties::common_types::computed;
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};
/// Encapsulates the borders, padding, and margins, which we collectively call the "box model". /// Encapsulates the borders, padding, and margins, which we collectively call the "box model".
pub struct BoxModel { pub struct BoxModel {
border: SideOffsets2D<Au>, border: SideOffsets2D<Au>,
@ -24,18 +19,6 @@ pub struct BoxModel {
content_box_width: Au, 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. /// Useful helper data type when computing values for blocks and positioned elements.
pub enum MaybeAuto { pub enum MaybeAuto {
Auto, Auto,
@ -43,27 +26,11 @@ pub enum MaybeAuto {
} }
impl MaybeAuto { impl MaybeAuto {
pub fn from_margin(margin: CSSMargin, containing_width: Au, font_size: CSSFontSize) -> MaybeAuto { pub fn from_style(length: computed::LengthOrPercentageOrAuto, containing_length: Au) -> MaybeAuto {
match margin { match length {
CSSMarginAuto => Auto, computed::LPA_Auto => Auto,
CSSMarginPercentage(percent) => Specified(containing_width.scale_by(percent as f64 / 100.0f64)), computed::LPA_Percentage(percent) => Specified(containing_length.scale_by(percent)),
CSSMarginLength(length) => Specified(from_length(length, font_size)) computed::LPA_Length(length) => Specified(length)
}
}
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))
} }
} }
@ -96,19 +63,19 @@ impl Zero for BoxModel {
impl BoxModel { impl BoxModel {
/// Populates the box model parameters from the given computed style. /// 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. // Compute the borders.
self.border.top = self.compute_border_width(style.border_top_width(), style.font_size()); self.border.top = style.Border.border_top_width;
self.border.right = self.compute_border_width(style.border_right_width(), style.font_size()); self.border.right = style.Border.border_right_width;
self.border.bottom = self.compute_border_width(style.border_bottom_width(), style.font_size()); self.border.bottom = style.Border.border_bottom_width;
self.border.left = self.compute_border_width(style.border_left_width(), style.font_size()); self.border.left = style.Border.border_left_width;
} }
pub fn compute_padding(&mut self, style: CompleteStyle, containing_width: Au) { pub fn compute_padding(&mut self, style: &ComputedValues, containing_width: Au) {
self.padding.top = self.compute_padding_length(style.padding_top(), containing_width, style.font_size()); self.padding.top = self.compute_padding_length(style.Padding.padding_top, containing_width);
self.padding.right = self.compute_padding_length(style.padding_right(), containing_width, style.font_size()); self.padding.right = self.compute_padding_length(style.Padding.padding_right, containing_width);
self.padding.bottom = self.compute_padding_length(style.padding_bottom(), containing_width, style.font_size()); self.padding.bottom = self.compute_padding_length(style.Padding.padding_bottom, containing_width);
self.padding.left = self.compute_padding_length(style.padding_left(), containing_width, style.font_size()); self.padding.left = self.compute_padding_length(style.Padding.padding_left, containing_width);
} }
pub fn noncontent_width(&self) -> Au { pub fn noncontent_width(&self) -> Au {
@ -127,20 +94,10 @@ impl BoxModel {
self.margin.left + self.border.left + self.padding.left 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_padding_length(&self, padding: computed::LengthOrPercentage, content_box_width: Au) -> Au {
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 {
match padding { match padding {
CSSPaddingLength(length) => from_length(length, font_size), computed::LP_Length(length) => length,
CSSPaddingPercentage(p) => content_box_width.scale_by(p as f64 / 100.0f64) computed::LP_Percentage(p) => content_box_width.scale_by(p)
} }
} }
} }

View file

@ -31,6 +31,7 @@ extern mod script;
extern mod servo_net (name = "net"); extern mod servo_net (name = "net");
extern mod servo_msg (name = "msg"); extern mod servo_msg (name = "msg");
extern mod servo_util (name = "util"); extern mod servo_util (name = "util");
extern mod style;
extern mod sharegl; extern mod sharegl;
extern mod stb_image; extern mod stb_image;
extern mod extra; extern mod extra;

View file

@ -13,7 +13,7 @@ use dom::document::AbstractDocument;
use dom::node::{ElementNodeTypeId, Node, ScriptView, AbstractNode}; use dom::node::{ElementNodeTypeId, Node, ScriptView, AbstractNode};
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery}; use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
use layout_interface::{ContentBoxesResponse}; use layout_interface::{ContentBoxesResponse};
use newcss::stylesheet::Stylesheet; use style;
use servo_util::tree::{TreeNodeRef, ElementLike}; use servo_util::tree::{TreeNodeRef, ElementLike};
use js::jsapi::{JSContext, JSObject}; use js::jsapi::{JSContext, JSObject};
@ -27,7 +27,7 @@ pub struct Element {
tag_name: ~str, // TODO: This should be an atom, not a ~str. tag_name: ~str, // TODO: This should be an atom, not a ~str.
attrs: HashMap<~str, ~str>, attrs: HashMap<~str, ~str>,
attrs_list: ~[~str], // store an order of attributes. attrs_list: ~[~str], // store an order of attributes.
style_attribute: Option<Stylesheet>, style_attribute: Option<style::PropertyDeclarationBlock>,
} }
impl Reflectable for Element { impl Reflectable for Element {
@ -173,9 +173,7 @@ impl<'self> Element {
}); });
if "style" == name { if "style" == name {
self.style_attribute = Some( self.style_attribute = Some(style::parse_style_attribute(
Stylesheet::from_attribute(
FromStr::from_str("http://www.example.com/").unwrap(),
null_str_as_empty_ref(raw_value))); null_str_as_empty_ref(raw_value)));
} }

View file

@ -25,7 +25,8 @@ use std::unstable::raw::Box;
use extra::arc::Arc; use extra::arc::Arc;
use js::jsapi::{JSObject, JSContext}; use js::jsapi::{JSObject, JSContext};
use netsurfcss::util::VoidPtrLike; 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::tree::{TreeNode, TreeNodeRef, TreeNodeRefAsElement};
use servo_util::range::Range; use servo_util::range::Range;
use gfx::display_list::DisplayList; use gfx::display_list::DisplayList;
@ -904,8 +905,11 @@ pub struct DisplayBoxes {
/// Data that layout associates with a node. /// Data that layout associates with a node.
pub struct LayoutData { pub struct LayoutData {
/// The results of CSS matching for this node.
applicable_declarations: ~[@[PropertyDeclaration]],
/// The results of CSS styling for this node. /// The results of CSS styling for this node.
style: Option<CompleteSelectResults>, style: Option<ComputedValues>,
/// Description of how to account for recent style changes. /// Description of how to account for recent style changes.
restyle_damage: Option<int>, restyle_damage: Option<int>,
@ -919,6 +923,7 @@ impl LayoutData {
/// Creates new layout data. /// Creates new layout data.
pub fn new() -> LayoutData { pub fn new() -> LayoutData {
LayoutData { LayoutData {
applicable_declarations: ~[],
style: None, style: None,
restyle_damage: None, restyle_damage: None,
boxes: DisplayBoxes { display_list: None, range: None }, boxes: DisplayBoxes { display_list: None, range: None },

View file

@ -8,9 +8,8 @@ use std::cell::Cell;
use std::comm; use std::comm;
use std::comm::Port; use std::comm::Port;
use std::task; use std::task;
use newcss::stylesheet::Stylesheet; use style::Stylesheet;
use newcss::util::DataStream; use servo_net::resource_task::{Load, ProgressMsg, Payload, Done, ResourceTask};
use servo_net::resource_task::{Load, LoadResponse, Payload, Done, ResourceTask, ProgressMsg};
use extra::url::Url; use extra::url::Url;
/// Where a style sheet comes from. /// Where a style sheet comes from.
@ -26,73 +25,42 @@ pub fn spawn_css_parser(provenance: StylesheetProvenance,
let provenance_cell = Cell::new(provenance); let provenance_cell = Cell::new(provenance);
do task::spawn { 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 { match *p {
UrlProvenance(ref the_url) => (*the_url).clone(), UrlProvenance(ref the_url) => (*the_url).clone(),
InlineProvenance(ref the_url, _) => (*the_url).clone() InlineProvenance(ref the_url, _) => (*the_url).clone()
} }
}; };
let sheet = Stylesheet::new(url, data_stream(provenance_cell.take(), let sheet = match provenance_cell.take() {
resource_task.clone())); 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); result_chan.send(sheet);
} }
return result_port; return result_port;
} }
fn data_stream(provenance: StylesheetProvenance, resource_task: ResourceTask) -> @mut DataStream { struct ProgressMsgPortIterator {
match provenance { progress_port: Port<ProgressMsg>
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)
}
}
} }
fn resource_port_to_data_stream(input_port: Port<LoadResponse>) -> @mut DataStream { impl Iterator<~[u8]> for ProgressMsgPortIterator {
let progress_port = input_port.recv().progress_port; fn next(&mut self) -> Option<~[u8]> {
struct ResourcePortDataStream {
progress_port: Port<ProgressMsg>,
};
impl DataStream for ResourcePortDataStream {
fn read(&mut self) -> Option<~[u8]> {
match self.progress_port.recv() { match self.progress_port.recv() {
Payload(data) => Some(data), Payload(data) => Some(data),
Done(*) => None 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
}

View file

@ -12,7 +12,7 @@ use dom::node::{AbstractNode, ElementNodeTypeId, Node, ScriptView};
use dom::types::*; use dom::types::*;
use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser}; use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
use js::jsapi::JSContext; use js::jsapi::JSContext;
use newcss::stylesheet::Stylesheet; use style::Stylesheet;
use script_task::page_from_context; use script_task::page_from_context;
use std::cast; use std::cast;

View file

@ -13,7 +13,7 @@ use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use geom::point::Point2D; use geom::point::Point2D;
use servo_util::geometry::Au; use servo_util::geometry::Au;
use newcss::stylesheet::Stylesheet; use style::Stylesheet;
use extra::url::Url; use extra::url::Url;
/// Asynchronous messages that script can send to layout. /// Asynchronous messages that script can send to layout.

View file

@ -21,6 +21,7 @@ extern mod netsurfcss;
extern mod newcss (name = "css"); extern mod newcss (name = "css");
extern mod servo_net (name = "net"); extern mod servo_net (name = "net");
extern mod servo_util (name = "util"); extern mod servo_util (name = "util");
extern mod style;
extern mod servo_msg (name = "msg"); extern mod servo_msg (name = "msg");
extern mod extra; extern mod extra;

View file

@ -371,7 +371,7 @@ pub mod longhands {
<%self:longhand name="font-family" inherited="True"> <%self:longhand name="font-family" inherited="True">
pub use to_computed_value = super::computed_as_specified; pub use to_computed_value = super::computed_as_specified;
#[deriving(Eq, Clone)] #[deriving(Eq, Clone)]
enum FontFamily { pub enum FontFamily {
FamilyName(~str), FamilyName(~str),
// Generic // Generic
// Serif, // Serif,
@ -563,9 +563,10 @@ pub mod longhands {
} }
pub mod computed_value { pub mod computed_value {
pub type T = super::SpecifiedValue; 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 { #[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 ] /// none | [ underline || overline || line-through || blink ]
pub fn parse(input: &[ComponentValue]) -> Option<SpecifiedValue> { pub fn parse(input: &[ComponentValue]) -> Option<SpecifiedValue> {
@ -978,7 +979,7 @@ fn get_initial_values() -> ComputedValues {
// Most specific/important declarations last // Most specific/important declarations last
pub fn cascade(applicable_declarations: &[~[PropertyDeclaration]], pub fn cascade(applicable_declarations: &[@[PropertyDeclaration]],
parent_style: Option< &ComputedValues>) parent_style: Option< &ComputedValues>)
-> ComputedValues { -> ComputedValues {
let initial_keep_alive; let initial_keep_alive;

View file

@ -90,7 +90,9 @@ pub fn parse_selector_list(input: ~[ComponentValue], namespaces: &NamespaceMap)
skip_whitespace(iter); skip_whitespace(iter);
match iter.peek() { match iter.peek() {
None => break, // EOF None => break, // EOF
Some(&Comma) => (), Some(&Comma) => {
iter.next();
}
_ => return None, _ => return None,
} }
match parse_selector(iter, namespaces) { match parse_selector(iter, namespaces) {
@ -116,6 +118,7 @@ fn parse_selector(iter: &mut Iter, namespaces: &NamespaceMap)
let any_whitespace = skip_whitespace(iter); let any_whitespace = skip_whitespace(iter);
let combinator = match iter.peek() { let combinator = match iter.peek() {
None => break, // EOF None => break, // EOF
Some(&Comma) => break,
Some(&Delim('>')) => { iter.next(); Child }, Some(&Delim('>')) => { iter.next(); Child },
Some(&Delim('+')) => { iter.next(); NextSibling }, Some(&Delim('+')) => { iter.next(); NextSibling },
Some(&Delim('~')) => { iter.next(); LaterSibling }, 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(&Delim('|')) => explicit_namespace(iter, allow_universal, Some(~"")),
Some(&IDHash(*)) => default_namespace(namespaces, None),
_ => return None, _ => return None,
} }
} }