mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
layout: Make the compositor rather than layout determine the position of
each iframe. The old code that attempted to do this during layout wasn't able to work for multiple reasons: it couldn't know where the iframe was going to be on the page (because of nested iframes), and at the time it was building the display list for a fragment it couldn't know where that fragment was going to be in page coordinates. This patch rewrites that code so that both the sizes and positions of iframes are determined by the compositor. Layout layerizes all iframes and marks the iframe layers with the appropriate pipeline and subpage IDs so that the compositor can place them correctly. This approach is similar in spirit to Gecko's `RefLayer` infrastructure. The logic that determines when it is time to take the screenshot for reftests has been significantly revamped to deal with this change in delegation of responsibility. Additionally, this code removes the infrastructure that sends layout data back to the layout task to be destroyed, since it is now all thread-safe and can be destroyed on the script task. The failing tests now fail because of a pre-existing bug related to intrinsic heights and borders on inline replaced elements. They happened to pass before because we never rendered the iframes at all, which meant they never had a chance to draw the red border the tests expect to not render! Closes #7377.
This commit is contained in:
parent
ed0d70e234
commit
c72d0c2ed0
20 changed files with 602 additions and 389 deletions
|
@ -22,7 +22,7 @@ use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT};
|
|||
use ipc_channel::ipc::IpcSender;
|
||||
use layout_debug;
|
||||
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, specified};
|
||||
use msg::constellation_msg::{ConstellationChan, Msg, PipelineId, SubpageId};
|
||||
use msg::constellation_msg::{PipelineId, SubpageId};
|
||||
use net_traits::image::base::Image;
|
||||
use net_traits::image_cache_task::UsePlaceholder;
|
||||
use rustc_serialize::{Encodable, Encoder};
|
||||
|
@ -2102,6 +2102,16 @@ impl Fragment {
|
|||
stacking_relative_border_box.size.height - border_padding.vertical()))
|
||||
}
|
||||
|
||||
/// Returns true if this fragment unconditionally layerizes.
|
||||
pub fn needs_layer(&self) -> bool {
|
||||
// Canvas and iframes always layerize, as an special case
|
||||
// FIXME(pcwalton): Don't unconditionally form stacking contexts for each canvas.
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this fragment establishes a new stacking context and false otherwise.
|
||||
pub fn establishes_stacking_context(&self) -> bool {
|
||||
if self.flags.contains(HAS_LAYER) {
|
||||
|
@ -2126,9 +2136,7 @@ impl Fragment {
|
|||
transform_style::T::auto => {}
|
||||
}
|
||||
|
||||
// Canvas always layerizes, as an special case
|
||||
// FIXME(pcwalton): Don't unconditionally form stacking contexts for each canvas.
|
||||
if let SpecificFragmentInfo::Canvas(_) = self.specific {
|
||||
if self.needs_layer() {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -2161,12 +2169,10 @@ impl Fragment {
|
|||
|
||||
/// Computes the overflow rect of this fragment relative to the start of the flow.
|
||||
pub fn compute_overflow(&self,
|
||||
relative_containing_block_size: &LogicalSize<Au>,
|
||||
relative_containing_block_mode: WritingMode)
|
||||
flow_size: &Size2D<Au>,
|
||||
relative_containing_block_size: &LogicalSize<Au>)
|
||||
-> Rect<Au> {
|
||||
let container_size =
|
||||
relative_containing_block_size.to_physical(relative_containing_block_mode);
|
||||
let mut border_box = self.border_box.to_physical(self.style.writing_mode, container_size);
|
||||
let mut border_box = self.border_box.to_physical(self.style.writing_mode, *flow_size);
|
||||
|
||||
// Relative position can cause us to draw outside our border box.
|
||||
//
|
||||
|
@ -2209,23 +2215,6 @@ impl Fragment {
|
|||
overflow
|
||||
}
|
||||
|
||||
/// Remove any compositor layers associated with this fragment - it is being
|
||||
/// removed from the tree or had its display property set to none.
|
||||
/// TODO(gw): This just hides the compositor layer for now. In the future
|
||||
/// it probably makes sense to provide a hint to the compositor whether
|
||||
/// the layers should be destroyed to free memory.
|
||||
pub fn remove_compositor_layers(&self, constellation_chan: ConstellationChan) {
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::Iframe(ref iframe_info) => {
|
||||
let ConstellationChan(ref chan) = constellation_chan;
|
||||
chan.send(Msg::FrameRect(iframe_info.pipeline_id,
|
||||
iframe_info.subpage_id,
|
||||
Rect::zero())).unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn requires_line_break_afterward_if_wrapping_on_newlines(&self) -> bool {
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::ScannedText(ref scanned_text) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue