aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2014-10-08 23:33:33 -0600
committerbors-servo <metajack+bors@gmail.com>2014-10-08 23:33:33 -0600
commitc4ac93b315f058d9a061b20ce64cacbead339f86 (patch)
tree65835acd80831ba3b41cd62d62da01b577a3030c
parenteff0de0ce12b20ffc4806d14c95777004003f2ae (diff)
parent01c90d8d6aa6876a4479d44c167b1b9ab0a7e0ba (diff)
downloadservo-c4ac93b315f058d9a061b20ce64cacbead339f86.tar.gz
servo-c4ac93b315f058d9a061b20ce64cacbead339f86.zip
auto merge of #3599 : pcwalton/servo/z-index, r=glennw
r? @glennw
-rw-r--r--components/gfx/display_list/mod.rs8
-rw-r--r--components/layout/block.rs9
-rw-r--r--components/layout/construct.rs7
-rw-r--r--components/layout/fragment.rs22
-rw-r--r--components/layout/inline.rs9
-rw-r--r--components/layout/layout_task.rs3
-rw-r--r--components/style/properties/mod.rs.mako35
-rw-r--r--components/util/opts.rs5
-rw-r--r--ports/cef/core.rs1
9 files changed, 81 insertions, 18 deletions
diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs
index 5025542765c..00a79c9d979 100644
--- a/components/gfx/display_list/mod.rs
+++ b/components/gfx/display_list/mod.rs
@@ -177,9 +177,6 @@ struct StackingContext {
/// All other content.
pub content: DisplayList,
/// Positioned descendant stacking contexts, along with their `z-index` levels.
- ///
- /// TODO(pcwalton): `z-index` should be the actual CSS property value in order to handle
- /// `auto`, not just an integer.
pub positioned_descendants: Vec<(i32, DisplayList)>,
}
@@ -383,7 +380,10 @@ impl DisplayList {
// Steps 1 and 2: Borders and background for the root.
result.push_all_move(background_and_borders);
- // TODO(pcwalton): Sort positioned children according to z-index.
+ // Sort positioned children according to z-index.
+ positioned_descendants.sort_by(|&(z_index_a, _), &(z_index_b, _)| {
+ z_index_a.cmp(&z_index_b)
+ });
// Step 3: Positioned descendants with negative z-indices.
for &(ref mut z_index, ref mut list) in positioned_descendants.iter_mut() {
diff --git a/components/layout/block.rs b/components/layout/block.rs
index eff98e27377..ae4f8753d3b 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -1239,11 +1239,10 @@ impl BlockFlow {
if !self.base.absolute_position_info.layers_needed_for_positioned_flows &&
!self.base.flags.needs_layer() {
// We didn't need a layer.
- //
- // TODO(#781, pcwalton): `z-index`.
- self.base.display_list =
- mem::replace(&mut self.base.display_list,
- DisplayList::new()).flatten(PositionedDescendantStackingLevel(0));
+ let z_index = self.fragment.style().get_box().z_index.number_or_zero();
+ let level = PositionedDescendantStackingLevel(z_index);
+ self.base.display_list = mem::replace(&mut self.base.display_list,
+ DisplayList::new()).flatten(level);
return
}
diff --git a/components/layout/construct.rs b/components/layout/construct.rs
index 83185801772..826a59a7ead 100644
--- a/components/layout/construct.rs
+++ b/components/layout/construct.rs
@@ -330,12 +330,17 @@ impl<'a> FlowConstructor<'a> {
{
let inline_flow = inline_flow_ref.get_mut().as_inline();
+
+ // We must scan for runs before computing minimum ascent and descent because scanning
+ // for runs might collapse so much whitespace away that only hypothetical fragments
+ // remain. In that case the inline flow will compute its ascent and descent to be zero.
+ TextRunScanner::new().scan_for_runs(self.layout_context.font_context(), inline_flow);
+
let (ascent, descent) =
inline_flow.compute_minimum_ascent_and_descent(self.layout_context.font_context(),
&**node.style());
inline_flow.minimum_block_size_above_baseline = ascent;
inline_flow.minimum_depth_below_baseline = descent;
- TextRunScanner::new().scan_for_runs(self.layout_context.font_context(), inline_flow);
}
inline_flow_ref.finish(self.layout_context);
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 244aa34b24f..aa7e586542f 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -1701,13 +1701,13 @@ impl Fragment {
&font_style);
InlineMetrics::from_block_height(&font_metrics, block_flow.base.position.size.block)
}
- InlineAbsoluteHypotheticalFragment(ref info) => {
- // See CSS 2.1 § 10.8.1.
- let block_flow = info.flow_ref.get().as_immutable_block();
- let font_style = text::computed_style_to_font_style(&*self.style);
- let font_metrics = text::font_metrics_for_style(layout_context.font_context(),
- &font_style);
- InlineMetrics::from_block_height(&font_metrics, block_flow.base.position.size.block)
+ InlineAbsoluteHypotheticalFragment(_) => {
+ // Hypothetical boxes take up no space.
+ InlineMetrics {
+ block_size_above_baseline: Au(0),
+ depth_below_baseline: Au(0),
+ ascent: Au(0),
+ }
}
_ => {
InlineMetrics {
@@ -1719,6 +1719,14 @@ impl Fragment {
}
}
+ /// Returns true if this fragment is a hypothetical box. See CSS 2.1 § 10.3.7.
+ pub fn is_hypothetical(&self) -> bool {
+ match self.specific {
+ InlineAbsoluteHypotheticalFragment(_) => true,
+ _ => false,
+ }
+ }
+
/// Returns true if this fragment can merge with another adjacent fragment or false otherwise.
pub fn can_merge_with_fragment(&self, other: &Fragment) -> bool {
match (&self.specific, &other.specific) {
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index 700ffa56602..b9901a3f13b 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -943,7 +943,14 @@ impl InlineFlow {
/// `style` is the style of the block.
pub fn compute_minimum_ascent_and_descent(&self,
font_context: &mut FontContext,
- style: &ComputedValues) -> (Au, Au) {
+ style: &ComputedValues)
+ -> (Au, Au) {
+ // As a special case, if this flow contains only hypothetical fragments, then the entire
+ // flow is hypothetical and takes up no space. See CSS 2.1 § 10.3.7.
+ if self.fragments.fragments.iter().all(|fragment| fragment.is_hypothetical()) {
+ return (Au(0), Au(0))
+ }
+
let font_style = text::computed_style_to_font_style(style);
let font_metrics = text::font_metrics_for_style(font_context, &font_style);
let line_height = text::line_height_from_style(style, &font_metrics);
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs
index e974b1287fc..5e2fb1b4426 100644
--- a/components/layout/layout_task.rs
+++ b/components/layout/layout_task.rs
@@ -800,6 +800,9 @@ impl LayoutTask {
if self.opts.trace_layout {
layout_debug::begin_trace(layout_root.clone());
}
+ if self.opts.dump_flow_tree {
+ layout_root.get_mut().dump();
+ }
// Propagate damage.
profile(time::LayoutDamagePropagateCategory, Some((&data.url, data.iframe, self.first_reflow.get())),
diff --git a/components/style/properties/mod.rs.mako b/components/style/properties/mod.rs.mako
index d51d5d91e14..c5ca7159893 100644
--- a/components/style/properties/mod.rs.mako
+++ b/components/style/properties/mod.rs.mako
@@ -345,6 +345,41 @@ pub mod longhands {
</%self:longhand>
+ <%self:single_component_value name="z-index">
+ pub use super::computed_as_specified as to_computed_value;
+ pub type SpecifiedValue = computed_value::T;
+ pub mod computed_value {
+ #[deriving(PartialEq, Clone)]
+ pub enum T {
+ Auto,
+ Number(i32),
+ }
+
+ impl T {
+ pub fn number_or_zero(self) -> i32 {
+ match self {
+ Auto => 0,
+ Number(value) => value,
+ }
+ }
+ }
+ }
+ #[inline]
+ pub fn get_initial_value() -> computed_value::T {
+ Auto
+ }
+ fn from_component_value(input: &ComponentValue, _: &Url) -> Result<SpecifiedValue,()> {
+ match *input {
+ Ident(ref keyword) if keyword.as_slice().eq_ignore_ascii_case("auto") => Ok(Auto),
+ ast::Number(ast::NumericValue {
+ int_value: Some(value),
+ ..
+ }) => Ok(Number(value as i32)),
+ _ => Err(())
+ }
+ }
+ </%self:single_component_value>
+
${new_style_struct("InheritedBox", is_inherited=True)}
${single_keyword("direction", "ltr rtl", experimental=True)}
diff --git a/components/util/opts.rs b/components/util/opts.rs
index 47a65797615..de8b295d1eb 100644
--- a/components/util/opts.rs
+++ b/components/util/opts.rs
@@ -94,6 +94,9 @@ pub struct Opts {
/// An optional string allowing the user agent to be set for testing.
pub user_agent: Option<String>,
+
+ /// Dumps the flow tree after a layout.
+ pub dump_flow_tree: bool,
}
fn print_usage(app: &str, opts: &[getopts::OptGroup]) {
@@ -131,6 +134,7 @@ pub fn from_cmdline_args(args: &[String]) -> Option<Opts> {
getopts::optflagopt("", "devtools", "Start remote devtools server on port", "6000"),
getopts::optopt("", "resolution", "Set window resolution.", "800x600"),
getopts::optopt("u", "user-agent", "Set custom user agent string", "NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)"),
+ getopts::optflag("", "dump-flow-tree", "Dump the flow (render) tree during each layout."),
getopts::optflag("h", "help", "Print this message")
);
@@ -248,6 +252,7 @@ pub fn from_cmdline_args(args: &[String]) -> Option<Opts> {
devtools_port: devtools_port,
initial_window_size: initial_window_size,
user_agent: opt_match.opt_str("u"),
+ dump_flow_tree: opt_match.opt_present("dump-flow-tree"),
})
}
diff --git a/ports/cef/core.rs b/ports/cef/core.rs
index f08bf007fed..d425252f3a2 100644
--- a/ports/cef/core.rs
+++ b/ports/cef/core.rs
@@ -71,6 +71,7 @@ pub extern "C" fn cef_run_message_loop() {
devtools_port: None,
initial_window_size: TypedSize2D(800, 600),
user_agent: None,
+ dump_flow_tree: false,
};
native::start(0, 0 as *const *const u8, proc() {
servo::run(opts);