mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
auto merge of #1109 : sanxiyn/servo/new-style, r=SimonSapin
Regressions are: * Incremental layout is broken * `:link` is broken * Source URL is not passed to CSS parser * `text-decoration` propagation for block containers establishing an inline formatting context is not handled This also does not remove NetSurf libcss from the build. That can be done in a followup. This was a team effort. 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:
commit
9b25df1968
28 changed files with 353 additions and 494 deletions
|
@ -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
|
||||||
|
|
|
@ -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 }
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
}
|
||||||
},
|
if new_run.decoration.overline {
|
||||||
CSSTextDecorationOverline => {
|
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);
|
}
|
||||||
},
|
if new_run.decoration.line_through {
|
||||||
CSSTextDecorationLineThrough => {
|
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);
|
|
||||||
},
|
|
||||||
_ => ()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 => {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
None => None,
|
||||||
* the node (the reader-auxiliary box in the COW model) with the
|
Some(ref style_attribute) => Some(style_attribute)
|
||||||
* computed style.
|
|
||||||
*/
|
|
||||||
fn restyle_subtree(&self, select_ctx: &SelectCtx) {
|
|
||||||
// Only elements have styles
|
|
||||||
if self.is_element() {
|
|
||||||
do self.with_imm_element |elem| {
|
|
||||||
let inline_style = match elem.style_attribute {
|
|
||||||
None => None,
|
|
||||||
Some(ref sheet) => Some(sheet),
|
|
||||||
};
|
|
||||||
let select_handler = NodeSelectHandler { node: *self };
|
|
||||||
let incomplete_results = select_ctx.select_style(self, inline_style, &select_handler);
|
|
||||||
// Combine this node's results with its parent's to resolve all inherited values
|
|
||||||
let complete_results = compose_results(*self, incomplete_results);
|
|
||||||
|
|
||||||
// If there was an existing style, compute the damage that
|
|
||||||
// incremental layout will need to fix.
|
|
||||||
if self.have_css_select_results() {
|
|
||||||
let damage = incremental::compute_damage(self, self.get_css_select_results(), &complete_results);
|
|
||||||
self.set_restyle_damage(damage);
|
|
||||||
}
|
|
||||||
self.set_css_select_results(complete_results);
|
|
||||||
};
|
};
|
||||||
|
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() {
|
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
v => v
|
||||||
CSSDisplayInlineTable => CSSDisplayInlineBlock,
|
}
|
||||||
CSSDisplayTableRowGroup => CSSDisplayBlock,
|
} else {
|
||||||
CSSDisplayTableHeaderGroup => CSSDisplayBlock,
|
match display {
|
||||||
CSSDisplayTableFooterGroup => CSSDisplayBlock,
|
display::none => return NoGenerator,
|
||||||
CSSDisplayTableRow => CSSDisplayBlock,
|
display::list_item => display::block,
|
||||||
CSSDisplayTableColumnGroup => return NoGenerator,
|
v => v
|
||||||
CSSDisplayTableColumn => return NoGenerator,
|
}
|
||||||
CSSDisplayTableCell => CSSDisplayBlock,
|
|
||||||
CSSDisplayTableCaption => CSSDisplayBlock,
|
|
||||||
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) => {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,10 +173,8 @@ impl<'self> Element {
|
||||||
});
|
});
|
||||||
|
|
||||||
if "style" == name {
|
if "style" == name {
|
||||||
self.style_attribute = Some(
|
self.style_attribute = Some(style::parse_style_attribute(
|
||||||
Stylesheet::from_attribute(
|
null_str_as_empty_ref(raw_value)));
|
||||||
FromStr::from_str("http://www.example.com/").unwrap(),
|
|
||||||
null_str_as_empty_ref(raw_value)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: update owner document's id hashmap for `document.getElementById()`
|
// TODO: update owner document's id hashmap for `document.getElementById()`
|
||||||
|
|
|
@ -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 },
|
||||||
|
|
|
@ -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();
|
impl Iterator<~[u8]> for ProgressMsgPortIterator {
|
||||||
resource_task.send(Load(url, input_chan));
|
fn next(&mut self) -> Option<~[u8]> {
|
||||||
resource_port_to_data_stream(input_port)
|
match self.progress_port.recv() {
|
||||||
}
|
Payload(data) => Some(data),
|
||||||
InlineProvenance(_, data) => {
|
Done(*) => None
|
||||||
data_to_data_stream(data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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]> {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue