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