diff options
author | bors-servo <metajack+bors@gmail.com> | 2014-10-21 17:51:43 -0600 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2014-10-21 17:51:43 -0600 |
commit | f5ad89f927864ba4f1cbb409b8b0e3b38febef76 (patch) | |
tree | bce8d4265a5058eec3bd7fb1e8e70402d76ee163 | |
parent | 3936d142607ef5a9b4a49d48e207daf4975cc7d5 (diff) | |
parent | adecdbd4cf6a03d49ef3640bc324f865fe25a2f9 (diff) | |
download | servo-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.rs | 30 | ||||
-rw-r--r-- | components/util/opts.rs | 5 | ||||
-rw-r--r-- | ports/cef/core.rs | 1 |
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()); |