mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Auto merge of #15331 - Manishearth:stylo-presattr, r=emilio,bz
Basic handling framework for presentation attributes in Stylo, with handling for font-size and color https://bugzilla.mozilla.org/show_bug.cgi?id=1330041 r=emilio,bz <!-- 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/15331) <!-- Reviewable:end -->
This commit is contained in:
commit
57fb07e9c0
6 changed files with 126 additions and 24 deletions
|
@ -123,7 +123,7 @@ impl HTMLFontElementLayoutHelpers for LayoutJS<HTMLFontElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size
|
/// https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size
|
||||||
pub fn parse_legacy_font_size(mut input: &str) -> Option<&'static str> {
|
fn parse_length(mut input: &str) -> Option<specified::Length> {
|
||||||
// Steps 1 & 2 are not relevant
|
// Steps 1 & 2 are not relevant
|
||||||
|
|
||||||
// Step 3
|
// Step 3
|
||||||
|
@ -153,8 +153,8 @@ pub fn parse_legacy_font_size(mut input: &str) -> Option<&'static str> {
|
||||||
|
|
||||||
// Steps 6, 7, 8
|
// Steps 6, 7, 8
|
||||||
let mut value = match read_numbers(input_chars) {
|
let mut value = match read_numbers(input_chars) {
|
||||||
(Some(v), _) => v,
|
(Some(v), _) if v >= 0 => v,
|
||||||
(None, _) => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 9
|
// Step 9
|
||||||
|
@ -165,18 +165,5 @@ pub fn parse_legacy_font_size(mut input: &str) -> Option<&'static str> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steps 10, 11, 12
|
// Steps 10, 11, 12
|
||||||
Some(match value {
|
Some(specified::Length::from_font_size_int(value as u8))
|
||||||
n if n >= 7 => "xxx-large",
|
|
||||||
6 => "xx-large",
|
|
||||||
5 => "x-large",
|
|
||||||
4 => "large",
|
|
||||||
3 => "medium",
|
|
||||||
2 => "small",
|
|
||||||
n if n <= 1 => "x-small",
|
|
||||||
_ => unreachable!(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_length(value: &str) -> Option<specified::Length> {
|
|
||||||
parse_legacy_font_size(&value).and_then(|parsed| specified::Length::from_str(&parsed))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink, Gecko
|
||||||
use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
|
use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
|
||||||
use gecko_bindings::bindings::Gecko_ClassOrClassList;
|
use gecko_bindings::bindings::Gecko_ClassOrClassList;
|
||||||
use gecko_bindings::bindings::Gecko_GetAnimationRule;
|
use gecko_bindings::bindings::Gecko_GetAnimationRule;
|
||||||
use gecko_bindings::bindings::Gecko_GetServoDeclarationBlock;
|
use gecko_bindings::bindings::Gecko_GetHTMLPresentationAttrDeclarationBlock;
|
||||||
|
use gecko_bindings::bindings::Gecko_GetStyleAttrDeclarationBlock;
|
||||||
use gecko_bindings::bindings::Gecko_GetStyleContext;
|
use gecko_bindings::bindings::Gecko_GetStyleContext;
|
||||||
use gecko_bindings::structs;
|
use gecko_bindings::structs;
|
||||||
use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode};
|
use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode};
|
||||||
|
@ -42,6 +43,7 @@ use parking_lot::RwLock;
|
||||||
use parser::ParserContextExtraData;
|
use parser::ParserContextExtraData;
|
||||||
use properties::{ComputedValues, parse_style_attribute};
|
use properties::{ComputedValues, parse_style_attribute};
|
||||||
use properties::PropertyDeclarationBlock;
|
use properties::PropertyDeclarationBlock;
|
||||||
|
use rule_tree::CascadeLevel as ServoCascadeLevel;
|
||||||
use selector_parser::{ElementExt, Snapshot};
|
use selector_parser::{ElementExt, Snapshot};
|
||||||
use selectors::Element;
|
use selectors::Element;
|
||||||
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
||||||
|
@ -385,7 +387,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_attribute(&self) -> Option<&Arc<RwLock<PropertyDeclarationBlock>>> {
|
fn style_attribute(&self) -> Option<&Arc<RwLock<PropertyDeclarationBlock>>> {
|
||||||
let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.0) };
|
let declarations = unsafe { Gecko_GetStyleAttrDeclarationBlock(self.0) };
|
||||||
declarations.map(|s| s.as_arc_opt()).unwrap_or(None)
|
declarations.map(|s| s.as_arc_opt()).unwrap_or(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,10 +485,16 @@ impl<'le> PartialEq for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
|
impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
|
||||||
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
|
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
|
||||||
where V: Push<ApplicableDeclarationBlock>,
|
where V: Push<ApplicableDeclarationBlock>,
|
||||||
{
|
{
|
||||||
// FIXME(bholley) - Need to implement this.
|
let declarations = unsafe { Gecko_GetHTMLPresentationAttrDeclarationBlock(self.0) };
|
||||||
|
let declarations = declarations.and_then(|s| s.as_arc_opt());
|
||||||
|
if let Some(decl) = declarations {
|
||||||
|
hints.push(
|
||||||
|
ApplicableDeclarationBlock::from_declarations(Clone::clone(decl), ServoCascadeLevel::PresHints)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -499,7 +499,11 @@ extern "C" {
|
||||||
-> u32;
|
-> u32;
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_GetServoDeclarationBlock(element: RawGeckoElementBorrowed)
|
pub fn Gecko_GetStyleAttrDeclarationBlock(element: RawGeckoElementBorrowed)
|
||||||
|
-> RawServoDeclarationBlockStrongBorrowedOrNull;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_GetHTMLPresentationAttrDeclarationBlock(element: RawGeckoElementBorrowed)
|
||||||
-> RawServoDeclarationBlockStrongBorrowedOrNull;
|
-> RawServoDeclarationBlockStrongBorrowedOrNull;
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -1391,6 +1395,13 @@ extern "C" {
|
||||||
property:
|
property:
|
||||||
nsCSSPropertyID);
|
nsCSSPropertyID);
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Servo_DeclarationBlock_AddPresValue(declarations:
|
||||||
|
RawServoDeclarationBlockBorrowed,
|
||||||
|
property: nsCSSPropertyID,
|
||||||
|
css_value:
|
||||||
|
nsCSSValueBorrowedMut);
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Servo_CSSSupports2(name: *const nsACString_internal,
|
pub fn Servo_CSSSupports2(name: *const nsACString_internal,
|
||||||
value: *const nsACString_internal) -> bool;
|
value: *const nsACString_internal) -> bool;
|
||||||
|
|
|
@ -12,7 +12,7 @@ use gecko_bindings::bindings::Gecko_CSSValue_GetPercentage;
|
||||||
use gecko_bindings::bindings::Gecko_CSSValue_SetAbsoluteLength;
|
use gecko_bindings::bindings::Gecko_CSSValue_SetAbsoluteLength;
|
||||||
use gecko_bindings::bindings::Gecko_CSSValue_SetCalc;
|
use gecko_bindings::bindings::Gecko_CSSValue_SetCalc;
|
||||||
use gecko_bindings::bindings::Gecko_CSSValue_SetPercentage;
|
use gecko_bindings::bindings::Gecko_CSSValue_SetPercentage;
|
||||||
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit, nsCSSValue_Array};
|
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit, nsCSSValue_Array, nscolor};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
@ -34,6 +34,28 @@ impl nsCSSValue {
|
||||||
unsafe { *self.mValue.mInt.as_ref() }
|
unsafe { *self.mValue.mInt.as_ref() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if it is an integer and returns it if so
|
||||||
|
pub fn integer(&self) -> Option<i32> {
|
||||||
|
if self.mUnit == nsCSSUnit::eCSSUnit_Integer ||
|
||||||
|
self.mUnit == nsCSSUnit::eCSSUnit_Enumerated ||
|
||||||
|
self.mUnit == nsCSSUnit::eCSSUnit_EnumColor {
|
||||||
|
Some(unsafe { *self.mValue.mInt.as_ref() })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if it is an RGBA color, returning it if so
|
||||||
|
/// Only use it with colors set by SetColorValue(),
|
||||||
|
/// which always sets RGBA colors
|
||||||
|
pub fn color_value(&self) -> Option<nscolor> {
|
||||||
|
if self.mUnit == nsCSSUnit::eCSSUnit_RGBAColor {
|
||||||
|
Some(unsafe { *self.mValue.mColor.as_ref() })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns this nsCSSValue value as a floating point value, unchecked in
|
/// Returns this nsCSSValue value as a floating point value, unchecked in
|
||||||
/// release builds.
|
/// release builds.
|
||||||
pub fn float_unchecked(&self) -> f32 {
|
pub fn float_unchecked(&self) -> f32 {
|
||||||
|
|
|
@ -293,6 +293,20 @@ impl NoCalcLength {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||||
|
pub fn from_font_size_int(i: u8) -> Self {
|
||||||
|
let au = match i {
|
||||||
|
0 | 1 => Au::from_px(FONT_MEDIUM_PX) * 3 / 4,
|
||||||
|
2 => Au::from_px(FONT_MEDIUM_PX) * 8 / 9,
|
||||||
|
3 => Au::from_px(FONT_MEDIUM_PX),
|
||||||
|
4 => Au::from_px(FONT_MEDIUM_PX) * 6 / 5,
|
||||||
|
5 => Au::from_px(FONT_MEDIUM_PX) * 3 / 2,
|
||||||
|
6 => Au::from_px(FONT_MEDIUM_PX) * 2,
|
||||||
|
_ => Au::from_px(FONT_MEDIUM_PX) * 3,
|
||||||
|
};
|
||||||
|
NoCalcLength::Absolute(au)
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a given absolute or relative dimension.
|
/// Parse a given absolute or relative dimension.
|
||||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<NoCalcLength, ()> {
|
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<NoCalcLength, ()> {
|
||||||
match_ignore_ascii_case! { unit,
|
match_ignore_ascii_case! { unit,
|
||||||
|
@ -429,6 +443,11 @@ impl Length {
|
||||||
NoCalcLength::parse_dimension(value, unit).map(Length::NoCalc)
|
NoCalcLength::parse_dimension(value, unit).map(Length::NoCalc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||||
|
pub fn from_font_size_int(i: u8) -> Self {
|
||||||
|
Length::NoCalc(NoCalcLength::from_font_size_int(i))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<Length, ()> {
|
fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<Length, ()> {
|
||||||
match try!(input.next()) {
|
match try!(input.next()) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSet
|
||||||
use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
|
use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
|
||||||
use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
|
use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
|
||||||
use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
|
use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
|
||||||
use style::gecko_bindings::bindings::{nsACString, nsAString};
|
use style::gecko_bindings::bindings::{nsACString, nsCSSValueBorrowedMut, nsAString};
|
||||||
use style::gecko_bindings::bindings::Gecko_AnimationAppendKeyframe;
|
use style::gecko_bindings::bindings::Gecko_AnimationAppendKeyframe;
|
||||||
use style::gecko_bindings::bindings::RawGeckoAnimationValueListBorrowedMut;
|
use style::gecko_bindings::bindings::RawGeckoAnimationValueListBorrowedMut;
|
||||||
use style::gecko_bindings::bindings::RawGeckoElementBorrowed;
|
use style::gecko_bindings::bindings::RawGeckoElementBorrowed;
|
||||||
|
@ -946,6 +946,61 @@ pub extern "C" fn Servo_DeclarationBlock_RemovePropertyById(declarations: RawSer
|
||||||
remove_property(declarations, get_property_id_from_nscsspropertyid!(property, ()))
|
remove_property(declarations, get_property_id_from_nscsspropertyid!(property, ()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_DeclarationBlock_AddPresValue(declarations: RawServoDeclarationBlockBorrowed,
|
||||||
|
property: nsCSSPropertyID,
|
||||||
|
css_value: nsCSSValueBorrowedMut) {
|
||||||
|
use style::gecko::values::convert_nscolor_to_rgba;
|
||||||
|
use style::properties::{DeclaredValue, LonghandId, PropertyDeclaration, PropertyId, longhands};
|
||||||
|
use style::values::specified;
|
||||||
|
|
||||||
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
||||||
|
let prop = PropertyId::from_nscsspropertyid(property);
|
||||||
|
|
||||||
|
let long = match prop {
|
||||||
|
Ok(PropertyId::Longhand(long)) => long,
|
||||||
|
_ => {
|
||||||
|
error!("stylo: unknown presentation property with id {:?}", property);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let decl = match long {
|
||||||
|
LonghandId::FontSize => {
|
||||||
|
if let Some(int) = css_value.integer() {
|
||||||
|
PropertyDeclaration::FontSize(DeclaredValue::Value(
|
||||||
|
longhands::font_size::SpecifiedValue(
|
||||||
|
specified::LengthOrPercentage::Length(
|
||||||
|
specified::NoCalcLength::from_font_size_int(int as u8)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
error!("stylo: got unexpected non-integer value for font-size presentation attribute");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LonghandId::Color => {
|
||||||
|
if let Some(color) = css_value.color_value() {
|
||||||
|
PropertyDeclaration::Color(DeclaredValue::Value(
|
||||||
|
specified::CSSRGBA {
|
||||||
|
parsed: convert_nscolor_to_rgba(color),
|
||||||
|
authored: None
|
||||||
|
}
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
error!("stylo: got unexpected non-integer value for color presentation attribute");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error!("stylo: cannot handle longhand {:?} from presentation attribute", long);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
};
|
||||||
|
declarations.write().declarations.push((decl, Importance::Normal));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_CSSSupports2(property: *const nsACString, value: *const nsACString) -> bool {
|
pub extern "C" fn Servo_CSSSupports2(property: *const nsACString, value: *const nsACString) -> bool {
|
||||||
let property = unsafe { property.as_ref().unwrap().as_str_unchecked() };
|
let property = unsafe { property.as_ref().unwrap().as_str_unchecked() };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue