mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Correctly paint the CSS canvas’ background
https://drafts.csswg.org/css-backgrounds/#special-backgrounds Fixes https://github.com/servo/servo/issues/25559 Closes https://github.com/servo/servo/pull/26121, as it is an alternative.
This commit is contained in:
parent
c7acfc37ed
commit
1f6efbf9e9
9 changed files with 312 additions and 37 deletions
|
@ -8,7 +8,7 @@ use crate::display_list::stacking_context::{
|
|||
ContainingBlock, ContainingBlockInfo, StackingContext, StackingContextBuildMode,
|
||||
StackingContextBuilder,
|
||||
};
|
||||
use crate::dom_traversal::{Contents, NodeExt};
|
||||
use crate::dom_traversal::{iter_child_nodes, Contents, NodeExt};
|
||||
use crate::element_data::LayoutBox;
|
||||
use crate::flow::construct::ContainsFloats;
|
||||
use crate::flow::float::FloatBox;
|
||||
|
@ -21,12 +21,14 @@ use crate::positioned::AbsolutelyPositionedBox;
|
|||
use crate::positioned::PositioningContext;
|
||||
use crate::replaced::ReplacedContent;
|
||||
use crate::sizing::ContentSizesRequest;
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
use crate::style_ext::{Display, DisplayGeneratingBox};
|
||||
use crate::DefiniteContainingBlock;
|
||||
use app_units::Au;
|
||||
use euclid::default::{Point2D, Rect, Size2D};
|
||||
use gfx_traits::print_tree::PrintTree;
|
||||
use script_layout_interface::wrapper_traits::LayoutNode;
|
||||
use script_layout_interface::{LayoutElementType, LayoutNodeType};
|
||||
use servo_arc::Arc;
|
||||
use style::dom::OpaqueNode;
|
||||
use style::properties::ComputedValues;
|
||||
|
@ -38,6 +40,9 @@ pub struct BoxTree {
|
|||
/// Contains typically exactly one block-level box, which was generated by the root element.
|
||||
/// There may be zero if that element has `display: none`.
|
||||
root: BlockFormattingContext,
|
||||
|
||||
/// https://drafts.csswg.org/css-backgrounds/#special-backgrounds
|
||||
canvas_background: CanvasBackground,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -54,10 +59,14 @@ pub struct FragmentTree {
|
|||
|
||||
/// The scrollable overflow rectangle for the entire tree
|
||||
/// https://drafts.csswg.org/css-overflow/#scrollable
|
||||
scrollable_overflow: PhysicalRect<Length>,
|
||||
pub(crate) scrollable_overflow: PhysicalRect<Length>,
|
||||
|
||||
/// The containing block used in the layout of this fragment tree.
|
||||
initial_containing_block: PhysicalRect<Length>,
|
||||
pub(crate) initial_containing_block: PhysicalRect<Length>,
|
||||
|
||||
/// https://drafts.csswg.org/css-backgrounds/#special-backgrounds
|
||||
#[serde(skip)]
|
||||
pub(crate) canvas_background: CanvasBackground,
|
||||
}
|
||||
|
||||
impl BoxTree {
|
||||
|
@ -75,6 +84,7 @@ impl BoxTree {
|
|||
contains_floats: contains_floats == ContainsFloats::Yes,
|
||||
contents: BlockContainer::BlockLevelBoxes(boxes),
|
||||
},
|
||||
canvas_background: CanvasBackground::for_root_element(context, root_element),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,6 +236,7 @@ impl BoxTree {
|
|||
root_fragments,
|
||||
scrollable_overflow,
|
||||
initial_containing_block: physical_containing_block,
|
||||
canvas_background: self.canvas_background.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -256,6 +267,14 @@ impl FragmentTree {
|
|||
}
|
||||
|
||||
stacking_context.sort();
|
||||
|
||||
// Paint the canvas’ background (if any) before/under everything else
|
||||
stacking_context.build_canvas_background_display_list(
|
||||
builder,
|
||||
self,
|
||||
&self.initial_containing_block,
|
||||
);
|
||||
|
||||
stacking_context.build_display_list(builder);
|
||||
}
|
||||
|
||||
|
@ -362,3 +381,64 @@ impl FragmentTree {
|
|||
.unwrap_or_else(Rect::zero)
|
||||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-backgrounds/#root-background
|
||||
#[derive(Clone, Serialize)]
|
||||
pub(crate) 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.
|
||||
#[serde(skip)]
|
||||
pub style: Option<Arc<ComputedValues>>,
|
||||
}
|
||||
|
||||
impl CanvasBackground {
|
||||
fn for_root_element<'dom>(context: &LayoutContext, root_element: impl NodeExt<'dom>) -> 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