зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #17058 - stylo: Support remaning longhands (from Manishearth:stylo-randomprops); r=emilio
r=xidorn https://bugzilla.mozilla.org/show_bug.cgi?id=1367275 Source-Repo: https://github.com/servo/servo Source-Revision: 369d5cf1242632efeb56278e18a5ea25a3c933a5 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 97e668f065ac48f4ec15be64d14f1e021e1dd288
This commit is contained in:
Родитель
e4124cb8f6
Коммит
b61188e68e
|
@ -1133,6 +1133,14 @@ extern "C" {
|
|||
pub fn Gecko_nsStyleSVG_CopyDashArray(dst: *mut nsStyleSVG,
|
||||
src: *const nsStyleSVG);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_nsStyleSVG_SetContextPropertiesLength(svg: *mut nsStyleSVG,
|
||||
len: u32);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_nsStyleSVG_CopyContextProperties(dst: *mut nsStyleSVG,
|
||||
src: *const nsStyleSVG);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_NewURLValue(uri: ServoBundledURI) -> *mut URLValue;
|
||||
}
|
||||
|
@ -1307,6 +1315,11 @@ extern "C" {
|
|||
pres_context:
|
||||
RawGeckoPresContextBorrowed);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_nsStyleFont_FixupMinFontSize(font: *mut nsStyleFont,
|
||||
pres_context:
|
||||
RawGeckoPresContextBorrowed);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_GetBaseSize(lang: *mut nsIAtom) -> FontSizePrefs;
|
||||
}
|
||||
|
|
|
@ -806,6 +806,11 @@ pub mod root {
|
|||
4;
|
||||
pub const NS_STYLE_CONTEXT_PROPERTY_FILL: ::std::os::raw::c_uint = 1;
|
||||
pub const NS_STYLE_CONTEXT_PROPERTY_STROKE: ::std::os::raw::c_uint = 2;
|
||||
pub const NS_STYLE_WINDOW_SHADOW_NONE: ::std::os::raw::c_uint = 0;
|
||||
pub const NS_STYLE_WINDOW_SHADOW_DEFAULT: ::std::os::raw::c_uint = 1;
|
||||
pub const NS_STYLE_WINDOW_SHADOW_MENU: ::std::os::raw::c_uint = 2;
|
||||
pub const NS_STYLE_WINDOW_SHADOW_TOOLTIP: ::std::os::raw::c_uint = 3;
|
||||
pub const NS_STYLE_WINDOW_SHADOW_SHEET: ::std::os::raw::c_uint = 4;
|
||||
pub const NS_STYLE_DOMINANT_BASELINE_AUTO: ::std::os::raw::c_uint = 0;
|
||||
pub const NS_STYLE_DOMINANT_BASELINE_USE_SCRIPT: ::std::os::raw::c_uint =
|
||||
1;
|
||||
|
@ -2191,7 +2196,8 @@ pub mod root {
|
|||
#[repr(C)]
|
||||
#[derive(Debug, Copy)]
|
||||
pub struct FontVariation {
|
||||
pub _bindgen_opaque_blob: [u32; 2usize],
|
||||
pub mTag: u32,
|
||||
pub mValue: f32,
|
||||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout_FontVariation() {
|
||||
|
@ -2202,6 +2208,17 @@ pub mod root {
|
|||
concat ! (
|
||||
"Alignment of " , stringify ! ( FontVariation )
|
||||
));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const FontVariation ) ) . mTag as *
|
||||
const _ as usize } , 0usize , concat ! (
|
||||
"Alignment of field: " , stringify ! (
|
||||
FontVariation ) , "::" , stringify ! ( mTag ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const FontVariation ) ) . mValue as
|
||||
* const _ as usize } , 4usize , concat ! (
|
||||
"Alignment of field: " , stringify ! (
|
||||
FontVariation ) , "::" , stringify ! ( mValue )
|
||||
));
|
||||
}
|
||||
impl Clone for FontVariation {
|
||||
fn clone(&self) -> Self { *self }
|
||||
|
|
|
@ -806,6 +806,11 @@ pub mod root {
|
|||
4;
|
||||
pub const NS_STYLE_CONTEXT_PROPERTY_FILL: ::std::os::raw::c_uint = 1;
|
||||
pub const NS_STYLE_CONTEXT_PROPERTY_STROKE: ::std::os::raw::c_uint = 2;
|
||||
pub const NS_STYLE_WINDOW_SHADOW_NONE: ::std::os::raw::c_uint = 0;
|
||||
pub const NS_STYLE_WINDOW_SHADOW_DEFAULT: ::std::os::raw::c_uint = 1;
|
||||
pub const NS_STYLE_WINDOW_SHADOW_MENU: ::std::os::raw::c_uint = 2;
|
||||
pub const NS_STYLE_WINDOW_SHADOW_TOOLTIP: ::std::os::raw::c_uint = 3;
|
||||
pub const NS_STYLE_WINDOW_SHADOW_SHEET: ::std::os::raw::c_uint = 4;
|
||||
pub const NS_STYLE_DOMINANT_BASELINE_AUTO: ::std::os::raw::c_uint = 0;
|
||||
pub const NS_STYLE_DOMINANT_BASELINE_USE_SCRIPT: ::std::os::raw::c_uint =
|
||||
1;
|
||||
|
@ -2097,7 +2102,8 @@ pub mod root {
|
|||
#[repr(C)]
|
||||
#[derive(Debug, Copy)]
|
||||
pub struct FontVariation {
|
||||
pub _bindgen_opaque_blob: [u32; 2usize],
|
||||
pub mTag: u32,
|
||||
pub mValue: f32,
|
||||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout_FontVariation() {
|
||||
|
@ -2108,6 +2114,17 @@ pub mod root {
|
|||
concat ! (
|
||||
"Alignment of " , stringify ! ( FontVariation )
|
||||
));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const FontVariation ) ) . mTag as *
|
||||
const _ as usize } , 0usize , concat ! (
|
||||
"Alignment of field: " , stringify ! (
|
||||
FontVariation ) , "::" , stringify ! ( mTag ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const FontVariation ) ) . mValue as
|
||||
* const _ as usize } , 4usize , concat ! (
|
||||
"Alignment of field: " , stringify ! (
|
||||
FontVariation ) , "::" , stringify ! ( mValue )
|
||||
));
|
||||
}
|
||||
impl Clone for FontVariation {
|
||||
fn clone(&self) -> Self { *self }
|
||||
|
|
|
@ -17,6 +17,7 @@ use gecko_bindings::sugar::ns_css_value::ToNsCssValue;
|
|||
use gecko_bindings::sugar::refptr::{RefPtr, UniqueRefPtr};
|
||||
use shared_lock::{ToCssWithGuard, SharedRwLockReadGuard};
|
||||
use std::{fmt, str};
|
||||
use values::generics::FontSettings;
|
||||
|
||||
/// A @font-face rule
|
||||
pub type FontFaceRule = RefPtr<nsCSSFontFaceRule>;
|
||||
|
@ -36,8 +37,8 @@ impl ToNsCssValue for font_weight::T {
|
|||
impl ToNsCssValue for font_feature_settings::T {
|
||||
fn convert(self, nscssvalue: &mut nsCSSValue) {
|
||||
match self {
|
||||
font_feature_settings::T::Normal => nscssvalue.set_normal(),
|
||||
font_feature_settings::T::Tag(tags) => {
|
||||
FontSettings::Normal => nscssvalue.set_normal(),
|
||||
FontSettings::Tag(tags) => {
|
||||
nscssvalue.set_pair_list(tags.into_iter().map(|entry| {
|
||||
let mut feature = nsCSSValue::null();
|
||||
let mut raw = [0u8; 4];
|
||||
|
@ -45,7 +46,7 @@ impl ToNsCssValue for font_feature_settings::T {
|
|||
feature.set_string(str::from_utf8(&raw).unwrap());
|
||||
|
||||
let mut index = nsCSSValue::null();
|
||||
index.set_integer(entry.value as i32);
|
||||
index.set_integer(entry.value.0 as i32);
|
||||
|
||||
(feature, index)
|
||||
}))
|
||||
|
|
|
@ -1486,27 +1486,28 @@ fn static_assert() {
|
|||
font-synthesis -x-lang font-variant-alternates
|
||||
font-variant-east-asian font-variant-ligatures
|
||||
font-variant-numeric font-language-override
|
||||
font-feature-settings"""
|
||||
font-feature-settings font-variation-settings
|
||||
-moz-min-font-size-ratio"""
|
||||
%>
|
||||
<%self:impl_trait style_struct_name="Font"
|
||||
skip_longhands="${skip_font_longhands}"
|
||||
skip_additionals="*">
|
||||
|
||||
pub fn set_font_feature_settings(&mut self, v: longhands::font_feature_settings::computed_value::T) {
|
||||
use properties::longhands::font_feature_settings::computed_value::T;
|
||||
use values::generics::FontSettings;
|
||||
|
||||
let current_settings = &mut self.gecko.mFont.fontFeatureSettings;
|
||||
current_settings.clear_pod();
|
||||
|
||||
match v {
|
||||
T::Normal => unsafe { current_settings.set_len_pod(0) },
|
||||
FontSettings::Normal => (), // do nothing, length is already 0
|
||||
|
||||
T::Tag(feature_settings) => {
|
||||
FontSettings::Tag(feature_settings) => {
|
||||
unsafe { current_settings.set_len_pod(feature_settings.len() as u32) };
|
||||
|
||||
for (current, feature) in current_settings.iter_mut().zip(feature_settings) {
|
||||
current.mTag = feature.tag;
|
||||
current.mValue = feature.value;
|
||||
current.mValue = feature.value.0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1526,6 +1527,40 @@ fn static_assert() {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_font_variation_settings(&mut self, v: longhands::font_variation_settings::computed_value::T) {
|
||||
use values::generics::FontSettings;
|
||||
|
||||
let current_settings = &mut self.gecko.mFont.fontVariationSettings;
|
||||
current_settings.clear_pod();
|
||||
|
||||
match v {
|
||||
FontSettings::Normal => (), // do nothing, length is already 0
|
||||
|
||||
FontSettings::Tag(feature_settings) => {
|
||||
unsafe { current_settings.set_len_pod(feature_settings.len() as u32) };
|
||||
|
||||
for (current, feature) in current_settings.iter_mut().zip(feature_settings) {
|
||||
current.mTag = feature.tag;
|
||||
current.mValue = feature.value.0;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn copy_font_variation_settings_from(&mut self, other: &Self ) {
|
||||
let current_settings = &mut self.gecko.mFont.fontVariationSettings;
|
||||
let feature_settings = &other.gecko.mFont.fontVariationSettings;
|
||||
let settings_length = feature_settings.len() as u32;
|
||||
|
||||
current_settings.clear_pod();
|
||||
unsafe { current_settings.set_len_pod(settings_length) };
|
||||
|
||||
for (current, feature) in current_settings.iter_mut().zip(feature_settings.iter()) {
|
||||
current.mTag = feature.mTag;
|
||||
current.mValue = feature.mValue;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fixup_none_generic(&mut self, device: &Device) {
|
||||
unsafe {
|
||||
bindings::Gecko_nsStyleFont_FixupNoneGeneric(&mut self.gecko, &*device.pres_context)
|
||||
|
@ -1595,7 +1630,6 @@ fn static_assert() {
|
|||
// actual computed size, and the other of which (mFont.size) is the 'display
|
||||
// size' which takes font zooming into account. We don't handle font zooming yet.
|
||||
pub fn set_font_size(&mut self, v: longhands::font_size::computed_value::T) {
|
||||
self.gecko.mFont.size = v.0;
|
||||
self.gecko.mSize = v.0;
|
||||
self.gecko.mScriptUnconstrainedSize = v.0;
|
||||
}
|
||||
|
@ -1603,21 +1637,27 @@ fn static_assert() {
|
|||
/// Set font size, taking into account scriptminsize and scriptlevel
|
||||
/// Returns Some(size) if we have to recompute the script unconstrained size
|
||||
pub fn apply_font_size(&mut self, v: longhands::font_size::computed_value::T,
|
||||
parent: &Self) -> Option<Au> {
|
||||
parent: &Self,
|
||||
device: &Device) -> Option<Au> {
|
||||
let (adjusted_size, adjusted_unconstrained_size)
|
||||
= self.calculate_script_level_size(parent);
|
||||
// In this case, we have been unaffected by scriptminsize, ignore it
|
||||
if parent.gecko.mSize == parent.gecko.mScriptUnconstrainedSize &&
|
||||
adjusted_size == adjusted_unconstrained_size {
|
||||
self.set_font_size(v);
|
||||
self.fixup_font_min_size(device);
|
||||
None
|
||||
} else {
|
||||
self.gecko.mFont.size = v.0;
|
||||
self.gecko.mSize = v.0;
|
||||
self.fixup_font_min_size(device);
|
||||
Some(Au(parent.gecko.mScriptUnconstrainedSize))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fixup_font_min_size(&mut self, device: &Device) {
|
||||
unsafe { bindings::Gecko_nsStyleFont_FixupMinFontSize(&mut self.gecko, &*device.pres_context) }
|
||||
}
|
||||
|
||||
pub fn apply_unconstrained_font_size(&mut self, v: Au) {
|
||||
self.gecko.mScriptUnconstrainedSize = v.0;
|
||||
}
|
||||
|
@ -1726,7 +1766,8 @@ fn static_assert() {
|
|||
///
|
||||
/// Returns true if the inherited keyword size was actually used
|
||||
pub fn inherit_font_size_from(&mut self, parent: &Self,
|
||||
kw_inherited_size: Option<Au>) -> bool {
|
||||
kw_inherited_size: Option<Au>,
|
||||
device: &Device) -> bool {
|
||||
let (adjusted_size, adjusted_unconstrained_size)
|
||||
= self.calculate_script_level_size(parent);
|
||||
if adjusted_size.0 != parent.gecko.mSize ||
|
||||
|
@ -1745,23 +1786,23 @@ fn static_assert() {
|
|||
|
||||
// In the case that MathML has given us an adjusted size, apply it.
|
||||
// Keep track of the unconstrained adjusted size.
|
||||
self.gecko.mFont.size = adjusted_size.0;
|
||||
self.gecko.mSize = adjusted_size.0;
|
||||
self.gecko.mScriptUnconstrainedSize = adjusted_unconstrained_size.0;
|
||||
self.fixup_font_min_size(device);
|
||||
false
|
||||
} else if let Some(size) = kw_inherited_size {
|
||||
// Parent element was a keyword-derived size.
|
||||
self.gecko.mFont.size = size.0;
|
||||
self.gecko.mSize = size.0;
|
||||
// MathML constraints didn't apply here, so we can ignore this.
|
||||
self.gecko.mScriptUnconstrainedSize = size.0;
|
||||
self.fixup_font_min_size(device);
|
||||
true
|
||||
} else {
|
||||
// MathML isn't affecting us, and our parent element does not
|
||||
// have a keyword-derived size. Set things normally.
|
||||
self.gecko.mFont.size = parent.gecko.mFont.size;
|
||||
self.gecko.mSize = parent.gecko.mSize;
|
||||
self.gecko.mScriptUnconstrainedSize = parent.gecko.mScriptUnconstrainedSize;
|
||||
self.fixup_font_min_size(device);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -1864,6 +1905,21 @@ fn static_assert() {
|
|||
}
|
||||
|
||||
${impl_simple_copy('font_variant_numeric', 'mFont.variantNumeric')}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set__moz_min_font_size_ratio(&mut self, v: longhands::_moz_min_font_size_ratio::computed_value::T) {
|
||||
let percentage = if v.0 > 255. {
|
||||
255.
|
||||
} else if v.0 < 0. {
|
||||
0.
|
||||
} else {
|
||||
v.0
|
||||
};
|
||||
|
||||
self.gecko.mMinFontSizeRatio = percentage as u8;
|
||||
}
|
||||
|
||||
${impl_simple_copy('_moz_min_font_size_ratio', 'mMinFontSizeRatio')}
|
||||
</%self:impl_trait>
|
||||
|
||||
<%def name="impl_copy_animation_or_transition_value(type, ident, gecko_ffi_name)">
|
||||
|
@ -4003,7 +4059,7 @@ clip-path
|
|||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="InheritedSVG"
|
||||
skip_longhands="paint-order stroke-dasharray stroke-dashoffset stroke-width"
|
||||
skip_longhands="paint-order stroke-dasharray stroke-dashoffset stroke-width -moz-context-properties"
|
||||
skip_additionals="*">
|
||||
pub fn set_paint_order(&mut self, v: longhands::paint_order::computed_value::T) {
|
||||
use self::longhands::paint_order;
|
||||
|
@ -4111,6 +4167,34 @@ clip-path
|
|||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set__moz_context_properties<I>(&mut self, v: I)
|
||||
where I: IntoIterator<Item = longhands::_moz_context_properties::computed_value::single_value::T>,
|
||||
I::IntoIter: ExactSizeIterator
|
||||
{
|
||||
let v = v.into_iter();
|
||||
unsafe {
|
||||
bindings::Gecko_nsStyleSVG_SetContextPropertiesLength(&mut self.gecko, v.len() as u32);
|
||||
}
|
||||
|
||||
self.gecko.mContextPropsBits = 0;
|
||||
for (mut gecko, servo) in self.gecko.mContextProps.iter_mut().zip(v) {
|
||||
if servo.0 == atom!("fill") {
|
||||
self.gecko.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_FILL as u8;
|
||||
} else if servo.0 == atom!("stroke") {
|
||||
self.gecko.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_STROKE as u8;
|
||||
}
|
||||
unsafe { gecko.set_raw_from_addrefed::<structs::nsIAtom>(servo.0.into_addrefed()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn copy__moz_context_properties_from(&mut self, other: &Self) {
|
||||
unsafe {
|
||||
bindings::Gecko_nsStyleSVG_CopyContextProperties(&mut self.gecko, &other.gecko);
|
||||
}
|
||||
}
|
||||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="Color"
|
||||
|
|
|
@ -54,9 +54,8 @@ ${helpers.predefined_type("column-rule-color", "CSSColor",
|
|||
complex_color=True, need_clone=True,
|
||||
spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color")}
|
||||
|
||||
// It's not implemented in servo or gecko yet.
|
||||
${helpers.single_keyword("column-span", "none all",
|
||||
products="none", animation_value_type="none",
|
||||
products="gecko", animation_value_type="none",
|
||||
spec="https://drafts.csswg.org/css-multicol/#propdef-column-span")}
|
||||
|
||||
${helpers.single_keyword("column-rule-style",
|
||||
|
|
|
@ -925,10 +925,12 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
}
|
||||
% endif
|
||||
|
||||
let parent_unconstrained = context.mutate_style()
|
||||
.mutate_font()
|
||||
.apply_font_size(computed,
|
||||
parent);
|
||||
let parent_unconstrained = {
|
||||
let (style, device) = context.mutate_style_with_device();
|
||||
|
||||
style.mutate_font().apply_font_size(computed, parent, device)
|
||||
};
|
||||
|
||||
|
||||
if let Some(parent) = parent_unconstrained {
|
||||
let new_unconstrained = specified_value
|
||||
|
@ -946,13 +948,14 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
let kw_inherited_size = context.style().font_size_keyword.map(|(kw, ratio)| {
|
||||
SpecifiedValue::Keyword(kw, ratio).to_computed_value(context)
|
||||
});
|
||||
let used_kw = context.mutate_style().mutate_font()
|
||||
.inherit_font_size_from(parent, kw_inherited_size);
|
||||
let parent_kw = context.inherited_style.font_computation_data.font_size_keyword;
|
||||
let (style, device) = context.mutate_style_with_device();
|
||||
let used_kw = style.mutate_font()
|
||||
.inherit_font_size_from(parent, kw_inherited_size, device);
|
||||
if used_kw {
|
||||
context.mutate_style().font_size_keyword =
|
||||
context.inherited_style.font_computation_data.font_size_keyword;
|
||||
style.font_size_keyword = parent_kw;
|
||||
} else {
|
||||
context.mutate_style().font_size_keyword = None;
|
||||
style.font_size_keyword = None;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -961,9 +964,12 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
// compute to the same value and depends on the font
|
||||
let computed = longhands::font_size::get_initial_specified_value()
|
||||
.to_computed_value(context);
|
||||
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
|
||||
.set_font_size(computed);
|
||||
context.mutate_style().font_size_keyword = Some((Default::default(), 1.));
|
||||
let (style, _device) = context.mutate_style_with_device();
|
||||
style.mutate_font().set_font_size(computed);
|
||||
% if product == "gecko":
|
||||
style.mutate_font().fixup_font_min_size(_device);
|
||||
% endif
|
||||
style.font_size_keyword = Some((Default::default(), 1.));
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
|
@ -1774,6 +1780,7 @@ ${helpers.single_keyword_system("font-variant-position",
|
|||
use properties::longhands::system_font::SystemFont;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::generics::FontSettings;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum SpecifiedValue {
|
||||
|
@ -1785,120 +1792,18 @@ ${helpers.single_keyword_system("font-variant-position",
|
|||
<%self:simple_system_boilerplate name="font_feature_settings"></%self:simple_system_boilerplate>
|
||||
|
||||
pub mod computed_value {
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum T {
|
||||
Normal,
|
||||
Tag(Vec<FeatureTagValue>)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct FeatureTagValue {
|
||||
pub tag: u32,
|
||||
pub value: u32
|
||||
}
|
||||
|
||||
impl ToCss for T {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
T::Normal => dest.write_str("normal"),
|
||||
T::Tag(ref ftvs) => {
|
||||
let mut iter = ftvs.iter();
|
||||
// handle head element
|
||||
try!(iter.next().unwrap().to_css(dest));
|
||||
// handle tail, precede each with a delimiter
|
||||
for ftv in iter {
|
||||
try!(dest.write_str(", "));
|
||||
try!(ftv.to_css(dest));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for T {
|
||||
/// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(T::Normal);
|
||||
}
|
||||
input.parse_comma_separated(|i| FeatureTagValue::parse(context, i)).map(T::Tag)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for FeatureTagValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
use std::str;
|
||||
use byteorder::{WriteBytesExt, BigEndian};
|
||||
use cssparser::serialize_string;
|
||||
|
||||
let mut raw: Vec<u8> = vec!();
|
||||
raw.write_u32::<BigEndian>(self.tag).unwrap();
|
||||
serialize_string(str::from_utf8(&raw).unwrap_or_default(), dest)?;
|
||||
|
||||
match self.value {
|
||||
1 => Ok(()),
|
||||
0 => dest.write_str(" off"),
|
||||
x => write!(dest, " {}", x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for FeatureTagValue {
|
||||
/// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
|
||||
/// <string> [ on | off | <integer> ]
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
use std::io::Cursor;
|
||||
use byteorder::{ReadBytesExt, BigEndian};
|
||||
|
||||
let tag = try!(input.expect_string());
|
||||
|
||||
// allowed strings of length 4 containing chars: <U+20, U+7E>
|
||||
if tag.len() != 4 ||
|
||||
tag.chars().any(|c| c < ' ' || c > '~')
|
||||
{
|
||||
return Err(())
|
||||
}
|
||||
|
||||
let mut raw = Cursor::new(tag.as_bytes());
|
||||
let u_tag = raw.read_u32::<BigEndian>().unwrap();
|
||||
|
||||
if let Ok(value) = input.try(|input| input.expect_integer()) {
|
||||
// handle integer, throw if it is negative
|
||||
if value >= 0 {
|
||||
Ok(FeatureTagValue { tag: u_tag, value: value as u32 })
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
} else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
|
||||
// on is an alias for '1'
|
||||
Ok(FeatureTagValue { tag: u_tag, value: 1 })
|
||||
} else if let Ok(_) = input.try(|input| input.expect_ident_matching("off")) {
|
||||
// off is an alias for '0'
|
||||
Ok(FeatureTagValue { tag: u_tag, value: 0 })
|
||||
} else {
|
||||
// empty value is an alias for '1'
|
||||
Ok(FeatureTagValue { tag: u_tag, value: 1 })
|
||||
}
|
||||
}
|
||||
}
|
||||
use values::generics::{FontSettings, FontSettingTagInt};
|
||||
pub type T = FontSettings<FontSettingTagInt>;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T::Normal
|
||||
FontSettings::Normal
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||
SpecifiedValue::Value(computed_value::T::Normal)
|
||||
SpecifiedValue::Value(FontSettings::Normal)
|
||||
}
|
||||
|
||||
/// normal | <feature-tag-value>#
|
||||
|
@ -1907,6 +1812,40 @@ ${helpers.single_keyword_system("font-variant-position",
|
|||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
<%
|
||||
# This spec link is too long to fit elsewhere
|
||||
variation_spec = """\
|
||||
https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-the-font-variation-settings-property\
|
||||
"""
|
||||
%>
|
||||
<%helpers:longhand name="font-variation-settings" products="gecko" animation_value_type="none"
|
||||
spec="${variation_spec}">
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
use values::generics::FontSettings;
|
||||
|
||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||
|
||||
pub type SpecifiedValue = computed_value::T;
|
||||
|
||||
no_viewport_percentage!(SpecifiedValue);
|
||||
|
||||
|
||||
pub mod computed_value {
|
||||
use values::generics::{FontSettings, FontSettingTagFloat};
|
||||
pub type T = FontSettings<FontSettingTagFloat>;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
FontSettings::Normal
|
||||
}
|
||||
|
||||
/// normal | <feature-tag-value>#
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
computed_value::T::parse(context, input)
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
<%helpers:longhand name="font-language-override" products="gecko" animation_value_type="none"
|
||||
extra_prefixes="moz" boxed="True"
|
||||
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override">
|
||||
|
@ -2453,3 +2392,11 @@ ${helpers.single_keyword("-moz-osx-font-smoothing",
|
|||
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth)",
|
||||
animation_value_type="none",
|
||||
need_clone=True)}
|
||||
|
||||
${helpers.predefined_type("-moz-min-font-size-ratio",
|
||||
"Percentage",
|
||||
"computed::Percentage::hundred()",
|
||||
animation_value_type="none",
|
||||
products="gecko",
|
||||
internal=True,
|
||||
spec="Nonstandard (Internal-only)")}
|
||||
|
|
|
@ -268,3 +268,28 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
|
|||
impl ComputedValueAsSpecified for SpecifiedValue { }
|
||||
</%helpers:longhand>
|
||||
|
||||
<%helpers:vector_longhand name="-moz-context-properties"
|
||||
animation_value_type="none"
|
||||
products="gecko"
|
||||
spec="Nonstandard (Internal-only)"
|
||||
internal="True"
|
||||
allow_empty="True">
|
||||
use values::CustomIdent;
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
|
||||
no_viewport_percentage!(SpecifiedValue);
|
||||
|
||||
impl ComputedValueAsSpecified for SpecifiedValue { }
|
||||
|
||||
pub type SpecifiedValue = CustomIdent;
|
||||
|
||||
pub mod computed_value {
|
||||
pub type T = super::SpecifiedValue;
|
||||
}
|
||||
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
let i = input.expect_ident()?;
|
||||
CustomIdent::from_ident(i, &["all", "none", "auto"])
|
||||
}
|
||||
</%helpers:vector_longhand>
|
||||
|
|
|
@ -31,6 +31,13 @@ ${helpers.single_keyword("-moz-window-dragging", "default drag no-drag", product
|
|||
animation_value_type="none",
|
||||
spec="None (Nonstandard Firefox-only property)")}
|
||||
|
||||
${helpers.single_keyword("-moz-window-shadow", "none default menu tooltip sheet", products="gecko",
|
||||
gecko_ffi_name="mWindowShadow",
|
||||
gecko_constant_prefix="NS_STYLE_WINDOW_SHADOW",
|
||||
animation_value_type="none",
|
||||
internal=True,
|
||||
spec="None (Nonstandard internal property)")}
|
||||
|
||||
<%helpers:longhand name="-moz-force-broken-image-icon"
|
||||
products="gecko"
|
||||
animation_value_type="none"
|
||||
|
|
|
@ -607,6 +607,7 @@ impl LonghandId {
|
|||
LonghandId::TransitionProperty |
|
||||
LonghandId::XLang |
|
||||
LonghandId::MozScriptLevel |
|
||||
LonghandId::MozMinFontSizeRatio |
|
||||
% endif
|
||||
LonghandId::FontSize |
|
||||
LonghandId::FontFamily |
|
||||
|
@ -1524,6 +1525,7 @@ pub mod style_structs {
|
|||
use super::longhands;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use logical_geometry::WritingMode;
|
||||
use media_queries::Device;
|
||||
|
||||
% for style_struct in data.active_style_structs():
|
||||
% if style_struct.name == "Font":
|
||||
|
@ -1634,14 +1636,15 @@ pub mod style_structs {
|
|||
|
||||
/// (Servo does not handle MathML, so this just calls copy_font_size_from)
|
||||
pub fn inherit_font_size_from(&mut self, parent: &Self,
|
||||
_: Option<Au>) -> bool {
|
||||
_: Option<Au>, _: &Device) -> bool {
|
||||
self.copy_font_size_from(parent);
|
||||
false
|
||||
}
|
||||
/// (Servo does not handle MathML, so this just calls set_font_size)
|
||||
pub fn apply_font_size(&mut self,
|
||||
v: longhands::font_size::computed_value::T,
|
||||
_: &Self) -> Option<Au> {
|
||||
_: &Self,
|
||||
_: &Device) -> Option<Au> {
|
||||
self.set_font_size(v);
|
||||
None
|
||||
}
|
||||
|
@ -2628,17 +2631,6 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
continue
|
||||
}
|
||||
|
||||
// The computed value of some properties depends on the
|
||||
// (sometimes computed) value of *other* properties.
|
||||
//
|
||||
// So we classify properties into "early" and "other", such that
|
||||
// the only dependencies can be from "other" to "early".
|
||||
//
|
||||
// We iterate applicable_declarations twice, first cascading
|
||||
// "early" properties then "other".
|
||||
//
|
||||
// Unfortunately, it’s not easy to check that this
|
||||
// classification is correct.
|
||||
if
|
||||
% if category_to_cascade_now == "early":
|
||||
!
|
||||
|
@ -2718,6 +2710,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
|||
// scriptlevel changes.
|
||||
} else if seen.contains(LonghandId::XLang) ||
|
||||
seen.contains(LonghandId::MozScriptLevel) ||
|
||||
seen.contains(LonghandId::MozMinFontSizeRatio) ||
|
||||
font_family.is_some() {
|
||||
let discriminant = LonghandId::FontSize as usize;
|
||||
let size = PropertyDeclaration::CSSWideKeyword(
|
||||
|
|
|
@ -106,6 +106,8 @@ impl<'a> Context<'a> {
|
|||
pub fn style(&self) -> &StyleBuilder { &self.style }
|
||||
/// A mutable reference to the current style.
|
||||
pub fn mutate_style(&mut self) -> &mut StyleBuilder<'a> { &mut self.style }
|
||||
/// Get a mutable reference to the current style as well as the device
|
||||
pub fn mutate_style_with_device(&mut self) -> (&mut StyleBuilder<'a>, &Device) { (&mut self.style, &self.device) }
|
||||
}
|
||||
|
||||
/// An iterator over a slice of computed values
|
||||
|
|
|
@ -10,7 +10,7 @@ use cssparser::Parser;
|
|||
use euclid::size::Size2D;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::fmt;
|
||||
use style_traits::{HasViewportPercentage, ToCss};
|
||||
use style_traits::{HasViewportPercentage, OneOrMoreCommaSeparated, ToCss};
|
||||
use super::CustomIdent;
|
||||
|
||||
pub use self::basic_shape::serialize_radius_values;
|
||||
|
@ -163,3 +163,152 @@ impl ToCss for CounterStyleOrNone {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A settings tag, defined by a four-character tag and a setting value
|
||||
///
|
||||
/// For font-feature-settings, this is a tag and an integer,
|
||||
/// for font-variation-settings this is a tag and a float
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct FontSettingTag<T> {
|
||||
/// A four-character tag, packed into a u32 (one byte per character)
|
||||
pub tag: u32,
|
||||
/// The value
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
impl<T> OneOrMoreCommaSeparated for FontSettingTag<T> {}
|
||||
|
||||
impl<T: ToCss> ToCss for FontSettingTag<T> {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
use byteorder::{WriteBytesExt, BigEndian};
|
||||
use cssparser::serialize_string;
|
||||
use std::str;
|
||||
|
||||
let mut raw: Vec<u8> = vec!();
|
||||
raw.write_u32::<BigEndian>(self.tag).unwrap();
|
||||
serialize_string(str::from_utf8(&raw).unwrap_or_default(), dest)?;
|
||||
|
||||
self.value.to_css(dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Parse> Parse for FontSettingTag<T> {
|
||||
/// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
|
||||
/// https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-
|
||||
/// settings-control-the-font-variation-settings-property
|
||||
/// <string> [ on | off | <integer> ]
|
||||
/// <string> <number>
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
use byteorder::{ReadBytesExt, BigEndian};
|
||||
use std::io::Cursor;
|
||||
|
||||
let tag = try!(input.expect_string());
|
||||
|
||||
// allowed strings of length 4 containing chars: <U+20, U+7E>
|
||||
if tag.len() != 4 ||
|
||||
tag.chars().any(|c| c < ' ' || c > '~')
|
||||
{
|
||||
return Err(())
|
||||
}
|
||||
|
||||
let mut raw = Cursor::new(tag.as_bytes());
|
||||
let u_tag = raw.read_u32::<BigEndian>().unwrap();
|
||||
|
||||
Ok(FontSettingTag { tag: u_tag, value: T::parse(context, input)? })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A font settings value for font-variation-settings or font-feature-settings
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum FontSettings<T> {
|
||||
/// No settings (default)
|
||||
Normal,
|
||||
/// Set of settings
|
||||
Tag(Vec<FontSettingTag<T>>)
|
||||
}
|
||||
|
||||
impl<T: ToCss> ToCss for FontSettings<T> {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
FontSettings::Normal => dest.write_str("normal"),
|
||||
FontSettings::Tag(ref ftvs) => ftvs.to_css(dest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Parse> Parse for FontSettings<T> {
|
||||
/// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(FontSettings::Normal);
|
||||
}
|
||||
Vec::parse(context, input).map(FontSettings::Tag)
|
||||
}
|
||||
}
|
||||
|
||||
/// An integer that can also parse "on" and "off",
|
||||
/// for font-feature-settings
|
||||
///
|
||||
/// Do not use this type anywhere except within FontSettings
|
||||
/// because it serializes with the preceding space
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct FontSettingTagInt(pub u32);
|
||||
/// A number value to be used for font-variation-settings
|
||||
///
|
||||
/// Do not use this type anywhere except within FontSettings
|
||||
/// because it serializes with the preceding space
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct FontSettingTagFloat(pub f32);
|
||||
|
||||
impl ToCss for FontSettingTagInt {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match self.0 {
|
||||
1 => Ok(()),
|
||||
0 => dest.write_str(" off"),
|
||||
x => write!(dest, " {}", x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for FontSettingTagInt {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if let Ok(value) = input.try(|input| input.expect_integer()) {
|
||||
// handle integer, throw if it is negative
|
||||
if value >= 0 {
|
||||
Ok(FontSettingTagInt(value as u32))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
} else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
|
||||
// on is an alias for '1'
|
||||
Ok(FontSettingTagInt(1))
|
||||
} else if let Ok(_) = input.try(|input| input.expect_ident_matching("off")) {
|
||||
// off is an alias for '0'
|
||||
Ok(FontSettingTagInt(0))
|
||||
} else {
|
||||
// empty value is an alias for '1'
|
||||
Ok(FontSettingTagInt(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Parse for FontSettingTagFloat {
|
||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
input.expect_number().map(FontSettingTagFloat)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for FontSettingTagFloat {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
dest.write_str(" ")?;
|
||||
self.0.to_css(dest)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -734,6 +734,12 @@ impl Percentage {
|
|||
pub fn parse_non_negative(input: &mut Parser) -> Result<Self, ()> {
|
||||
Self::parse_with_clamping_mode(input, AllowedNumericType::NonNegative)
|
||||
}
|
||||
|
||||
/// 100%
|
||||
#[inline]
|
||||
pub fn hundred() -> Self {
|
||||
Percentage(1.)
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Percentage {
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
use parsing::parse;
|
||||
use style::properties::longhands::{font_feature_settings, font_weight};
|
||||
use style::properties::longhands::font_feature_settings::SpecifiedValue;
|
||||
use style::properties::longhands::font_feature_settings::computed_value;
|
||||
use style::properties::longhands::font_feature_settings::computed_value::FeatureTagValue;
|
||||
use style::values::generics::{FontSettings, FontSettingTag, FontSettingTagInt};
|
||||
use style_traits::ToCss;
|
||||
|
||||
#[test]
|
||||
|
@ -15,7 +14,7 @@ fn font_feature_settings_should_parse_properly() {
|
|||
use std::io::Cursor;
|
||||
|
||||
let normal = parse_longhand!(font_feature_settings, "normal");
|
||||
let normal_computed = SpecifiedValue::Value(computed_value::T::Normal);
|
||||
let normal_computed = SpecifiedValue::Value(FontSettings::Normal);
|
||||
assert_eq!(normal, normal_computed);
|
||||
|
||||
let mut a_d_bytes = Cursor::new(b"abcd");
|
||||
|
@ -25,33 +24,33 @@ fn font_feature_settings_should_parse_properly() {
|
|||
let efgh = e_h_bytes.read_u32::<BigEndian>().unwrap();
|
||||
|
||||
let on = parse_longhand!(font_feature_settings, "\"abcd\" on");
|
||||
let on_computed = SpecifiedValue::Value(computed_value::T::Tag(vec![
|
||||
FeatureTagValue { tag: abcd, value: 1 }
|
||||
let on_computed = SpecifiedValue::Value(FontSettings::Tag(vec![
|
||||
FontSettingTag { tag: abcd, value: FontSettingTagInt(1) }
|
||||
]));
|
||||
assert_eq!(on, on_computed);
|
||||
|
||||
let off = parse_longhand!(font_feature_settings, "\"abcd\" off");
|
||||
let off_computed = SpecifiedValue::Value(computed_value::T::Tag(vec![
|
||||
FeatureTagValue { tag: abcd, value: 0 }
|
||||
let off_computed = SpecifiedValue::Value(FontSettings::Tag(vec![
|
||||
FontSettingTag { tag: abcd, value: FontSettingTagInt(0) }
|
||||
]));
|
||||
assert_eq!(off, off_computed);
|
||||
|
||||
let no_value = parse_longhand!(font_feature_settings, "\"abcd\"");
|
||||
let no_value_computed = SpecifiedValue::Value(computed_value::T::Tag(vec![
|
||||
FeatureTagValue { tag: abcd, value: 1 }
|
||||
let no_value_computed = SpecifiedValue::Value(FontSettings::Tag(vec![
|
||||
FontSettingTag { tag: abcd, value: FontSettingTagInt(1) }
|
||||
]));
|
||||
assert_eq!(no_value, no_value_computed);
|
||||
|
||||
let pos_integer = parse_longhand!(font_feature_settings, "\"abcd\" 100");
|
||||
let pos_integer_computed = SpecifiedValue::Value(computed_value::T::Tag(vec![
|
||||
FeatureTagValue { tag: abcd, value: 100 }
|
||||
let pos_integer_computed = SpecifiedValue::Value(FontSettings::Tag(vec![
|
||||
FontSettingTag { tag: abcd, value: FontSettingTagInt(100) }
|
||||
]));
|
||||
assert_eq!(pos_integer, pos_integer_computed);
|
||||
|
||||
let multiple = parse_longhand!(font_feature_settings, "\"abcd\" off, \"efgh\"");
|
||||
let multiple_computed = SpecifiedValue::Value(computed_value::T::Tag(vec![
|
||||
FeatureTagValue { tag: abcd, value: 0 },
|
||||
FeatureTagValue { tag: efgh, value: 1 }
|
||||
let multiple_computed = SpecifiedValue::Value(FontSettings::Tag(vec![
|
||||
FontSettingTag { tag: abcd, value: FontSettingTagInt(0) },
|
||||
FontSettingTag { tag: efgh, value: FontSettingTagInt(1) }
|
||||
]));
|
||||
assert_eq!(multiple, multiple_computed);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче