aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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());