mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Auto merge of #21623 - emilio:gecko-sync, r=emilio
style: Sync changes from mozilla-central. See each commit for details. https://bugzilla.mozilla.org/show_bug.cgi?id=1488854 <!-- 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/21623) <!-- Reviewable:end -->
This commit is contained in:
commit
af777fcf15
5 changed files with 136 additions and 116 deletions
|
@ -155,22 +155,11 @@ where
|
|||
return false;
|
||||
}
|
||||
|
||||
// If we are sensitive to visitedness and the visited state changed, we
|
||||
// force a restyle here. Matching doesn't depend on the actual visited
|
||||
// state at all, so we can't look at matching results to decide what to
|
||||
// do for this case.
|
||||
if state_changes.intersects(ElementState::IN_VISITED_OR_UNVISITED_STATE) &&
|
||||
self.shared_context.visited_styles_enabled
|
||||
{
|
||||
// If we the visited state changed, we force a restyle here. Matching
|
||||
// doesn't depend on the actual visited state at all, so we can't look
|
||||
// at matching results to decide what to do for this case.
|
||||
if state_changes.intersects(ElementState::IN_VISITED_OR_UNVISITED_STATE) {
|
||||
trace!(" > visitedness change, force subtree restyle");
|
||||
// We shouldn't get here with visited links disabled, but it's hard
|
||||
// to assert in cases where you record a visitedness change and
|
||||
// afterwards you change some of the stuff (like the pref) that
|
||||
// changes whether visited styles are enabled.
|
||||
//
|
||||
// So just avoid the restyle here, because it kind of would kill the
|
||||
// point of disabling visited links.
|
||||
//
|
||||
// We can't just return here because there may also be attribute
|
||||
// changes as well that imply additional hints for siblings.
|
||||
self.data.hint.insert(RestyleHint::restyle_subtree());
|
||||
|
|
|
@ -1296,9 +1296,27 @@ impl Animate for ComputedTransformOperation {
|
|||
&TransformOperation::Perspective(ref fd),
|
||||
&TransformOperation::Perspective(ref td),
|
||||
) => {
|
||||
Ok(TransformOperation::Perspective(
|
||||
fd.animate(td, procedure)?
|
||||
))
|
||||
use values::computed::CSSPixelLength;
|
||||
use values::generics::transform::create_perspective_matrix;
|
||||
|
||||
// From https://drafts.csswg.org/css-transforms-2/#interpolation-of-transform-functions:
|
||||
//
|
||||
// The transform functions matrix(), matrix3d() and
|
||||
// perspective() get converted into 4x4 matrices first and
|
||||
// interpolated as defined in section Interpolation of
|
||||
// Matrices afterwards.
|
||||
//
|
||||
let from = create_perspective_matrix(fd.px());
|
||||
let to = create_perspective_matrix(td.px());
|
||||
|
||||
let interpolated =
|
||||
Matrix3D::from(from).animate(&Matrix3D::from(to), procedure)?;
|
||||
|
||||
let decomposed = decompose_3d_matrix(interpolated)?;
|
||||
let perspective_z = decomposed.perspective.2;
|
||||
let used_value =
|
||||
if perspective_z == 0. { 0. } else { -1. / perspective_z };
|
||||
Ok(TransformOperation::Perspective(CSSPixelLength::new(used_value)))
|
||||
},
|
||||
_ if self.is_translate() && other.is_translate() => {
|
||||
self.to_translate_3d().animate(&other.to_translate_3d(), procedure)
|
||||
|
|
|
@ -1129,8 +1129,6 @@ impl Stylist {
|
|||
let rule_hash_target = element.rule_hash_target();
|
||||
|
||||
let matches_user_rules = rule_hash_target.matches_user_and_author_rules();
|
||||
let matches_author_rules =
|
||||
matches_user_rules && self.author_styles_enabled == AuthorStylesEnabled::Yes;
|
||||
|
||||
// Normal user-agent rules.
|
||||
if let Some(map) = self.cascade_data
|
||||
|
@ -1195,7 +1193,11 @@ impl Stylist {
|
|||
}
|
||||
}
|
||||
|
||||
let mut match_document_author_rules = matches_author_rules;
|
||||
if self.author_styles_enabled == AuthorStylesEnabled::No {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut match_document_author_rules = matches_user_rules;
|
||||
let mut shadow_cascade_order = 0;
|
||||
|
||||
// XBL / Shadow DOM rules, which are author rules too.
|
||||
|
@ -1204,99 +1206,102 @@ impl Stylist {
|
|||
// particular, normally document rules override ::slotted() rules, but
|
||||
// for !important it should be the other way around. So probably we need
|
||||
// to add some sort of AuthorScoped cascade level or something.
|
||||
if matches_author_rules {
|
||||
if let Some(shadow) = rule_hash_target.shadow_root() {
|
||||
if let Some(map) = shadow.style_data().and_then(|data| data.host_rules(pseudo_element)) {
|
||||
context.with_shadow_host(Some(rule_hash_target), |context| {
|
||||
map.get_all_matching_rules(
|
||||
element,
|
||||
rule_hash_target,
|
||||
applicable_declarations,
|
||||
context,
|
||||
flags_setter,
|
||||
CascadeLevel::InnerShadowNormal,
|
||||
shadow_cascade_order,
|
||||
);
|
||||
});
|
||||
shadow_cascade_order += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Match slotted rules in reverse order, so that the outer slotted
|
||||
// rules come before the inner rules (and thus have less priority).
|
||||
let mut slots = SmallVec::<[_; 3]>::new();
|
||||
let mut current = rule_hash_target.assigned_slot();
|
||||
while let Some(slot) = current {
|
||||
slots.push(slot);
|
||||
current = slot.assigned_slot();
|
||||
}
|
||||
|
||||
for slot in slots.iter().rev() {
|
||||
let shadow = slot.containing_shadow().unwrap();
|
||||
if let Some(map) = shadow.style_data().and_then(|data| data.slotted_rules(pseudo_element)) {
|
||||
context.with_shadow_host(Some(shadow.host()), |context| {
|
||||
map.get_all_matching_rules(
|
||||
element,
|
||||
rule_hash_target,
|
||||
applicable_declarations,
|
||||
context,
|
||||
flags_setter,
|
||||
CascadeLevel::InnerShadowNormal,
|
||||
shadow_cascade_order,
|
||||
);
|
||||
});
|
||||
shadow_cascade_order += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(containing_shadow) = rule_hash_target.containing_shadow() {
|
||||
let cascade_data = containing_shadow.style_data();
|
||||
let host = containing_shadow.host();
|
||||
if let Some(map) = cascade_data.and_then(|data| data.normal_rules(pseudo_element)) {
|
||||
context.with_shadow_host(Some(host), |context| {
|
||||
map.get_all_matching_rules(
|
||||
element,
|
||||
rule_hash_target,
|
||||
applicable_declarations,
|
||||
context,
|
||||
flags_setter,
|
||||
CascadeLevel::SameTreeAuthorNormal,
|
||||
shadow_cascade_order,
|
||||
);
|
||||
});
|
||||
shadow_cascade_order += 1;
|
||||
}
|
||||
|
||||
// NOTE(emilio): Hack so <svg:use> matches document rules as
|
||||
// expected.
|
||||
//
|
||||
// This is not a problem for invalidation and that kind of stuff
|
||||
// because they still don't match rules based on elements
|
||||
// outside of the shadow tree, and because the <svg:use> subtree
|
||||
// is immutable and recreated each time the source tree changes.
|
||||
//
|
||||
// See: https://github.com/w3c/svgwg/issues/504
|
||||
//
|
||||
// Note that we always resolve URLs against the document, so we
|
||||
// can't get into a nested shadow situation here.
|
||||
//
|
||||
// See: https://github.com/w3c/svgwg/issues/505
|
||||
//
|
||||
// FIXME(emilio, bug 1487259): We now do after bug 1483882, we
|
||||
// should jump out of the <svg:use> shadow tree chain now.
|
||||
//
|
||||
// Unless the used node is cross-doc, I guess, in which case doc
|
||||
// rules are probably ok...
|
||||
let host_is_svg_use =
|
||||
host.is_svg_element() &&
|
||||
host.local_name() == &*local_name!("use");
|
||||
|
||||
match_document_author_rules = host_is_svg_use;
|
||||
if let Some(shadow) = rule_hash_target.shadow_root() {
|
||||
if let Some(map) = shadow.style_data().and_then(|data| data.host_rules(pseudo_element)) {
|
||||
context.with_shadow_host(Some(rule_hash_target), |context| {
|
||||
map.get_all_matching_rules(
|
||||
element,
|
||||
rule_hash_target,
|
||||
applicable_declarations,
|
||||
context,
|
||||
flags_setter,
|
||||
CascadeLevel::InnerShadowNormal,
|
||||
shadow_cascade_order,
|
||||
);
|
||||
});
|
||||
shadow_cascade_order += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(emilio): This doesn't account for the author_styles_enabled
|
||||
// stuff...
|
||||
// Match slotted rules in reverse order, so that the outer slotted
|
||||
// rules come before the inner rules (and thus have less priority).
|
||||
let mut slots = SmallVec::<[_; 3]>::new();
|
||||
let mut current = rule_hash_target.assigned_slot();
|
||||
while let Some(slot) = current {
|
||||
slots.push(slot);
|
||||
current = slot.assigned_slot();
|
||||
}
|
||||
|
||||
for slot in slots.iter().rev() {
|
||||
let shadow = slot.containing_shadow().unwrap();
|
||||
if let Some(map) = shadow.style_data().and_then(|data| data.slotted_rules(pseudo_element)) {
|
||||
context.with_shadow_host(Some(shadow.host()), |context| {
|
||||
map.get_all_matching_rules(
|
||||
element,
|
||||
rule_hash_target,
|
||||
applicable_declarations,
|
||||
context,
|
||||
flags_setter,
|
||||
CascadeLevel::InnerShadowNormal,
|
||||
shadow_cascade_order,
|
||||
);
|
||||
});
|
||||
shadow_cascade_order += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let mut current_containing_shadow = rule_hash_target.containing_shadow();
|
||||
while let Some(containing_shadow) = current_containing_shadow {
|
||||
let cascade_data = containing_shadow.style_data();
|
||||
let host = containing_shadow.host();
|
||||
if let Some(map) = cascade_data.and_then(|data| data.normal_rules(pseudo_element)) {
|
||||
context.with_shadow_host(Some(host), |context| {
|
||||
map.get_all_matching_rules(
|
||||
element,
|
||||
rule_hash_target,
|
||||
applicable_declarations,
|
||||
context,
|
||||
flags_setter,
|
||||
CascadeLevel::SameTreeAuthorNormal,
|
||||
shadow_cascade_order,
|
||||
);
|
||||
});
|
||||
shadow_cascade_order += 1;
|
||||
}
|
||||
|
||||
let host_is_svg_use_element =
|
||||
host.is_svg_element() &&
|
||||
host.local_name() == &*local_name!("use");
|
||||
|
||||
if !host_is_svg_use_element {
|
||||
match_document_author_rules = false;
|
||||
break;
|
||||
}
|
||||
|
||||
debug_assert!(
|
||||
cascade_data.is_none(),
|
||||
"We allow no stylesheets in <svg:use> subtrees"
|
||||
);
|
||||
|
||||
// NOTE(emilio): Hack so <svg:use> matches the rules of the
|
||||
// enclosing tree.
|
||||
//
|
||||
// This is not a problem for invalidation and that kind of stuff
|
||||
// because they still don't match rules based on elements
|
||||
// outside of the shadow tree, and because the <svg:use>
|
||||
// subtrees are immutable and recreated each time the source
|
||||
// tree changes.
|
||||
//
|
||||
// We historically allow cross-document <svg:use> to have these
|
||||
// rules applied, but I think that's not great. Gecko is the
|
||||
// only engine supporting that.
|
||||
//
|
||||
// See https://github.com/w3c/svgwg/issues/504 for the relevant
|
||||
// spec discussion.
|
||||
current_containing_shadow = host.containing_shadow();
|
||||
match_document_author_rules = current_containing_shadow.is_none();
|
||||
}
|
||||
|
||||
let cut_xbl_binding_inheritance =
|
||||
element.each_xbl_cascade_data(|cascade_data, quirks_mode| {
|
||||
if let Some(map) = cascade_data.normal_rules(pseudo_element) {
|
||||
|
|
|
@ -42,6 +42,7 @@ impl TransformOrigin {
|
|||
|
||||
/// computed value of matrix3d()
|
||||
pub type Matrix3D = generic::Matrix3D<Number>;
|
||||
|
||||
/// computed value of matrix()
|
||||
pub type Matrix = generic::Matrix<Number>;
|
||||
|
||||
|
|
|
@ -49,17 +49,24 @@ pub type ShapeRadius = generic::ShapeRadius<LengthOrPercentage>;
|
|||
/// The specified value of `Polygon`
|
||||
pub type Polygon = generic::Polygon<LengthOrPercentage>;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn is_clip_path_path_enabled(context: &ParserContext) -> bool {
|
||||
use gecko_bindings::structs::mozilla;
|
||||
context.chrome_rules_enabled() ||
|
||||
unsafe { mozilla::StaticPrefs_sVarCache_layout_css_clip_path_path_enabled }
|
||||
}
|
||||
#[cfg(feature = "servo")]
|
||||
fn is_clip_path_path_enabled(_: &ParserContext) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
impl Parse for ClippingShape {
|
||||
#[inline]
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
// |clip-path:path()| is a chrome-only property value support for now. `path()` is
|
||||
// defined in css-shape-2, but the spec is not stable enough, and we haven't decided
|
||||
// to make it public yet. However, it has some benefits for the front-end, so we
|
||||
// implement it.
|
||||
if context.chrome_rules_enabled() {
|
||||
if is_clip_path_path_enabled(context) {
|
||||
if let Ok(p) = input.try(|i| Path::parse(context, i)) {
|
||||
return Ok(ShapeSource::Path(p));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue