mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Auto merge of #16266 - Manishearth:stylo-nshtmlss, r=heycam
stylo: Support all extra style rules from nsHTMLStyleSheet r=heycam from https://bugzilla.mozilla.org/show_bug.cgi?id=1341714 <!-- 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/16266) <!-- Reviewable:end -->
This commit is contained in:
commit
21979bf715
8 changed files with 219 additions and 33 deletions
|
@ -51,7 +51,7 @@ use gecko_bindings::structs::NODE_IS_NATIVE_ANONYMOUS;
|
|||
use gecko_bindings::sugar::ownership::HasArcFFI;
|
||||
use parking_lot::RwLock;
|
||||
use properties::{ComputedValues, parse_style_attribute};
|
||||
use properties::PropertyDeclarationBlock;
|
||||
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
|
||||
use properties::animated_properties::AnimationValueMap;
|
||||
use rule_tree::CascadeLevel as ServoCascadeLevel;
|
||||
use selector_parser::{ElementExt, Snapshot};
|
||||
|
@ -624,6 +624,50 @@ impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
|
|||
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
|
||||
where V: Push<ApplicableDeclarationBlock>,
|
||||
{
|
||||
use properties::longhands::_x_lang::SpecifiedValue as SpecifiedLang;
|
||||
use properties::longhands::color::SpecifiedValue as SpecifiedColor;
|
||||
use properties::longhands::text_align::SpecifiedValue as SpecifiedTextAlign;
|
||||
use values::specified::color::Color;
|
||||
lazy_static! {
|
||||
static ref TH_RULE: ApplicableDeclarationBlock = {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let pdb = PropertyDeclarationBlock::with_one(
|
||||
PropertyDeclaration::TextAlign(SpecifiedTextAlign::MozCenterOrInherit),
|
||||
Importance::Normal
|
||||
);
|
||||
let arc = Arc::new(global_style_data.shared_lock.wrap(pdb));
|
||||
ApplicableDeclarationBlock::from_declarations(arc, ServoCascadeLevel::PresHints)
|
||||
};
|
||||
static ref TABLE_COLOR_RULE: ApplicableDeclarationBlock = {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let pdb = PropertyDeclarationBlock::with_one(
|
||||
PropertyDeclaration::Color(SpecifiedColor(Color::InheritFromBodyQuirk.into())),
|
||||
Importance::Normal
|
||||
);
|
||||
let arc = Arc::new(global_style_data.shared_lock.wrap(pdb));
|
||||
ApplicableDeclarationBlock::from_declarations(arc, ServoCascadeLevel::PresHints)
|
||||
};
|
||||
static ref MATHML_LANG_RULE: ApplicableDeclarationBlock = {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let pdb = PropertyDeclarationBlock::with_one(
|
||||
PropertyDeclaration::XLang(SpecifiedLang(atom!("x-math"))),
|
||||
Importance::Normal
|
||||
);
|
||||
let arc = Arc::new(global_style_data.shared_lock.wrap(pdb));
|
||||
ApplicableDeclarationBlock::from_declarations(arc, ServoCascadeLevel::PresHints)
|
||||
};
|
||||
};
|
||||
|
||||
let ns = self.get_namespace();
|
||||
// <th> elements get a default MozCenterOrInherit which may get overridden
|
||||
if ns == &*Namespace(atom!("http://www.w3.org/1999/xhtml")) {
|
||||
if self.get_local_name().as_ptr() == atom!("th").as_ptr() {
|
||||
hints.push(TH_RULE.clone());
|
||||
} else if self.get_local_name().as_ptr() == atom!("table").as_ptr() &&
|
||||
self.as_node().owner_doc().mCompatMode == structs::nsCompatibility::eCompatibility_NavQuirks {
|
||||
hints.push(TABLE_COLOR_RULE.clone());
|
||||
}
|
||||
}
|
||||
let declarations = unsafe { Gecko_GetHTMLPresentationAttrDeclarationBlock(self.0) };
|
||||
let declarations = declarations.and_then(|s| s.as_arc_opt());
|
||||
if let Some(decl) = declarations {
|
||||
|
@ -638,6 +682,30 @@ impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
|
|||
ApplicableDeclarationBlock::from_declarations(Clone::clone(decl), ServoCascadeLevel::PresHints)
|
||||
);
|
||||
}
|
||||
|
||||
// xml:lang has precedence over lang, which can be
|
||||
// set by Gecko_GetHTMLPresentationAttrDeclarationBlock
|
||||
//
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#language
|
||||
let ptr = unsafe {
|
||||
bindings::Gecko_GetXMLLangValue(self.0)
|
||||
};
|
||||
if !ptr.is_null() {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
|
||||
let pdb = PropertyDeclarationBlock::with_one(
|
||||
PropertyDeclaration::XLang(SpecifiedLang(Atom::from(ptr))),
|
||||
Importance::Normal
|
||||
);
|
||||
let arc = Arc::new(global_style_data.shared_lock.wrap(pdb));
|
||||
hints.push(ApplicableDeclarationBlock::from_declarations(arc, ServoCascadeLevel::PresHints))
|
||||
}
|
||||
// MathML's default lang has precedence over both `lang` and `xml:lang`
|
||||
if ns == &*Namespace(atom!("http://www.w3.org/1998/Math/MathML")) {
|
||||
if self.get_local_name().as_ptr() == atom!("math").as_ptr() {
|
||||
hints.push(MATHML_LANG_RULE.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -479,6 +479,10 @@ extern "C" {
|
|||
pub fn Gecko_GetElementId(element: RawGeckoElementBorrowed)
|
||||
-> *mut nsIAtom;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_GetXMLLangValue(element: RawGeckoElementBorrowed)
|
||||
-> *mut nsIAtom;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_AtomAttrValue(element: RawGeckoElementBorrowed,
|
||||
attribute: *mut nsIAtom) -> *mut nsIAtom;
|
||||
|
@ -1050,6 +1054,10 @@ extern "C" {
|
|||
extern "C" {
|
||||
pub fn Gecko_CSSFontFaceRule_Release(aPtr: *mut nsCSSFontFaceRule);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_GetBody(pres_context: RawGeckoPresContextBorrowed)
|
||||
-> RawGeckoElementBorrowedOrNull;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_GetLookAndFeelSystemColor(color_id: i32,
|
||||
pres_context:
|
||||
|
|
|
@ -2797,8 +2797,12 @@ fn static_assert() {
|
|||
-webkit-text-stroke-width text-emphasis-position -moz-tab-size -moz-text-size-adjust">
|
||||
|
||||
<% text_align_keyword = Keyword("text-align", "start end left right center justify -moz-center -moz-left " +
|
||||
"-moz-right match-parent char") %>
|
||||
"-moz-right char") %>
|
||||
<% text_align_reachable_keyword = Keyword("text-align", "start end left right center justify char") %>
|
||||
${impl_keyword('text_align', 'mTextAlign', text_align_keyword, need_clone=False)}
|
||||
// Stable rust errors on unreachable patterns, and there is overlap, so we run with the overlapping
|
||||
// constants removed
|
||||
${impl_keyword_clone('text_align', 'mTextAlign', text_align_reachable_keyword)}
|
||||
|
||||
pub fn set_text_shadow(&mut self, v: longhands::text_shadow::computed_value::T) {
|
||||
self.gecko.mTextShadow.replace_with_new(v.0.len() as u32);
|
||||
|
|
|
@ -26,10 +26,7 @@
|
|||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
SpecifiedValue(CSSColor {
|
||||
parsed: Color::RGBA(*computed),
|
||||
authored: None,
|
||||
})
|
||||
SpecifiedValue(Color::RGBA(*computed).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -250,11 +250,10 @@ ${helpers.single_keyword("text-align-last",
|
|||
spec="https://drafts.csswg.org/css-text/#propdef-text-align-last")}
|
||||
|
||||
// TODO make this a shorthand and implement text-align-last/text-align-all
|
||||
<%helpers:longhand name="text-align" animatable="False" spec="https://drafts.csswg.org/css-text/#propdef-text-align">
|
||||
pub use self::computed_value::T as SpecifiedValue;
|
||||
<%helpers:longhand name="text-align" animatable="False" need_clone="True"
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-text-align">
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
use values::HasViewportPercentage;
|
||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||
no_viewport_percentage!(SpecifiedValue);
|
||||
pub mod computed_value {
|
||||
use style_traits::ToCss;
|
||||
|
@ -299,21 +298,110 @@ ${helpers.single_keyword("text-align-last",
|
|||
_moz_center("-moz-center") => 6,
|
||||
_moz_left("-moz-left") => 7,
|
||||
_moz_right("-moz-right") => 8,
|
||||
match_parent("match-parent") => 9,
|
||||
char("char") => 10,
|
||||
% endif
|
||||
}
|
||||
|
||||
${helpers.gecko_keyword_conversion(Keyword('text-align',
|
||||
"""left right center justify -moz-left -moz-right
|
||||
-moz-center char end""",
|
||||
gecko_strip_moz_prefix=False), type="T")}
|
||||
}
|
||||
|
||||
#[inline] pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T::start
|
||||
}
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
computed_value::T::parse(input)
|
||||
}
|
||||
${helpers.gecko_keyword_conversion(Keyword('text-align',
|
||||
"""left right center justify -moz-left -moz-right
|
||||
-moz-center char end match-parent""",
|
||||
gecko_strip_moz_prefix=False))}
|
||||
|
||||
|
||||
% if product == "gecko":
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
|
||||
pub enum SpecifiedValue {
|
||||
Keyword(computed_value::T),
|
||||
MatchParent,
|
||||
MozCenterOrInherit,
|
||||
}
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
// MozCenterOrInherit cannot be parsed, only set directly on th elements
|
||||
if let Ok(key) = input.try(computed_value::T::parse) {
|
||||
Ok(SpecifiedValue::Keyword(key))
|
||||
} else {
|
||||
input.expect_ident_matching("match-parent")?;
|
||||
Ok(SpecifiedValue::MatchParent)
|
||||
}
|
||||
}
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
SpecifiedValue::Keyword(key) => key.to_css(dest),
|
||||
SpecifiedValue::MatchParent => dest.write_str("match-parent"),
|
||||
SpecifiedValue::MozCenterOrInherit => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecifiedValue {
|
||||
pub fn from_gecko_keyword(kw: u32) -> Self {
|
||||
use gecko_bindings::structs::NS_STYLE_TEXT_ALIGN_MATCH_PARENT;
|
||||
if kw == NS_STYLE_TEXT_ALIGN_MATCH_PARENT {
|
||||
SpecifiedValue::MatchParent
|
||||
} else {
|
||||
SpecifiedValue::Keyword(computed_value::T::from_gecko_keyword(kw))
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
match *self {
|
||||
SpecifiedValue::Keyword(key) => key,
|
||||
SpecifiedValue::MatchParent => {
|
||||
// on the root <html> element we should still respect the dir
|
||||
// but the parent dir of that element is LTR even if it's <html dir=rtl>
|
||||
// and will only be RTL if certain prefs have been set.
|
||||
// In that case, the default behavior here will set it to left,
|
||||
// but we want to set it to right -- instead set it to the default (`start`),
|
||||
// which will do the right thing in this case (but not the general case)
|
||||
if context.is_root_element {
|
||||
return get_initial_value();
|
||||
}
|
||||
let parent = context.inherited_style().get_inheritedtext().clone_text_align();
|
||||
let ltr = context.inherited_style().writing_mode.is_bidi_ltr();
|
||||
match (parent, ltr) {
|
||||
(computed_value::T::start, true) => computed_value::T::left,
|
||||
(computed_value::T::start, false) => computed_value::T::right,
|
||||
(computed_value::T::end, true) => computed_value::T::right,
|
||||
(computed_value::T::end, false) => computed_value::T::left,
|
||||
_ => parent
|
||||
}
|
||||
}
|
||||
SpecifiedValue::MozCenterOrInherit => {
|
||||
let parent = context.inherited_style().get_inheritedtext().clone_text_align();
|
||||
if parent == computed_value::T::start {
|
||||
computed_value::T::center
|
||||
} else {
|
||||
parent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
SpecifiedValue::Keyword(*computed)
|
||||
}
|
||||
}
|
||||
% else:
|
||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||
pub use self::computed_value::T as SpecifiedValue;
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
computed_value::T::parse(input)
|
||||
}
|
||||
% endif
|
||||
</%helpers:longhand>
|
||||
|
||||
// FIXME: This prop should be animatable.
|
||||
|
|
|
@ -209,6 +209,24 @@ impl ToComputedValue for specified::Color {
|
|||
specified::Color::MozHyperlinktext => to_rgba(pres_context.mLinkColor),
|
||||
specified::Color::MozActiveHyperlinktext => to_rgba(pres_context.mActiveLinkColor),
|
||||
specified::Color::MozVisitedHyperlinktext => to_rgba(pres_context.mVisitedLinkColor),
|
||||
specified::Color::InheritFromBodyQuirk => {
|
||||
use dom::TElement;
|
||||
use gecko::wrapper::GeckoElement;
|
||||
use gecko_bindings::bindings::Gecko_GetBody;
|
||||
let body = unsafe {
|
||||
Gecko_GetBody(pres_context)
|
||||
};
|
||||
if let Some(body) = body {
|
||||
let wrap = GeckoElement(body);
|
||||
let borrow = wrap.borrow_data();
|
||||
borrow.as_ref().unwrap()
|
||||
.styles().primary.values()
|
||||
.get_color()
|
||||
.clone_color()
|
||||
} else {
|
||||
to_rgba(pres_context.mDefaultColor)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,13 +257,10 @@ impl ToComputedValue for specified::CSSColor {
|
|||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &CSSColor) -> Self {
|
||||
specified::CSSColor {
|
||||
parsed: match *computed {
|
||||
CSSColor::RGBA(rgba) => specified::Color::RGBA(rgba),
|
||||
CSSColor::CurrentColor => specified::Color::CurrentColor,
|
||||
},
|
||||
authored: None,
|
||||
}
|
||||
(match *computed {
|
||||
CSSColor::RGBA(rgba) => specified::Color::RGBA(rgba),
|
||||
CSSColor::CurrentColor => specified::Color::CurrentColor,
|
||||
}).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ mod gecko {
|
|||
MozActiveHyperlinktext,
|
||||
/// -moz-visitedhyperlinktext
|
||||
MozVisitedHyperlinktext,
|
||||
/// Quirksmode-only rule for inheriting color from the body
|
||||
InheritFromBodyQuirk,
|
||||
}
|
||||
|
||||
no_viewport_percentage!(Color);
|
||||
|
@ -89,6 +91,7 @@ mod gecko {
|
|||
Color::MozHyperlinktext => dest.write_str("-moz-hyperlinktext"),
|
||||
Color::MozActiveHyperlinktext => dest.write_str("-moz-activehyperlinktext"),
|
||||
Color::MozVisitedHyperlinktext => dest.write_str("-moz-visitedhyperlinktext"),
|
||||
Color::InheritFromBodyQuirk => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,24 +107,27 @@ impl ToCss for CSSColor {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Color> for CSSColor {
|
||||
fn from(color: Color) -> Self {
|
||||
CSSColor {
|
||||
parsed: color,
|
||||
authored: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CSSColor {
|
||||
#[inline]
|
||||
/// Returns currentcolor value.
|
||||
pub fn currentcolor() -> CSSColor {
|
||||
CSSColor {
|
||||
parsed: Color::CurrentColor,
|
||||
authored: None,
|
||||
}
|
||||
Color::CurrentColor.into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns transparent value.
|
||||
pub fn transparent() -> CSSColor {
|
||||
CSSColor {
|
||||
parsed: Color::RGBA(cssparser::RGBA::transparent()),
|
||||
// This should probably be "transparent", but maybe it doesn't matter.
|
||||
authored: None,
|
||||
}
|
||||
// We should probably set authored to "transparent", but maybe it doesn't matter.
|
||||
Color::RGBA(cssparser::RGBA::transparent()).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue