--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -497,17 +497,17 @@ mod bindings {
.disable_name_namespacing()
.with_codegen_config(CodegenConfig {
functions: true,
..CodegenConfig::nothing()
})
.header(add_include("mozilla/ServoBindings.h"))
.hide_type("nsACString_internal")
.hide_type("nsAString_internal")
- .raw_line("pub use nsstring::{nsACString, nsAString};")
+ .raw_line("pub use nsstring::{nsACString, nsAString, nsString};")
.raw_line("type nsACString_internal = nsACString;")
.raw_line("type nsAString_internal = nsAString;")
.whitelisted_function("Servo_.*")
.whitelisted_function("Gecko_.*");
let structs_types = [
"mozilla::css::URLValue",
"RawGeckoDocument",
"RawGeckoElement",
@@ -579,16 +579,17 @@ mod bindings {
"nsStyleUIReset",
"nsStyleUnion",
"nsStyleUnit",
"nsStyleUserInterface",
"nsStyleVariables",
"nsStyleVisibility",
"nsStyleXUL",
"nsTimingFunction",
+ "nscolor",
"nscoord",
"nsresult",
"Loader",
"ServoStyleSheet",
"EffectCompositor_CascadeLevel",
"RawServoAnimationValueBorrowedListBorrowed",
];
struct ArrayType {
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -1,11 +1,11 @@
/* automatically generated by rust-bindgen */
-pub use nsstring::{nsACString, nsAString};
+pub use nsstring::{nsACString, nsAString, nsString};
type nsACString_internal = nsACString;
type nsAString_internal = nsAString;
use gecko_bindings::structs::mozilla::css::URLValue;
use gecko_bindings::structs::RawGeckoDocument;
use gecko_bindings::structs::RawGeckoElement;
use gecko_bindings::structs::RawGeckoKeyframeList;
use gecko_bindings::structs::RawGeckoNode;
use gecko_bindings::structs::RawGeckoAnimationValueList;
@@ -154,16 +154,17 @@ unsafe impl Send for nsStyleVariables {}
unsafe impl Sync for nsStyleVariables {}
use gecko_bindings::structs::nsStyleVisibility;
unsafe impl Send for nsStyleVisibility {}
unsafe impl Sync for nsStyleVisibility {}
use gecko_bindings::structs::nsStyleXUL;
unsafe impl Send for nsStyleXUL {}
unsafe impl Sync for nsStyleXUL {}
use gecko_bindings::structs::nsTimingFunction;
+use gecko_bindings::structs::nscolor;
use gecko_bindings::structs::nscoord;
use gecko_bindings::structs::nsresult;
use gecko_bindings::structs::Loader;
use gecko_bindings::structs::ServoStyleSheet;
use gecko_bindings::structs::EffectCompositor_CascadeLevel;
use gecko_bindings::structs::RawServoAnimationValueBorrowedListBorrowed;
pub type nsTArrayBorrowed_uintptr_t<'a> = &'a mut ::gecko_bindings::structs::nsTArray<usize>;
pub type ServoComputedValuesStrong = ::gecko_bindings::sugar::ownership::Strong<ServoComputedValues>;
@@ -849,16 +850,24 @@ extern "C" {
extern "C" {
pub fn Gecko_ReleaseCSSValueSharedListArbitraryThread(aPtr:
*mut nsCSSValueSharedList);
}
extern "C" {
pub fn Gecko_PropertyId_IsPrefEnabled(id: nsCSSPropertyID) -> bool;
}
extern "C" {
+ pub fn Gecko_nsStyleFont_SetLang(font: *mut nsStyleFont,
+ atom: *mut nsIAtom);
+}
+extern "C" {
+ pub fn Gecko_nsStyleFont_CopyLangFrom(aFont: *mut nsStyleFont,
+ aSource: *const nsStyleFont);
+}
+extern "C" {
pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature;
}
extern "C" {
pub fn Gecko_Construct_Default_nsStyleFont(ptr: *mut nsStyleFont,
pres_context:
RawGeckoPresContextBorrowed);
}
extern "C" {
@@ -1435,21 +1444,77 @@ extern "C" {
}
extern "C" {
pub fn Servo_DeclarationBlock_RemovePropertyById(declarations:
RawServoDeclarationBlockBorrowed,
property:
nsCSSPropertyID);
}
extern "C" {
- pub fn Servo_DeclarationBlock_AddPresValue(declarations:
+ pub fn Servo_DeclarationBlock_PropertyIsSet(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID)
+ -> bool;
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_SetIdentStringValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property:
+ nsCSSPropertyID,
+ value: *mut nsIAtom);
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_SetKeywordValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID,
+ value: i32);
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_SetIntValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID,
+ value: i32);
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_SetPixelValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID,
+ value: f32);
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_SetPercentValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID,
+ value: f32);
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_SetAutoValue(declarations:
RawServoDeclarationBlockBorrowed,
- property: nsCSSPropertyID,
- css_value:
- nsCSSValueBorrowedMut);
+ property: nsCSSPropertyID);
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_SetCurrentColor(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID);
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_SetColorValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID,
+ value: nscolor);
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_SetFontFamily(declarations:
+ RawServoDeclarationBlockBorrowed,
+ value:
+ *const nsAString_internal);
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_SetTextDecorationColorOverride(declarations:
+ RawServoDeclarationBlockBorrowed);
}
extern "C" {
pub fn Servo_CSSSupports2(name: *const nsACString_internal,
value: *const nsACString_internal) -> bool;
}
extern "C" {
pub fn Servo_CSSSupports(cond: *const nsACString_internal) -> bool;
}
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -62,17 +62,17 @@ class Keyword(object):
if product == "gecko":
return self.gecko_values()
elif product == "servo":
return self.servo_values()
else:
raise Exception("Bad product: " + product)
def gecko_constant(self, value):
- moz_stripped = value.replace("-moz-", '') if self.gecko_strip_moz_prefix else value
+ moz_stripped = value.replace("-moz-", '') if self.gecko_strip_moz_prefix else value.replace("-moz-", 'moz-')
mapped = self.consts_map.get(value)
if self.gecko_enum_prefix:
parts = moz_stripped.split('-')
parts = mapped if mapped else [p.title() for p in parts]
return self.gecko_enum_prefix + "::" + "".join(parts)
else:
suffix = mapped if mapped else moz_stripped.replace("-", "_")
return self.gecko_constant_prefix + "_" + suffix.upper()
--- a/servo/components/style/properties/declaration_block.rs
+++ b/servo/components/style/properties/declaration_block.rs
@@ -35,16 +35,23 @@ impl Importance {
pub fn important(self) -> bool {
match self {
Importance::Normal => false,
Importance::Important => true,
}
}
}
+impl Default for Importance {
+ #[inline]
+ fn default() -> Self {
+ Importance::Normal
+ }
+}
+
/// Overridden declarations are skipped.
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct PropertyDeclarationBlock {
/// The group of declarations, along with their importance.
///
/// Only deduplicated declarations appear here.
#[cfg_attr(feature = "servo", ignore_heap_size_of = "#7038")]
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -28,16 +28,18 @@ use gecko_bindings::bindings::Gecko_Copy
use gecko_bindings::bindings::Gecko_CopyListStyleTypeFrom;
use gecko_bindings::bindings::Gecko_EnsureImageLayersLength;
use gecko_bindings::bindings::Gecko_FontFamilyList_AppendGeneric;
use gecko_bindings::bindings::Gecko_FontFamilyList_AppendNamed;
use gecko_bindings::bindings::Gecko_FontFamilyList_Clear;
use gecko_bindings::bindings::Gecko_SetCursorArrayLength;
use gecko_bindings::bindings::Gecko_SetCursorImage;
use gecko_bindings::bindings::Gecko_NewCSSShadowArray;
+use gecko_bindings::bindings::Gecko_nsStyleFont_SetLang;
+use gecko_bindings::bindings::Gecko_nsStyleFont_CopyLangFrom;
use gecko_bindings::bindings::Gecko_SetListStyleImage;
use gecko_bindings::bindings::Gecko_SetListStyleImageNone;
use gecko_bindings::bindings::Gecko_SetListStyleType;
use gecko_bindings::bindings::Gecko_SetNullImageValue;
use gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
use gecko_bindings::bindings::{Gecko_ResetFilters, Gecko_CopyFiltersFrom};
use gecko_bindings::bindings::RawGeckoPresContextBorrowed;
use gecko_bindings::structs;
@@ -48,17 +50,17 @@ use gecko::values::convert_nscolor_to_rg
use gecko::values::convert_rgba_to_nscolor;
use gecko::values::GeckoStyleCoordConvertible;
use gecko::values::round_border_to_device_pixels;
use logical_geometry::WritingMode;
use properties::longhands;
use properties::{DeclaredValue, Importance, LonghandId};
use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId};
use std::fmt::{self, Debug};
-use std::mem::{transmute, zeroed};
+use std::mem::{forget, transmute, zeroed};
use std::ptr;
use std::sync::Arc;
use std::cmp;
use values::computed::ToComputedValue;
use values::{Either, Auto};
use computed_values::border_style;
pub mod style_structs {
@@ -228,18 +230,16 @@ pub struct ${style_struct.gecko_struct_n
def get_gecko_property(ffi_name, self_param = "self"):
if "mBorderColor" in ffi_name:
return ffi_name.replace("mBorderColor",
"unsafe { *%s.gecko.__bindgen_anon_1.mBorderColor.as_ref() }"
% self_param)
return "%s.gecko.%s" % (self_param, ffi_name)
def set_gecko_property(ffi_name, expr):
- if ffi_name == "__LIST_STYLE_TYPE__":
- return "unsafe { Gecko_SetListStyleType(&mut self.gecko, %s as u32); }" % expr
if "mBorderColor" in ffi_name:
ffi_name = ffi_name.replace("mBorderColor",
"*self.gecko.__bindgen_anon_1.mBorderColor.as_mut()")
return "unsafe { %s = %s };" % (ffi_name, expr)
return "self.gecko.%s = %s;" % (ffi_name, expr)
%>
<%def name="impl_keyword_setter(ident, gecko_ffi_name, keyword, cast_type='u8')">
@@ -1116,17 +1116,17 @@ fn static_assert() {
% endfor
pub fn outline_has_nonzero_width(&self) -> bool {
self.gecko.mActualOutlineWidth != 0
}
</%self:impl_trait>
<%self:impl_trait style_struct_name="Font"
- skip_longhands="font-family font-size font-size-adjust font-weight font-synthesis"
+ skip_longhands="font-family font-size font-size-adjust font-weight font-synthesis -x-lang"
skip_additionals="*">
pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) {
use properties::longhands::font_family::computed_value::FontFamily;
use gecko_bindings::structs::FontFamilyType;
let list = &mut self.gecko.mFont.fontlist;
unsafe { Gecko_FontFamilyList_Clear(list); }
@@ -1225,16 +1225,31 @@ fn static_assert() {
use values::specified::Number;
match self.gecko.mFont.sizeAdjust {
-1.0 => T::None,
_ => T::Number(Number(self.gecko.mFont.sizeAdjust)),
}
}
+ #[allow(non_snake_case)]
+ pub fn set__x_lang(&mut self, v: longhands::_x_lang::computed_value::T) {
+ let ptr = v.0.as_ptr();
+ forget(v);
+ unsafe {
+ Gecko_nsStyleFont_SetLang(&mut self.gecko, ptr);
+ }
+ }
+
+ #[allow(non_snake_case)]
+ pub fn copy__x_lang_from(&mut self, other: &Self) {
+ unsafe {
+ Gecko_nsStyleFont_CopyLangFrom(&mut self.gecko, &other.gecko);
+ }
+ }
</%self:impl_trait>
<%def name="impl_copy_animation_value(ident, gecko_ffi_name)">
#[allow(non_snake_case)]
pub fn copy_animation_${ident}_from(&mut self, other: &Self) {
unsafe { self.gecko.mAnimations.ensure_len(other.gecko.mAnimations.len()) };
let count = other.gecko.mAnimation${gecko_ffi_name}Count;
@@ -2149,18 +2164,42 @@ fn static_assert() {
}
}
}
pub fn copy_list_style_image_from(&mut self, other: &Self) {
unsafe { Gecko_CopyListStyleImageFrom(&mut self.gecko, &other.gecko); }
}
- ${impl_keyword_setter("list_style_type", "__LIST_STYLE_TYPE__",
- data.longhands_by_name["list-style-type"].keyword)}
+ pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) {
+ use properties::longhands::list_style_type::computed_value::T as Keyword;
+ <%
+ keyword = data.longhands_by_name["list-style-type"].keyword
+ # The first four are @counter-styles
+ # The rest have special fallback behavior
+ special = """upper-roman lower-roman upper-alpha lower-alpha
+ japanese-informal japanese-formal korean-hangul-formal korean-hanja-informal
+ korean-hanja-formal simp-chinese-informal simp-chinese-formal
+ trad-chinese-informal trad-chinese-formal""".split()
+ %>
+ let result = match v {
+ % for value in keyword.values_for('gecko'):
+ % if value in special:
+ // Special keywords are implemented as @counter-styles
+ // and need to be manually set as strings
+ Keyword::${to_rust_ident(value)} => structs::${keyword.gecko_constant("none")},
+ % else:
+ Keyword::${to_rust_ident(value)} =>
+ structs::${keyword.gecko_constant(value)},
+ % endif
+ % endfor
+ };
+ unsafe { Gecko_SetListStyleType(&mut self.gecko, result as u32); }
+ }
+
pub fn copy_list_style_type_from(&mut self, other: &Self) {
unsafe {
Gecko_CopyListStyleTypeFrom(&mut self.gecko, &other.gecko);
}
}
pub fn set_quotes(&mut self, other: longhands::quotes::computed_value::T) {
@@ -2203,16 +2242,25 @@ fn static_assert() {
}
}
}
${impl_simple_copy('_moz_image_region', 'mImageRegion')}
</%self:impl_trait>
+<%self:impl_trait style_struct_name="Table" skip_longhands="-x-span">
+ #[allow(non_snake_case)]
+ pub fn set__x_span(&mut self, v: longhands::_x_span::computed_value::T) {
+ self.gecko.mSpan = v.0
+ }
+
+ ${impl_simple_copy('_x_span', 'mSpan')}
+</%self:impl_trait>
+
<%self:impl_trait style_struct_name="Effects"
skip_longhands="box-shadow filter">
pub fn set_box_shadow(&mut self, v: longhands::box_shadow::computed_value::T) {
self.gecko.mBoxShadow.replace_with_new(v.0.len() as u32);
for (servo, gecko_shadow) in v.0.into_iter()
.zip(self.gecko.mBoxShadow.iter_mut()) {
@@ -2374,17 +2422,17 @@ fn static_assert() {
</%self:impl_trait>
<%self:impl_trait style_struct_name="InheritedText"
skip_longhands="text-align text-emphasis-style text-shadow line-height letter-spacing word-spacing
-webkit-text-stroke-width text-emphasis-position -moz-tab-size">
<% text_align_keyword = Keyword("text-align", "start end left right center justify -moz-center -moz-left " +
- "-moz-right match-parent") %>
+ "-moz-right match-parent char") %>
${impl_keyword('text_align', 'mTextAlign', text_align_keyword, need_clone=False)}
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);
for (servo, gecko_shadow) in v.0.into_iter()
.zip(self.gecko.mTextShadow.iter_mut()) {
@@ -2574,16 +2622,19 @@ fn static_assert() {
bits |= structs::NS_STYLE_TEXT_DECORATION_LINE_OVERLINE as u8;
}
if v.contains(longhands::text_decoration_line::LINE_THROUGH) {
bits |= structs::NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH as u8;
}
if v.contains(longhands::text_decoration_line::BLINK) {
bits |= structs::NS_STYLE_TEXT_DECORATION_LINE_BLINK as u8;
}
+ if v.contains(longhands::text_decoration_line::COLOR_OVERRIDE) {
+ bits |= structs::NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL as u8;
+ }
self.gecko.mTextDecorationLine = bits;
}
${impl_simple_copy('text_decoration_line', 'mTextDecorationLine')}
fn clear_overflow_sides_if_string(&mut self) {
use gecko_bindings::structs::nsStyleTextOverflowSide;
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -371,30 +371,67 @@
<%call expr="single_keyword_computed(name, values, vector, **kwargs)">
use values::computed::ComputedValueAsSpecified;
use values::HasViewportPercentage;
impl ComputedValueAsSpecified for SpecifiedValue {}
no_viewport_percentage!(SpecifiedValue);
</%call>
</%def>
-<%def name="single_keyword_computed(name, values, vector=False, extra_specified=None, **kwargs)">
+<%def name="gecko_keyword_conversion(keyword, values=None, type='SpecifiedValue')">
+ <%
+ if not values:
+ values = keyword.values_for(product)
+ %>
+ #[cfg(feature = "gecko")]
+ impl ${type} {
+ /// Obtain a specified value from a Gecko keyword value
+ ///
+ /// Intended for use with presentation attributes, not style structs
+ pub fn from_gecko_keyword(kw: u32) -> Self {
+ use gecko_bindings::structs;
+ % if keyword.gecko_enum_prefix:
+ % for value in values:
+ // We can't match on enum values if we're matching on a u32
+ const ${to_rust_ident(value).upper()}: u32
+ = structs::${keyword.gecko_enum_prefix}::${to_camel_case(value)} as u32;
+ % endfor
+ match kw {
+ % for value in values:
+ ${to_rust_ident(value).upper()} => ${type}::${to_rust_ident(value)},
+ % endfor
+ x => panic!("Found unexpected value in style struct for ${keyword.name} property: {:?}", x),
+ }
+ % else:
+ match kw {
+ % for value in values:
+ structs::${keyword.gecko_constant(value)} => ${type}::${to_rust_ident(value)},
+ % endfor
+ x => panic!("Found unexpected value in style struct for ${keyword.name} property: {:?}", x),
+ }
+ % endif
+ }
+ }
+</%def>
+
+<%def name="single_keyword_computed(name, values, vector=False,
+ extra_specified=None, needs_conversion=False, **kwargs)">
<%
keyword_kwargs = {a: kwargs.pop(a, None) for a in [
'gecko_constant_prefix', 'gecko_enum_prefix',
'extra_gecko_values', 'extra_servo_values',
'custom_consts', 'gecko_inexhaustive',
]}
%>
- <%def name="inner_body()">
+ <%def name="inner_body(keyword, extra_specified=None, needs_conversion=False)">
% if extra_specified:
use style_traits::ToCss;
define_css_keyword_enum! { SpecifiedValue:
- % for value in data.longhands_by_name[name].keyword.values_for(product) + extra_specified.split():
+ % for value in keyword.values_for(product) + extra_specified.split():
"${value}" => ${to_rust_ident(value)},
% endfor
}
% else:
pub use self::computed_value::T as SpecifiedValue;
% endif
pub mod computed_value {
use style_traits::ToCss;
@@ -419,25 +456,35 @@
}
impl Parse for SpecifiedValue {
#[inline]
fn parse(_context: &ParserContext, input: &mut Parser)
-> Result<SpecifiedValue, ()> {
SpecifiedValue::parse(input)
}
}
+
+ % if needs_conversion:
+ <%
+ conversion_values = keyword.values_for(product)
+ if extra_specified:
+ conversion_values += extra_specified.split()
+ %>
+ ${gecko_keyword_conversion(keyword, values=conversion_values)}
+ % endif
</%def>
% if vector:
<%call expr="vector_longhand(name, keyword=Keyword(name, values, **keyword_kwargs), **kwargs)">
- ${inner_body()}
+ ${inner_body(Keyword(name, values, **keyword_kwargs))}
${caller.body()}
</%call>
% else:
<%call expr="longhand(name, keyword=Keyword(name, values, **keyword_kwargs), **kwargs)">
- ${inner_body()}
+ ${inner_body(Keyword(name, values, **keyword_kwargs),
+ extra_specified=extra_specified, needs_conversion=needs_conversion)}
${caller.body()}
</%call>
% endif
</%def>
<%def name="shorthand(name, sub_properties, experimental=False, **kwargs)">
<%
shorthand = data.declare_shorthand(name, sub_properties.split(), experimental=experimental,
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -1,14 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
<%namespace name="helpers" file="/helpers.mako.rs" />
-<% from data import Method, PHYSICAL_SIDES, ALL_SIDES, maybe_moz_logical_alias %>
+<% from data import Keyword, Method, PHYSICAL_SIDES, ALL_SIDES, maybe_moz_logical_alias %>
<% data.new_style_struct("Border", inherited=False,
additional_methods=[Method("border_" + side + "_has_nonzero_width",
"bool") for side in ["top", "right", "bottom", "left"]]) %>
<%
def maybe_logical_spec(side, kind):
if side[1]: # if it is logical
return "https://drafts.csswg.org/css-logical-props/#propdef-border-%s-%s" % (side[0], kind)
@@ -27,16 +27,19 @@
${helpers.predefined_type("border-%s-style" % side[0], "BorderStyle",
"specified::BorderStyle::none",
need_clone=True,
alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-style"),
spec=maybe_logical_spec(side, "style"),
animatable=False, logical = side[1])}
% endfor
+${helpers.gecko_keyword_conversion(Keyword('border-style',
+ "none solid double dotted dashed hidden groove ridge inset outset"),
+ type="::values::specified::BorderStyle")}
% for side in ALL_SIDES:
<%helpers:longhand name="border-${side[0]}-width" animatable="True" logical="${side[1]}"
alias="${maybe_moz_logical_alias(product, side, '-moz-border-%s-width')}"
spec="${maybe_logical_spec(side, 'width')}">
use app_units::Au;
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -1,14 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
<%namespace name="helpers" file="/helpers.mako.rs" />
-<% from data import Keyword, Method, to_rust_ident %>
+<% from data import Keyword, Method, to_rust_ident, to_camel_case%>
<% data.new_style_struct("Box",
inherited=False,
gecko_name="Display") %>
// TODO(SimonSapin): don't parse `inline-table`, since we don't support it
<%helpers:longhand name="display"
need_clone="True"
@@ -88,16 +88,19 @@
_cacheable: &mut bool,
_error_reporter: &mut StdBox<ParseErrorReporter + Send>) {
longhands::_servo_display_for_hypothetical_box::derive_from_display(context);
longhands::_servo_text_decorations_in_effect::derive_from_display(context);
longhands::_servo_under_display_none::derive_from_display(context);
}
% endif
+ ${helpers.gecko_keyword_conversion(Keyword('display', ' '.join(values),
+ gecko_enum_prefix='StyleDisplay'))}
+
</%helpers:longhand>
${helpers.single_keyword("-moz-top-layer", "none top",
gecko_constant_prefix="NS_STYLE_TOP_LAYER",
gecko_ffi_name="mTopLayer", need_clone=True,
products="gecko", animatable=False, internal=True,
spec="Internal (not web-exposed)")}
@@ -141,16 +144,17 @@
}
}
</%helpers:single_keyword_computed>
<%helpers:single_keyword_computed name="float"
values="none left right"
// https://drafts.csswg.org/css-logical-props/#float-clear
extra_specified="inline-start inline-end"
+ needs_conversion="True"
animatable="False"
need_clone="True"
gecko_enum_prefix="StyleFloat"
gecko_inexhaustive="True"
gecko_ffi_name="mFloat"
spec="https://drafts.csswg.org/css-box/#propdef-float">
use values::HasViewportPercentage;
no_viewport_percentage!(SpecifiedValue);
@@ -185,16 +189,17 @@
}
}
</%helpers:single_keyword_computed>
<%helpers:single_keyword_computed name="clear"
values="none left right both"
// https://drafts.csswg.org/css-logical-props/#float-clear
extra_specified="inline-start inline-end"
+ needs_conversion="True"
animatable="False"
gecko_enum_prefix="StyleClear"
gecko_ffi_name="mBreakType"
spec="https://www.w3.org/TR/CSS2/visuren.html#flow-control">
use values::HasViewportPercentage;
no_viewport_percentage!(SpecifiedValue);
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
@@ -251,16 +256,18 @@
use values::HasViewportPercentage;
<% vertical_align = data.longhands_by_name["vertical-align"] %>
<% vertical_align.keyword = Keyword("vertical-align",
"baseline sub super top text-top middle bottom text-bottom",
extra_gecko_values="middle-with-baseline") %>
<% vertical_align_keywords = vertical_align.keyword.values_for(product) %>
+ ${helpers.gecko_keyword_conversion(vertical_align.keyword)}
+
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedValue::LengthOrPercentage(ref length) => length.has_viewport_percentage(),
_ => false
}
}
}
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -14,17 +14,17 @@
use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified;
pub use self::computed_value::T as SpecifiedValue;
impl ComputedValueAsSpecified for SpecifiedValue {}
no_viewport_percentage!(SpecifiedValue);
pub mod computed_value {
- use cssparser::CssStringWriter;
+ use cssparser::{CssStringWriter, Parser};
use std::fmt::{self, Write};
use Atom;
use style_traits::ToCss;
pub use self::FontFamily as SingleComputedValue;
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub enum FontFamily {
@@ -68,16 +68,63 @@
"sans-serif" => return FontFamily::Generic(atom!("sans-serif")),
"cursive" => return FontFamily::Generic(atom!("cursive")),
"fantasy" => return FontFamily::Generic(atom!("fantasy")),
"monospace" => return FontFamily::Generic(atom!("monospace")),
_ => {}
}
FontFamily::FamilyName(FamilyName(input))
}
+
+ /// Parse a font-family value
+ pub fn parse(input: &mut Parser) -> Result<Self, ()> {
+ if let Ok(value) = input.try(|input| input.expect_string()) {
+ return Ok(FontFamily::FamilyName(FamilyName(Atom::from(&*value))))
+ }
+ let first_ident = try!(input.expect_ident());
+
+ // FIXME(bholley): The fast thing to do here would be to look up the
+ // string (as lowercase) in the static atoms table. We don't have an
+ // API to do that yet though, so we do the simple thing for now.
+ let mut css_wide_keyword = false;
+ match_ignore_ascii_case! { first_ident,
+ "serif" => return Ok(FontFamily::Generic(atom!("serif"))),
+ "sans-serif" => return Ok(FontFamily::Generic(atom!("sans-serif"))),
+ "cursive" => return Ok(FontFamily::Generic(atom!("cursive"))),
+ "fantasy" => return Ok(FontFamily::Generic(atom!("fantasy"))),
+ "monospace" => return Ok(FontFamily::Generic(atom!("monospace"))),
+
+ // https://drafts.csswg.org/css-fonts/#propdef-font-family
+ // "Font family names that happen to be the same as a keyword value
+ // (`inherit`, `serif`, `sans-serif`, `monospace`, `fantasy`, and `cursive`)
+ // must be quoted to prevent confusion with the keywords with the same names.
+ // The keywords ‘initial’ and ‘default’ are reserved for future use
+ // and must also be quoted when used as font names.
+ // UAs must not consider these keywords as matching the <family-name> type."
+ "inherit" => css_wide_keyword = true,
+ "initial" => css_wide_keyword = true,
+ "unset" => css_wide_keyword = true,
+ "default" => css_wide_keyword = true,
+ _ => {}
+ }
+
+ let mut value = first_ident.into_owned();
+ // These keywords are not allowed by themselves.
+ // The only way this value can be valid with with another keyword.
+ if css_wide_keyword {
+ let ident = input.expect_ident()?;
+ value.push_str(" ");
+ value.push_str(&ident);
+ }
+ while let Ok(ident) = input.try(|input| input.expect_ident()) {
+ value.push_str(" ");
+ value.push_str(&ident);
+ }
+ Ok(FontFamily::FamilyName(FamilyName(Atom::from(value))))
+ }
}
impl ToCss for FamilyName {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
dest.write_char('"')?;
write!(CssStringWriter::new(dest), "{}", self.0)?;
dest.write_char('"')
}
@@ -114,85 +161,37 @@
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T(vec![FontFamily::Generic(atom!("serif"))])
}
/// <family-name>#
/// <family-name> = <string> | [ <ident>+ ]
/// TODO: <generic-family>
- pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
- Vec::<FontFamily>::parse(context, input).map(SpecifiedValue)
+ pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
+ SpecifiedValue::parse(input)
}
- impl Parse for Vec<FontFamily> {
- fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
- input.parse_comma_separated(|input| FontFamily::parse(context, input))
+ impl SpecifiedValue {
+ pub fn parse(input: &mut Parser) -> Result<Self, ()> {
+ input.parse_comma_separated(|input| FontFamily::parse(input)).map(SpecifiedValue)
}
}
/// `FamilyName::parse` is based on `FontFamily::parse` and not the other way around
/// because we want the former to exclude generic family keywords.
impl Parse for FamilyName {
- fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
- match FontFamily::parse(context, input) {
+ fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
+ match FontFamily::parse(input) {
Ok(FontFamily::FamilyName(name)) => Ok(name),
Ok(FontFamily::Generic(_)) |
Err(()) => Err(())
}
}
}
-
- impl Parse for FontFamily {
- fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
- if let Ok(value) = input.try(|input| input.expect_string()) {
- return Ok(FontFamily::FamilyName(FamilyName(Atom::from(&*value))))
- }
- let first_ident = try!(input.expect_ident());
-
- // FIXME(bholley): The fast thing to do here would be to look up the
- // string (as lowercase) in the static atoms table. We don't have an
- // API to do that yet though, so we do the simple thing for now.
- let mut css_wide_keyword = false;
- match_ignore_ascii_case! { first_ident,
- "serif" => return Ok(FontFamily::Generic(atom!("serif"))),
- "sans-serif" => return Ok(FontFamily::Generic(atom!("sans-serif"))),
- "cursive" => return Ok(FontFamily::Generic(atom!("cursive"))),
- "fantasy" => return Ok(FontFamily::Generic(atom!("fantasy"))),
- "monospace" => return Ok(FontFamily::Generic(atom!("monospace"))),
-
- // https://drafts.csswg.org/css-fonts/#propdef-font-family
- // "Font family names that happen to be the same as a keyword value
- // (‘inherit’, ‘serif’, ‘sans-serif’, ‘monospace’, ‘fantasy’, and ‘cursive’)
- // must be quoted to prevent confusion with the keywords with the same names.
- // The keywords ‘initial’ and ‘default’ are reserved for future use
- // and must also be quoted when used as font names.
- // UAs must not consider these keywords as matching the <family-name> type."
- "inherit" => css_wide_keyword = true,
- "initial" => css_wide_keyword = true,
- "unset" => css_wide_keyword = true,
- "default" => css_wide_keyword = true,
- _ => {}
- }
-
- let mut value = first_ident.into_owned();
- // These keywords are not allowed by themselves.
- // The only way this value can be valid with with another keyword.
- if css_wide_keyword {
- let ident = input.expect_ident()?;
- value.push_str(" ");
- value.push_str(&ident);
- }
- while let Ok(ident) = input.try(|input| input.expect_ident()) {
- value.push_str(" ");
- value.push_str(&ident);
- }
- Ok(FontFamily::FamilyName(FamilyName(Atom::from(value))))
- }
- }
</%helpers:longhand>
${helpers.single_keyword("font-style",
"normal italic oblique",
gecko_constant_prefix="NS_FONT_STYLE",
gecko_ffi_name="mFont.style",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-style",
@@ -757,8 +756,45 @@
Ok(SpecifiedValue::Normal)
} else {
input.expect_string().map(|cow| {
SpecifiedValue::Override(cow.into_owned())
})
}
}
</%helpers:longhand>
+
+<%helpers:longhand name="-x-lang" products="gecko" animatable="False" internal="True"
+ spec="Internal (not web-exposed)"
+ internal="True">
+ use values::HasViewportPercentage;
+ use values::computed::ComputedValueAsSpecified;
+ pub use self::computed_value::T as SpecifiedValue;
+
+ impl ComputedValueAsSpecified for SpecifiedValue {}
+ no_viewport_percentage!(SpecifiedValue);
+
+ pub mod computed_value {
+ use Atom;
+ use std::fmt;
+ use style_traits::ToCss;
+
+ impl ToCss for T {
+ fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
+ Ok(())
+ }
+ }
+
+ #[derive(Clone, Debug, PartialEq)]
+ #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+ pub struct T(pub Atom);
+ }
+
+ #[inline]
+ pub fn get_initial_value() -> computed_value::T {
+ computed_value::T(atom!(""))
+ }
+
+ pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
+ debug_assert!(false, "Should be set directly by presentation attributes only.");
+ Err(())
+ }
+</%helpers:longhand>
--- a/servo/components/style/properties/longhand/inherited_table.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_table.mako.rs
@@ -11,16 +11,17 @@
animatable=False,
spec="https://drafts.csswg.org/css-tables/#propdef-border-collapse")}
${helpers.single_keyword("empty-cells", "show hide",
gecko_constant_prefix="NS_STYLE_TABLE_EMPTY_CELLS",
animatable=False,
spec="https://drafts.csswg.org/css-tables/#propdef-empty-cells")}
${helpers.single_keyword("caption-side", "top bottom",
extra_gecko_values="right left top-outside bottom-outside",
+ needs_conversion="True",
animatable=False,
spec="https://drafts.csswg.org/css-tables/#propdef-caption-side")}
<%helpers:longhand name="border-spacing" animatable="False" boxed="True"
spec="https://drafts.csswg.org/css-tables/#propdef-border-spacing">
use app_units::Au;
use std::fmt;
use style_traits::ToCss;
--- a/servo/components/style/properties/longhand/inherited_text.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_text.mako.rs
@@ -1,14 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
<%namespace name="helpers" file="/helpers.mako.rs" />
-
+<% from data import Keyword %>
<% data.new_style_struct("InheritedText", inherited=True, gecko_name="Text") %>
<%helpers:longhand name="line-height" animatable="True"
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height">
use std::fmt;
use style_traits::ToCss;
use values::{CSSFloat, HasViewportPercentage};
@@ -246,25 +246,30 @@
servo_center("-servo-center") => 6,
servo_left("-servo-left") => 7,
servo_right("-servo-right") => 8,
% else:
_moz_center("-moz-center") => 6,
_moz_left("-moz-left") => 7,
_moz_right("-moz-right") => 8,
match_parent("match-parent") => 9,
+ char("char") => 10,
% endif
}
}
#[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))}
</%helpers:longhand>
// FIXME: This prop should be animatable.
<%helpers:longhand name="letter-spacing" animatable="False"
spec="https://drafts.csswg.org/css-text/#propdef-letter-spacing">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
@@ -510,16 +515,17 @@
let derived = derive(context);
context.mutate_style().mutate_inheritedtext().set__servo_text_decorations_in_effect(derived);
}
</%helpers:longhand>
<%helpers:single_keyword_computed name="white-space"
values="normal pre nowrap pre-wrap pre-line"
gecko_constant_prefix="NS_STYLE_WHITESPACE"
+ needs_conversion="True"
animatable="False"
spec="https://drafts.csswg.org/css-text/#propdef-white-space">
use values::computed::ComputedValueAsSpecified;
use values::HasViewportPercentage;
impl ComputedValueAsSpecified for SpecifiedValue {}
no_viewport_percentage!(SpecifiedValue);
impl SpecifiedValue {
--- a/servo/components/style/properties/longhand/list.mako.rs
+++ b/servo/components/style/properties/longhand/list.mako.rs
@@ -11,25 +11,34 @@
// TODO(pcwalton): Implement the full set of counter styles per CSS-COUNTER-STYLES [1] 6.1:
//
// decimal-leading-zero, armenian, upper-armenian, lower-armenian, georgian, lower-roman,
// upper-roman
//
// TODO(bholley): Missing quite a few gecko properties here as well.
//
+// In gecko, {upper,lower}-{roman,alpha} are implemented as @counter-styles in the
+// UA, however they can also be set from pres attrs. When @counter-style is supported
+// we may need to look into this and handle these differently.
+//
// [1]: http://dev.w3.org/csswg/css-counter-styles/
${helpers.single_keyword("list-style-type", """
- disc none circle square decimal disclosure-open disclosure-closed
+ disc none circle square decimal disclosure-open disclosure-closed lower-alpha upper-alpha
""", extra_servo_values="""arabic-indic bengali cambodian cjk-decimal devanagari
gujarati gurmukhi kannada khmer lao malayalam mongolian
myanmar oriya persian telugu thai tibetan cjk-earthly-branch
cjk-heavenly-stem lower-greek hiragana hiragana-iroha katakana
- katakana-iroha lower-alpha upper-alpha""",
+ katakana-iroha""",
+ extra_gecko_values="""japanese-informal japanese-formal korean-hangul-formal
+ korean-hanja-formal korean-hanja-informal simp-chinese-informal simp-chinese-formal
+ trad-chinese-informal trad-chinese-formal ethiopic-numeric upper-roman lower-roman
+ """,
gecko_constant_prefix="NS_STYLE_LIST_STYLE",
+ needs_conversion="True",
animatable=False,
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type")}
${helpers.predefined_type("list-style-image", "UrlOrNone", "Either::Second(None_)",
animatable=False,
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image")}
<%helpers:longhand name="quotes" animatable="False"
--- a/servo/components/style/properties/longhand/pointing.mako.rs
+++ b/servo/components/style/properties/longhand/pointing.mako.rs
@@ -154,17 +154,17 @@
gecko_enum_prefix="StyleUserInput",
gecko_inexhaustive=True,
animatable=False,
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-input)")}
${helpers.single_keyword("-moz-user-modify", "read-only read-write write-only",
products="gecko", gecko_ffi_name="mUserModify",
gecko_enum_prefix="StyleUserModify",
- gecko_inexhaustive=True,
+ needs_conversion=True,
animatable=False,
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-modify)")}
${helpers.single_keyword("-moz-user-focus",
"none ignore normal select-after select-before select-menu select-same select-all",
products="gecko", gecko_ffi_name="mUserFocus",
gecko_enum_prefix="StyleUserFocus",
gecko_inexhaustive=True,
--- a/servo/components/style/properties/longhand/table.mako.rs
+++ b/servo/components/style/properties/longhand/table.mako.rs
@@ -4,8 +4,44 @@
<%namespace name="helpers" file="/helpers.mako.rs" />
<% data.new_style_struct("Table", inherited=False) %>
${helpers.single_keyword("table-layout", "auto fixed",
gecko_ffi_name="mLayoutStrategy", animatable=False,
spec="https://drafts.csswg.org/css-tables/#propdef-table-layout")}
+
+<%helpers:longhand name="-x-span" products="gecko"
+ spec="Internal-only (for `<col span>` pres attr)"
+ animatable="False"
+ internal="True">
+ use values::HasViewportPercentage;
+ use values::computed::ComputedValueAsSpecified;
+
+ impl ComputedValueAsSpecified for SpecifiedValue {}
+ no_viewport_percentage!(SpecifiedValue);
+ pub type SpecifiedValue = computed_value::T;
+ pub mod computed_value {
+ use std::fmt;
+ use style_traits::ToCss;
+
+ #[derive(PartialEq, Clone, Copy, Debug)]
+ #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+ pub struct T(pub i32);
+
+ impl ToCss for T {
+ fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
+ Ok(())
+ }
+ }
+ }
+
+ #[inline]
+ pub fn get_initial_value() -> computed_value::T {
+ computed_value::T(1)
+ }
+
+ // never parse it, only set via presentation attribute
+ fn parse(_: &ParserContext, _: &mut Parser) -> Result<SpecifiedValue, ()> {
+ Err(())
+ }
+</%helpers:longhand>
--- a/servo/components/style/properties/longhand/text.mako.rs
+++ b/servo/components/style/properties/longhand/text.mako.rs
@@ -117,16 +117,26 @@
bitflags! {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub flags SpecifiedValue: u8 {
const NONE = 0,
const OVERLINE = 0x01,
const UNDERLINE = 0x02,
const LINE_THROUGH = 0x04,
const BLINK = 0x08,
+ % if product == "gecko":
+ /// Only set by presentation attributes
+ ///
+ /// Setting this will mean that text-decorations use the color
+ /// specified by `color` in quirks mode.
+ ///
+ /// For example, this gives <a href=foo><font color="red">text</font></a>
+ /// a red text decoration
+ const COLOR_OVERRIDE = 0x10,
+ % endif
}
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
let mut has_any = false;
macro_rules! write_value {
($line:ident => $css:expr) => {
--- a/servo/components/style/properties/shorthand/font.mako.rs
+++ b/servo/components/style/properties/shorthand/font.mako.rs
@@ -7,20 +7,19 @@
<%helpers:shorthand name="font" sub_properties="font-style font-variant font-weight font-stretch
font-size line-height font-family
${'font-size-adjust' if product == 'gecko' else ''}
${'font-kerning' if product == 'gecko' else ''}
${'font-variant-caps' if product == 'gecko' else ''}
${'font-variant-position' if product == 'gecko' else ''}
${'font-language-override' if product == 'none' else ''}"
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
- use parser::Parse;
use properties::longhands::{font_style, font_variant, font_weight, font_stretch};
- use properties::longhands::{font_size, line_height, font_family};
- use properties::longhands::font_family::computed_value::FontFamily;
+ use properties::longhands::{font_size, line_height};
+ use properties::longhands::font_family::SpecifiedValue as FontFamily;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
let mut nb_normals = 0;
let mut style = None;
let mut variant = None;
let mut weight = None;
let mut stretch = None;
let size;
@@ -66,25 +65,25 @@
if size.is_none() || (count(&style) + count(&weight) + count(&variant) + count(&stretch) + nb_normals) > 4 {
return Err(())
}
let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
Some(try!(line_height::parse(context, input)))
} else {
None
};
- let family = Vec::<FontFamily>::parse(context, input)?;
+ let family = FontFamily::parse(input)?;
Ok(Longhands {
font_style: style,
font_variant: variant,
font_weight: weight,
font_stretch: stretch,
font_size: size,
line_height: line_height,
- font_family: Some(font_family::SpecifiedValue(family)),
+ font_family: Some(family),
% if product == "gecko":
font_size_adjust: None,
font_kerning: None,
font_variant_caps: None,
font_variant_position: None,
% endif
% if product == "none":
font_language_override: None,
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -363,16 +363,23 @@ pub enum Length {
///
/// https://drafts.csswg.org/css-values/#calc-notation
///
/// TODO(emilio): We have more `Calc` variants around, we should only use
/// one.
Calc(Box<CalcLengthOrPercentage>, AllowedNumericType),
}
+impl From<NoCalcLength> for Length {
+ #[inline]
+ fn from(len: NoCalcLength) -> Self {
+ Length::NoCalc(len)
+ }
+}
+
impl HasViewportPercentage for Length {
fn has_viewport_percentage(&self) -> bool {
match *self {
Length::NoCalc(ref inner) => inner.has_viewport_percentage(),
Length::Calc(ref calc, _) => calc.has_viewport_percentage(),
}
}
}
@@ -933,16 +940,30 @@ impl From<Length> for LengthOrPercentage
fn from(len: Length) -> LengthOrPercentage {
match len {
Length::NoCalc(l) => LengthOrPercentage::Length(l),
Length::Calc(l, _) => LengthOrPercentage::Calc(l),
}
}
}
+impl From<NoCalcLength> for LengthOrPercentage {
+ #[inline]
+ fn from(len: NoCalcLength) -> Self {
+ LengthOrPercentage::Length(len)
+ }
+}
+
+impl From<Percentage> for LengthOrPercentage {
+ #[inline]
+ fn from(pc: Percentage) -> Self {
+ LengthOrPercentage::Percentage(pc)
+ }
+}
+
impl HasViewportPercentage for LengthOrPercentage {
fn has_viewport_percentage(&self) -> bool {
match *self {
LengthOrPercentage::Length(ref length) => length.has_viewport_percentage(),
LengthOrPercentage::Calc(ref calc) => calc.has_viewport_percentage(),
_ => false
}
}
@@ -1038,16 +1059,31 @@ impl Parse for LengthOrPercentage {
#[allow(missing_docs)]
pub enum LengthOrPercentageOrAuto {
Length(NoCalcLength),
Percentage(Percentage),
Auto,
Calc(Box<CalcLengthOrPercentage>),
}
+
+impl From<NoCalcLength> for LengthOrPercentageOrAuto {
+ #[inline]
+ fn from(len: NoCalcLength) -> Self {
+ LengthOrPercentageOrAuto::Length(len)
+ }
+}
+
+impl From<Percentage> for LengthOrPercentageOrAuto {
+ #[inline]
+ fn from(pc: Percentage) -> Self {
+ LengthOrPercentageOrAuto::Percentage(pc)
+ }
+}
+
impl HasViewportPercentage for LengthOrPercentageOrAuto {
fn has_viewport_percentage(&self) -> bool {
match *self {
LengthOrPercentageOrAuto::Length(ref length) => length.has_viewport_percentage(),
LengthOrPercentageOrAuto::Calc(ref calc) => calc.has_viewport_percentage(),
_ => false
}
}
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -31,17 +31,17 @@ use style::gecko::wrapper::DUMMY_BASE_UR
use style::gecko::wrapper::GeckoElement;
use style::gecko_bindings::bindings;
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
use style::gecko_bindings::bindings::{RawServoStyleRuleBorrowed, RawServoStyleRuleStrong};
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
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, nsCSSValueBorrowedMut, nsAString};
+use style::gecko_bindings::bindings::{nsACString, nsAString};
use style::gecko_bindings::bindings::Gecko_AnimationAppendKeyframe;
use style::gecko_bindings::bindings::RawGeckoAnimationValueListBorrowedMut;
use style::gecko_bindings::bindings::RawGeckoElementBorrowed;
use style::gecko_bindings::bindings::RawGeckoKeyframeListBorrowedMut;
use style::gecko_bindings::bindings::RawGeckoPresContextBorrowed;
use style::gecko_bindings::bindings::RawServoAnimationValueBorrowed;
use style::gecko_bindings::bindings::RawServoAnimationValueStrong;
use style::gecko_bindings::bindings::RawServoImportRuleBorrowed;
@@ -947,69 +947,287 @@ pub extern "C" fn Servo_DeclarationBlock
}
#[no_mangle]
pub extern "C" fn Servo_DeclarationBlock_RemovePropertyById(declarations: RawServoDeclarationBlockBorrowed,
property: nsCSSPropertyID) {
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,
- _ => {
- warn!("stylo: unknown presentation property with id {:?}", property);
- return
+macro_rules! get_longhand_from_id {
+ ($id:expr, $retval:expr) => {
+ match PropertyId::from_nscsspropertyid($id) {
+ Ok(PropertyId::Longhand(long)) => long,
+ _ => {
+ error!("stylo: unknown presentation property with id {:?}", $id);
+ return $retval
+ }
}
};
- 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 {
- warn!("stylo: got unexpected non-integer value for font-size presentation attribute");
+ ($id:expr) => {
+ get_longhand_from_id!($id, ())
+ }
+}
+
+macro_rules! match_wrap_declared {
+ ($longhand:ident, $($property:ident => $inner:expr,)*) => (
+ match $longhand {
+ $(
+ LonghandId::$property => PropertyDeclaration::$property(DeclaredValue::Value($inner)),
+ )*
+ _ => {
+ error!("stylo: Don't know how to handle presentation property {:?}", $longhand);
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 {
- warn!("stylo: got unexpected non-integer value for color presentation attribute");
- return
+ )
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_PropertyIsSet(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID)
+ -> bool {
+ use style::properties::PropertyDeclarationId;
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let long = get_longhand_from_id!(property, false);
+ declarations.read().get(PropertyDeclarationId::Longhand(long)).is_some()
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_SetIdentStringValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property:
+ nsCSSPropertyID,
+ value:
+ *mut nsIAtom) {
+ use style::properties::{DeclaredValue, PropertyDeclaration, LonghandId};
+ use style::properties::longhands::_x_lang::computed_value::T as Lang;
+
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let long = get_longhand_from_id!(property);
+ let prop = match_wrap_declared! { long,
+ XLang => Lang(Atom::from(value)),
+ };
+ declarations.write().declarations.push((prop, Default::default()));
+}
+
+#[no_mangle]
+#[allow(unreachable_code)]
+pub extern "C" fn Servo_DeclarationBlock_SetKeywordValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID,
+ value: i32) {
+ use style::properties::{DeclaredValue, PropertyDeclaration, LonghandId};
+ use style::properties::longhands;
+ use style::values::specified::{BorderStyle, NoCalcLength};
+
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let long = get_longhand_from_id!(property);
+ let value = value as u32;
+
+ let prop = match_wrap_declared! { long,
+ MozUserModify => longhands::_moz_user_modify::SpecifiedValue::from_gecko_keyword(value),
+ // TextEmphasisPosition => FIXME implement text-emphasis-position
+ Display => longhands::display::SpecifiedValue::from_gecko_keyword(value),
+ Float => longhands::float::SpecifiedValue::from_gecko_keyword(value),
+ VerticalAlign => longhands::vertical_align::SpecifiedValue::from_gecko_keyword(value),
+ TextAlign => longhands::text_align::SpecifiedValue::from_gecko_keyword(value),
+ Clear => longhands::clear::SpecifiedValue::from_gecko_keyword(value),
+ FontSize => {
+ // We rely on Gecko passing in font-size values (0...7) here.
+ longhands::font_size::SpecifiedValue(NoCalcLength::from_font_size_int(value as u8).into())
+ },
+ ListStyleType => longhands::list_style_type::SpecifiedValue::from_gecko_keyword(value),
+ WhiteSpace => longhands::white_space::SpecifiedValue::from_gecko_keyword(value),
+ CaptionSide => longhands::caption_side::SpecifiedValue::from_gecko_keyword(value),
+ BorderTopStyle => BorderStyle::from_gecko_keyword(value),
+ BorderRightStyle => BorderStyle::from_gecko_keyword(value),
+ BorderBottomStyle => BorderStyle::from_gecko_keyword(value),
+ BorderLeftStyle => BorderStyle::from_gecko_keyword(value),
+ };
+ declarations.write().declarations.push((prop, Default::default()));
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_SetIntValue(declarations: RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID,
+ value: i32) {
+ use style::properties::{DeclaredValue, PropertyDeclaration, LonghandId};
+ use style::properties::longhands::_x_span::computed_value::T as Span;
+
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let long = get_longhand_from_id!(property);
+ let prop = match_wrap_declared! { long,
+ XSpan => Span(value),
+ };
+ declarations.write().declarations.push((prop, Default::default()));
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID,
+ value: f32) {
+ use style::properties::{DeclaredValue, PropertyDeclaration, LonghandId};
+ use style::properties::longhands::border_spacing::SpecifiedValue as BorderSpacing;
+ use style::values::specified::BorderWidth;
+ use style::values::specified::length::NoCalcLength;
+
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let long = get_longhand_from_id!(property);
+ let nocalc = NoCalcLength::from_px(value);
+
+ let prop = match_wrap_declared! { long,
+ Height => nocalc.into(),
+ Width => nocalc.into(),
+ BorderTopWidth => BorderWidth::Width(nocalc.into()),
+ BorderRightWidth => BorderWidth::Width(nocalc.into()),
+ BorderBottomWidth => BorderWidth::Width(nocalc.into()),
+ BorderLeftWidth => BorderWidth::Width(nocalc.into()),
+ MarginTop => nocalc.into(),
+ MarginRight => nocalc.into(),
+ MarginBottom => nocalc.into(),
+ MarginLeft => nocalc.into(),
+ PaddingTop => nocalc.into(),
+ PaddingRight => nocalc.into(),
+ PaddingBottom => nocalc.into(),
+ PaddingLeft => nocalc.into(),
+ BorderSpacing => Box::new(
+ BorderSpacing {
+ horizontal: nocalc.into(),
+ vertical: nocalc.into(),
}
+ ),
+ };
+ declarations.write().declarations.push((prop, Default::default()));
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_SetPercentValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID,
+ value: f32) {
+ use style::properties::{DeclaredValue, PropertyDeclaration, LonghandId};
+ use style::values::specified::length::Percentage;
+
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let long = get_longhand_from_id!(property);
+ let pc = Percentage(value);
+
+ let prop = match_wrap_declared! { long,
+ Height => pc.into(),
+ Width => pc.into(),
+ MarginTop => pc.into(),
+ MarginRight => pc.into(),
+ MarginBottom => pc.into(),
+ MarginLeft => pc.into(),
+ };
+ declarations.write().declarations.push((prop, Default::default()));
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_SetAutoValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID) {
+ use style::properties::{DeclaredValue, PropertyDeclaration, LonghandId};
+ use style::values::specified::LengthOrPercentageOrAuto;
+
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let long = get_longhand_from_id!(property);
+ let auto = LengthOrPercentageOrAuto::Auto;
+
+ let prop = match_wrap_declared! { long,
+ Height => auto,
+ Width => auto,
+ MarginTop => auto,
+ MarginRight => auto,
+ MarginBottom => auto,
+ MarginLeft => auto,
+ };
+ declarations.write().declarations.push((prop, Default::default()));
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_SetCurrentColor(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID) {
+ use cssparser::Color;
+ use style::properties::{DeclaredValue, PropertyDeclaration, LonghandId};
+ use style::values::specified::CSSColor;
+
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let long = get_longhand_from_id!(property);
+ let cc = CSSColor { parsed: Color::CurrentColor, authored: None };
+
+ let prop = match_wrap_declared! { long,
+ BorderTopColor => cc,
+ BorderRightColor => cc,
+ BorderBottomColor => cc,
+ BorderLeftColor => cc,
+ };
+ declarations.write().declarations.push((prop, Default::default()));
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_SetColorValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: nsCSSPropertyID,
+ value: structs::nscolor) {
+ use cssparser::Color;
+ use style::gecko::values::convert_nscolor_to_rgba;
+ use style::properties::{DeclaredValue, PropertyDeclaration, LonghandId};
+ use style::values::specified::{CSSColor, CSSRGBA};
+
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let long = get_longhand_from_id!(property);
+ let rgba = convert_nscolor_to_rgba(value);
+ let color = CSSColor { parsed: Color::RGBA(rgba), authored: None };
+
+ let prop = match_wrap_declared! { long,
+ BorderTopColor => color,
+ BorderRightColor => color,
+ BorderBottomColor => color,
+ BorderLeftColor => color,
+ Color => CSSRGBA { parsed: rgba, authored: None },
+ BackgroundColor => color,
+ };
+ declarations.write().declarations.push((prop, Default::default()));
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_SetFontFamily(declarations:
+ RawServoDeclarationBlockBorrowed,
+ value: *const nsAString) {
+ use cssparser::Parser;
+ use style::properties::{DeclaredValue, PropertyDeclaration};
+ use style::properties::longhands::font_family::SpecifiedValue as FontFamily;
+
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let string = unsafe { (*value).to_string() };
+ let mut parser = Parser::new(&string);
+ if let Ok(family) = FontFamily::parse(&mut parser) {
+ if parser.is_exhausted() {
+ let decl = PropertyDeclaration::FontFamily(DeclaredValue::Value(family));
+ declarations.write().declarations.push((decl, Default::default()));
}
- _ => {
- warn!("stylo: cannot handle longhand {:?} from presentation attribute", long);
- return
- }
- };
- declarations.write().declarations.push((decl, Importance::Normal));
+ }
+}
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_SetTextDecorationColorOverride(declarations:
+ RawServoDeclarationBlockBorrowed) {
+ use style::properties::{DeclaredValue, PropertyDeclaration};
+ use style::properties::longhands::text_decoration_line;
+
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let mut decoration = text_decoration_line::computed_value::none;
+ decoration |= text_decoration_line::COLOR_OVERRIDE;
+ let decl = PropertyDeclaration::TextDecorationLine(DeclaredValue::Value(decoration));
+ declarations.write().declarations.push((decl, Default::default()));
}
#[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() };
let id = if let Ok(id) = PropertyId::parse(property.into()) {
id
} else {