mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Simplify stacking context creation
Have Fragment::create_stacking_context understand which stacking contexts need layers and which do not. This simplifies the way it is called and eliminates a bunch of code.
This commit is contained in:
parent
fb6d0946cb
commit
1a494b1a73
3 changed files with 67 additions and 94 deletions
|
@ -50,7 +50,7 @@ use layout_debug;
|
|||
use layout_task::DISPLAY_PORT_SIZE_FACTOR;
|
||||
use model::{CollapsibleMargins, MaybeAuto, specified, specified_or_none};
|
||||
use model::{IntrinsicISizes, MarginCollapseInfo};
|
||||
use msg::compositor_msg::{LayerId, LayerType};
|
||||
use msg::compositor_msg::LayerId;
|
||||
use rustc_serialize::{Encodable, Encoder};
|
||||
use std::cmp::{max, min};
|
||||
use std::fmt;
|
||||
|
@ -63,7 +63,6 @@ use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
|||
use util::geometry::{Au, MAX_AU, MAX_RECT};
|
||||
use util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode};
|
||||
use util::opts;
|
||||
use wrapper::PseudoElementType;
|
||||
|
||||
/// Information specific to floated blocks.
|
||||
#[derive(Clone, RustcEncodable)]
|
||||
|
@ -2076,16 +2075,11 @@ impl Flow for BlockFlow {
|
|||
}
|
||||
|
||||
fn layer_id(&self) -> LayerId {
|
||||
let layer_type = match self.fragment.pseudo {
|
||||
PseudoElementType::Normal => LayerType::FragmentBody,
|
||||
PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
|
||||
PseudoElementType::After(_) => LayerType::AfterPseudoContent
|
||||
};
|
||||
LayerId::new_of_type(layer_type, self.fragment.node.id() as usize)
|
||||
self.fragment.layer_id()
|
||||
}
|
||||
|
||||
fn layer_id_for_overflow_scroll(&self) -> LayerId {
|
||||
LayerId::new_of_type(LayerType::OverflowScroll, self.fragment.node.id() as usize)
|
||||
self.fragment.layer_id_for_overflow_scroll()
|
||||
}
|
||||
|
||||
fn is_absolute_containing_block(&self) -> bool {
|
||||
|
|
|
@ -34,7 +34,7 @@ use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
|
|||
use ipc_channel::ipc::{self, IpcSharedMemory};
|
||||
use list_item::ListItemFlow;
|
||||
use model::{self, MaybeAuto, ToGfxMatrix};
|
||||
use msg::compositor_msg::{LayerId, ScrollPolicy, SubpageLayerInfo};
|
||||
use msg::compositor_msg::{ScrollPolicy, SubpageLayerInfo};
|
||||
use net_traits::image::base::{Image, PixelFormat};
|
||||
use net_traits::image_cache_task::UsePlaceholder;
|
||||
use std::default::Default;
|
||||
|
@ -64,12 +64,6 @@ use util::range::Range;
|
|||
/// The logical width of an insertion point: at the moment, a one-pixel-wide line.
|
||||
const INSERTION_POINT_LOGICAL_WIDTH: Au = Au(1 * AU_PER_PX);
|
||||
|
||||
/// Whether a stacking context needs a layer or not.
|
||||
pub enum StackingContextLayerNecessity {
|
||||
Always(LayerId, ScrollPolicy),
|
||||
IfCanvasOrIframe(LayerId),
|
||||
}
|
||||
|
||||
/// The results of display list building for a single flow.
|
||||
pub enum DisplayListBuildingResult {
|
||||
None,
|
||||
|
@ -257,7 +251,7 @@ pub trait FragmentDisplayListBuilding {
|
|||
base_flow: &BaseFlow,
|
||||
display_list: Box<DisplayList>,
|
||||
layout_context: &LayoutContext,
|
||||
needs_layer: StackingContextLayerNecessity,
|
||||
scroll_policy: ScrollPolicy,
|
||||
mode: StackingContextCreationMode)
|
||||
-> Arc<StackingContext>;
|
||||
}
|
||||
|
@ -1171,7 +1165,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
base_flow: &BaseFlow,
|
||||
display_list: Box<DisplayList>,
|
||||
layout_context: &LayoutContext,
|
||||
needs_layer: StackingContextLayerNecessity,
|
||||
scroll_policy: ScrollPolicy,
|
||||
mode: StackingContextCreationMode)
|
||||
-> Arc<StackingContext> {
|
||||
let border_box = match mode {
|
||||
|
@ -1284,24 +1278,23 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
filters.push(Filter::Opacity(effects.opacity))
|
||||
}
|
||||
|
||||
// Ensure every canvas or iframe has a layer.
|
||||
let (scroll_policy, layer_id) = match needs_layer {
|
||||
StackingContextLayerNecessity::Always(layer_id, scroll_policy) => {
|
||||
(scroll_policy, Some(layer_id))
|
||||
}
|
||||
StackingContextLayerNecessity::IfCanvasOrIframe(layer_id) => {
|
||||
// FIXME(pcwalton): So so bogus :(
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) => {
|
||||
(ScrollPolicy::Scrollable, Some(layer_id))
|
||||
}
|
||||
_ => (ScrollPolicy::Scrollable, None),
|
||||
}
|
||||
}
|
||||
let canvas_or_iframe = match self.specific {
|
||||
SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) => true,
|
||||
_ => false
|
||||
};
|
||||
|
||||
// If it's a canvas we must propagate the layer and the renderer to the paint
|
||||
// task
|
||||
// There are three situations that need layers: when the fragment has the HAS_LAYER
|
||||
// flag, when this is a canvas or iframe fragment, and when we are building a layer
|
||||
// tree for overflow scrolling.
|
||||
let layer_id = if mode == StackingContextCreationMode::InnerScrollWrapper {
|
||||
Some(self.layer_id_for_overflow_scroll())
|
||||
} else if self.flags.contains(HAS_LAYER) || canvas_or_iframe {
|
||||
Some(self.layer_id())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// If it's a canvas we must propagate the layer and the renderer to the paint task.
|
||||
if let SpecificFragmentInfo::Canvas(ref fragment_info) = self.specific {
|
||||
let layer_id = layer_id.unwrap();
|
||||
if let Some(ref ipc_renderer) = fragment_info.ipc_renderer {
|
||||
|
@ -1585,27 +1578,19 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
border_painting_mode,
|
||||
background_border_level);
|
||||
|
||||
self.base.display_list_building_result = if self.fragment.flags.contains(HAS_LAYER) {
|
||||
self.base.display_list_building_result = if self.fragment.establishes_stacking_context() {
|
||||
let scroll_policy = if self.is_fixed() {
|
||||
ScrollPolicy::FixedPosition
|
||||
} else {
|
||||
ScrollPolicy::Scrollable
|
||||
};
|
||||
|
||||
let stacking_context = self.fragment.create_stacking_context(
|
||||
&self.base,
|
||||
display_list,
|
||||
layout_context,
|
||||
StackingContextLayerNecessity::Always(self.layer_id(), scroll_policy),
|
||||
StackingContextCreationMode::Normal);
|
||||
DisplayListBuildingResult::StackingContext(stacking_context)
|
||||
} else if self.fragment.establishes_stacking_context() {
|
||||
DisplayListBuildingResult::StackingContext(
|
||||
self.fragment.create_stacking_context(
|
||||
&self.base,
|
||||
display_list,
|
||||
layout_context,
|
||||
StackingContextLayerNecessity::IfCanvasOrIframe(self.layer_id()),
|
||||
scroll_policy,
|
||||
StackingContextCreationMode::Normal))
|
||||
} else {
|
||||
match self.fragment.style.get_box().position {
|
||||
|
@ -1670,22 +1655,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
}
|
||||
};
|
||||
|
||||
if !self.fragment.flags.contains(HAS_LAYER) {
|
||||
if !self.fragment.establishes_stacking_context() {
|
||||
display_list.form_pseudo_stacking_context_for_positioned_content();
|
||||
self.base.display_list_building_result =
|
||||
DisplayListBuildingResult::Normal(display_list);
|
||||
} else {
|
||||
self.base.display_list_building_result =
|
||||
DisplayListBuildingResult::StackingContext(
|
||||
self.fragment.create_stacking_context(
|
||||
&self.base,
|
||||
display_list,
|
||||
layout_context,
|
||||
StackingContextLayerNecessity::IfCanvasOrIframe(self.layer_id()),
|
||||
StackingContextCreationMode::Normal));
|
||||
}
|
||||
return
|
||||
if !self.fragment.flags.contains(HAS_LAYER) && !self.fragment.establishes_stacking_context() {
|
||||
display_list.form_pseudo_stacking_context_for_positioned_content();
|
||||
self.base.display_list_building_result =
|
||||
DisplayListBuildingResult::Normal(display_list);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we got here, then we need a new layer.
|
||||
|
@ -1695,40 +1669,33 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
ScrollPolicy::Scrollable
|
||||
};
|
||||
|
||||
let stacking_context_creation_mode = if outer_display_list_for_overflow_scroll.is_some() {
|
||||
StackingContextCreationMode::InnerScrollWrapper
|
||||
} else {
|
||||
StackingContextCreationMode::Normal
|
||||
};
|
||||
|
||||
let layer_id = if outer_display_list_for_overflow_scroll.is_some() {
|
||||
self.layer_id_for_overflow_scroll()
|
||||
} else {
|
||||
self.layer_id()
|
||||
};
|
||||
let stacking_context = self.fragment.create_stacking_context(
|
||||
&self.base,
|
||||
display_list,
|
||||
layout_context,
|
||||
StackingContextLayerNecessity::Always(layer_id, scroll_policy),
|
||||
stacking_context_creation_mode);
|
||||
|
||||
let outermost_stacking_context = match outer_display_list_for_overflow_scroll {
|
||||
Some(mut outer_display_list_for_overflow_scroll) => {
|
||||
outer_display_list_for_overflow_scroll.children.push_back(stacking_context);
|
||||
|
||||
let stacking_context = match outer_display_list_for_overflow_scroll {
|
||||
Some(mut outer_display_list) => {
|
||||
outer_display_list.children.push_back(self.fragment.create_stacking_context(
|
||||
&self.base,
|
||||
display_list,
|
||||
layout_context,
|
||||
scroll_policy,
|
||||
StackingContextCreationMode::InnerScrollWrapper));
|
||||
self.fragment.create_stacking_context(
|
||||
&self.base,
|
||||
outer_display_list_for_overflow_scroll,
|
||||
outer_display_list,
|
||||
layout_context,
|
||||
StackingContextLayerNecessity::Always(self.layer_id(), scroll_policy),
|
||||
scroll_policy,
|
||||
StackingContextCreationMode::OuterScrollWrapper)
|
||||
}
|
||||
None => stacking_context,
|
||||
None => {
|
||||
self.fragment.create_stacking_context(
|
||||
&self.base,
|
||||
display_list,
|
||||
layout_context,
|
||||
scroll_policy,
|
||||
StackingContextCreationMode::Normal)
|
||||
}
|
||||
};
|
||||
|
||||
self.base.display_list_building_result =
|
||||
DisplayListBuildingResult::StackingContext(outermost_stacking_context)
|
||||
DisplayListBuildingResult::StackingContext(stacking_context)
|
||||
}
|
||||
|
||||
fn build_display_list_for_floating_block(&mut self,
|
||||
|
@ -1743,12 +1710,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
|
||||
self.base.display_list_building_result = if self.fragment.establishes_stacking_context() {
|
||||
DisplayListBuildingResult::StackingContext(
|
||||
self.fragment.create_stacking_context(
|
||||
&self.base,
|
||||
display_list,
|
||||
layout_context,
|
||||
StackingContextLayerNecessity::IfCanvasOrIframe(self.layer_id()),
|
||||
StackingContextCreationMode::Normal))
|
||||
self.fragment.create_stacking_context(&self.base,
|
||||
display_list,
|
||||
layout_context,
|
||||
ScrollPolicy::Scrollable,
|
||||
StackingContextCreationMode::Normal))
|
||||
} else {
|
||||
DisplayListBuildingResult::Normal(display_list)
|
||||
}
|
||||
|
@ -1851,8 +1817,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
|||
&self.base,
|
||||
display_list,
|
||||
layout_context,
|
||||
StackingContextLayerNecessity::Always(self.layer_id(),
|
||||
ScrollPolicy::Scrollable),
|
||||
ScrollPolicy::Scrollable,
|
||||
StackingContextCreationMode::Normal))
|
||||
} else {
|
||||
DisplayListBuildingResult::Normal(display_list)
|
||||
|
|
|
@ -22,6 +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::compositor_msg::{LayerId, LayerType};
|
||||
use msg::constellation_msg::{PipelineId, SubpageId};
|
||||
use net_traits::image::base::Image;
|
||||
use net_traits::image_cache_task::UsePlaceholder;
|
||||
|
@ -2423,6 +2424,19 @@ impl Fragment {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn layer_id(&self) -> LayerId {
|
||||
let layer_type = match self.pseudo {
|
||||
PseudoElementType::Normal => LayerType::FragmentBody,
|
||||
PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
|
||||
PseudoElementType::After(_) => LayerType::AfterPseudoContent
|
||||
};
|
||||
LayerId::new_of_type(layer_type, self.node.id() as usize)
|
||||
}
|
||||
|
||||
pub fn layer_id_for_overflow_scroll(&self) -> LayerId {
|
||||
LayerId::new_of_type(LayerType::OverflowScroll, self.node.id() as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Fragment {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue