aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2014-10-21 17:51:43 -0600
committerbors-servo <metajack+bors@gmail.com>2014-10-21 17:51:43 -0600
commitf5ad89f927864ba4f1cbb409b8b0e3b38febef76 (patch)
treebce8d4265a5058eec3bd7fb1e8e70402d76ee163
parent3936d142607ef5a9b4a49d48e207daf4975cc7d5 (diff)
parentadecdbd4cf6a03d49ef3640bc324f865fe25a2f9 (diff)
downloadservo-f5ad89f927864ba4f1cbb409b8b0e3b38febef76.tar.gz
servo-f5ad89f927864ba4f1cbb409b8b0e3b38febef76.zip
auto merge of #3747 : mrobinson/servo/validate-display-list, r=pcwalton
When this option is enabled, the layout task will print an error when display list items draw outside their owning Flow's position rect. This will make it easier to detect layout errors before they break rendering. This is a command-line option for the moment, because we violate this rule quite a bit still. Once all bugs causing this are fixed, we can be more aggressive about enabling the option.
-rw-r--r--components/layout/flow.rs30
-rw-r--r--components/util/opts.rs5
-rw-r--r--ports/cef/core.rs1
3 files changed, 36 insertions, 0 deletions
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index b8f9a2b55e0..269aac1b81d 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -54,6 +54,7 @@ use servo_msg::compositor_msg::LayerId;
use servo_util::geometry::Au;
use servo_util::logical_geometry::WritingMode;
use servo_util::logical_geometry::{LogicalRect, LogicalSize};
+use servo_util::opts;
use std::mem;
use std::num::Zero;
use std::fmt;
@@ -405,6 +406,9 @@ pub trait ImmutableFlowUtils {
/// Dumps the flow tree for debugging, with a prefix to indicate that we're at the given level.
fn dump_with_level(self, level: uint);
+
+ /// Print an error when this Flow's display list items are not within its boundaries.
+ fn validate_display_list_geometry(self);
}
pub trait MutableFlowUtils {
@@ -1024,6 +1028,28 @@ impl<'a> ImmutableFlowUtils for &'a Flow + 'a {
kid.dump_with_level(level + 1)
}
}
+
+ fn validate_display_list_geometry(self) {
+ let position_with_overflow = base(self).position.union(&base(self).overflow);
+ let bounds = Rect(base(self).abs_position,
+ Size2D(position_with_overflow.size.inline,
+ position_with_overflow.size.block));
+
+ for item in base(self).display_list.iter() {
+ let paint_bounds = match item.base().bounds.intersection(&item.base().clip_rect) {
+ None => continue,
+ Some(rect) => rect,
+ };
+
+ if paint_bounds.is_empty() {
+ continue;
+ }
+
+ if bounds.union(&paint_bounds) != bounds {
+ error!("DisplayList item {} outside of Flow overflow ({})", item, paint_bounds);
+ }
+ }
+ }
}
impl<'a> MutableFlowUtils for &'a mut Flow + 'a {
@@ -1116,6 +1142,10 @@ impl<'a> MutableFlowUtils for &'a mut Flow + 'a {
// Nothing to do here, as column groups don't render.
}
}
+
+ if opts::get().validate_display_list_geometry {
+ self.validate_display_list_geometry();
+ }
}
/// Collect and update static y-offsets bubbled up by kids.
diff --git a/components/util/opts.rs b/components/util/opts.rs
index 8a201d81329..3805a03ec04 100644
--- a/components/util/opts.rs
+++ b/components/util/opts.rs
@@ -99,6 +99,9 @@ pub struct Opts {
/// Dumps the flow tree after a layout.
pub dump_flow_tree: bool,
+
+ /// Whether to show an error when display list geometry escapes flow overflow regions.
+ pub validate_display_list_geometry: bool,
}
fn print_usage(app: &str, opts: &[getopts::OptGroup]) {
@@ -147,6 +150,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
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("", "validate-display-list-geometry", "Display an error when display list geometry escapes overflow region."),
getopts::optflag("h", "help", "Print this message")
);
@@ -249,6 +253,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
initial_window_size: initial_window_size,
user_agent: opt_match.opt_str("u"),
dump_flow_tree: opt_match.opt_present("dump-flow-tree"),
+ validate_display_list_geometry: opt_match.opt_present("validate-display-list-geometry"),
};
set_opts(opts);
diff --git a/ports/cef/core.rs b/ports/cef/core.rs
index 5a51c351398..cdde5e9a4bf 100644
--- a/ports/cef/core.rs
+++ b/ports/cef/core.rs
@@ -74,6 +74,7 @@ pub extern "C" fn cef_run_message_loop() {
initial_window_size: TypedSize2D(800, 600),
user_agent: None,
dump_flow_tree: false,
+ validate_display_list_geometry: false,
};
native::start(0, 0 as *const *const u8, proc() {
let window = Some(glfw_app::create_window());