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:
bors-servo 2018-09-05 16:32:19 -04:00 committed by GitHub
commit af777fcf15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 136 additions and 116 deletions

View file

@ -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());

View file

@ -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)

View file

@ -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) {

View file

@ -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>;

View file

@ -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));
}