diff options
-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()); |