mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +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
|
||||
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
|
||||
|
||||
// Step 3
|
||||
|
@ -153,8 +153,8 @@ pub fn parse_legacy_font_size(mut input: &str) -> Option<&'static str> {
|
|||
|
||||
// Steps 6, 7, 8
|
||||
let mut value = match read_numbers(input_chars) {
|
||||
(Some(v), _) => v,
|
||||
(None, _) => return None,
|
||||
(Some(v), _) if v >= 0 => v,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
// Step 9
|
||||
|
@ -165,18 +165,5 @@ pub fn parse_legacy_font_size(mut input: &str) -> Option<&'static str> {
|
|||
}
|
||||
|
||||
// Steps 10, 11, 12
|
||||
Some(match value {
|
||||
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))
|
||||
Some(specified::Length::from_font_size_int(value as u8))
|
||||
}
|
||||
|
|
|
@ -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_ClassOrClassList;
|
||||
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::structs;
|
||||
use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode};
|
||||
|
@ -42,6 +43,7 @@ use parking_lot::RwLock;
|
|||
use parser::ParserContextExtraData;
|
||||
use properties::{ComputedValues, parse_style_attribute};
|
||||
use properties::PropertyDeclarationBlock;
|
||||
use rule_tree::CascadeLevel as ServoCascadeLevel;
|
||||
use selector_parser::{ElementExt, Snapshot};
|
||||
use selectors::Element;
|
||||
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
||||
|
@ -385,7 +387,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -483,10 +485,16 @@ impl<'le> PartialEq 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>,
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_GetServoDeclarationBlock(element: RawGeckoElementBorrowed)
|
||||
pub fn Gecko_GetStyleAttrDeclarationBlock(element: RawGeckoElementBorrowed)
|
||||
-> RawServoDeclarationBlockStrongBorrowedOrNull;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_GetHTMLPresentationAttrDeclarationBlock(element: RawGeckoElementBorrowed)
|
||||
-> RawServoDeclarationBlockStrongBorrowedOrNull;
|
||||
}
|
||||
extern "C" {
|
||||
|
@ -1391,6 +1395,13 @@ extern "C" {
|
|||
property:
|
||||
nsCSSPropertyID);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_DeclarationBlock_AddPresValue(declarations:
|
||||
RawServoDeclarationBlockBorrowed,
|
||||
property: nsCSSPropertyID,
|
||||
css_value:
|
||||
nsCSSValueBorrowedMut);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_CSSSupports2(name: *const nsACString_internal,
|
||||
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_SetCalc;
|
||||
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::ops::Index;
|
||||
use std::slice;
|
||||
|
@ -34,6 +34,28 @@ impl nsCSSValue {
|
|||
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
|
||||
/// release builds.
|
||||
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.
|
||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<NoCalcLength, ()> {
|
||||
match_ignore_ascii_case! { unit,
|
||||
|
@ -429,6 +443,11 @@ impl Length {
|
|||
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]
|
||||
fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<Length, ()> {
|
||||
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::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
|
||||
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::RawGeckoAnimationValueListBorrowedMut;
|
||||
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, ()))
|
||||
}
|
||||
|
||||
#[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]
|
||||
pub extern "C" fn Servo_CSSSupports2(property: *const nsACString, value: *const nsACString) -> bool {
|
||||
let property = unsafe { property.as_ref().unwrap().as_str_unchecked() };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue