Auto merge of #22684 - servo:next-layout, r=emilio,SimonSapin

Some janitoring over the layout crate

This PR moves a bunch of code around and makes some methods from one-use traits into inherent methods.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/22684)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-01-14 14:35:28 -05:00 committed by GitHub
commit c242abd999
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 386 additions and 805 deletions

1
Cargo.lock generated
View file

@ -3315,7 +3315,6 @@ dependencies = [
"html5ever 0.22.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"malloc_size_of 0.0.1",
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"metrics 0.0.1",

View file

@ -27,9 +27,10 @@
use crate::context::LayoutContext;
use crate::display_list::items::DisplayListSection;
use crate::display_list::StackingContextCollectionState;
use crate::display_list::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use crate::display_list::{DisplayListBuildState, StackingContextCollectionFlags};
use crate::display_list::{
BorderPaintingMode, DisplayListBuildState, StackingContextCollectionFlags,
StackingContextCollectionState,
};
use crate::floats::{ClearType, FloatKind, Floats, PlacementInfo};
use crate::flow::{
BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag, GetBaseFlow,

View file

@ -419,8 +419,17 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
SpecificFragmentInfo::Media(Box::new(MediaFragmentInfo::new(data)))
},
Some(LayoutNodeType::Element(LayoutElementType::HTMLObjectElement)) => {
let elem = node.as_element().unwrap();
let type_and_data = (
elem.get_attr(&ns!(), &local_name!("type")),
elem.get_attr(&ns!(), &local_name!("data")),
);
let object_data = match type_and_data {
(None, Some(uri)) if is_image_data(uri) => ServoUrl::parse(uri).ok(),
_ => None,
};
let image_info = Box::new(ImageFragmentInfo::new(
node.object_data(),
object_data,
None,
node,
&self.layout_context,
@ -1015,7 +1024,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
}
let node_style = node.style(self.style_context());
if is_empty && node_style.has_padding_or_border() {
if is_empty && has_padding_or_border(&node_style) {
// An empty inline box needs at least one fragment to draw its background and borders.
let info = SpecificFragmentInfo::UnscannedText(Box::new(
UnscannedTextFragmentInfo::new(Box::<str>::from(""), None),
@ -1976,7 +1985,15 @@ where
Some(LayoutNodeType::Element(LayoutElementType::HTMLCanvasElement)) |
Some(LayoutNodeType::Element(LayoutElementType::SVGSVGElement)) => true,
Some(LayoutNodeType::Element(LayoutElementType::HTMLObjectElement)) => {
self.has_object_data()
let elem = self.as_element().unwrap();
let type_and_data = (
elem.get_attr(&ns!(), &local_name!("type")),
elem.get_attr(&ns!(), &local_name!("data")),
);
match type_and_data {
(None, Some(uri)) => is_image_data(uri),
_ => false,
}
},
Some(LayoutNodeType::Element(_)) => false,
None => self.get_pseudo_element_type().is_replaced_content(),
@ -2007,61 +2024,7 @@ where
}
}
/// Methods for interacting with HTMLObjectElement nodes
trait ObjectElement {
/// Returns true if this node has object data that is correct uri.
fn has_object_data(&self) -> bool;
/// Returns the "data" attribute value parsed as a URL
fn object_data(&self) -> Option<ServoUrl>;
}
impl<N> ObjectElement for N
where
N: ThreadSafeLayoutNode,
{
fn has_object_data(&self) -> bool {
let elem = self.as_element().unwrap();
let type_and_data = (
elem.get_attr(&ns!(), &local_name!("type")),
elem.get_attr(&ns!(), &local_name!("data")),
);
match type_and_data {
(None, Some(uri)) => is_image_data(uri),
_ => false,
}
}
fn object_data(&self) -> Option<ServoUrl> {
let elem = self.as_element().unwrap();
let type_and_data = (
elem.get_attr(&ns!(), &local_name!("type")),
elem.get_attr(&ns!(), &local_name!("data")),
);
match type_and_data {
(None, Some(uri)) if is_image_data(uri) => ServoUrl::parse(uri).ok(),
_ => None,
}
}
}
// This must not be public because only the layout constructor can call these
// methods.
trait FlowConstructionUtils {
/// Adds a new flow as a child of this flow. Removes the flow from the given leaf set if
/// it's present.
fn add_new_child(&mut self, new_child: FlowRef);
/// Finishes a flow. Once a flow is finished, no more child flows or boxes may be added to it.
/// This will normally run the bubble-inline-sizes (minimum and preferred -- i.e. intrinsic --
/// inline-size) calculation, unless the global `bubble_inline-sizes_separately` flag is on.
///
/// All flows must be finished at some point, or they will not have their intrinsic inline-
/// sizes properly computed. (This is not, however, a memory safety problem.)
fn finish(&mut self);
}
impl FlowConstructionUtils for FlowRef {
impl FlowRef {
/// Adds a new flow as a child of this flow. Fails if this flow is marked as a leaf.
fn add_new_child(&mut self, mut new_child: FlowRef) {
{
@ -2207,16 +2170,10 @@ where
)
}
/// Convenience methods for computed CSS values
trait ComputedValueUtils {
/// Returns true if this node has non-zero padding or border.
fn has_padding_or_border(&self) -> bool;
}
impl ComputedValueUtils for ComputedValues {
fn has_padding_or_border(&self) -> bool {
let padding = self.get_padding();
let border = self.get_border();
fn has_padding_or_border(values: &ComputedValues) -> bool {
let padding = values.get_padding();
let border = values.get_border();
!padding.padding_top.is_definitely_zero() ||
!padding.padding_right.is_definitely_zero() ||
@ -2227,7 +2184,6 @@ impl ComputedValueUtils for ComputedValues {
border.border_bottom_width.px() != 0. ||
border.border_left_width.px() != 0.
}
}
/// Maintains a stack of anonymous boxes needed to ensure that the flow tree is *legal*. The tree
/// is legal if it follows the rules in CSS 2.1 § 17.2.1.

View file

@ -22,13 +22,11 @@ use crate::display_list::items::{PopAllTextShadowsDisplayItem, PushTextShadowDis
use crate::display_list::items::{StackingContext, StackingContextType, StickyFrameData};
use crate::display_list::items::{TextOrientation, WebRenderImageInfo};
use crate::display_list::ToLayout;
use crate::flex::FlexFlow;
use crate::flow::{BaseFlow, Flow, FlowFlags};
use crate::flow_ref::FlowRef;
use crate::fragment::SpecificFragmentInfo;
use crate::fragment::{CanvasFragmentSource, CoordinateSystem, Fragment, ScannedTextFragmentInfo};
use crate::inline::{InlineFlow, InlineFragmentNodeFlags};
use crate::list_item::ListItemFlow;
use crate::inline::InlineFragmentNodeFlags;
use crate::model::MaybeAuto;
use crate::table_cell::CollapsedBordersForCell;
use app_units::{Au, AU_PER_PX};
@ -61,43 +59,16 @@ use style::values::computed::image::Image as ComputedImage;
use style::values::computed::Gradient;
use style::values::generics::background::BackgroundSize;
use style::values::generics::image::{GradientKind, Image, PaintWorklet};
use style::values::generics::ui::Cursor;
use style::values::{Either, RGBA};
use style_traits::cursor::CursorKind;
use style_traits::CSSPixel;
use style_traits::ToCss;
use webrender_api::{self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF};
use webrender_api::{ExternalScrollId, FilterOp, GlyphInstance, ImageRendering, LayoutRect};
use webrender_api::{LayoutSize, LayoutTransform, LayoutVector2D, LineStyle, NinePatchBorder};
use webrender_api::{NinePatchBorderSource, NormalBorder, ScrollSensitivity, StickyOffsetBounds};
fn establishes_containing_block_for_absolute(
flags: StackingContextCollectionFlags,
positioning: StylePosition,
established_reference_frame: bool,
) -> bool {
if established_reference_frame {
return true;
}
!flags.contains(StackingContextCollectionFlags::POSITION_NEVER_CREATES_CONTAINING_BLOCK) &&
StylePosition::Static != positioning
}
trait RgbColor {
fn rgb(r: u8, g: u8, b: u8) -> Self;
}
impl RgbColor for ColorF {
fn rgb(r: u8, g: u8, b: u8) -> Self {
ColorF {
r: (r as f32) / (255.0 as f32),
g: (g as f32) / (255.0 as f32),
b: (b as f32) / (255.0 as f32),
a: 1.0 as f32,
}
}
}
use webrender_api::{
self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF, ColorU,
ExternalScrollId, FilterOp, GlyphInstance, ImageRendering, LayoutRect, LayoutSize,
LayoutTransform, LayoutVector2D, LineStyle, NinePatchBorder, NinePatchBorderSource,
NormalBorder, ScrollSensitivity, StickyOffsetBounds,
};
static THREAD_TINT_COLORS: [ColorF; 8] = [
ColorF {
@ -581,230 +552,6 @@ impl<'a> DisplayListBuildState<'a> {
/// 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);
pub trait FragmentDisplayListBuilding {
fn collect_stacking_contexts_for_blocklike_fragment(
&mut self,
state: &mut StackingContextCollectionState,
) -> bool;
fn create_stacking_context_for_inline_block(
&mut self,
base: &BaseFlow,
state: &mut StackingContextCollectionState,
) -> bool;
/// Adds the display items necessary to paint the background of this fragment to the display
/// list if necessary.
fn build_display_list_for_background_if_applicable(
&self,
state: &mut DisplayListBuildState,
style: &ComputedValues,
display_list_section: DisplayListSection,
absolute_bounds: Rect<Au>,
);
/// Same as build_display_list_for_background_if_applicable, but lets you
/// override the actual background used
fn build_display_list_for_background_if_applicable_with_background(
&self,
state: &mut DisplayListBuildState,
style: &ComputedValues,
background: &style_structs::Background,
background_color: RGBA,
display_list_section: DisplayListSection,
absolute_bounds: Rect<Au>,
);
/// Adds the display items necessary to paint a webrender image of this fragment to the
/// appropriate section of the display list.
fn build_display_list_for_webrender_image(
&self,
state: &mut DisplayListBuildState,
style: &ComputedValues,
display_list_section: DisplayListSection,
absolute_bounds: Rect<Au>,
webrender_image: WebRenderImageInfo,
index: usize,
);
/// Calculates the webrender image for a paint worklet.
/// Returns None if the worklet is not registered.
/// If the worklet has missing image URLs, it passes them to the image cache for loading.
fn get_webrender_image_for_paint_worklet(
&self,
state: &mut DisplayListBuildState,
style: &ComputedValues,
paint_worklet: &PaintWorklet,
size: Size2D<Au>,
) -> Option<WebRenderImageInfo>;
/// Adds the display items necessary to paint the background linear gradient of this fragment
/// to the appropriate section of the display list.
fn build_display_list_for_background_gradient(
&self,
state: &mut DisplayListBuildState,
display_list_section: DisplayListSection,
absolute_bounds: Rect<Au>,
gradient: &Gradient,
style: &ComputedValues,
index: usize,
);
/// Adds the display items necessary to paint the borders of this fragment to a display list if
/// necessary.
fn build_display_list_for_borders_if_applicable(
&self,
state: &mut DisplayListBuildState,
style: &ComputedValues,
inline_node_info: Option<InlineNodeBorderInfo>,
border_painting_mode: BorderPaintingMode,
bounds: Rect<Au>,
display_list_section: DisplayListSection,
clip: Rect<Au>,
);
/// Add display item for image border.
///
/// Returns `Some` if the addition was successful.
fn build_display_list_for_border_image(
&self,
state: &mut DisplayListBuildState,
style: &ComputedValues,
base: BaseDisplayItem,
bounds: Rect<Au>,
image: &ComputedImage,
border_width: SideOffsets2D<Au>,
) -> Option<()>;
/// Adds the display items necessary to paint the outline of this fragment to the display list
/// if necessary.
fn build_display_list_for_outline_if_applicable(
&self,
state: &mut DisplayListBuildState,
style: &ComputedValues,
bounds: Rect<Au>,
clip: Rect<Au>,
);
/// Adds the display items necessary to paint the box shadow of this fragment to the display
/// list if necessary.
fn build_display_list_for_box_shadow_if_applicable(
&self,
state: &mut DisplayListBuildState,
style: &ComputedValues,
display_list_section: DisplayListSection,
absolute_bounds: Rect<Au>,
clip: Rect<Au>,
);
/// Adds display items necessary to draw debug boxes around a scanned text fragment.
fn build_debug_borders_around_text_fragments(
&self,
state: &mut DisplayListBuildState,
style: &ComputedValues,
stacking_relative_border_box: Rect<Au>,
stacking_relative_content_box: Rect<Au>,
text_fragment: &ScannedTextFragmentInfo,
clip: Rect<Au>,
);
/// Adds display items necessary to draw debug boxes around this fragment.
fn build_debug_borders_around_fragment(
&self,
state: &mut DisplayListBuildState,
stacking_relative_border_box: Rect<Au>,
clip: Rect<Au>,
);
/// Adds the display items for this fragment to the given display list.
///
/// Arguments:
///
/// * `state`: The display building state, including the display list currently
/// under construction and other metadata useful for constructing it.
/// * `dirty`: The dirty rectangle in the coordinate system of the owning flow.
/// * `clip`: The region to clip the display items to.
/// * `overflow_content_size`: The size of content associated with this fragment
/// that must have overflow handling applied to it. For a scrollable block
/// flow, it is expected that this is the size of the child boxes.
fn build_display_list(
&mut self,
state: &mut DisplayListBuildState,
stacking_relative_border_box: Rect<Au>,
border_painting_mode: BorderPaintingMode,
display_list_section: DisplayListSection,
clip: Rect<Au>,
overflow_content_size: Option<Size2D<Au>>,
);
/// build_display_list, but don't update the restyle damage
///
/// Must be paired with a self.restyle_damage.remove(REPAINT) somewhere
fn build_display_list_no_damage(
&self,
state: &mut DisplayListBuildState,
stacking_relative_border_box: Rect<Au>,
border_painting_mode: BorderPaintingMode,
display_list_section: DisplayListSection,
clip: Rect<Au>,
overflow_content_size: Option<Size2D<Au>>,
);
/// Builds the display items necessary to paint the selection and/or caret for this fragment,
/// if any.
fn build_display_items_for_selection_if_necessary(
&self,
state: &mut DisplayListBuildState,
stacking_relative_border_box: Rect<Au>,
display_list_section: DisplayListSection,
clip: Rect<Au>,
);
/// Creates the text display item for one text fragment. This can be called multiple times for
/// one fragment if there are text shadows.
///
/// `text_shadow` will be `Some` if this is rendering a shadow.
fn build_display_list_for_text_fragment(
&self,
state: &mut DisplayListBuildState,
text_fragment: &ScannedTextFragmentInfo,
stacking_relative_content_box: Rect<Au>,
text_shadows: &[SimpleShadow],
clip: Rect<Au>,
);
/// Creates the display item for a text decoration: underline, overline, or line-through.
fn build_display_list_for_text_decoration(
&self,
state: &mut DisplayListBuildState,
color: &RGBA,
stacking_relative_box: &LogicalRect<Au>,
clip: Rect<Au>,
);
/// A helper method that `build_display_list` calls to create per-fragment-type display items.
fn build_fragment_type_specific_display_items(
&self,
state: &mut DisplayListBuildState,
stacking_relative_border_box: Rect<Au>,
clip: Rect<Au>,
);
/// Creates a stacking context for associated fragment.
fn create_stacking_context(
&self,
id: StackingContextId,
base_flow: &BaseFlow,
context_type: StackingContextType,
established_reference_frame: Option<ClipScrollNodeIndex>,
parent_clipping_and_scrolling: ClippingAndScrolling,
) -> StackingContext;
fn unique_id(&self) -> u64;
fn fragment_type(&self) -> FragmentType;
}
/// Get the border radius for the rectangle inside of a rounded border. This is useful
/// for building the clip for the content inside the border.
fn build_border_radius_for_inner_rect(
@ -823,8 +570,8 @@ fn build_border_radius_for_inner_rect(
border::inner_radii(radii, border_widths)
}
impl FragmentDisplayListBuilding for Fragment {
fn collect_stacking_contexts_for_blocklike_fragment(
impl Fragment {
pub fn collect_stacking_contexts_for_blocklike_fragment(
&mut self,
state: &mut StackingContextCollectionState,
) -> bool {
@ -852,7 +599,7 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
fn create_stacking_context_for_inline_block(
pub fn create_stacking_context_for_inline_block(
&mut self,
base: &BaseFlow,
state: &mut StackingContextCollectionState,
@ -881,6 +628,8 @@ impl FragmentDisplayListBuilding for Fragment {
true
}
/// Adds the display items necessary to paint the background of this fragment to the display
/// list if necessary.
fn build_display_list_for_background_if_applicable(
&self,
state: &mut DisplayListBuildState,
@ -902,6 +651,8 @@ impl FragmentDisplayListBuilding for Fragment {
)
}
/// Same as build_display_list_for_background_if_applicable, but lets you
/// override the actual background used
fn build_display_list_for_background_if_applicable_with_background(
&self,
state: &mut DisplayListBuildState,
@ -940,7 +691,7 @@ impl FragmentDisplayListBuilding for Fragment {
bounds,
bounds,
self.node,
style.get_cursor(CursorKind::Default),
get_cursor(&style, CursorKind::Default),
display_list_section,
);
state.add_display_item(DisplayItem::Rectangle(CommonDisplayItem::new(
@ -1028,6 +779,8 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
/// Adds the display items necessary to paint a webrender image of this fragment to the
/// appropriate section of the display list.
fn build_display_list_for_webrender_image(
&self,
state: &mut DisplayListBuildState,
@ -1069,7 +822,7 @@ impl FragmentDisplayListBuilding for Fragment {
placement.bounds,
placement.clip_rect,
self.node,
style.get_cursor(CursorKind::Default),
get_cursor(&style, CursorKind::Default),
display_list_section,
);
@ -1088,6 +841,9 @@ impl FragmentDisplayListBuilding for Fragment {
});
}
/// Calculates the webrender image for a paint worklet.
/// Returns None if the worklet is not registered.
/// If the worklet has missing image URLs, it passes them to the image cache for loading.
fn get_webrender_image_for_paint_worklet(
&self,
state: &mut DisplayListBuildState,
@ -1148,6 +904,8 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
/// Adds the display items necessary to paint the background linear gradient of this fragment
/// to the appropriate section of the display list.
fn build_display_list_for_background_gradient(
&self,
state: &mut DisplayListBuildState,
@ -1179,7 +937,7 @@ impl FragmentDisplayListBuilding for Fragment {
placement.bounds,
placement.clip_rect,
self.node,
style.get_cursor(CursorKind::Default),
get_cursor(&style, CursorKind::Default),
display_list_section,
);
@ -1220,6 +978,8 @@ impl FragmentDisplayListBuilding for Fragment {
});
}
/// Adds the display items necessary to paint the box shadow of this fragment to the display
/// list if necessary.
fn build_display_list_for_box_shadow_if_applicable(
&self,
state: &mut DisplayListBuildState,
@ -1243,7 +1003,7 @@ impl FragmentDisplayListBuilding for Fragment {
bounds,
clip,
self.node,
style.get_cursor(CursorKind::Default),
get_cursor(&style, CursorKind::Default),
display_list_section,
);
let border_radius = border::radii(absolute_bounds, style.get_border());
@ -1269,6 +1029,8 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
/// Adds the display items necessary to paint the borders of this fragment to a display list if
/// necessary.
fn build_display_list_for_borders_if_applicable(
&self,
state: &mut DisplayListBuildState,
@ -1325,7 +1087,7 @@ impl FragmentDisplayListBuilding for Fragment {
bounds,
clip,
self.node,
style.get_cursor(CursorKind::Default),
get_cursor(&style, CursorKind::Default),
display_list_section,
);
@ -1381,6 +1143,9 @@ impl FragmentDisplayListBuilding for Fragment {
)));
}
/// Add display item for image border.
///
/// Returns `Some` if the addition was successful.
fn build_display_list_for_border_image(
&self,
state: &mut DisplayListBuildState,
@ -1483,6 +1248,8 @@ impl FragmentDisplayListBuilding for Fragment {
Some(())
}
/// Adds the display items necessary to paint the outline of this fragment to the display list
/// if necessary.
fn build_display_list_for_outline_if_applicable(
&self,
state: &mut DisplayListBuildState,
@ -1519,7 +1286,7 @@ impl FragmentDisplayListBuilding for Fragment {
bounds,
clip,
self.node,
style.get_cursor(CursorKind::Default),
get_cursor(&style, CursorKind::Default),
DisplayListSection::Outlines,
);
state.add_display_item(DisplayItem::Border(CommonDisplayItem::with_data(
@ -1532,6 +1299,7 @@ impl FragmentDisplayListBuilding for Fragment {
)));
}
/// Adds display items necessary to draw debug boxes around a scanned text fragment.
fn build_debug_borders_around_text_fragments(
&self,
state: &mut DisplayListBuildState,
@ -1549,7 +1317,7 @@ impl FragmentDisplayListBuilding for Fragment {
stacking_relative_border_box,
clip,
self.node,
style.get_cursor(CursorKind::Default),
get_cursor(&style, CursorKind::Default),
DisplayListSection::Content,
);
state.add_display_item(DisplayItem::Border(CommonDisplayItem::with_data(
@ -1557,7 +1325,7 @@ impl FragmentDisplayListBuilding for Fragment {
webrender_api::BorderDisplayItem {
widths: SideOffsets2D::new_all_same(Au::from_px(1)).to_layout(),
details: BorderDetails::Normal(border::simple(
ColorF::rgb(0, 0, 200),
ColorU::new(0, 0, 200, 1).into(),
webrender_api::BorderStyle::Solid,
)),
},
@ -1578,7 +1346,7 @@ impl FragmentDisplayListBuilding for Fragment {
baseline,
clip,
self.node,
style.get_cursor(CursorKind::Default),
get_cursor(&style, CursorKind::Default),
DisplayListSection::Content,
);
// TODO(gw): Use a better estimate for wavy line thickness.
@ -1588,12 +1356,13 @@ impl FragmentDisplayListBuilding for Fragment {
webrender_api::LineDisplayItem {
orientation: webrender_api::LineOrientation::Horizontal,
wavy_line_thickness,
color: ColorF::rgb(0, 200, 0),
color: ColorU::new(0, 200, 0, 1).into(),
style: LineStyle::Dashed,
},
)));
}
/// Adds display items necessary to draw debug boxes around this fragment.
fn build_debug_borders_around_fragment(
&self,
state: &mut DisplayListBuildState,
@ -1605,7 +1374,7 @@ impl FragmentDisplayListBuilding for Fragment {
stacking_relative_border_box,
clip,
self.node,
self.style.get_cursor(CursorKind::Default),
get_cursor(&self.style, CursorKind::Default),
DisplayListSection::Content,
);
state.add_display_item(DisplayItem::Border(CommonDisplayItem::with_data(
@ -1613,7 +1382,7 @@ impl FragmentDisplayListBuilding for Fragment {
webrender_api::BorderDisplayItem {
widths: SideOffsets2D::new_all_same(Au::from_px(1)).to_layout(),
details: BorderDetails::Normal(border::simple(
ColorF::rgb(0, 0, 200),
ColorU::new(0, 0, 200, 1).into(),
webrender_api::BorderStyle::Solid,
)),
},
@ -1621,6 +1390,8 @@ impl FragmentDisplayListBuilding for Fragment {
)));
}
/// Builds the display items necessary to paint the selection and/or caret for this fragment,
/// if any.
fn build_display_items_for_selection_if_necessary(
&self,
state: &mut DisplayListBuildState,
@ -1645,7 +1416,7 @@ impl FragmentDisplayListBuilding for Fragment {
stacking_relative_border_box,
clip,
self.node,
self.style.get_cursor(CursorKind::Default),
get_cursor(&self.style, CursorKind::Default),
display_list_section,
);
state.add_display_item(DisplayItem::Rectangle(CommonDisplayItem::new(
@ -1691,7 +1462,7 @@ impl FragmentDisplayListBuilding for Fragment {
insertion_point_bounds,
clip,
self.node,
self.style.get_cursor(cursor),
get_cursor(&self.style, cursor),
display_list_section,
);
state.add_display_item(DisplayItem::Rectangle(CommonDisplayItem::new(
@ -1702,7 +1473,18 @@ impl FragmentDisplayListBuilding for Fragment {
)));
}
fn build_display_list(
/// Adds the display items for this fragment to the given display list.
///
/// Arguments:
///
/// * `state`: The display building state, including the display list currently
/// under construction and other metadata useful for constructing it.
/// * `dirty`: The dirty rectangle in the coordinate system of the owning flow.
/// * `clip`: The region to clip the display items to.
/// * `overflow_content_size`: The size of content associated with this fragment
/// that must have overflow handling applied to it. For a scrollable block
/// flow, it is expected that this is the size of the child boxes.
pub fn build_display_list(
&mut self,
state: &mut DisplayListBuildState,
stacking_relative_border_box: Rect<Au>,
@ -1729,6 +1511,9 @@ impl FragmentDisplayListBuilding for Fragment {
state.current_clipping_and_scrolling = previous_clipping_and_scrolling;
}
/// build_display_list, but don't update the restyle damage
///
/// Must be paired with a self.restyle_damage.remove(REPAINT) somewhere
fn build_display_list_no_damage(
&self,
state: &mut DisplayListBuildState,
@ -1859,9 +1644,7 @@ impl FragmentDisplayListBuilding for Fragment {
content_size,
content_size,
self.node,
self.style
.get_cursor(CursorKind::Default)
.or_else(|| Some(CursorKind::Default)),
get_cursor(&self.style, CursorKind::Default).or(Some(CursorKind::Default)),
DisplayListSection::Content,
);
state.add_display_item(DisplayItem::Rectangle(CommonDisplayItem::new(
@ -1886,6 +1669,7 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
/// A helper method that `build_display_list` calls to create per-fragment-type display items.
fn build_fragment_type_specific_display_items(
&self,
state: &mut DisplayListBuildState,
@ -1911,7 +1695,7 @@ impl FragmentDisplayListBuilding for Fragment {
stacking_relative_content_box,
stacking_relative_border_box,
self.node,
self.style.get_cursor(CursorKind::Default),
get_cursor(&self.style, CursorKind::Default),
DisplayListSection::Content,
)
};
@ -2087,6 +1871,7 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
/// Creates a stacking context for associated fragment.
fn create_stacking_context(
&self,
id: StackingContextId,
@ -2139,6 +1924,10 @@ impl FragmentDisplayListBuilding for Fragment {
)
}
/// Creates the text display item for one text fragment. This can be called multiple times for
/// one fragment if there are text shadows.
///
/// `text_shadow` will be `Some` if this is rendering a shadow.
fn build_display_list_for_text_fragment(
&self,
state: &mut DisplayListBuildState,
@ -2182,7 +1971,7 @@ impl FragmentDisplayListBuilding for Fragment {
stacking_relative_content_box,
clip,
self.node,
self.style().get_cursor(cursor),
get_cursor(&self.style, cursor),
DisplayListSection::Content,
);
@ -2290,6 +2079,7 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
/// Creates the display item for a text decoration: underline, overline, or line-through.
fn build_display_list_for_text_decoration(
&self,
state: &mut DisplayListBuildState,
@ -2305,7 +2095,7 @@ impl FragmentDisplayListBuilding for Fragment {
stacking_relative_box,
clip,
self.node,
self.style.get_cursor(CursorKind::Default),
get_cursor(&self.style, CursorKind::Default),
DisplayListSection::Content,
);
@ -2344,81 +2134,6 @@ bitflags! {
}
}
pub trait BlockFlowDisplayListBuilding {
fn collect_stacking_contexts_for_block(
&mut self,
state: &mut StackingContextCollectionState,
flags: StackingContextCollectionFlags,
);
fn transform_clip_to_coordinate_space(
&mut self,
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState,
);
fn setup_clipping_for_block(
&mut self,
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState,
stacking_context_type: Option<StackingContextType>,
established_reference_frame: Option<ClipScrollNodeIndex>,
flags: StackingContextCollectionFlags,
) -> ClippingAndScrolling;
fn setup_clip_scroll_node_for_position(
&mut self,
state: &mut StackingContextCollectionState,
border_box: Rect<Au>,
);
fn setup_clip_scroll_node_for_overflow(
&mut self,
state: &mut StackingContextCollectionState,
border_box: Rect<Au>,
);
fn setup_clip_scroll_node_for_css_clip(
&mut self,
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState,
stacking_relative_border_box: Rect<Au>,
);
fn create_pseudo_stacking_context_for_block(
&mut self,
stacking_context_type: StackingContextType,
parent_stacking_context_id: StackingContextId,
parent_clip_and_scroll_info: ClippingAndScrolling,
state: &mut StackingContextCollectionState,
);
fn create_real_stacking_context_for_block(
&mut self,
parent_stacking_context_id: StackingContextId,
parent_clipping_and_scrolling: ClippingAndScrolling,
established_reference_frame: Option<ClipScrollNodeIndex>,
state: &mut StackingContextCollectionState,
);
fn build_display_list_for_block(
&mut self,
state: &mut DisplayListBuildState,
border_painting_mode: BorderPaintingMode,
);
fn build_display_list_for_block_no_damage(
&self,
state: &mut DisplayListBuildState,
border_painting_mode: BorderPaintingMode,
);
fn build_display_list_for_background_if_applicable_with_background(
&self,
state: &mut DisplayListBuildState,
background: &style_structs::Background,
background_color: RGBA,
);
fn stacking_context_type(
&self,
flags: StackingContextCollectionFlags,
) -> Option<StackingContextType>;
fn is_reference_frame(&self, context_type: Option<StackingContextType>) -> bool;
}
/// This structure manages ensuring that modification to StackingContextCollectionState is
/// only temporary. It's useful for moving recursively down the flow tree and ensuring
/// that the state is restored for siblings. To use this structure, we must call
@ -2498,7 +2213,7 @@ impl SavedStackingContextCollectionState {
}
}
impl BlockFlowDisplayListBuilding for BlockFlow {
impl BlockFlow {
fn transform_clip_to_coordinate_space(
&mut self,
state: &mut StackingContextCollectionState,
@ -2576,7 +2291,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
}
}
fn collect_stacking_contexts_for_block(
pub fn collect_stacking_contexts_for_block(
&mut self,
state: &mut StackingContextCollectionState,
flags: StackingContextCollectionFlags,
@ -2614,11 +2329,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
flags,
);
if establishes_containing_block_for_absolute(
flags,
self.positioning(),
established_reference_frame.is_some(),
) {
let creates_containing_block = !flags
.contains(StackingContextCollectionFlags::POSITION_NEVER_CREATES_CONTAINING_BLOCK);
let abspos_containing_block = established_reference_frame.is_some() ||
(creates_containing_block && self.positioning() != StylePosition::Static);
if abspos_containing_block {
state.containing_block_clipping_and_scrolling = state.current_clipping_and_scrolling;
}
@ -2970,7 +2685,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
self.base.collect_stacking_contexts_for_children(state);
}
fn build_display_list_for_block_no_damage(
pub fn build_display_list_for_block_no_damage(
&self,
state: &mut DisplayListBuildState,
border_painting_mode: BorderPaintingMode,
@ -3005,7 +2720,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
state.processing_scrolling_overflow_element = false;
}
fn build_display_list_for_block(
pub fn build_display_list_for_block(
&mut self,
state: &mut DisplayListBuildState,
border_painting_mode: BorderPaintingMode,
@ -3016,7 +2731,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
self.build_display_list_for_block_no_damage(state, border_painting_mode);
}
fn build_display_list_for_background_if_applicable_with_background(
pub fn build_display_list_for_background_if_applicable_with_background(
&self,
state: &mut DisplayListBuildState,
background: &style_structs::Background,
@ -3071,164 +2786,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
}
}
pub trait InlineFlowDisplayListBuilding {
fn collect_stacking_contexts_for_inline(&mut self, state: &mut StackingContextCollectionState);
fn build_display_list_for_inline_fragment_at_index(
&mut self,
state: &mut DisplayListBuildState,
index: usize,
);
fn build_display_list_for_inline(&mut self, state: &mut DisplayListBuildState);
}
impl InlineFlowDisplayListBuilding for InlineFlow {
fn collect_stacking_contexts_for_inline(&mut self, state: &mut StackingContextCollectionState) {
self.base.stacking_context_id = state.current_stacking_context_id;
self.base.clipping_and_scrolling = Some(state.current_clipping_and_scrolling);
self.base.clip = state
.clip_stack
.last()
.cloned()
.unwrap_or_else(Rect::max_rect);
let previous_cb_clipping_and_scrolling = state.containing_block_clipping_and_scrolling;
for fragment in self.fragments.fragments.iter_mut() {
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;
if establishes_containing_block_for_absolute(
StackingContextCollectionFlags::empty(),
fragment.style.get_box().position,
false,
) {
state.containing_block_clipping_and_scrolling =
state.current_clipping_and_scrolling;
}
// We clear this here, but it might be set again if we create a stacking context for
// this fragment.
fragment.established_reference_frame = None;
if !fragment.collect_stacking_contexts_for_blocklike_fragment(state) {
if !fragment.establishes_stacking_context() {
fragment.stacking_context_id = state.current_stacking_context_id;
} else {
fragment.create_stacking_context_for_inline_block(&self.base, state);
}
}
// Reset the containing block clipping and scrolling before each loop iteration,
// so we don't pollute subsequent fragments.
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;
}
}
fn build_display_list_for_inline_fragment_at_index(
&mut self,
state: &mut DisplayListBuildState,
index: usize,
) {
let fragment = self.fragments.fragments.get_mut(index).unwrap();
let stacking_relative_border_box = self
.base
.stacking_relative_border_box_for_display_list(fragment);
fragment.build_display_list(
state,
stacking_relative_border_box,
BorderPaintingMode::Separate,
DisplayListSection::Content,
self.base.clip,
None,
);
}
fn build_display_list_for_inline(&mut self, state: &mut DisplayListBuildState) {
debug!(
"Flow: building display list for {} inline fragments",
self.fragments.len()
);
// We iterate using an index here, because we want to avoid doing a doing
// a double-borrow of self (one mutable for the method call and one immutable
// for the self.fragments.fragment iterator itself).
for index in 0..self.fragments.fragments.len() {
let (establishes_stacking_context, stacking_context_id) = {
let fragment = self.fragments.fragments.get(index).unwrap();
(
self.base.stacking_context_id != fragment.stacking_context_id,
fragment.stacking_context_id,
)
};
let parent_stacking_context_id = state.current_stacking_context_id;
if establishes_stacking_context {
state.current_stacking_context_id = stacking_context_id;
}
self.build_display_list_for_inline_fragment_at_index(state, index);
if establishes_stacking_context {
state.current_stacking_context_id = parent_stacking_context_id
}
}
if !self.fragments.fragments.is_empty() {
self.base
.build_display_items_for_debugging_tint(state, self.fragments.fragments[0].node);
}
}
}
pub trait ListItemFlowDisplayListBuilding {
fn build_display_list_for_list_item(&mut self, state: &mut DisplayListBuildState);
}
impl ListItemFlowDisplayListBuilding for ListItemFlow {
fn build_display_list_for_list_item(&mut self, state: &mut DisplayListBuildState) {
// Draw the marker, if applicable.
for marker in &mut self.marker_fragments {
let stacking_relative_border_box = self
.block_flow
.base
.stacking_relative_border_box_for_display_list(marker);
marker.build_display_list(
state,
stacking_relative_border_box,
BorderPaintingMode::Separate,
DisplayListSection::Content,
self.block_flow.base.clip,
None,
);
}
// Draw the rest of the block.
self.block_flow
.build_display_list_for_block(state, BorderPaintingMode::Separate)
}
}
pub trait FlexFlowDisplayListBuilding {
fn build_display_list_for_flex(&mut self, state: &mut DisplayListBuildState);
}
impl FlexFlowDisplayListBuilding for FlexFlow {
fn build_display_list_for_flex(&mut self, state: &mut DisplayListBuildState) {
// Draw the rest of the block.
self.as_mut_block()
.build_display_list_for_block(state, BorderPaintingMode::Separate)
}
}
trait BaseFlowDisplayListBuilding {
fn build_display_items_for_debugging_tint(
&self,
state: &mut DisplayListBuildState,
node: OpaqueNode,
);
}
impl BaseFlowDisplayListBuilding for BaseFlow {
fn build_display_items_for_debugging_tint(
impl BaseFlow {
pub fn build_display_items_for_debugging_tint(
&self,
state: &mut DisplayListBuildState,
node: OpaqueNode,
@ -3266,31 +2825,19 @@ impl BaseFlowDisplayListBuilding for BaseFlow {
}
}
trait ComputedValuesCursorUtility {
fn get_cursor(&self, default_cursor: CursorKind) -> Option<CursorKind>;
}
impl ComputedValuesCursorUtility for ComputedValues {
/// Gets the cursor to use given the specific ComputedValues. `default_cursor` specifies
/// the cursor to use if `cursor` is `auto`. Typically, this will be `PointerCursor`, but for
/// text display items it may be `TextCursor` or `VerticalTextCursor`.
#[inline]
fn get_cursor(&self, default_cursor: CursorKind) -> Option<CursorKind> {
match (
self.get_inherited_ui().pointer_events,
&self.get_inherited_ui().cursor,
) {
(PointerEvents::None, _) => None,
(
PointerEvents::Auto,
&Cursor {
keyword: CursorKind::Auto,
..
},
) => Some(default_cursor),
(PointerEvents::Auto, &Cursor { keyword, .. }) => Some(keyword),
}
fn get_cursor(values: &ComputedValues, default_cursor: CursorKind) -> Option<CursorKind> {
let inherited_ui = values.get_inherited_ui();
if inherited_ui.pointer_events == PointerEvents::None {
return None;
}
Some(match inherited_ui.cursor.keyword {
CursorKind::Auto => default_cursor,
keyword => keyword,
})
}
/// Adjusts `content_rect` as necessary for the given spread, and blur so that the resulting

View file

@ -565,11 +565,11 @@ impl ClippingRegion {
//
// http://www.inrg.csie.ntu.edu.tw/algorithm2014/presentation/D&C%20Lee-84.pdf
for existing_complex_region in &mut self.complex {
if existing_complex_region.completely_encloses(&new_complex_region) {
if completely_encloses(&existing_complex_region, &new_complex_region) {
*existing_complex_region = new_complex_region;
return;
}
if new_complex_region.completely_encloses(existing_complex_region) {
if completely_encloses(&new_complex_region, &existing_complex_region) {
return;
}
}
@ -618,31 +618,26 @@ impl fmt::Debug for ClippingRegion {
}
}
pub trait CompletelyEncloses {
fn completely_encloses(&self, other: &Self) -> bool;
}
impl CompletelyEncloses for ComplexClipRegion {
// TODO(pcwalton): This could be more aggressive by considering points that touch the inside of
// the border radius ellipse.
fn completely_encloses(&self, other: &Self) -> bool {
let left = self.radii.top_left.width.max(self.radii.bottom_left.width);
let top = self.radii.top_left.height.max(self.radii.top_right.height);
let right = self
fn completely_encloses(this: &ComplexClipRegion, other: &ComplexClipRegion) -> bool {
let left = this.radii.top_left.width.max(this.radii.bottom_left.width);
let top = this.radii.top_left.height.max(this.radii.top_right.height);
let right = this
.radii
.top_right
.width
.max(self.radii.bottom_right.width);
let bottom = self
.max(this.radii.bottom_right.width);
let bottom = this
.radii
.bottom_left
.height
.max(self.radii.bottom_right.height);
.max(this.radii.bottom_right.height);
let interior = LayoutRect::new(
LayoutPoint::new(self.rect.origin.x + left, self.rect.origin.y + top),
LayoutPoint::new(this.rect.origin.x + left, this.rect.origin.y + top),
LayoutSize::new(
self.rect.size.width - left - right,
self.rect.size.height - top - bottom,
this.rect.size.width - left - right,
this.rect.size.height - top - bottom,
),
);
interior.origin.x <= other.rect.origin.x &&
@ -650,7 +645,6 @@ impl CompletelyEncloses for ComplexClipRegion {
interior.max_x() >= other.rect.max_x() &&
interior.max_y() >= other.rect.max_y()
}
}
/// Metadata attached to each display item. This is useful for performing auxiliary threads with
/// the display list involving hit testing: finding the originating DOM node and determining the

View file

@ -2,13 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
pub use self::builder::BlockFlowDisplayListBuilding;
pub use self::builder::BorderPaintingMode;
pub use self::builder::DisplayListBuildState;
pub use self::builder::FlexFlowDisplayListBuilding;
pub use self::builder::IndexableText;
pub use self::builder::InlineFlowDisplayListBuilding;
pub use self::builder::ListItemFlowDisplayListBuilding;
pub use self::builder::StackingContextCollectionFlags;
pub use self::builder::StackingContextCollectionState;
pub use self::conversions::ToLayout;

View file

@ -6,8 +6,9 @@
use crate::block::{AbsoluteAssignBSizesTraversal, BlockFlow, MarginsMayCollapseFlag};
use crate::context::LayoutContext;
use crate::display_list::StackingContextCollectionState;
use crate::display_list::{DisplayListBuildState, FlexFlowDisplayListBuilding};
use crate::display_list::{
BorderPaintingMode, DisplayListBuildState, StackingContextCollectionState,
};
use crate::floats::FloatKind;
use crate::flow::{Flow, FlowClass, FlowFlags, GetBaseFlow, ImmutableFlowUtils, OpaqueFlow};
use crate::fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
@ -1090,7 +1091,9 @@ impl Flow for FlexFlow {
}
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.build_display_list_for_flex(state);
// Draw the rest of the block.
self.as_mut_block()
.build_display_list_for_block(state, BorderPaintingMode::Separate)
}
fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) {

View file

@ -22,13 +22,8 @@ bitflags! {
}
}
pub trait LayoutDamageComputation {
fn compute_layout_damage(self) -> SpecialRestyleDamage;
fn reflow_entire_document(self);
}
impl<'a> LayoutDamageComputation for &'a mut dyn Flow {
fn compute_layout_damage(self) -> SpecialRestyleDamage {
impl dyn Flow {
pub fn compute_layout_damage(&mut self) -> SpecialRestyleDamage {
let mut special_damage = SpecialRestyleDamage::empty();
let is_absolutely_positioned = self
.base()
@ -91,7 +86,7 @@ impl<'a> LayoutDamageComputation for &'a mut dyn Flow {
special_damage
}
fn reflow_entire_document(self) {
pub fn reflow_entire_document(&mut self) {
let self_base = self.mut_base();
self_base
.restyle_damage

View file

@ -4,9 +4,10 @@
use crate::block::AbsoluteAssignBSizesTraversal;
use crate::context::{LayoutContext, LayoutFontContext};
use crate::display_list::items::OpaqueNode;
use crate::display_list::StackingContextCollectionState;
use crate::display_list::{DisplayListBuildState, InlineFlowDisplayListBuilding};
use crate::display_list::items::{DisplayListSection, OpaqueNode};
use crate::display_list::{
BorderPaintingMode, DisplayListBuildState, StackingContextCollectionState,
};
use crate::floats::{FloatKind, Floats, PlacementInfo};
use crate::flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag};
use crate::flow::{EarlyAbsolutePositionInfo, FlowFlags, GetBaseFlow, OpaqueFlow};
@ -20,11 +21,12 @@ use crate::text;
use crate::traversal::PreorderFlowTraversal;
use crate::ServoArc;
use app_units::{Au, MIN_AU};
use euclid::{Point2D, Size2D};
use euclid::{Point2D, Rect, Size2D};
use gfx::font::FontMetrics;
use gfx_traits::print_tree::PrintTree;
use range::{Range, RangeIndex};
use script_layout_interface::wrapper_traits::PseudoElementType;
use servo_geometry::MaxRect;
use std::cmp::max;
use std::collections::VecDeque;
use std::sync::Arc;
@ -1427,6 +1429,25 @@ impl InlineFlow {
}
None
}
fn build_display_list_for_inline_fragment_at_index(
&mut self,
state: &mut DisplayListBuildState,
index: usize,
) {
let fragment = self.fragments.fragments.get_mut(index).unwrap();
let stacking_relative_border_box = self
.base
.stacking_relative_border_box_for_display_list(fragment);
fragment.build_display_list(
state,
stacking_relative_border_box,
BorderPaintingMode::Separate,
DisplayListSection::Content,
self.base.clip,
None,
);
}
}
impl Flow for InlineFlow {
@ -1830,11 +1851,77 @@ impl Flow for InlineFlow {
fn update_late_computed_block_position_if_necessary(&mut self, _: Au) {}
fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) {
self.collect_stacking_contexts_for_inline(state);
self.base.stacking_context_id = state.current_stacking_context_id;
self.base.clipping_and_scrolling = Some(state.current_clipping_and_scrolling);
self.base.clip = state
.clip_stack
.last()
.cloned()
.unwrap_or_else(Rect::max_rect);
let previous_cb_clipping_and_scrolling = state.containing_block_clipping_and_scrolling;
for fragment in self.fragments.fragments.iter_mut() {
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;
let abspos_containing_block = fragment.style.get_box().position != Position::Static;
if abspos_containing_block {
state.containing_block_clipping_and_scrolling =
state.current_clipping_and_scrolling;
}
// We clear this here, but it might be set again if we create a stacking context for
// this fragment.
fragment.established_reference_frame = None;
if !fragment.collect_stacking_contexts_for_blocklike_fragment(state) {
if !fragment.establishes_stacking_context() {
fragment.stacking_context_id = state.current_stacking_context_id;
} else {
fragment.create_stacking_context_for_inline_block(&self.base, state);
}
}
// Reset the containing block clipping and scrolling before each loop iteration,
// so we don't pollute subsequent fragments.
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;
}
}
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.build_display_list_for_inline(state);
debug!(
"Flow: building display list for {} inline fragments",
self.fragments.len()
);
// We iterate using an index here, because we want to avoid doing a doing
// a double-borrow of self (one mutable for the method call and one immutable
// for the self.fragments.fragment iterator itself).
for index in 0..self.fragments.fragments.len() {
let (establishes_stacking_context, stacking_context_id) = {
let fragment = self.fragments.fragments.get(index).unwrap();
(
self.base.stacking_context_id != fragment.stacking_context_id,
fragment.stacking_context_id,
)
};
let parent_stacking_context_id = state.current_stacking_context_id;
if establishes_stacking_context {
state.current_stacking_context_id = stacking_context_id;
}
self.build_display_list_for_inline_fragment_at_index(state, index);
if establishes_stacking_context {
state.current_stacking_context_id = parent_stacking_context_id
}
}
if !self.fragments.fragments.is_empty() {
self.base
.build_display_items_for_debugging_tint(state, self.fragments.fragments[0].node);
}
}
fn repair_style(&mut self, _: &ServoArc<ComputedValues>) {}

View file

@ -7,8 +7,10 @@
use crate::block::BlockFlow;
use crate::context::{with_thread_local_font_context, LayoutContext};
use crate::display_list::StackingContextCollectionState;
use crate::display_list::{DisplayListBuildState, ListItemFlowDisplayListBuilding};
use crate::display_list::items::DisplayListSection;
use crate::display_list::{
BorderPaintingMode, DisplayListBuildState, StackingContextCollectionState,
};
use crate::floats::FloatKind;
use crate::flow::{Flow, FlowClass, OpaqueFlow};
use crate::fragment::Overflow;
@ -189,7 +191,25 @@ impl Flow for ListItemFlow {
}
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.build_display_list_for_list_item(state);
// Draw the marker, if applicable.
for marker in &mut self.marker_fragments {
let stacking_relative_border_box = self
.block_flow
.base
.stacking_relative_border_box_for_display_list(marker);
marker.build_display_list(
state,
stacking_relative_border_box,
BorderPaintingMode::Separate,
DisplayListSection::Content,
self.block_flow.base.clip,
None,
);
}
// Draw the rest of the block.
self.block_flow
.build_display_list_for_block(state, BorderPaintingMode::Separate)
}
fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) {

View file

@ -7,9 +7,9 @@
use crate::block::{BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer};
use crate::block::{ISizeConstraintInput, ISizeConstraintSolution};
use crate::context::LayoutContext;
use crate::display_list::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use crate::display_list::{
DisplayListBuildState, StackingContextCollectionFlags, StackingContextCollectionState,
BorderPaintingMode, DisplayListBuildState, StackingContextCollectionFlags,
StackingContextCollectionState,
};
use crate::flow::{
BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, GetBaseFlow, ImmutableFlowUtils,

View file

@ -6,8 +6,9 @@
use crate::block::BlockFlow;
use crate::context::LayoutContext;
use crate::display_list::{BlockFlowDisplayListBuilding, DisplayListBuildState};
use crate::display_list::{StackingContextCollectionFlags, StackingContextCollectionState};
use crate::display_list::{
DisplayListBuildState, StackingContextCollectionFlags, StackingContextCollectionState,
};
use crate::flow::{Flow, FlowClass, OpaqueFlow};
use crate::fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use app_units::Au;

View file

@ -6,8 +6,9 @@
use crate::block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
use crate::context::LayoutContext;
use crate::display_list::{BlockFlowDisplayListBuilding, DisplayListBuildState};
use crate::display_list::{StackingContextCollectionFlags, StackingContextCollectionState};
use crate::display_list::{
DisplayListBuildState, StackingContextCollectionFlags, StackingContextCollectionState,
};
use crate::flow::{Flow, FlowClass, FlowFlags, GetBaseFlow, OpaqueFlow};
use crate::fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use crate::layout_debug;

View file

@ -6,8 +6,9 @@
use crate::block::{BlockFlow, ISizeAndMarginsComputer};
use crate::context::LayoutContext;
use crate::display_list::{BlockFlowDisplayListBuilding, DisplayListBuildState};
use crate::display_list::{StackingContextCollectionFlags, StackingContextCollectionState};
use crate::display_list::{
DisplayListBuildState, StackingContextCollectionFlags, StackingContextCollectionState,
};
use crate::flow::{
EarlyAbsolutePositionInfo, Flow, FlowClass, GetBaseFlow, ImmutableFlowUtils, OpaqueFlow,
};

View file

@ -6,8 +6,9 @@
use crate::block::{BlockFlow, ISizeAndMarginsComputer};
use crate::context::LayoutContext;
use crate::display_list::{BlockFlowDisplayListBuilding, DisplayListBuildState};
use crate::display_list::{StackingContextCollectionFlags, StackingContextCollectionState};
use crate::display_list::{
DisplayListBuildState, StackingContextCollectionFlags, StackingContextCollectionState,
};
use crate::flow::{Flow, FlowClass, OpaqueFlow};
use crate::fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use crate::layout_debug;

View file

@ -17,9 +17,7 @@ use crate::block::{
use crate::block::{ISizeConstraintSolution, MarginsMayCollapseFlag};
use crate::context::LayoutContext;
use crate::display_list::StackingContextCollectionState;
use crate::display_list::{
BlockFlowDisplayListBuilding, DisplayListBuildState, StackingContextCollectionFlags,
};
use crate::display_list::{DisplayListBuildState, StackingContextCollectionFlags};
use crate::floats::FloatKind;
use crate::flow::{Flow, FlowClass, FlowFlags, ImmutableFlowUtils, OpaqueFlow};
use crate::fragment::{Fragment, FragmentBorderBoxIterator, Overflow};

View file

@ -45,7 +45,7 @@ use layout::display_list::items::{OpaqueNode, WebRenderImageInfo};
use layout::display_list::{IndexableText, ToLayout, WebRenderDisplayListConverter};
use layout::flow::{Flow, GetBaseFlow, ImmutableFlowUtils, MutableOwnedFlowUtils};
use layout::flow_ref::FlowRef;
use layout::incremental::{LayoutDamageComputation, RelayoutMode, SpecialRestyleDamage};
use layout::incremental::{RelayoutMode, SpecialRestyleDamage};
use layout::layout_debug;
use layout::parallel;
use layout::query::{
@ -75,7 +75,7 @@ use parking_lot::RwLock;
use profile_traits::mem::{self as profile_mem, Report, ReportKind, ReportsChan};
use profile_traits::time::{self as profile_time, profile, TimerMetadata};
use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
use script_layout_interface::message::{Msg, NewLayoutThreadInfo, NodesFromPointQueryType, Reflow};
use script_layout_interface::message::{LayoutThreadInit, Msg, NodesFromPointQueryType, Reflow};
use script_layout_interface::message::{QueryMsg, ReflowComplete, ReflowGoal, ScriptReflow};
use script_layout_interface::rpc::TextIndexResponse;
use script_layout_interface::rpc::{LayoutRPC, OffsetParentResponse, StyleResponse};
@ -842,7 +842,7 @@ impl LayoutThread {
reports_chan.send(reports);
}
fn create_layout_thread(&self, info: NewLayoutThreadInfo) {
fn create_layout_thread(&self, info: LayoutThreadInit) {
LayoutThread::create(
info.id,
self.top_level_browsing_context_id,

View file

@ -85,7 +85,6 @@ use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceFetchTiming, Re
use offscreen_gl_context::GLLimits;
use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::time::ProfilerChan as TimeProfilerChan;
use script_layout_interface::reporter::CSSErrorReporter;
use script_layout_interface::rpc::LayoutRPC;
use script_layout_interface::OpaqueStyleAndLayoutData;
use script_traits::DrawAPaintImageResult;
@ -116,6 +115,7 @@ use std::sync::{Arc, Mutex};
use std::time::{Instant, SystemTime};
use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto};
use style::context::QuirksMode;
use style::dom::OpaqueNode;
use style::element_state::*;
use style::media_queries::MediaList;
use style::properties::PropertyDeclarationBlock;
@ -419,7 +419,7 @@ unsafe_no_jsmanaged_fields!(BufferQueue, QuirksMode, StrTendril);
unsafe_no_jsmanaged_fields!(Runtime);
unsafe_no_jsmanaged_fields!(HeaderMap, Method);
unsafe_no_jsmanaged_fields!(WindowProxyHandler);
unsafe_no_jsmanaged_fields!(UntrustedNodeAddress);
unsafe_no_jsmanaged_fields!(UntrustedNodeAddress, OpaqueNode);
unsafe_no_jsmanaged_fields!(LengthOrPercentageOrAuto);
unsafe_no_jsmanaged_fields!(RGBA);
unsafe_no_jsmanaged_fields!(StorageType);
@ -455,7 +455,6 @@ unsafe_no_jsmanaged_fields!(Instant);
unsafe_no_jsmanaged_fields!(RelativePos);
unsafe_no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
unsafe_no_jsmanaged_fields!(PathBuf);
unsafe_no_jsmanaged_fields!(CSSErrorReporter);
unsafe_no_jsmanaged_fields!(DrawAPaintImageResult);
unsafe_no_jsmanaged_fields!(DocumentId);
unsafe_no_jsmanaged_fields!(ImageKey);

View file

@ -69,7 +69,7 @@ use base64;
use bluetooth_traits::BluetoothRequest;
use canvas_traits::webgl::WebGLChan;
use crossbeam_channel::{unbounded, Sender, TryRecvError};
use cssparser::{Parser, ParserInput};
use cssparser::{Parser, ParserInput, SourceLocation};
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg;
@ -94,7 +94,6 @@ use profile_traits::ipc as ProfiledIpc;
use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::time::ProfilerChan as TimeProfilerChan;
use script_layout_interface::message::{Msg, QueryMsg, Reflow, ReflowGoal, ScriptReflow};
use script_layout_interface::reporter::CSSErrorReporter;
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC};
use script_layout_interface::rpc::{
NodeScrollIdResponse, ResolvedStyleResponse, TextIndexResponse,
@ -103,7 +102,7 @@ use script_layout_interface::{PendingImageState, TrustedNodeAddress};
use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
use script_traits::{ConstellationControlMsg, DocumentState, LoadData};
use script_traits::{ScriptMsg, ScriptToConstellationChan, ScrollState, TimerEvent, TimerEventId};
use script_traits::{TimerSchedulerMsg, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
use script_traits::{TimerSchedulerMsg, WindowSizeData, WindowSizeType};
use selectors::attr::CaseSensitivity;
use servo_config::opts;
use servo_geometry::{f32_rect_to_au_rect, MaxRect};
@ -120,7 +119,8 @@ use std::mem;
use std::rc::Rc;
use std::sync::atomic::Ordering;
use std::sync::{Arc, Mutex};
use style::error_reporting::ParseErrorReporter;
use style::dom::OpaqueNode;
use style::error_reporting::{ContextualParseError, ParseErrorReporter};
use style::media_queries;
use style::parser::ParserContext as CssParserContext;
use style::properties::{ComputedValues, PropertyId};
@ -248,7 +248,7 @@ pub struct Window {
error_reporter: CSSErrorReporter,
/// A list of scroll offsets for each scrollable element.
scroll_offsets: DomRefCell<HashMap<UntrustedNodeAddress, Vector2D<f32>>>,
scroll_offsets: DomRefCell<HashMap<OpaqueNode, Vector2D<f32>>>,
/// All the MediaQueryLists we need to update
media_query_lists: DOMTracker<MediaQueryList>,
@ -390,7 +390,7 @@ impl Window {
/// Sets a new list of scroll offsets.
///
/// This is called when layout gives us new ones and WebRender is in use.
pub fn set_scroll_offsets(&self, offsets: HashMap<UntrustedNodeAddress, Vector2D<f32>>) {
pub fn set_scroll_offsets(&self, offsets: HashMap<OpaqueNode, Vector2D<f32>>) {
*self.scroll_offsets.borrow_mut() = offsets
}
@ -1602,11 +1602,7 @@ impl Window {
}
pub fn scroll_offset_query(&self, node: &Node) -> Vector2D<f32> {
if let Some(scroll_offset) = self
.scroll_offsets
.borrow()
.get(&node.to_untrusted_node_address())
{
if let Some(scroll_offset) = self.scroll_offsets.borrow().get(&node.to_opaque()) {
return *scroll_offset;
}
Vector2D::new(0.0, 0.0)
@ -1621,10 +1617,9 @@ impl Window {
// The scroll offsets are immediatly updated since later calls
// to topScroll and others may access the properties before
// webrender has a chance to update the offsets.
self.scroll_offsets.borrow_mut().insert(
node.to_untrusted_node_address(),
Vector2D::new(x_ as f32, y_ as f32),
);
self.scroll_offsets
.borrow_mut()
.insert(node.to_opaque(), Vector2D::new(x_ as f32, y_ as f32));
let NodeScrollIdResponse(scroll_id) = self.layout_rpc.node_scroll_id();
@ -2242,3 +2237,41 @@ impl Window {
));
}
}
#[derive(Clone, MallocSizeOf)]
pub struct CSSErrorReporter {
pub pipelineid: PipelineId,
// Arc+Mutex combo is necessary to make this struct Sync,
// which is necessary to fulfill the bounds required by the
// uses of the ParseErrorReporter trait.
#[ignore_malloc_size_of = "Arc is defined in libstd"]
pub script_chan: Arc<Mutex<IpcSender<ConstellationControlMsg>>>,
}
unsafe_no_jsmanaged_fields!(CSSErrorReporter);
impl ParseErrorReporter for CSSErrorReporter {
fn report_error(&self, url: &ServoUrl, location: SourceLocation, error: ContextualParseError) {
if log_enabled!(log::Level::Info) {
info!(
"Url:\t{}\n{}:{} {}",
url.as_str(),
location.line,
location.column,
error
)
}
//TODO: report a real filename
let _ = self
.script_chan
.lock()
.unwrap()
.send(ConstellationControlMsg::ReportCSSError(
self.pipelineid,
url.to_string(),
location.line,
location.column,
error.to_string(),
));
}
}

View file

@ -118,7 +118,7 @@ use net_traits::{
};
use profile_traits::mem::{self as profile_mem, OpaqueSender, ReportsChan};
use profile_traits::time::{self as profile_time, profile, ProfilerCategory};
use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowGoal};
use script_layout_interface::message::{self, LayoutThreadInit, Msg, ReflowGoal};
use script_traits::webdriver_msg::WebDriverScriptCommand;
use script_traits::CompositorEvent::{
CompositionEvent, KeyboardEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent, TouchEvent,
@ -146,6 +146,7 @@ use std::result::Result;
use std::sync::Arc;
use std::thread;
use std::time::{Duration, SystemTime};
use style::dom::OpaqueNode;
use style::thread_state::{self, ThreadState};
use time::{at_utc, get_time, precise_time_ns, Timespec};
use url::percent_encoding::percent_decode;
@ -1914,7 +1915,7 @@ impl ScriptThread {
if node_address == UntrustedNodeAddress(ptr::null()) {
window.update_viewport_for_scroll(-scroll_offset.x, -scroll_offset.y);
} else {
scroll_offsets.insert(node_address, -*scroll_offset);
scroll_offsets.insert(OpaqueNode(node_address.0 as usize), -*scroll_offset);
}
}
window.set_scroll_offsets(scroll_offsets)
@ -1936,7 +1937,7 @@ impl ScriptThread {
let layout_pair = unbounded();
let layout_chan = layout_pair.0.clone();
let msg = message::Msg::CreateLayoutThread(NewLayoutThreadInfo {
let msg = message::Msg::CreateLayoutThread(LayoutThreadInit {
id: new_pipeline_id,
url: load_data.url.clone(),
is_parent: false,

View file

@ -21,7 +21,6 @@ gfx_traits = {path = "../gfx_traits"}
html5ever = "0.22"
ipc-channel = "0.11"
libc = "0.2"
log = "0.4"
time = "0.1.17"
malloc_size_of = { path = "../malloc_size_of" }
malloc_size_of_derive = "0.1"

View file

@ -11,12 +11,9 @@
#[macro_use]
extern crate html5ever;
#[macro_use]
extern crate log;
#[macro_use]
extern crate malloc_size_of_derive;
pub mod message;
pub mod reporter;
pub mod rpc;
pub mod wrapper_traits;

View file

@ -82,7 +82,7 @@ pub enum Msg {
/// Creates a new layout thread.
///
/// This basically exists to keep the script-layout dependency one-way.
CreateLayoutThread(NewLayoutThreadInfo),
CreateLayoutThread(LayoutThreadInit),
/// Set the final Url.
SetFinalUrl(ServoUrl),
@ -143,18 +143,18 @@ impl ReflowGoal {
pub fn needs_display_list(&self) -> bool {
match *self {
ReflowGoal::Full | ReflowGoal::TickAnimations => true,
ReflowGoal::LayoutQuery(ref querymsg, _) => match querymsg {
&QueryMsg::NodesFromPointQuery(..) |
&QueryMsg::TextIndexQuery(..) |
&QueryMsg::ElementInnerTextQuery(_) => true,
&QueryMsg::ContentBoxQuery(_) |
&QueryMsg::ContentBoxesQuery(_) |
&QueryMsg::NodeGeometryQuery(_) |
&QueryMsg::NodeScrollGeometryQuery(_) |
&QueryMsg::NodeScrollIdQuery(_) |
&QueryMsg::ResolvedStyleQuery(..) |
&QueryMsg::OffsetParentQuery(_) |
&QueryMsg::StyleQuery(_) => false,
ReflowGoal::LayoutQuery(ref querymsg, _) => match *querymsg {
QueryMsg::NodesFromPointQuery(..) |
QueryMsg::TextIndexQuery(..) |
QueryMsg::ElementInnerTextQuery(_) => true,
QueryMsg::ContentBoxQuery(_) |
QueryMsg::ContentBoxesQuery(_) |
QueryMsg::NodeGeometryQuery(_) |
QueryMsg::NodeScrollGeometryQuery(_) |
QueryMsg::NodeScrollIdQuery(_) |
QueryMsg::ResolvedStyleQuery(..) |
QueryMsg::OffsetParentQuery(_) |
QueryMsg::StyleQuery(_) => false,
},
}
}
@ -164,18 +164,18 @@ impl ReflowGoal {
pub fn needs_display(&self) -> bool {
match *self {
ReflowGoal::Full | ReflowGoal::TickAnimations => true,
ReflowGoal::LayoutQuery(ref querymsg, _) => match querymsg {
&QueryMsg::NodesFromPointQuery(..) |
&QueryMsg::TextIndexQuery(..) |
&QueryMsg::ElementInnerTextQuery(_) => true,
&QueryMsg::ContentBoxQuery(_) |
&QueryMsg::ContentBoxesQuery(_) |
&QueryMsg::NodeGeometryQuery(_) |
&QueryMsg::NodeScrollGeometryQuery(_) |
&QueryMsg::NodeScrollIdQuery(_) |
&QueryMsg::ResolvedStyleQuery(..) |
&QueryMsg::OffsetParentQuery(_) |
&QueryMsg::StyleQuery(_) => false,
ReflowGoal::LayoutQuery(ref querymsg, _) => match *querymsg {
QueryMsg::NodesFromPointQuery(..) |
QueryMsg::TextIndexQuery(..) |
QueryMsg::ElementInnerTextQuery(_) => true,
QueryMsg::ContentBoxQuery(_) |
QueryMsg::ContentBoxesQuery(_) |
QueryMsg::NodeGeometryQuery(_) |
QueryMsg::NodeScrollGeometryQuery(_) |
QueryMsg::NodeScrollIdQuery(_) |
QueryMsg::ResolvedStyleQuery(..) |
QueryMsg::OffsetParentQuery(_) |
QueryMsg::StyleQuery(_) => false,
},
}
}
@ -214,7 +214,7 @@ pub struct ScriptReflow {
pub dom_count: u32,
}
pub struct NewLayoutThreadInfo {
pub struct LayoutThreadInit {
pub id: PipelineId,
pub url: ServoUrl,
pub is_parent: bool,

View file

@ -1,48 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use cssparser::SourceLocation;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::PipelineId;
use script_traits::ConstellationControlMsg;
use servo_url::ServoUrl;
use std::sync::{Arc, Mutex};
use style::error_reporting::{ContextualParseError, ParseErrorReporter};
#[derive(Clone, MallocSizeOf)]
pub struct CSSErrorReporter {
pub pipelineid: PipelineId,
// Arc+Mutex combo is necessary to make this struct Sync,
// which is necessary to fulfill the bounds required by the
// uses of the ParseErrorReporter trait.
#[ignore_malloc_size_of = "Arc is defined in libstd"]
pub script_chan: Arc<Mutex<IpcSender<ConstellationControlMsg>>>,
}
impl ParseErrorReporter for CSSErrorReporter {
fn report_error(&self, url: &ServoUrl, location: SourceLocation, error: ContextualParseError) {
if log_enabled!(log::Level::Info) {
info!(
"Url:\t{}\n{}:{} {}",
url.as_str(),
location.line,
location.column,
error
)
}
//TODO: report a real filename
let _ = self
.script_chan
.lock()
.unwrap()
.send(ConstellationControlMsg::ReportCSSError(
self.pipelineid,
"".to_owned(),
location.line,
location.column,
error.to_string(),
));
}
}