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)
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

View file

@ -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 }
}

View file

@ -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<E> {
list: ~[DisplayItem<E>]
@ -110,7 +108,7 @@ pub struct BorderDisplayItem<E> {
color: SideOffsets2D<Color>,
/// The border styles.
style: SideOffsets2D<CSSBorderStyle>
style: SideOffsets2D<border_style::T>
}
impl<E> DisplayItem<E> {
@ -143,25 +141,22 @@ impl<E> DisplayItem<E> {
let strikeout_size = font.metrics.strikeout_size;
let strikeout_offset = font.metrics.strikeout_offset;
match new_run.decoration {
CSSTextDecorationUnderline => {
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);
},
CSSTextDecorationOverline => {
}
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);
},
CSSTextDecorationLineThrough => {
}
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);
},
_ => ()
}
}

View file

@ -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.

View file

@ -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

View file

@ -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<Au>,
border: SideOffsets2D<Au>,
color: SideOffsets2D<Color>,
style: SideOffsets2D<CSSBorderStyle>) {
style: SideOffsets2D<border_style::T>) {
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
}
}
}

View file

@ -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<GlyphStore>],
}
@ -24,7 +24,7 @@ pub struct TextRun {
pub struct SendableTextRun {
text: ~str,
font: FontDescriptor,
decoration: CSSTextDecoration,
decoration: text_decoration::T,
priv glyphs: ~[Arc<GlyphStore>],
}
@ -117,7 +117,7 @@ impl<'self> Iterator<Range> 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 {

View file

@ -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<AbstractNode<LayoutView>>);
fn cascade_subtree(&self, parent: Option<AbstractNode<LayoutView>>);
}
impl MatchMethods for AbstractNode<LayoutView> {
/**
* 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 {
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 sheet) => Some(sheet),
Some(ref style_attribute) => Some(style_attribute)
};
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);
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<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 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);
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,
for kid in self.children() {
if kid.is_element() {
kid.cascade_subtree(Some(*self));
}
}
}
}

View file

@ -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<LayoutView> {
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 {

View file

@ -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<LayoutView> {
* 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<LayoutView> {
}
/// 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()));
}

View file

@ -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 {

View file

@ -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);
}

View file

@ -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<FontStyle>,
text_decoration: Option<CSSTextDecoration>,
text_decoration: Option<text_decoration::T>,
}
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<ClearType> {
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<LayoutView>) -> CSSTextDecoration {
fn get_propagated_text_decoration(element: AbstractNode<LayoutView>) -> 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 {

View file

@ -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,
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) => {

View file

@ -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)
}
}

View file

@ -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);

View file

@ -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
},
_ => {

View file

@ -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<Arc<DisplayList<AbstractNode<()>>>>,
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);
}
}
}

View file

@ -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<Au>,
@ -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)
}
}
}

View file

@ -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;

View file

@ -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<Stylesheet>,
style_attribute: Option<style::PropertyDeclarationBlock>,
}
impl Reflectable for Element {
@ -173,9 +173,7 @@ impl<'self> Element {
});
if "style" == name {
self.style_attribute = Some(
Stylesheet::from_attribute(
FromStr::from_str("http://www.example.com/").unwrap(),
self.style_attribute = Some(style::parse_style_attribute(
null_str_as_empty_ref(raw_value)));
}

View file

@ -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<CompleteSelectResults>,
style: Option<ComputedValues>,
/// Description of how to account for recent style changes.
restyle_damage: Option<int>,
@ -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 },

View file

@ -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<ProgressMsg>
}
fn resource_port_to_data_stream(input_port: Port<LoadResponse>) -> @mut DataStream {
let progress_port = input_port.recv().progress_port;
struct ResourcePortDataStream {
progress_port: Port<ProgressMsg>,
};
impl DataStream for ResourcePortDataStream {
fn read(&mut self) -> Option<~[u8]> {
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
}

View file

@ -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;

View file

@ -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.

View file

@ -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;

View file

@ -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<SpecifiedValue> {
@ -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;

View file

@ -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,
}
}