--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -8,16 +8,19 @@ PHYSICAL_SIDES = ["top", "left", "bottom
LOGICAL_SIDES = ["block-start", "block-end", "inline-start", "inline-end"]
PHYSICAL_SIZES = ["width", "height"]
LOGICAL_SIZES = ["block-size", "inline-size"]
# bool is True when logical
ALL_SIDES = [(side, False) for side in PHYSICAL_SIDES] + [(side, True) for side in LOGICAL_SIDES]
ALL_SIZES = [(size, False) for size in PHYSICAL_SIZES] + [(size, True) for size in LOGICAL_SIZES]
+SYSTEM_FONT_LONGHANDS = """font_family font_size font_style
+ font_variant_caps font_stretch font_kerning
+ font_variant_position""".split()
def maybe_moz_logical_alias(product, side, prop):
if product == "gecko" and side[1]:
axis, dir = side[0].split("-")
if axis == "inline":
return prop % dir
return None
@@ -27,16 +30,20 @@ def to_rust_ident(name):
if name in ["static", "super", "box", "move"]: # Rust keywords
name += "_"
return name
def to_camel_case(ident):
return re.sub("(^|_|-)([a-z])", lambda m: m.group(2).upper(), ident.strip("_").strip("-"))
+def to_camel_case_lower(ident):
+ camel = to_camel_case(ident)
+ return camel[0].lower() + camel[1:]
+
class Keyword(object):
def __init__(self, name, values, gecko_constant_prefix=None,
gecko_enum_prefix=None, custom_consts=None,
extra_gecko_values=None, extra_servo_values=None,
gecko_strip_moz_prefix=True,
gecko_inexhaustive=None):
self.name = name
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -1,13 +1,16 @@
/* 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/. */
-<%! from data import Keyword, to_rust_ident, to_camel_case, LOGICAL_SIDES, PHYSICAL_SIDES, LOGICAL_SIZES %>
+<%!
+ from data import Keyword, to_rust_ident, to_camel_case
+ from data import LOGICAL_SIDES, PHYSICAL_SIDES, LOGICAL_SIZES, SYSTEM_FONT_LONGHANDS
+%>
<%def name="predefined_type(name, type, initial_value, parse_method='parse',
needs_context=True, vector=False, initial_specified_value=None, **kwargs)">
<%def name="predefined_type_inner(name, type, initial_value, parse_method)">
#[allow(unused_imports)]
use app_units::Au;
use cssparser::{Color as CSSParserColor, RGBA};
pub use values::specified::${type} as SpecifiedValue;
@@ -194,17 +197,16 @@
.collect())
}
}
% else:
${caller.body()}
% endif
</%call>
</%def>
-
<%def name="longhand(*args, **kwargs)">
<%
property = data.declare_longhand(*args, **kwargs)
if property is None:
return ""
%>
/// ${property.spec}
pub mod ${property.ident} {
@@ -260,17 +262,17 @@
&value);
}
% if property.logical:
let wm = context.style.writing_mode;
% endif
<% maybe_wm = ", wm" if property.logical else "" %>
match *value {
DeclaredValue::Value(ref specified_value) => {
- % if property.ident in "font_size font_family".split() and product == "gecko":
+ % if property.ident in SYSTEM_FONT_LONGHANDS and product == "gecko":
if let Some(sf) = specified_value.get_system() {
longhands::system_font::resolve_system_font(sf, context);
}
% endif
let computed = specified_value.to_computed_value(context);
% if property.ident == "font_size":
if let longhands::font_size::SpecifiedValue::Keyword(kw, fraction)
= **specified_value {
@@ -393,57 +395,154 @@
specified.map(|s| PropertyDeclaration::${property.camel_case}(s))
}
}
}
% endif
}
</%def>
+<%def name="single_keyword_system(name, values, **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',
+ ]}
+ keyword = keyword=Keyword(name, values, **keyword_kwargs)
+ %>
+ <%call expr="longhand(name, keyword=Keyword(name, values, **keyword_kwargs), **kwargs)">
+ use values::HasViewportPercentage;
+ use properties::longhands::system_font::SystemFont;
+ use std::fmt;
+ use style_traits::ToCss;
+ no_viewport_percentage!(SpecifiedValue);
+
+ pub mod computed_value {
+ use cssparser::Parser;
+ use parser::{Parse, ParserContext};
+
+ use style_traits::ToCss;
+ define_css_keyword_enum! { T:
+ % for value in keyword.values_for(product):
+ "${value}" => ${to_rust_ident(value)},
+ % endfor
+ }
+
+ impl Parse for T {
+ fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
+ T::parse(input)
+ }
+ }
+
+ ${gecko_keyword_conversion(keyword, keyword.values_for(product), type="T", cast_to="i32")}
+ }
+
+ #[derive(Debug, Clone, PartialEq, Eq, Copy)]
+ pub enum SpecifiedValue {
+ Keyword(computed_value::T),
+ System(SystemFont),
+ }
+
+ impl ToCss for SpecifiedValue {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ match *self {
+ SpecifiedValue::Keyword(k) => k.to_css(dest),
+ SpecifiedValue::System(_) => Ok(())
+ }
+ }
+ }
+
+ pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
+ Ok(SpecifiedValue::Keyword(computed_value::T::parse(input)?))
+ }
+
+ impl ToComputedValue for SpecifiedValue {
+ type ComputedValue = computed_value::T;
+ fn to_computed_value(&self, _cx: &Context) -> Self::ComputedValue {
+ match *self {
+ SpecifiedValue::Keyword(v) => v,
+ SpecifiedValue::System(_) => {
+ % if product == "gecko":
+ _cx.style.cached_system_font.as_ref().unwrap().${to_rust_ident(name)}
+ % else:
+ unreachable!()
+ % endif
+ }
+ }
+ }
+ fn from_computed_value(other: &computed_value::T) -> Self {
+ SpecifiedValue::Keyword(*other)
+ }
+ }
+
+ impl From<computed_value::T> for SpecifiedValue {
+ fn from(other: computed_value::T) -> Self {
+ SpecifiedValue::Keyword(other)
+ }
+ }
+
+ #[inline]
+ pub fn get_initial_value() -> computed_value::T {
+ computed_value::T::${to_rust_ident(values.split()[0])}
+ }
+ #[inline]
+ pub fn get_initial_specified_value() -> SpecifiedValue {
+ SpecifiedValue::Keyword(computed_value::T::${to_rust_ident(values.split()[0])})
+ }
+
+ impl SpecifiedValue {
+ pub fn system_font(f: SystemFont) -> Self {
+ SpecifiedValue::System(f)
+ }
+ pub fn get_system(&self) -> Option<SystemFont> {
+ if let SpecifiedValue::System(s) = *self {
+ Some(s)
+ } else {
+ None
+ }
+ }
+ }
+ </%call>
+</%def>
+
<%def name="single_keyword(name, values, vector=False, **kwargs)">
<%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="gecko_keyword_conversion(keyword, values=None, type='SpecifiedValue')">
+<%def name="gecko_keyword_conversion(keyword, values=None, type='SpecifiedValue', cast_to=None)">
<%
if not values:
values = keyword.values_for(product)
+ maybe_cast = "as %s" % cast_to if cast_to else ""
+ const_type = cast_to if cast_to else "u32"
%>
#[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()}: ${const_type}
+ = structs::${keyword.gecko_constant(value)} as ${const_type};
+ % endfor
+ match kw ${maybe_cast} {
% 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;
+ ${to_rust_ident(value).upper()} => ${type}::${to_rust_ident(value)},
% 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
+ x => panic!("Found unexpected value in style struct for ${keyword.name} property: {:?}", x),
+ }
}
}
</%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 [
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -1,14 +1,16 @@
/* 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 SYSTEM_FONT_LONGHANDS %>
+
use app_units::Au;
use cssparser::{Color as CSSParserColor, Parser, RGBA};
use euclid::{Point2D, Size2D};
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSPropertyID;
use properties::{CSSWideKeyword, PropertyDeclaration};
use properties::longhands;
use properties::longhands::background_size::computed_value::T as BackgroundSize;
use properties::longhands::font_weight::computed_value::T as FontWeight;
@@ -349,21 +351,21 @@ impl AnimationValue {
use error_reporting::StdoutErrorReporter;
use properties::LonghandId;
use properties::DeclaredValue;
match *decl {
% for prop in data.longhands:
% if prop.animatable:
PropertyDeclaration::${prop.camel_case}(ref val) => {
- % if prop.ident in "font_size font_family".split() and product == "gecko":
- if let Some(sf) = val.get_system() {
- longhands::system_font::resolve_system_font(sf, context);
- }
- % endif
+ % if prop.ident in SYSTEM_FONT_LONGHANDS and product == "gecko":
+ if let Some(sf) = val.get_system() {
+ longhands::system_font::resolve_system_font(sf, context);
+ }
+ % endif
Some(AnimationValue::${prop.camel_case}(val.to_computed_value(context)))
},
% endif
% endfor
PropertyDeclaration::CSSWideKeyword(id, keyword) => {
match id {
// We put all the animatable properties first in the hopes
// that it might increase match locality.
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -88,17 +88,18 @@
_error_reporter: &ParseErrorReporter) {
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'))}
+ gecko_enum_prefix='StyleDisplay',
+ gecko_strip_moz_prefix=False))}
</%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", animation_type="none", internal=True,
spec="Internal (not web-exposed)")}
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.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, to_camel_case, to_rust_ident %>
+<% from data import Method, to_camel_case, to_rust_ident, to_camel_case_lower, SYSTEM_FONT_LONGHANDS %>
<% data.new_style_struct("Font",
inherited=True) %>
<%def name="nongecko_unreachable()">
%if product == "gecko":
${caller.body()}
%else:
@@ -277,40 +277,38 @@
Ok(FontFamily::FamilyName(name)) => Ok(name),
Ok(FontFamily::Generic(_)) |
Err(()) => Err(())
}
}
}
</%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",
- animation_type="none",
- needs_conversion=True)}
+${helpers.single_keyword_system("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",
+ animation_type="none")}
<% font_variant_caps_custom_consts= { "small-caps": "SMALLCAPS",
"all-small": "ALLSMALL",
"petite-caps": "PETITECAPS",
"all-petite": "ALLPETITE",
"titling-caps": "TITLING" } %>
-${helpers.single_keyword("font-variant-caps",
- "normal small-caps",
- extra_gecko_values="all-small petite-caps unicase titling-caps",
- gecko_constant_prefix="NS_FONT_VARIANT_CAPS",
- gecko_ffi_name="mFont.variantCaps",
- spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
- custom_consts=font_variant_caps_custom_consts,
- animation_type="none")}
+${helpers.single_keyword_system("font-variant-caps",
+ "normal small-caps",
+ extra_gecko_values="all-small petite-caps unicase titling-caps",
+ gecko_constant_prefix="NS_FONT_VARIANT_CAPS",
+ gecko_ffi_name="mFont.variantCaps",
+ spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
+ custom_consts=font_variant_caps_custom_consts,
+ animation_type="none")}
<%helpers:longhand name="font-weight" need_clone="True" animation_type="normal"
spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
no_viewport_percentage!(SpecifiedValue);
@@ -949,33 +947,33 @@
Ok(result)
},
_ => Err(())
}
}
</%helpers:longhand>
// FIXME: This prop should be animatable
-${helpers.single_keyword("font-stretch",
- "normal ultra-condensed extra-condensed condensed \
- semi-condensed semi-expanded expanded extra-expanded \
- ultra-expanded",
- gecko_ffi_name="mFont.stretch",
- gecko_constant_prefix="NS_FONT_STRETCH",
- cast_type='i16',
- spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch",
- animation_type="none")}
+${helpers.single_keyword_system("font-stretch",
+ "normal ultra-condensed extra-condensed condensed \
+ semi-condensed semi-expanded expanded extra-expanded \
+ ultra-expanded",
+ gecko_ffi_name="mFont.stretch",
+ gecko_constant_prefix="NS_FONT_STRETCH",
+ cast_type='i16',
+ spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch",
+ animation_type="none")}
-${helpers.single_keyword("font-kerning",
- "auto none normal",
- products="gecko",
- gecko_ffi_name="mFont.kerning",
- gecko_constant_prefix="NS_FONT_KERNING",
- spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch",
- animation_type="none")}
+${helpers.single_keyword_system("font-kerning",
+ "auto none normal",
+ products="gecko",
+ gecko_ffi_name="mFont.kerning",
+ gecko_constant_prefix="NS_FONT_KERNING",
+ spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch",
+ animation_type="none")}
/// FIXME: Implement proper handling of each values.
/// https://github.com/servo/servo/issues/15957
<%helpers:longhand name="font-variant-alternates" products="gecko" animation_type="none"
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
@@ -1456,23 +1454,23 @@ macro_rules! exclusive_value {
if !result.is_empty() {
Ok(result)
} else {
Err(())
}
}
</%helpers:longhand>
-${helpers.single_keyword("font-variant-position",
- "normal sub super",
- products="gecko",
- gecko_ffi_name="mFont.variantPosition",
- gecko_constant_prefix="NS_FONT_VARIANT_POSITION",
- spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position",
- animation_type="none")}
+${helpers.single_keyword_system("font-variant-position",
+ "normal sub super",
+ products="gecko",
+ gecko_ffi_name="mFont.variantPosition",
+ gecko_constant_prefix="NS_FONT_VARIANT_POSITION",
+ spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position",
+ animation_type="none")}
<%helpers:longhand name="font-feature-settings" products="none" animation_type="none" extra_prefixes="moz"
spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified;
pub use self::computed_value::T as SpecifiedValue;
@@ -1892,16 +1890,18 @@ macro_rules! exclusive_value {
use cssparser::Parser;
use properties::longhands;
use values::computed::{ToComputedValue, Context};
<%
system_fonts = """caption icon menu message-box small-caption status-bar
-moz-window -moz-document -moz-workspace -moz-desktop
-moz-info -moz-dialog -moz-button -moz-pull-down-menu
-moz-list -moz-field""".split()
+ kw_font_props = """font_style font_variant_caps font_stretch
+ font_kerning font_variant_position""".split()
%>
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum SystemFont {
% for font in system_fonts:
${to_camel_case(font)},
% endfor
}
@@ -1932,16 +1932,21 @@ macro_rules! exclusive_value {
FontFamily::FamilyName(FamilyName {
name: (&*font.mName).into(),
quoted: true
})
}).collect::<Vec<_>>();
let ret = ComputedSystemFont {
font_family: longhands::font_family::computed_value::T(family),
font_size: Au(system.size),
+ % for kwprop in kw_font_props:
+ ${kwprop}: longhands::${kwprop}::computed_value::T::from_gecko_keyword(
+ system.${to_camel_case_lower(kwprop.replace('font_', ''))} as u32
+ ),
+ % endfor
system_font: *self,
};
unsafe { bindings::Gecko_nsFont_Destroy(&mut system); }
ret
}
fn from_computed_value(_: &ComputedSystemFont) -> Self {
unreachable!()
@@ -1958,18 +1963,19 @@ macro_rules! exclusive_value {
let computed = system.to_computed_value(context);
context.style.cached_system_font = Some(computed);
}
debug_assert!(system == context.style.cached_system_font.as_ref().unwrap().system_font)
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ComputedSystemFont {
- pub font_family: longhands::font_family::computed_value::T,
- pub font_size: longhands::font_size::computed_value::T,
+ % for name in SYSTEM_FONT_LONGHANDS:
+ pub ${name}: longhands::${name}::computed_value::T,
+ % endfor
pub system_font: SystemFont,
}
impl SystemFont {
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
Ok(match_ignore_ascii_case! { &*input.expect_ident()?,
% for font in system_fonts:
"${font}" => SystemFont::${to_camel_case(font)},
--- a/servo/components/style/properties/shorthand/font.mako.rs
+++ b/servo/components/style/properties/shorthand/font.mako.rs
@@ -1,13 +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 SYSTEM_FONT_LONGHANDS %>
<%helpers:shorthand name="font"
sub_properties="font-style font-variant-caps font-weight font-stretch
font-size line-height font-family
${'font-size-adjust' if product == 'gecko' or data.testing else ''}
${'font-kerning' if product == 'gecko' or data.testing else ''}
${'font-variant-alternates' if product == 'gecko' or data.testing else ''}
${'font-variant-east-asian' if product == 'gecko' or data.testing else ''}
@@ -37,21 +38,23 @@
let mut style = None;
let mut variant_caps = None;
let mut weight = None;
let mut stretch = None;
let size;
% if product == "gecko":
if let Ok(sys) = input.try(SystemFont::parse) {
return Ok(Longhands {
- % for name in "family size".split():
- font_${name}: font_${name}::SpecifiedValue::system_font(sys),
+ % for name in SYSTEM_FONT_LONGHANDS:
+ ${name}: ${name}::SpecifiedValue::system_font(sys),
% endfor
- % for name in "style weight stretch variant_caps".split() + gecko_sub_properties:
- font_${name}: font_${name}::get_initial_specified_value(),
+ % for name in gecko_sub_properties + "weight variant_caps stretch".split():
+ % if "font_" + name not in SYSTEM_FONT_LONGHANDS:
+ font_${name}: font_${name}::get_initial_specified_value(),
+ % endif
% endfor
line_height: line_height::get_initial_specified_value(),
})
}
% endif
loop {
// Special-case 'normal' because it is valid in each of
// font-style, font-weight, font-variant and font-stretch.
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1374,17 +1374,17 @@ pub extern "C" fn Servo_DeclarationBlock
VerticalAlign => longhands::vertical_align::SpecifiedValue::from_gecko_keyword(value),
TextAlign => longhands::text_align::SpecifiedValue::from_gecko_keyword(value),
TextEmphasisPosition => longhands::text_emphasis_position::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::from_html_size(value as u8)
},
- FontStyle => longhands::font_style::SpecifiedValue::from_gecko_keyword(value),
+ FontStyle => longhands::font_style::computed_value::T::from_gecko_keyword(value).into(),
FontWeight => longhands::font_weight::SpecifiedValue::from_gecko_keyword(value),
ListStyleType => longhands::list_style_type::SpecifiedValue::from_gecko_keyword(value),
MozMathVariant => longhands::_moz_math_variant::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),