mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
stylo: System font support for keyword font longhands
This commit is contained in:
parent
c1c4c8fa59
commit
b0dcb72722
7 changed files with 193 additions and 75 deletions
|
@ -13,6 +13,9 @@ LOGICAL_SIZES = ["block-size", "inline-size"]
|
|||
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]:
|
||||
|
@ -32,6 +35,10 @@ def to_rust_ident(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:]
|
||||
|
||||
|
||||
def parse_aliases(value):
|
||||
aliases = {}
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
* 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)">
|
||||
|
@ -212,7 +215,6 @@
|
|||
% endif
|
||||
</%call>
|
||||
</%def>
|
||||
|
||||
<%def name="longhand(*args, **kwargs)">
|
||||
<%
|
||||
property = data.declare_longhand(*args, **kwargs)
|
||||
|
@ -278,7 +280,7 @@
|
|||
<% 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);
|
||||
}
|
||||
|
@ -393,6 +395,110 @@
|
|||
}
|
||||
</%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)">
|
||||
% if not "extra_specified" in kwargs and ("aliases" in kwargs or (("extra_%s_aliases" % product) in kwargs)):
|
||||
|
@ -426,10 +532,12 @@
|
|||
</%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} {
|
||||
|
@ -438,26 +546,17 @@
|
|||
/// 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>
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
<%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};
|
||||
|
@ -418,11 +420,11 @@ impl AnimationValue {
|
|||
% 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
|
||||
|
|
|
@ -93,7 +93,8 @@
|
|||
% endif
|
||||
|
||||
${helpers.gecko_keyword_conversion(Keyword('display', ' '.join(values),
|
||||
gecko_enum_prefix='StyleDisplay'))}
|
||||
gecko_enum_prefix='StyleDisplay',
|
||||
gecko_strip_moz_prefix=False))}
|
||||
|
||||
</%helpers:longhand>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* 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) %>
|
||||
|
@ -282,14 +282,12 @@
|
|||
}
|
||||
</%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",
|
||||
|
@ -298,14 +296,14 @@ ${helpers.single_keyword("font-style",
|
|||
"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">
|
||||
|
@ -1034,23 +1032,23 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
</%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
|
||||
|
@ -1541,13 +1539,13 @@ macro_rules! exclusive_value {
|
|||
}
|
||||
</%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">
|
||||
|
@ -1977,6 +1975,8 @@ ${helpers.single_keyword("-moz-math-variant",
|
|||
-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 {
|
||||
|
@ -2017,6 +2017,11 @@ ${helpers.single_keyword("-moz-math-variant",
|
|||
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); }
|
||||
|
@ -2043,8 +2048,9 @@ ${helpers.single_keyword("-moz-math-variant",
|
|||
|
||||
#[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,
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* 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
|
||||
|
@ -42,11 +43,13 @@
|
|||
% 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(),
|
||||
})
|
||||
|
|
|
@ -1393,7 +1393,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetKeywordValue(declarations:
|
|||
// 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),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue