mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
layout: Resolve canvas background properties during painting (#36917)
Instead of resolving the canvas background properties (essentially keeping a possible reference to the `<body>`'s style) during fragment tree construction, wait until painting to possibly find the style on an appropriate `<body>` fragment. This is possible now because `Fragment` keeps a list of flags with relevant information about the root and `<body>` elements. A benefit of this approach is that styles aren't cached in the fragment tree, which would be problematic for incremental layout. In addition, the old code was making an effort to transform the `<body>`'s background by the root element's transform. Only Safari does this and there was a resolution the WG that this should not happen in https://github.com/w3c/csswg-drafts/issues/6683. Testing: - `/css/css-transforms/transform-translate-background-001.html` - `/css/css-transforms/transform-translate-background-002.html` - `/css/CSS2/floats/float-root.html` Fixes: #30475. Closes: #30569. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
c6f61e6b6e
commit
53be79a5b5
9 changed files with 116 additions and 195 deletions
|
@ -12,7 +12,7 @@ use script_layout_interface::wrapper_traits::{
|
|||
};
|
||||
use script_layout_interface::{LayoutElementType, LayoutNodeType};
|
||||
use servo_arc::Arc;
|
||||
use style::dom::{NodeInfo, OpaqueNode, TNode};
|
||||
use style::dom::{NodeInfo, TNode};
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::Overflow;
|
||||
use style_traits::CSSPixel;
|
||||
|
@ -30,7 +30,7 @@ use crate::fragment_tree::FragmentTree;
|
|||
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize};
|
||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
|
||||
use crate::replaced::ReplacedContents;
|
||||
use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayInside};
|
||||
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
|
||||
use crate::taffy::{TaffyItemBox, TaffyItemBoxInner};
|
||||
use crate::{DefiniteContainingBlock, PropagatedBoxTreeData};
|
||||
|
||||
|
@ -40,9 +40,6 @@ pub struct BoxTree {
|
|||
/// There may be zero if that element has `display: none`.
|
||||
root: BlockFormattingContext,
|
||||
|
||||
/// <https://drafts.csswg.org/css-backgrounds/#special-backgrounds>
|
||||
canvas_background: CanvasBackground,
|
||||
|
||||
/// Whether or not the viewport should be sensitive to scrolling input events in two axes
|
||||
viewport_scroll_sensitivity: AxesScrollSensitivity,
|
||||
}
|
||||
|
@ -96,7 +93,6 @@ impl BoxTree {
|
|||
contents,
|
||||
contains_floats,
|
||||
},
|
||||
canvas_background: CanvasBackground::for_root_element(context, root_element),
|
||||
// From https://www.w3.org/TR/css-overflow-3/#overflow-propagation:
|
||||
// > If visible is applied to the viewport, it must be interpreted as auto.
|
||||
// > If clip is applied to the viewport, it must be interpreted as hidden.
|
||||
|
@ -425,69 +421,7 @@ impl BoxTree {
|
|||
root_fragments,
|
||||
scrollable_overflow,
|
||||
physical_containing_block,
|
||||
self.canvas_background.clone(),
|
||||
self.viewport_scroll_sensitivity,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/css-backgrounds/#root-background>
|
||||
#[derive(Clone, MallocSizeOf)]
|
||||
pub struct CanvasBackground {
|
||||
/// DOM node for the root element
|
||||
pub root_element: OpaqueNode,
|
||||
|
||||
/// The element whose style the canvas takes background properties from (see next field).
|
||||
/// This can be the root element (same as the previous field), or the HTML `<body>` element.
|
||||
/// See <https://drafts.csswg.org/css-backgrounds/#body-background>
|
||||
pub from_element: OpaqueNode,
|
||||
|
||||
/// The computed styles to take background properties from.
|
||||
#[conditional_malloc_size_of]
|
||||
pub style: Option<Arc<ComputedValues>>,
|
||||
}
|
||||
|
||||
impl CanvasBackground {
|
||||
fn for_root_element(context: &LayoutContext, root_element: ServoLayoutNode<'_>) -> Self {
|
||||
let root_style = root_element.style(context);
|
||||
|
||||
let mut style = root_style;
|
||||
let mut from_element = root_element;
|
||||
|
||||
// https://drafts.csswg.org/css-backgrounds/#body-background
|
||||
// “if the computed value of background-image on the root element is none
|
||||
// and its background-color is transparent”
|
||||
if style.background_is_transparent() &&
|
||||
// “For documents whose root element is an HTML `HTML` element
|
||||
// or an XHTML `html` element”
|
||||
root_element.type_id() == LayoutNodeType::Element(LayoutElementType::HTMLHtmlElement) &&
|
||||
// Don’t try to access styles for an unstyled subtree
|
||||
!matches!(style.clone_display().into(), Display::None)
|
||||
{
|
||||
// “that element’s first HTML `BODY` or XHTML `body` child element”
|
||||
if let Some(body) = iter_child_nodes(root_element).find(|child| {
|
||||
child.is_element() &&
|
||||
child.type_id() ==
|
||||
LayoutNodeType::Element(LayoutElementType::HTMLBodyElement)
|
||||
}) {
|
||||
style = body.style(context);
|
||||
from_element = body;
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
root_element: root_element.opaque(),
|
||||
from_element: from_element.opaque(),
|
||||
|
||||
// “However, if no boxes are generated for the element
|
||||
// whose background would be used for the canvas
|
||||
// (for example, if the root element has display: none),
|
||||
// then the canvas background is transparent.”
|
||||
style: if let Display::GeneratingBox(_) = style.clone_display().into() {
|
||||
Some(style)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue