mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #16517 - Manishearth:stylo-sys, r=xidorn
stylo: Support system fonts r=xidorn https://bugzilla.mozilla.org/show_bug.cgi?id=1349417 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16517) <!-- Reviewable:end -->
This commit is contained in:
commit
2f8d9013a0
11 changed files with 858 additions and 192 deletions
|
@ -468,7 +468,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
hints.push(from_declaration(
|
hints.push(from_declaration(
|
||||||
shared_lock,
|
shared_lock,
|
||||||
PropertyDeclaration::FontFamily(
|
PropertyDeclaration::FontFamily(
|
||||||
font_family::computed_value::T(vec![
|
font_family::SpecifiedValue::Values(vec![
|
||||||
font_family::computed_value::FontFamily::from_atom(
|
font_family::computed_value::FontFamily::from_atom(
|
||||||
font_family)]))));
|
font_family)]))));
|
||||||
}
|
}
|
||||||
|
|
|
@ -695,6 +695,9 @@ extern "C" {
|
||||||
pub fn Gecko_Atomize(aString: *const ::std::os::raw::c_char, aLength: u32)
|
pub fn Gecko_Atomize(aString: *const ::std::os::raw::c_char, aLength: u32)
|
||||||
-> *mut nsIAtom;
|
-> *mut nsIAtom;
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_Atomize16(aString: *const nsAString) -> *mut nsIAtom;
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_AddRefAtom(aAtom: *mut nsIAtom);
|
pub fn Gecko_AddRefAtom(aAtom: *mut nsIAtom);
|
||||||
}
|
}
|
||||||
|
@ -731,6 +734,14 @@ extern "C" {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_CopyFontFamilyFrom(dst: *mut nsFont, src: *const nsFont);
|
pub fn Gecko_CopyFontFamilyFrom(dst: *mut nsFont, src: *const nsFont);
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_nsFont_InitSystem(dst: *mut nsFont, font_id: i32,
|
||||||
|
font: *const nsStyleFont,
|
||||||
|
pres_context: RawGeckoPresContextBorrowed);
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_nsFont_Destroy(dst: *mut nsFont);
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_SetImageOrientation(aVisibility: *mut nsStyleVisibility,
|
pub fn Gecko_SetImageOrientation(aVisibility: *mut nsStyleVisibility,
|
||||||
aRadians: f64, aFlip: bool);
|
aRadians: f64, aFlip: bool);
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
|
|
||||||
use gecko_bindings::bindings::Gecko_AddRefAtom;
|
use gecko_bindings::bindings::Gecko_AddRefAtom;
|
||||||
use gecko_bindings::bindings::Gecko_Atomize;
|
use gecko_bindings::bindings::Gecko_Atomize;
|
||||||
|
use gecko_bindings::bindings::Gecko_Atomize16;
|
||||||
use gecko_bindings::bindings::Gecko_ReleaseAtom;
|
use gecko_bindings::bindings::Gecko_ReleaseAtom;
|
||||||
use gecko_bindings::structs::nsIAtom;
|
use gecko_bindings::structs::nsIAtom;
|
||||||
|
use nsstring::nsAString;
|
||||||
use precomputed_hash::PrecomputedHash;
|
use precomputed_hash::PrecomputedHash;
|
||||||
use std::borrow::{Cow, Borrow};
|
use std::borrow::{Cow, Borrow};
|
||||||
use std::char::{self, DecodeUtf16};
|
use std::char::{self, DecodeUtf16};
|
||||||
|
@ -281,6 +283,17 @@ impl<'a> From<&'a str> for Atom {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a nsAString> for Atom {
|
||||||
|
#[inline]
|
||||||
|
fn from(string: &nsAString) -> Atom {
|
||||||
|
unsafe {
|
||||||
|
Atom(WeakAtom::new(
|
||||||
|
Gecko_Atomize16(string)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> From<Cow<'a, str>> for Atom {
|
impl<'a> From<Cow<'a, str>> for Atom {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(string: Cow<'a, str>) -> Atom {
|
fn from(string: Cow<'a, str>) -> Atom {
|
||||||
|
|
|
@ -13,6 +13,13 @@ LOGICAL_SIZES = ["block-size", "inline-size"]
|
||||||
ALL_SIDES = [(side, False) for side in PHYSICAL_SIDES] + [(side, True) for side in LOGICAL_SIDES]
|
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]
|
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 font_weight
|
||||||
|
font_size_adjust font_variant_alternates
|
||||||
|
font_variant_ligatures font_variant_east_asian
|
||||||
|
font_variant_numeric font_language_override""".split()
|
||||||
|
|
||||||
|
|
||||||
def maybe_moz_logical_alias(product, side, prop):
|
def maybe_moz_logical_alias(product, side, prop):
|
||||||
if product == "gecko" and side[1]:
|
if product == "gecko" and side[1]:
|
||||||
|
@ -33,6 +40,11 @@ def to_camel_case(ident):
|
||||||
return re.sub("(^|_|-)([a-z])", lambda m: m.group(2).upper(), ident.strip("_").strip("-"))
|
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):
|
def parse_aliases(value):
|
||||||
aliases = {}
|
aliases = {}
|
||||||
for pair in value.split():
|
for pair in value.split():
|
||||||
|
|
|
@ -95,6 +95,8 @@ pub struct ComputedValues {
|
||||||
/// When this is Some, we compute font sizes by computing the keyword against
|
/// When this is Some, we compute font sizes by computing the keyword against
|
||||||
/// the generic font, and then multiplying it by the ratio.
|
/// the generic font, and then multiplying it by the ratio.
|
||||||
pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
||||||
|
/// The cached system font. See longhand/font.mako.rs
|
||||||
|
pub cached_system_font: Option<longhands::system_font::ComputedSystemFont>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComputedValues {
|
impl ComputedValues {
|
||||||
|
@ -104,6 +106,7 @@ impl ComputedValues {
|
||||||
writing_mode: parent.writing_mode,
|
writing_mode: parent.writing_mode,
|
||||||
root_font_size: parent.root_font_size,
|
root_font_size: parent.root_font_size,
|
||||||
font_size_keyword: parent.font_size_keyword,
|
font_size_keyword: parent.font_size_keyword,
|
||||||
|
cached_system_font: None,
|
||||||
% for style_struct in data.style_structs:
|
% for style_struct in data.style_structs:
|
||||||
% if style_struct.inherited:
|
% if style_struct.inherited:
|
||||||
${style_struct.ident}: parent.${style_struct.ident}.clone(),
|
${style_struct.ident}: parent.${style_struct.ident}.clone(),
|
||||||
|
@ -126,6 +129,7 @@ impl ComputedValues {
|
||||||
custom_properties: custom_properties,
|
custom_properties: custom_properties,
|
||||||
writing_mode: writing_mode,
|
writing_mode: writing_mode,
|
||||||
root_font_size: root_font_size,
|
root_font_size: root_font_size,
|
||||||
|
cached_system_font: None,
|
||||||
font_size_keyword: font_size_keyword,
|
font_size_keyword: font_size_keyword,
|
||||||
% for style_struct in data.style_structs:
|
% for style_struct in data.style_structs:
|
||||||
${style_struct.ident}: ${style_struct.ident},
|
${style_struct.ident}: ${style_struct.ident},
|
||||||
|
@ -139,6 +143,7 @@ impl ComputedValues {
|
||||||
writing_mode: WritingMode::empty(), // FIXME(bz): This seems dubious
|
writing_mode: WritingMode::empty(), // FIXME(bz): This seems dubious
|
||||||
root_font_size: longhands::font_size::get_initial_value(), // FIXME(bz): Also seems dubious?
|
root_font_size: longhands::font_size::get_initial_value(), // FIXME(bz): Also seems dubious?
|
||||||
font_size_keyword: Some((Default::default(), 1.)),
|
font_size_keyword: Some((Default::default(), 1.)),
|
||||||
|
cached_system_font: None,
|
||||||
% for style_struct in data.style_structs:
|
% for style_struct in data.style_structs:
|
||||||
${style_struct.ident}: style_structs::${style_struct.name}::default(pres_context),
|
${style_struct.ident}: style_structs::${style_struct.name}::default(pres_context),
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -294,27 +299,6 @@ def set_gecko_property(ffi_name, expr):
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="impl_bitflags_setter(ident, gecko_ffi_name, bit_map, gecko_bit_prefix, cast_type='u8')">
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
|
||||||
% for gecko_bit in bit_map.values():
|
|
||||||
use gecko_bindings::structs::${gecko_bit_prefix}${gecko_bit};
|
|
||||||
% endfor
|
|
||||||
|
|
||||||
let mut bits: ${cast_type} = 0;
|
|
||||||
// FIXME: if we ensure that the Servo bitflags storage is the same
|
|
||||||
// as Gecko's one, we can just copy it.
|
|
||||||
% for servo_bit, gecko_bit in bit_map.iteritems():
|
|
||||||
if v.contains(longhands::${ident}::${servo_bit}) {
|
|
||||||
bits |= ${gecko_bit_prefix}${gecko_bit} as ${cast_type};
|
|
||||||
}
|
|
||||||
% endfor
|
|
||||||
|
|
||||||
self.gecko.${gecko_ffi_name} = bits as ${cast_type};
|
|
||||||
}
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
|
|
||||||
/// Convert a Servo color into an nscolor; with currentColor as 0
|
/// Convert a Servo color into an nscolor; with currentColor as 0
|
||||||
///
|
///
|
||||||
/// Call sites will need to be updated after https://bugzilla.mozilla.org/show_bug.cgi?id=760345
|
/// Call sites will need to be updated after https://bugzilla.mozilla.org/show_bug.cgi?id=760345
|
||||||
|
@ -1431,20 +1415,10 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
${impl_simple_copy('font_language_override', 'mFont.languageOverride')}
|
${impl_simple_copy('font_language_override', 'mFont.languageOverride')}
|
||||||
|
|
||||||
<% font_variant_alternates_map = { "HISTORICAL_FORMS": "HISTORICAL",
|
pub fn set_font_variant_alternates(&mut self, v: longhands::font_variant_alternates::computed_value::T) {
|
||||||
"STYLISTIC": "STYLISTIC",
|
self.gecko.mFont.variantAlternates = v.to_gecko_keyword()
|
||||||
"STYLESET": "STYLESET",
|
}
|
||||||
"CHARACTER_VARIANT": "CHARACTER_VARIANT",
|
|
||||||
"SWASH": "SWASH",
|
|
||||||
"ORNAMENTS": "ORNAMENTS",
|
|
||||||
"ANNOTATION": "ANNOTATION" } %>
|
|
||||||
// FIXME: Set alternateValues as well.
|
|
||||||
// self.gecko.mFont.alternateValues = xxx;
|
|
||||||
${impl_bitflags_setter('font_variant_alternates',
|
|
||||||
'mFont.variantAlternates',
|
|
||||||
font_variant_alternates_map,
|
|
||||||
'NS_FONT_VARIANT_ALTERNATES_',
|
|
||||||
cast_type='u16')}
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn copy_font_variant_alternates_from(&mut self, other: &Self) {
|
pub fn copy_font_variant_alternates_from(&mut self, other: &Self) {
|
||||||
self.gecko.mFont.variantAlternates = other.gecko.mFont.variantAlternates;
|
self.gecko.mFont.variantAlternates = other.gecko.mFont.variantAlternates;
|
||||||
|
@ -1452,53 +1426,22 @@ fn static_assert() {
|
||||||
// self.gecko.mFont.alternateValues = other.gecko.mFont.alternateValues;
|
// self.gecko.mFont.alternateValues = other.gecko.mFont.alternateValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
// servo_bit: gecko_bit
|
pub fn set_font_variant_ligatures(&mut self, v: longhands::font_variant_ligatures::computed_value::T) {
|
||||||
<% font_variant_ligatures_map = { "NONE": "NONE",
|
self.gecko.mFont.variantLigatures = v.to_gecko_keyword()
|
||||||
"COMMON_LIGATURES": "COMMON",
|
}
|
||||||
"NO_COMMON_LIGATURES": "NO_COMMON",
|
|
||||||
"DISCRETIONARY_LIGATURES": "DISCRETIONARY",
|
|
||||||
"NO_DISCRETIONARY_LIGATURES": "NO_DISCRETIONARY",
|
|
||||||
"HISTORICAL_LIGATURES": "HISTORICAL",
|
|
||||||
"NO_HISTORICAL_LIGATURES": "NO_HISTORICAL",
|
|
||||||
"CONTEXTUAL": "CONTEXTUAL",
|
|
||||||
"NO_CONTEXTUAL": "NO_CONTEXTUAL" } %>
|
|
||||||
${impl_bitflags_setter('font_variant_ligatures',
|
|
||||||
'mFont.variantLigatures',
|
|
||||||
font_variant_ligatures_map,
|
|
||||||
'NS_FONT_VARIANT_LIGATURES_',
|
|
||||||
cast_type='u16')}
|
|
||||||
${impl_simple_copy('font_variant_ligatures', 'mFont.variantLigatures')}
|
${impl_simple_copy('font_variant_ligatures', 'mFont.variantLigatures')}
|
||||||
|
|
||||||
// servo_bit: gecko_bit
|
pub fn set_font_variant_east_asian(&mut self, v: longhands::font_variant_east_asian::computed_value::T) {
|
||||||
<% font_variant_east_asian_map = { "JIS78": "JIS78",
|
self.gecko.mFont.variantEastAsian = v.to_gecko_keyword()
|
||||||
"JIS83": "JIS83",
|
}
|
||||||
"JIS90": "JIS90",
|
|
||||||
"JIS04": "JIS04",
|
|
||||||
"SIMPLIFIED": "SIMPLIFIED",
|
|
||||||
"TRADITIONAL": "TRADITIONAL",
|
|
||||||
"FULL_WIDTH": "FULL_WIDTH",
|
|
||||||
"PROPORTIONAL_WIDTH": "PROP_WIDTH",
|
|
||||||
"RUBY": "RUBY" } %>
|
|
||||||
${impl_bitflags_setter('font_variant_east_asian',
|
|
||||||
'mFont.variantEastAsian',
|
|
||||||
font_variant_east_asian_map,
|
|
||||||
'NS_FONT_VARIANT_EAST_ASIAN_',
|
|
||||||
cast_type='u16')}
|
|
||||||
${impl_simple_copy('font_variant_east_asian', 'mFont.variantEastAsian')}
|
${impl_simple_copy('font_variant_east_asian', 'mFont.variantEastAsian')}
|
||||||
|
|
||||||
// servo_bit: gecko_bit
|
pub fn set_font_variant_numeric(&mut self, v: longhands::font_variant_numeric::computed_value::T) {
|
||||||
<% font_variant_numeric_map = { "LINING_NUMS": "LINING",
|
self.gecko.mFont.variantNumeric = v.to_gecko_keyword()
|
||||||
"OLDSTYLE_NUMS": "OLDSTYLE",
|
}
|
||||||
"PROPORTIONAL_NUMS": "PROPORTIONAL",
|
|
||||||
"TABULAR_NUMS": "TABULAR",
|
|
||||||
"DIAGONAL_FRACTIONS": "DIAGONAL_FRACTIONS",
|
|
||||||
"STACKED_FRACTIONS": "STACKED_FRACTIONS",
|
|
||||||
"SLASHED_ZERO": "SLASHZERO",
|
|
||||||
"ORDINAL": "ORDINAL" } %>
|
|
||||||
${impl_bitflags_setter('font_variant_numeric',
|
|
||||||
'mFont.variantNumeric',
|
|
||||||
font_variant_numeric_map,
|
|
||||||
'NS_FONT_VARIANT_NUMERIC_')}
|
|
||||||
${impl_simple_copy('font_variant_numeric', 'mFont.variantNumeric')}
|
${impl_simple_copy('font_variant_numeric', 'mFont.variantNumeric')}
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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',
|
<%def name="predefined_type(name, type, initial_value, parse_method='parse',
|
||||||
needs_context=True, vector=False, initial_specified_value=None, **kwargs)">
|
needs_context=True, vector=False, initial_specified_value=None, **kwargs)">
|
||||||
|
@ -199,7 +202,6 @@
|
||||||
% endif
|
% endif
|
||||||
</%call>
|
</%call>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="longhand(*args, **kwargs)">
|
<%def name="longhand(*args, **kwargs)">
|
||||||
<%
|
<%
|
||||||
property = data.declare_longhand(*args, **kwargs)
|
property = data.declare_longhand(*args, **kwargs)
|
||||||
|
@ -265,6 +267,11 @@
|
||||||
<% maybe_wm = ", wm" if property.logical else "" %>
|
<% maybe_wm = ", wm" if property.logical else "" %>
|
||||||
match *value {
|
match *value {
|
||||||
DeclaredValue::Value(ref specified_value) => {
|
DeclaredValue::Value(ref specified_value) => {
|
||||||
|
% 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);
|
let computed = specified_value.to_computed_value(context);
|
||||||
% if property.ident == "font_size":
|
% if property.ident == "font_size":
|
||||||
if let longhands::font_size::SpecifiedValue::Keyword(kw, fraction)
|
if let longhands::font_size::SpecifiedValue::Keyword(kw, fraction)
|
||||||
|
@ -393,6 +400,110 @@
|
||||||
}
|
}
|
||||||
</%def>
|
</%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)">
|
<%def name="single_keyword(name, values, vector=False, **kwargs)">
|
||||||
<%call expr="single_keyword_computed(name, values, vector, **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)):
|
% if not "extra_specified" in kwargs and ("aliases" in kwargs or (("extra_%s_aliases" % product) in kwargs)):
|
||||||
|
@ -426,10 +537,12 @@
|
||||||
</%call>
|
</%call>
|
||||||
</%def>
|
</%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:
|
if not values:
|
||||||
values = keyword.values_for(product)
|
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")]
|
#[cfg(feature = "gecko")]
|
||||||
impl ${type} {
|
impl ${type} {
|
||||||
|
@ -438,26 +551,55 @@
|
||||||
/// Intended for use with presentation attributes, not style structs
|
/// Intended for use with presentation attributes, not style structs
|
||||||
pub fn from_gecko_keyword(kw: u32) -> Self {
|
pub fn from_gecko_keyword(kw: u32) -> Self {
|
||||||
use gecko_bindings::structs;
|
use gecko_bindings::structs;
|
||||||
% if keyword.gecko_enum_prefix:
|
|
||||||
% for value in values:
|
% for value in values:
|
||||||
// We can't match on enum values if we're matching on a u32
|
// We can't match on enum values if we're matching on a u32
|
||||||
const ${to_rust_ident(value).upper()}: u32
|
const ${to_rust_ident(value).upper()}: ${const_type}
|
||||||
= structs::${keyword.gecko_enum_prefix}::${to_camel_case(value)} as u32;
|
= structs::${keyword.gecko_constant(value)} as ${const_type};
|
||||||
% endfor
|
% endfor
|
||||||
match kw {
|
match kw ${maybe_cast} {
|
||||||
% for value in values:
|
% for value in values:
|
||||||
${to_rust_ident(value).upper()} => ${type}::${to_rust_ident(value)},
|
${to_rust_ident(value).upper()} => ${type}::${to_rust_ident(value)},
|
||||||
% endfor
|
% endfor
|
||||||
x => panic!("Found unexpected value in style struct for ${keyword.name} property: {:?}", x),
|
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="gecko_bitflags_conversion(bit_map, gecko_bit_prefix, type, kw_type='u8')">
|
||||||
|
#[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: ${kw_type}) -> Self {
|
||||||
|
% for gecko_bit in bit_map.values():
|
||||||
|
use gecko_bindings::structs::${gecko_bit_prefix}${gecko_bit};
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
let mut bits = ${type}::empty();
|
||||||
|
% for servo_bit, gecko_bit in bit_map.iteritems():
|
||||||
|
if kw & (${gecko_bit_prefix}${gecko_bit} as ${kw_type}) != 0 {
|
||||||
|
bits |= ${servo_bit};
|
||||||
|
}
|
||||||
|
% endfor
|
||||||
|
bits
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_gecko_keyword(self) -> ${kw_type} {
|
||||||
|
% for gecko_bit in bit_map.values():
|
||||||
|
use gecko_bindings::structs::${gecko_bit_prefix}${gecko_bit};
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
let mut bits: ${kw_type} = 0;
|
||||||
|
// FIXME: if we ensure that the Servo bitflags storage is the same
|
||||||
|
// as Gecko's one, we can just copy it.
|
||||||
|
% for servo_bit, gecko_bit in bit_map.iteritems():
|
||||||
|
if self.contains(${servo_bit}) {
|
||||||
|
bits |= ${gecko_bit_prefix}${gecko_bit} as ${kw_type};
|
||||||
|
}
|
||||||
|
% endfor
|
||||||
|
bits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||||
|
|
||||||
|
<% from data import SYSTEM_FONT_LONGHANDS %>
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::{Color as CSSParserColor, Parser, RGBA};
|
use cssparser::{Color as CSSParserColor, Parser, RGBA};
|
||||||
use euclid::{Point2D, Size2D};
|
use euclid::{Point2D, Size2D};
|
||||||
|
@ -358,7 +360,8 @@ impl AnimationValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct an AnimationValue from a property declaration
|
/// Construct an AnimationValue from a property declaration
|
||||||
pub fn from_declaration(decl: &PropertyDeclaration, context: &Context, initial: &ComputedValues) -> Option<Self> {
|
pub fn from_declaration(decl: &PropertyDeclaration, context: &mut Context,
|
||||||
|
initial: &ComputedValues) -> Option<Self> {
|
||||||
use error_reporting::StdoutErrorReporter;
|
use error_reporting::StdoutErrorReporter;
|
||||||
use properties::LonghandId;
|
use properties::LonghandId;
|
||||||
use properties::DeclaredValue;
|
use properties::DeclaredValue;
|
||||||
|
@ -367,6 +370,11 @@ impl AnimationValue {
|
||||||
% for prop in data.longhands:
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
PropertyDeclaration::${prop.camel_case}(ref val) => {
|
PropertyDeclaration::${prop.camel_case}(ref val) => {
|
||||||
|
% 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)))
|
Some(AnimationValue::${prop.camel_case}(val.to_computed_value(context)))
|
||||||
},
|
},
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -93,7 +93,8 @@
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
${helpers.gecko_keyword_conversion(Keyword('display', ' '.join(values),
|
${helpers.gecko_keyword_conversion(Keyword('display', ' '.join(values),
|
||||||
gecko_enum_prefix='StyleDisplay'))}
|
gecko_enum_prefix='StyleDisplay',
|
||||||
|
gecko_strip_moz_prefix=False))}
|
||||||
|
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
|
|
@ -3,22 +3,79 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||||
<% from data import Method %>
|
<% from data import Method, to_camel_case, to_rust_ident, to_camel_case_lower, SYSTEM_FONT_LONGHANDS %>
|
||||||
|
|
||||||
<% data.new_style_struct("Font",
|
<% data.new_style_struct("Font",
|
||||||
inherited=True) %>
|
inherited=True) %>
|
||||||
<%helpers:longhand name="font-family" animation_type="none" need_index="True"
|
|
||||||
|
<%def name="nongecko_unreachable()">
|
||||||
|
%if product == "gecko":
|
||||||
|
${caller.body()}
|
||||||
|
%else:
|
||||||
|
unreachable!()
|
||||||
|
%endif
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
// Define ToComputedValue, ToCss, and other boilerplate for a specified value
|
||||||
|
// which is of the form `enum SpecifiedValue {Value(..), System(SystemFont)}`
|
||||||
|
<%def name="simple_system_boilerplate(name)">
|
||||||
|
impl ToCss for SpecifiedValue {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
SpecifiedValue::Value(v) => v.to_css(dest),
|
||||||
|
SpecifiedValue::System(_) => Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
type ComputedValue = computed_value::T;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
|
||||||
|
match *self {
|
||||||
|
SpecifiedValue::Value(v) => v,
|
||||||
|
SpecifiedValue::System(_) => {
|
||||||
|
<%self:nongecko_unreachable>
|
||||||
|
_context.style.cached_system_font.as_ref().unwrap().${name}
|
||||||
|
</%self:nongecko_unreachable>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_computed_value(other: &computed_value::T) -> Self {
|
||||||
|
SpecifiedValue::Value(*other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%helpers:longhand name="font-family" animation_type="none" need_index="True" boxed="${product == 'gecko'}"
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-family">
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-family">
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
use self::computed_value::{FontFamily, FamilyName};
|
use self::computed_value::{FontFamily, FamilyName};
|
||||||
|
use std::fmt;
|
||||||
|
use style_traits::ToCss;
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
pub use self::computed_value::T as SpecifiedValue;
|
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use cssparser::{CssStringWriter, Parser, serialize_identifier};
|
use cssparser::{CssStringWriter, Parser, serialize_identifier};
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use Atom;
|
use Atom;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
@ -200,9 +257,61 @@
|
||||||
SpecifiedValue::parse(input)
|
SpecifiedValue::parse(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum SpecifiedValue {
|
||||||
|
Values(Vec<FontFamily>),
|
||||||
|
System(SystemFont),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
type ComputedValue = computed_value::T;
|
||||||
|
fn to_computed_value(&self, _cx: &Context) -> Self::ComputedValue {
|
||||||
|
match *self {
|
||||||
|
SpecifiedValue::Values(ref v) => computed_value::T(v.clone()),
|
||||||
|
SpecifiedValue::System(_) => {
|
||||||
|
<%self:nongecko_unreachable>
|
||||||
|
_cx.style.cached_system_font.as_ref().unwrap().font_family.clone()
|
||||||
|
</%self:nongecko_unreachable>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn from_computed_value(other: &computed_value::T) -> Self {
|
||||||
|
SpecifiedValue::Values(other.0.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SpecifiedValue {
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||||
input.parse_comma_separated(|input| FontFamily::parse(input)).map(SpecifiedValue)
|
input.parse_comma_separated(|input| FontFamily::parse(input)).map(SpecifiedValue::Values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl ToCss for SpecifiedValue {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
SpecifiedValue::Values(ref v) => {
|
||||||
|
let mut iter = v.iter();
|
||||||
|
iter.next().unwrap().to_css(dest)?;
|
||||||
|
for family in iter {
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
family.to_css(dest)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,14 +328,12 @@
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
${helpers.single_keyword_system("font-style",
|
||||||
${helpers.single_keyword("font-style",
|
|
||||||
"normal italic oblique",
|
"normal italic oblique",
|
||||||
gecko_constant_prefix="NS_FONT_STYLE",
|
gecko_constant_prefix="NS_FONT_STYLE",
|
||||||
gecko_ffi_name="mFont.style",
|
gecko_ffi_name="mFont.style",
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-style",
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-style",
|
||||||
animation_type="none",
|
animation_type="none")}
|
||||||
needs_conversion=True)}
|
|
||||||
|
|
||||||
|
|
||||||
<% font_variant_caps_custom_consts= { "small-caps": "SMALLCAPS",
|
<% font_variant_caps_custom_consts= { "small-caps": "SMALLCAPS",
|
||||||
|
@ -235,7 +342,7 @@ ${helpers.single_keyword("font-style",
|
||||||
"all-petite": "ALLPETITE",
|
"all-petite": "ALLPETITE",
|
||||||
"titling-caps": "TITLING" } %>
|
"titling-caps": "TITLING" } %>
|
||||||
|
|
||||||
${helpers.single_keyword("font-variant-caps",
|
${helpers.single_keyword_system("font-variant-caps",
|
||||||
"normal small-caps",
|
"normal small-caps",
|
||||||
extra_gecko_values="all-small petite-caps unicase titling-caps",
|
extra_gecko_values="all-small petite-caps unicase titling-caps",
|
||||||
gecko_constant_prefix="NS_FONT_VARIANT_CAPS",
|
gecko_constant_prefix="NS_FONT_VARIANT_CAPS",
|
||||||
|
@ -249,6 +356,7 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
|
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
|
@ -262,6 +370,7 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
% for weight in range(100, 901, 100):
|
% for weight in range(100, 901, 100):
|
||||||
Weight${weight},
|
Weight${weight},
|
||||||
% endfor
|
% endfor
|
||||||
|
System(SystemFont),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
impl ToCss for SpecifiedValue {
|
||||||
|
@ -274,9 +383,11 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
% for weight in range(100, 901, 100):
|
% for weight in range(100, 901, 100):
|
||||||
SpecifiedValue::Weight${weight} => dest.write_str("${weight}"),
|
SpecifiedValue::Weight${weight} => dest.write_str("${weight}"),
|
||||||
% endfor
|
% endfor
|
||||||
|
SpecifiedValue::System(_) => Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
/// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
input.try(|input| {
|
input.try(|input| {
|
||||||
|
@ -308,6 +419,19 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Used in @font-face, where relative keywords are not allowed.
|
/// Used in @font-face, where relative keywords are not allowed.
|
||||||
impl Parse for computed_value::T {
|
impl Parse for computed_value::T {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||||
|
@ -318,7 +442,8 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
SpecifiedValue::Normal => Ok(computed_value::T::Weight400),
|
SpecifiedValue::Normal => Ok(computed_value::T::Weight400),
|
||||||
SpecifiedValue::Bold => Ok(computed_value::T::Weight700),
|
SpecifiedValue::Bold => Ok(computed_value::T::Weight700),
|
||||||
SpecifiedValue::Bolder |
|
SpecifiedValue::Bolder |
|
||||||
SpecifiedValue::Lighter => Err(())
|
SpecifiedValue::Lighter => Err(()),
|
||||||
|
SpecifiedValue::System(..) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,6 +467,15 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Obtain a Servo computed value from a Gecko computed font-weight
|
||||||
|
pub unsafe fn from_gecko_weight(weight: u16) -> Self {
|
||||||
|
use std::mem::transmute;
|
||||||
|
debug_assert!(weight >= 100);
|
||||||
|
debug_assert!(weight <= 900);
|
||||||
|
debug_assert!(weight % 10 == 0);
|
||||||
|
transmute(weight)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ToCss for computed_value::T {
|
impl ToCss for computed_value::T {
|
||||||
|
@ -396,6 +530,11 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
computed_value::T::Weight800 => computed_value::T::Weight700,
|
computed_value::T::Weight800 => computed_value::T::Weight700,
|
||||||
computed_value::T::Weight900 => computed_value::T::Weight700,
|
computed_value::T::Weight900 => computed_value::T::Weight700,
|
||||||
},
|
},
|
||||||
|
SpecifiedValue::System(_) => {
|
||||||
|
<%self:nongecko_unreachable>
|
||||||
|
context.style.cached_system_font.as_ref().unwrap().font_weight.clone()
|
||||||
|
</%self:nongecko_unreachable>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,6 +557,7 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
use values::{FONT_MEDIUM_PX, HasViewportPercentage};
|
use values::{FONT_MEDIUM_PX, HasViewportPercentage};
|
||||||
use values::specified::{FontRelativeLength, LengthOrPercentage, Length};
|
use values::specified::{FontRelativeLength, LengthOrPercentage, Length};
|
||||||
use values::specified::{NoCalcLength, Percentage};
|
use values::specified::{NoCalcLength, Percentage};
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
impl ToCss for SpecifiedValue {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
@ -426,6 +566,7 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
SpecifiedValue::Keyword(kw, _) => kw.to_css(dest),
|
SpecifiedValue::Keyword(kw, _) => kw.to_css(dest),
|
||||||
SpecifiedValue::Smaller => dest.write_str("smaller"),
|
SpecifiedValue::Smaller => dest.write_str("smaller"),
|
||||||
SpecifiedValue::Larger => dest.write_str("larger"),
|
SpecifiedValue::Larger => dest.write_str("larger"),
|
||||||
|
SpecifiedValue::System(_) => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -452,6 +593,7 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
Keyword(KeywordSize, f32),
|
Keyword(KeywordSize, f32),
|
||||||
Smaller,
|
Smaller,
|
||||||
Larger,
|
Larger,
|
||||||
|
System(SystemFont)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<specified::LengthOrPercentage> for SpecifiedValue {
|
impl From<specified::LengthOrPercentage> for SpecifiedValue {
|
||||||
|
@ -677,6 +819,12 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
FontRelativeLength::Em(1.2).to_computed_value(context,
|
FontRelativeLength::Em(1.2).to_computed_value(context,
|
||||||
/* use_inherited */ true)
|
/* use_inherited */ true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpecifiedValue::System(_) => {
|
||||||
|
<%self:nongecko_unreachable>
|
||||||
|
context.style.cached_system_font.as_ref().unwrap().font_size
|
||||||
|
</%self:nongecko_unreachable>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,10 +851,23 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
<%helpers:longhand products="gecko" name="font-size-adjust" animation_type="normal"
|
<%helpers:longhand products="gecko" name="font-size-adjust" animation_type="normal"
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust">
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust">
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
|
@ -718,6 +879,7 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
pub enum SpecifiedValue {
|
pub enum SpecifiedValue {
|
||||||
None,
|
None,
|
||||||
Number(specified::Number),
|
Number(specified::Number),
|
||||||
|
System(SystemFont),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
impl ToCss for SpecifiedValue {
|
||||||
|
@ -727,6 +889,7 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::None => dest.write_str("none"),
|
SpecifiedValue::None => dest.write_str("none"),
|
||||||
SpecifiedValue::Number(number) => number.to_css(dest),
|
SpecifiedValue::Number(number) => number.to_css(dest),
|
||||||
|
SpecifiedValue::System(_) => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -738,6 +901,11 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::None => computed_value::T::None,
|
SpecifiedValue::None => computed_value::T::None,
|
||||||
SpecifiedValue::Number(ref n) => computed_value::T::Number(n.to_computed_value(context)),
|
SpecifiedValue::Number(ref n) => computed_value::T::Number(n.to_computed_value(context)),
|
||||||
|
SpecifiedValue::System(_) => {
|
||||||
|
<%self:nongecko_unreachable>
|
||||||
|
context.style.cached_system_font.as_ref().unwrap().font_size_adjust
|
||||||
|
</%self:nongecko_unreachable>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -749,6 +917,19 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use properties::animated_properties::Interpolate;
|
use properties::animated_properties::Interpolate;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -773,6 +954,15 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl T {
|
||||||
|
pub fn from_gecko_adjust(gecko: f32) -> Self {
|
||||||
|
match gecko {
|
||||||
|
-1.0 => T::None,
|
||||||
|
_ => T::Number(gecko),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Interpolate for T {
|
impl Interpolate for T {
|
||||||
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
|
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
|
||||||
match (*self, *other) {
|
match (*self, *other) {
|
||||||
|
@ -870,7 +1060,7 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
// FIXME: This prop should be animatable
|
// FIXME: This prop should be animatable
|
||||||
${helpers.single_keyword("font-stretch",
|
${helpers.single_keyword_system("font-stretch",
|
||||||
"normal ultra-condensed extra-condensed condensed \
|
"normal ultra-condensed extra-condensed condensed \
|
||||||
semi-condensed semi-expanded expanded extra-expanded \
|
semi-condensed semi-expanded expanded extra-expanded \
|
||||||
ultra-expanded",
|
ultra-expanded",
|
||||||
|
@ -880,7 +1070,7 @@ ${helpers.single_keyword("font-stretch",
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch",
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch",
|
||||||
animation_type="none")}
|
animation_type="none")}
|
||||||
|
|
||||||
${helpers.single_keyword("font-kerning",
|
${helpers.single_keyword_system("font-kerning",
|
||||||
"auto none normal",
|
"auto none normal",
|
||||||
products="gecko",
|
products="gecko",
|
||||||
gecko_ffi_name="mFont.kerning",
|
gecko_ffi_name="mFont.kerning",
|
||||||
|
@ -892,17 +1082,16 @@ ${helpers.single_keyword("font-kerning",
|
||||||
/// https://github.com/servo/servo/issues/15957
|
/// https://github.com/servo/servo/issues/15957
|
||||||
<%helpers:longhand name="font-variant-alternates" products="gecko" animation_type="none"
|
<%helpers:longhand name="font-variant-alternates" products="gecko" animation_type="none"
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates">
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates">
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub flags SpecifiedValue: u8 {
|
pub flags VariantAlternates: u8 {
|
||||||
const NORMAL = 0,
|
const NORMAL = 0,
|
||||||
const HISTORICAL_FORMS = 0x01,
|
const HISTORICAL_FORMS = 0x01,
|
||||||
const STYLISTIC = 0x02,
|
const STYLISTIC = 0x02,
|
||||||
|
@ -914,7 +1103,25 @@ ${helpers.single_keyword("font-kerning",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum SpecifiedValue {
|
||||||
|
Value(VariantAlternates),
|
||||||
|
System(SystemFont)
|
||||||
|
}
|
||||||
|
|
||||||
|
<%self:simple_system_boilerplate name="font_variant_alternates"></%self:simple_system_boilerplate>
|
||||||
|
|
||||||
|
<% font_variant_alternates_map = { "HISTORICAL_FORMS": "HISTORICAL",
|
||||||
|
"STYLISTIC": "STYLISTIC",
|
||||||
|
"STYLESET": "STYLESET",
|
||||||
|
"CHARACTER_VARIANT": "CHARACTER_VARIANT",
|
||||||
|
"SWASH": "SWASH",
|
||||||
|
"ORNAMENTS": "ORNAMENTS",
|
||||||
|
"ANNOTATION": "ANNOTATION" } %>
|
||||||
|
${helpers.gecko_bitflags_conversion(font_variant_alternates_map, 'NS_FONT_VARIANT_ALTERNATES_',
|
||||||
|
'VariantAlternates', kw_type='u16')}
|
||||||
|
|
||||||
|
impl ToCss for VariantAlternates {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
return dest.write_str("normal")
|
return dest.write_str("normal")
|
||||||
|
@ -948,7 +1155,7 @@ ${helpers.single_keyword("font-kerning",
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
pub type T = super::SpecifiedValue;
|
pub type T = super::VariantAlternates;
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
|
@ -956,7 +1163,7 @@ ${helpers.single_keyword("font-kerning",
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||||
SpecifiedValue::empty()
|
SpecifiedValue::Value(VariantAlternates::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// normal |
|
/// normal |
|
||||||
|
@ -968,10 +1175,10 @@ ${helpers.single_keyword("font-kerning",
|
||||||
/// ornaments(<feature-value-name>) ||
|
/// ornaments(<feature-value-name>) ||
|
||||||
/// annotation(<feature-value-name>) ]
|
/// annotation(<feature-value-name>) ]
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
let mut result = SpecifiedValue::empty();
|
let mut result = VariantAlternates::empty();
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
return Ok(result)
|
return Ok(SpecifiedValue::Value(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||||
|
@ -992,7 +1199,7 @@ ${helpers.single_keyword("font-kerning",
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(result)
|
Ok(SpecifiedValue::Value(result))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
@ -1011,17 +1218,16 @@ macro_rules! exclusive_value {
|
||||||
|
|
||||||
<%helpers:longhand name="font-variant-east-asian" products="gecko" animation_type="none"
|
<%helpers:longhand name="font-variant-east-asian" products="gecko" animation_type="none"
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-east-asian">
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-east-asian">
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub flags SpecifiedValue: u16 {
|
pub flags VariantEastAsian: u16 {
|
||||||
const NORMAL = 0,
|
const NORMAL = 0,
|
||||||
const JIS78 = 0x01,
|
const JIS78 = 0x01,
|
||||||
const JIS83 = 0x02,
|
const JIS83 = 0x02,
|
||||||
|
@ -1035,7 +1241,31 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum SpecifiedValue {
|
||||||
|
Value(VariantEastAsian),
|
||||||
|
System(SystemFont)
|
||||||
|
}
|
||||||
|
|
||||||
|
<%self:simple_system_boilerplate name="font_variant_east_asian"></%self:simple_system_boilerplate>
|
||||||
|
|
||||||
|
// servo_bit: gecko_bit
|
||||||
|
<% font_variant_east_asian_map = { "JIS78": "JIS78",
|
||||||
|
"JIS83": "JIS83",
|
||||||
|
"JIS90": "JIS90",
|
||||||
|
"JIS04": "JIS04",
|
||||||
|
"SIMPLIFIED": "SIMPLIFIED",
|
||||||
|
"TRADITIONAL": "TRADITIONAL",
|
||||||
|
"FULL_WIDTH": "FULL_WIDTH",
|
||||||
|
"PROPORTIONAL_WIDTH": "PROP_WIDTH",
|
||||||
|
"RUBY": "RUBY" } %>
|
||||||
|
|
||||||
|
${helpers.gecko_bitflags_conversion(font_variant_east_asian_map, 'NS_FONT_VARIANT_EAST_ASIAN_',
|
||||||
|
'VariantEastAsian', kw_type='u16')}
|
||||||
|
|
||||||
|
|
||||||
|
impl ToCss for VariantEastAsian {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
return dest.write_str("normal")
|
return dest.write_str("normal")
|
||||||
|
@ -1071,7 +1301,7 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
pub type T = super::SpecifiedValue;
|
pub type T = super::VariantEastAsian;
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
|
@ -1079,7 +1309,7 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||||
SpecifiedValue::empty()
|
SpecifiedValue::Value(VariantEastAsian::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// normal | [ <east-asian-variant-values> || <east-asian-width-values> || ruby ]
|
/// normal | [ <east-asian-variant-values> || <east-asian-width-values> || ruby ]
|
||||||
|
@ -1088,10 +1318,10 @@ macro_rules! exclusive_value {
|
||||||
<% east_asian_variant_values = "JIS78 | JIS83 | JIS90 | JIS04 | SIMPLIFIED | TRADITIONAL" %>
|
<% east_asian_variant_values = "JIS78 | JIS83 | JIS90 | JIS04 | SIMPLIFIED | TRADITIONAL" %>
|
||||||
<% east_asian_width_values = "FULL_WIDTH | PROPORTIONAL_WIDTH" %>
|
<% east_asian_width_values = "FULL_WIDTH | PROPORTIONAL_WIDTH" %>
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
let mut result = SpecifiedValue::empty();
|
let mut result = VariantEastAsian::empty();
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
return Ok(result)
|
return Ok(SpecifiedValue::Value(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||||
|
@ -1120,7 +1350,7 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(result)
|
Ok(SpecifiedValue::Value(result))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
@ -1129,17 +1359,16 @@ macro_rules! exclusive_value {
|
||||||
|
|
||||||
<%helpers:longhand name="font-variant-ligatures" products="gecko" animation_type="none"
|
<%helpers:longhand name="font-variant-ligatures" products="gecko" animation_type="none"
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-ligatures">
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-ligatures">
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub flags SpecifiedValue: u16 {
|
pub flags VariantLigatures: u16 {
|
||||||
const NORMAL = 0,
|
const NORMAL = 0,
|
||||||
const NONE = 0x01,
|
const NONE = 0x01,
|
||||||
const COMMON_LIGATURES = 0x02,
|
const COMMON_LIGATURES = 0x02,
|
||||||
|
@ -1153,7 +1382,30 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum SpecifiedValue {
|
||||||
|
Value(VariantLigatures),
|
||||||
|
System(SystemFont)
|
||||||
|
}
|
||||||
|
|
||||||
|
<%self:simple_system_boilerplate name="font_variant_ligatures"></%self:simple_system_boilerplate>
|
||||||
|
|
||||||
|
// servo_bit: gecko_bit
|
||||||
|
<% font_variant_ligatures_map = { "NONE": "NONE",
|
||||||
|
"COMMON_LIGATURES": "COMMON",
|
||||||
|
"NO_COMMON_LIGATURES": "NO_COMMON",
|
||||||
|
"DISCRETIONARY_LIGATURES": "DISCRETIONARY",
|
||||||
|
"NO_DISCRETIONARY_LIGATURES": "NO_DISCRETIONARY",
|
||||||
|
"HISTORICAL_LIGATURES": "HISTORICAL",
|
||||||
|
"NO_HISTORICAL_LIGATURES": "NO_HISTORICAL",
|
||||||
|
"CONTEXTUAL": "CONTEXTUAL",
|
||||||
|
"NO_CONTEXTUAL": "NO_CONTEXTUAL" } %>
|
||||||
|
|
||||||
|
${helpers.gecko_bitflags_conversion(font_variant_ligatures_map, 'NS_FONT_VARIANT_LIGATURES_',
|
||||||
|
'VariantLigatures', kw_type='u16')}
|
||||||
|
|
||||||
|
impl ToCss for VariantLigatures {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
return dest.write_str("normal")
|
return dest.write_str("normal")
|
||||||
|
@ -1191,7 +1443,7 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
pub type T = super::SpecifiedValue;
|
pub type T = super::VariantLigatures;
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
|
@ -1199,7 +1451,7 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||||
SpecifiedValue::empty()
|
SpecifiedValue::Value(VariantLigatures::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// normal | none |
|
/// normal | none |
|
||||||
|
@ -1216,13 +1468,13 @@ macro_rules! exclusive_value {
|
||||||
<% historical_lig_values = "HISTORICAL_LIGATURES | NO_HISTORICAL_LIGATURES" %>
|
<% historical_lig_values = "HISTORICAL_LIGATURES | NO_HISTORICAL_LIGATURES" %>
|
||||||
<% contextual_alt_values = "CONTEXTUAL | NO_CONTEXTUAL" %>
|
<% contextual_alt_values = "CONTEXTUAL | NO_CONTEXTUAL" %>
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
let mut result = SpecifiedValue::empty();
|
let mut result = VariantLigatures::empty();
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
return Ok(result)
|
return Ok(SpecifiedValue::Value(result))
|
||||||
}
|
}
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(NONE)
|
return Ok(SpecifiedValue::Value(NONE))
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||||
|
@ -1249,7 +1501,7 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(result)
|
Ok(SpecifiedValue::Value(result))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
@ -1258,17 +1510,16 @@ macro_rules! exclusive_value {
|
||||||
|
|
||||||
<%helpers:longhand name="font-variant-numeric" products="gecko" animation_type="none"
|
<%helpers:longhand name="font-variant-numeric" products="gecko" animation_type="none"
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-numeric">
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-numeric">
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::HasViewportPercentage;
|
use values::HasViewportPercentage;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub flags SpecifiedValue: u8 {
|
pub flags VariantNumeric: u8 {
|
||||||
const NORMAL = 0,
|
const NORMAL = 0,
|
||||||
const LINING_NUMS = 0x01,
|
const LINING_NUMS = 0x01,
|
||||||
const OLDSTYLE_NUMS = 0x02,
|
const OLDSTYLE_NUMS = 0x02,
|
||||||
|
@ -1281,7 +1532,31 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum SpecifiedValue {
|
||||||
|
Value(VariantNumeric),
|
||||||
|
System(SystemFont)
|
||||||
|
}
|
||||||
|
|
||||||
|
<%self:simple_system_boilerplate name="font_variant_numeric"></%self:simple_system_boilerplate>
|
||||||
|
|
||||||
|
|
||||||
|
// servo_bit: gecko_bit
|
||||||
|
<% font_variant_numeric_map = { "LINING_NUMS": "LINING",
|
||||||
|
"OLDSTYLE_NUMS": "OLDSTYLE",
|
||||||
|
"PROPORTIONAL_NUMS": "PROPORTIONAL",
|
||||||
|
"TABULAR_NUMS": "TABULAR",
|
||||||
|
"DIAGONAL_FRACTIONS": "DIAGONAL_FRACTIONS",
|
||||||
|
"STACKED_FRACTIONS": "STACKED_FRACTIONS",
|
||||||
|
"SLASHED_ZERO": "SLASHZERO",
|
||||||
|
"ORDINAL": "ORDINAL" } %>
|
||||||
|
|
||||||
|
${helpers.gecko_bitflags_conversion(font_variant_numeric_map, 'NS_FONT_VARIANT_NUMERIC_',
|
||||||
|
'VariantNumeric')}
|
||||||
|
|
||||||
|
impl ToCss for VariantNumeric {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
return dest.write_str("normal")
|
return dest.write_str("normal")
|
||||||
|
@ -1316,7 +1591,7 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
pub type T = super::SpecifiedValue;
|
pub type T = super::VariantNumeric;
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
|
@ -1324,7 +1599,7 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||||
SpecifiedValue::empty()
|
SpecifiedValue::Value(VariantNumeric::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// normal |
|
/// normal |
|
||||||
|
@ -1340,10 +1615,10 @@ macro_rules! exclusive_value {
|
||||||
<% numeric_spacing_values = "PROPORTIONAL_NUMS | TABULAR_NUMS" %>
|
<% numeric_spacing_values = "PROPORTIONAL_NUMS | TABULAR_NUMS" %>
|
||||||
<% numeric_fraction_values = "DIAGONAL_FRACTIONS | STACKED_FRACTIONS" %>
|
<% numeric_fraction_values = "DIAGONAL_FRACTIONS | STACKED_FRACTIONS" %>
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
let mut result = SpecifiedValue::empty();
|
let mut result = VariantNumeric::empty();
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
return Ok(result)
|
return Ok(SpecifiedValue::Value(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||||
|
@ -1370,14 +1645,14 @@ macro_rules! exclusive_value {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(result)
|
Ok(SpecifiedValue::Value(result))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
${helpers.single_keyword("font-variant-position",
|
${helpers.single_keyword_system("font-variant-position",
|
||||||
"normal sub super",
|
"normal sub super",
|
||||||
products="gecko",
|
products="gecko",
|
||||||
gecko_ffi_name="mFont.variantPosition",
|
gecko_ffi_name="mFont.variantPosition",
|
||||||
|
@ -1495,8 +1770,10 @@ ${helpers.single_keyword("font-variant-position",
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
<%helpers:longhand name="font-language-override" products="gecko" animation_type="none" extra_prefixes="moz"
|
<%helpers:longhand name="font-language-override" products="gecko" animation_type="none"
|
||||||
|
extra_prefixes="moz" boxed="True"
|
||||||
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override">
|
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override">
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
|
@ -1508,6 +1785,7 @@ ${helpers.single_keyword("font-variant-position",
|
||||||
pub enum SpecifiedValue {
|
pub enum SpecifiedValue {
|
||||||
Normal,
|
Normal,
|
||||||
Override(String),
|
Override(String),
|
||||||
|
System(SystemFont)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
impl ToCss for SpecifiedValue {
|
||||||
|
@ -1517,6 +1795,20 @@ ${helpers.single_keyword("font-variant-position",
|
||||||
SpecifiedValue::Normal => dest.write_str("normal"),
|
SpecifiedValue::Normal => dest.write_str("normal"),
|
||||||
SpecifiedValue::Override(ref lang) =>
|
SpecifiedValue::Override(ref lang) =>
|
||||||
cssparser::serialize_string(lang, dest),
|
cssparser::serialize_string(lang, dest),
|
||||||
|
SpecifiedValue::System(_) => Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1567,7 +1859,7 @@ ${helpers.single_keyword("font-variant-position",
|
||||||
type ComputedValue = computed_value::T;
|
type ComputedValue = computed_value::T;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, _: &Context) -> computed_value::T {
|
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::Normal => computed_value::T(0),
|
SpecifiedValue::Normal => computed_value::T(0),
|
||||||
|
@ -1582,6 +1874,11 @@ ${helpers.single_keyword("font-variant-position",
|
||||||
let bytes = computed_lang.into_bytes();
|
let bytes = computed_lang.into_bytes();
|
||||||
computed_value::T(BigEndian::read_u32(&bytes))
|
computed_value::T(BigEndian::read_u32(&bytes))
|
||||||
}
|
}
|
||||||
|
SpecifiedValue::System(_) => {
|
||||||
|
<%self:nongecko_unreachable>
|
||||||
|
_context.style.cached_system_font.as_ref().unwrap().font_language_override
|
||||||
|
</%self:nongecko_unreachable>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1801,3 +2098,185 @@ ${helpers.single_keyword("-moz-math-variant",
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
|
||||||
|
% if product == "gecko":
|
||||||
|
pub mod system_font {
|
||||||
|
//! We deal with system fonts here
|
||||||
|
//!
|
||||||
|
//! System fonts can only be set as a group via the font shorthand.
|
||||||
|
//! They resolve at compute time (not parse time -- this lets the
|
||||||
|
//! browser respond to changes to the OS font settings).
|
||||||
|
//!
|
||||||
|
//! While Gecko handles these as a separate property and keyword
|
||||||
|
//! values on each property indicating that the font should be picked
|
||||||
|
//! from the -x-system-font property, we avoid this. Instead,
|
||||||
|
//! each font longhand has a special SystemFont variant which contains
|
||||||
|
//! the specified system font. When the cascade function (in helpers)
|
||||||
|
//! detects that a value has a system font, it will resolve it, and
|
||||||
|
//! cache it on the ComputedValues. After this, it can be just fetched
|
||||||
|
//! whenever a font longhand on the same element needs the system font.
|
||||||
|
|
||||||
|
use app_units::Au;
|
||||||
|
use cssparser::Parser;
|
||||||
|
use properties::longhands;
|
||||||
|
use std::fmt;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
use style_traits::ToCss;
|
||||||
|
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 font_variant_alternates
|
||||||
|
font_variant_ligatures font_variant_east_asian
|
||||||
|
font_variant_numeric""".split()
|
||||||
|
kw_cast = """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
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for SystemFont {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
dest.write_str(match *self {
|
||||||
|
% for font in system_fonts:
|
||||||
|
SystemFont::${to_camel_case(font)} => "${font}",
|
||||||
|
% endfor
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComputedValues are compared at times
|
||||||
|
// so we need these impls. We don't want to
|
||||||
|
// add Eq to Number (which contains a float)
|
||||||
|
// so instead we have an eq impl which skips the
|
||||||
|
// cached values
|
||||||
|
impl PartialEq for ComputedSystemFont {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.system_font == other.system_font
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Eq for ComputedSystemFont {}
|
||||||
|
|
||||||
|
impl Hash for ComputedSystemFont {
|
||||||
|
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||||
|
self.system_font.hash(hasher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToComputedValue for SystemFont {
|
||||||
|
type ComputedValue = ComputedSystemFont;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
|
||||||
|
use gecko_bindings::bindings;
|
||||||
|
use gecko_bindings::structs::{LookAndFeel_FontID, nsFont};
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
let id = match *self {
|
||||||
|
% for font in system_fonts:
|
||||||
|
SystemFont::${to_camel_case(font)} => {
|
||||||
|
LookAndFeel_FontID::eFont_${to_camel_case(font.replace("-moz-", ""))}
|
||||||
|
}
|
||||||
|
% endfor
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut system: nsFont = unsafe { mem::uninitialized() };
|
||||||
|
unsafe {
|
||||||
|
bindings::Gecko_nsFont_InitSystem(&mut system, id as i32,
|
||||||
|
cx.style.get_font().gecko(),
|
||||||
|
&*cx.device.pres_context)
|
||||||
|
}
|
||||||
|
let family = system.fontlist.mFontlist.iter().map(|font| {
|
||||||
|
use properties::longhands::font_family::computed_value::*;
|
||||||
|
FontFamily::FamilyName(FamilyName {
|
||||||
|
name: (&*font.mName).into(),
|
||||||
|
quoted: true
|
||||||
|
})
|
||||||
|
}).collect::<Vec<_>>();
|
||||||
|
let weight = unsafe {
|
||||||
|
longhands::font_weight::computed_value::T::from_gecko_weight(system.weight)
|
||||||
|
};
|
||||||
|
let ret = ComputedSystemFont {
|
||||||
|
font_family: longhands::font_family::computed_value::T(family),
|
||||||
|
font_size: Au(system.size),
|
||||||
|
font_weight: weight,
|
||||||
|
font_size_adjust: longhands::font_size_adjust::computed_value
|
||||||
|
::T::from_gecko_adjust(system.sizeAdjust),
|
||||||
|
% for kwprop in kw_font_props:
|
||||||
|
${kwprop}: longhands::${kwprop}::computed_value::T::from_gecko_keyword(
|
||||||
|
system.${to_camel_case_lower(kwprop.replace('font_', ''))}
|
||||||
|
% if kwprop in kw_cast:
|
||||||
|
as u32
|
||||||
|
% endif
|
||||||
|
),
|
||||||
|
% endfor
|
||||||
|
font_language_override: longhands::font_language_override::computed_value
|
||||||
|
::T(system.languageOverride),
|
||||||
|
system_font: *self,
|
||||||
|
};
|
||||||
|
unsafe { bindings::Gecko_nsFont_Destroy(&mut system); }
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_computed_value(_: &ComputedSystemFont) -> Self {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Compute and cache a system font
|
||||||
|
///
|
||||||
|
/// Must be called before attempting to compute a system font
|
||||||
|
/// specified value
|
||||||
|
pub fn resolve_system_font(system: SystemFont, context: &mut Context) {
|
||||||
|
if context.style.cached_system_font.is_none() {
|
||||||
|
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)]
|
||||||
|
pub struct ComputedSystemFont {
|
||||||
|
% 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)},
|
||||||
|
% endfor
|
||||||
|
_ => return Err(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
% else:
|
||||||
|
pub mod system_font {
|
||||||
|
use cssparser::Parser;
|
||||||
|
|
||||||
|
// We don't parse system fonts, but in the interest of not littering
|
||||||
|
// a lot of code with `if product == gecko` conditionals, we have a
|
||||||
|
// dummy system font module that does nothing
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
/// void enum for system font, can never exist
|
||||||
|
pub enum SystemFont {}
|
||||||
|
impl SystemFont {
|
||||||
|
pub fn parse(_: &mut Parser) -> Result<Self, ()> {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
% endif
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||||
|
<% from data import SYSTEM_FONT_LONGHANDS %>
|
||||||
|
|
||||||
<%helpers:shorthand name="font"
|
<%helpers:shorthand name="font"
|
||||||
sub_properties="font-style font-variant-caps font-weight font-stretch
|
sub_properties="font-style font-variant-caps font-weight font-stretch
|
||||||
|
@ -16,8 +17,10 @@
|
||||||
${'font-variant-position' if product == 'gecko' or data.testing else ''}
|
${'font-variant-position' if product == 'gecko' or data.testing else ''}
|
||||||
${'font-language-override' if product == 'gecko' or data.testing else ''}"
|
${'font-language-override' if product == 'gecko' or data.testing else ''}"
|
||||||
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
|
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
|
||||||
use properties::longhands::{font_style, font_variant_caps, font_weight, font_stretch};
|
use properties::longhands::{font_family, font_style, font_weight, font_stretch};
|
||||||
use properties::longhands::{font_size, line_height};
|
use properties::longhands::{font_size, line_height, font_variant_caps};
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
use properties::longhands::system_font::SystemFont;
|
||||||
<%
|
<%
|
||||||
gecko_sub_properties = "kerning language_override size_adjust \
|
gecko_sub_properties = "kerning language_override size_adjust \
|
||||||
variant_alternates variant_east_asian \
|
variant_alternates variant_east_asian \
|
||||||
|
@ -29,7 +32,7 @@
|
||||||
use properties::longhands::font_${prop};
|
use properties::longhands::font_${prop};
|
||||||
% endfor
|
% endfor
|
||||||
% endif
|
% endif
|
||||||
use properties::longhands::font_family::SpecifiedValue as FontFamily;
|
use self::font_family::SpecifiedValue as FontFamily;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||||
let mut nb_normals = 0;
|
let mut nb_normals = 0;
|
||||||
|
@ -38,6 +41,17 @@
|
||||||
let mut weight = None;
|
let mut weight = None;
|
||||||
let mut stretch = None;
|
let mut stretch = None;
|
||||||
let size;
|
let size;
|
||||||
|
% if product == "gecko":
|
||||||
|
if let Ok(sys) = input.try(SystemFont::parse) {
|
||||||
|
return Ok(Longhands {
|
||||||
|
% for name in SYSTEM_FONT_LONGHANDS:
|
||||||
|
${name}: ${name}::SpecifiedValue::system_font(sys),
|
||||||
|
% endfor
|
||||||
|
// line-height is just reset to initial
|
||||||
|
line_height: line_height::get_initial_specified_value(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
% endif
|
||||||
loop {
|
loop {
|
||||||
// Special-case 'normal' because it is valid in each of
|
// Special-case 'normal' because it is valid in each of
|
||||||
// font-style, font-weight, font-variant and font-stretch.
|
// font-style, font-weight, font-variant and font-stretch.
|
||||||
|
@ -88,7 +102,7 @@
|
||||||
};
|
};
|
||||||
let family = FontFamily::parse(input)?;
|
let family = FontFamily::parse(input)?;
|
||||||
Ok(Longhands {
|
Ok(Longhands {
|
||||||
% for name in "style variant_caps weight stretch size".split():
|
% for name in "style weight stretch size variant_caps".split():
|
||||||
font_${name}: unwrap_or_initial!(font_${name}, ${name}),
|
font_${name}: unwrap_or_initial!(font_${name}, ${name}),
|
||||||
% endfor
|
% endfor
|
||||||
line_height: unwrap_or_initial!(line_height),
|
line_height: unwrap_or_initial!(line_height),
|
||||||
|
@ -101,9 +115,51 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
% if product == "gecko":
|
||||||
|
enum CheckSystemResult {
|
||||||
|
AllSystem(SystemFont),
|
||||||
|
SomeSystem,
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LonghandsToSerialize<'a> {
|
||||||
|
/// Check if some or all members are system fonts
|
||||||
|
fn check_system(&self) -> CheckSystemResult {
|
||||||
|
let mut sys = None;
|
||||||
|
let mut all = true;
|
||||||
|
|
||||||
|
% for prop in SYSTEM_FONT_LONGHANDS:
|
||||||
|
if let Some(s) = self.${prop}.get_system() {
|
||||||
|
debug_assert!(sys.is_none() || s == sys.unwrap());
|
||||||
|
sys = Some(s);
|
||||||
|
} else {
|
||||||
|
all = false;
|
||||||
|
}
|
||||||
|
% endfor
|
||||||
|
if self.line_height != &line_height::get_initial_specified_value() {
|
||||||
|
all = false
|
||||||
|
}
|
||||||
|
if all {
|
||||||
|
CheckSystemResult::AllSystem(sys.unwrap())
|
||||||
|
} else if sys.is_some() {
|
||||||
|
CheckSystemResult::SomeSystem
|
||||||
|
} else {
|
||||||
|
CheckSystemResult::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
% endif
|
||||||
|
|
||||||
// This may be a bit off, unsure, possibly needs changes
|
// This may be a bit off, unsure, possibly needs changes
|
||||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
% if product == "gecko":
|
||||||
|
match self.check_system() {
|
||||||
|
CheckSystemResult::AllSystem(sys) => return sys.to_css(dest),
|
||||||
|
CheckSystemResult::SomeSystem => return Ok(()),
|
||||||
|
CheckSystemResult::None => ()
|
||||||
|
}
|
||||||
|
% endif
|
||||||
|
|
||||||
% if product == "gecko" or data.testing:
|
% if product == "gecko" or data.testing:
|
||||||
% for name in gecko_sub_properties:
|
% for name in gecko_sub_properties:
|
||||||
|
|
|
@ -1393,7 +1393,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetKeywordValue(declarations:
|
||||||
// We rely on Gecko passing in font-size values (0...7) here.
|
// We rely on Gecko passing in font-size values (0...7) here.
|
||||||
longhands::font_size::SpecifiedValue::from_html_size(value as u8)
|
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),
|
FontWeight => longhands::font_weight::SpecifiedValue::from_gecko_keyword(value),
|
||||||
ListStyleType => longhands::list_style_type::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),
|
MozMathVariant => longhands::_moz_math_variant::SpecifiedValue::from_gecko_keyword(value),
|
||||||
|
@ -1631,7 +1631,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetFontFamily(declarations:
|
||||||
let mut parser = Parser::new(&string);
|
let mut parser = Parser::new(&string);
|
||||||
if let Ok(family) = FontFamily::parse(&mut parser) {
|
if let Ok(family) = FontFamily::parse(&mut parser) {
|
||||||
if parser.is_exhausted() {
|
if parser.is_exhausted() {
|
||||||
let decl = PropertyDeclaration::FontFamily(family);
|
let decl = PropertyDeclaration::FontFamily(Box::new(family));
|
||||||
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
||||||
decls.push(decl, Importance::Normal);
|
decls.push(decl, Importance::Normal);
|
||||||
})
|
})
|
||||||
|
@ -1928,7 +1928,7 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis
|
||||||
let default_values = data.default_computed_values();
|
let default_values = data.default_computed_values();
|
||||||
let metrics = get_metrics_provider_for_product();
|
let metrics = get_metrics_provider_for_product();
|
||||||
|
|
||||||
let context = Context {
|
let mut context = Context {
|
||||||
is_root_element: false,
|
is_root_element: false,
|
||||||
device: &data.stylist.device,
|
device: &data.stylist.device,
|
||||||
inherited_style: parent_style.unwrap_or(default_values),
|
inherited_style: parent_style.unwrap_or(default_values),
|
||||||
|
@ -1956,7 +1956,8 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis
|
||||||
.filter_map(|&(ref decl, imp)| {
|
.filter_map(|&(ref decl, imp)| {
|
||||||
if imp == Importance::Normal {
|
if imp == Importance::Normal {
|
||||||
let property = TransitionProperty::from_declaration(decl);
|
let property = TransitionProperty::from_declaration(decl);
|
||||||
let animation = AnimationValue::from_declaration(decl, &context, default_values);
|
let animation = AnimationValue::from_declaration(decl, &mut context,
|
||||||
|
default_values);
|
||||||
debug_assert!(property.is_none() == animation.is_none(),
|
debug_assert!(property.is_none() == animation.is_none(),
|
||||||
"The failure condition of TransitionProperty::from_declaration \
|
"The failure condition of TransitionProperty::from_declaration \
|
||||||
and AnimationValue::from_declaration should be the same");
|
and AnimationValue::from_declaration should be the same");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue