mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #16421 - hiikezoe:font-variant-shorthand, r=heycam
Font variant shorthand <!-- Please describe your changes on the following line: --> This is a PR of https://bugzilla.mozilla.org/show_bug.cgi?id=1354876 --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors <!-- Either: --> - [X] These changes do not require tests because gecko has a bunch of test cases. <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- 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/16421) <!-- Reviewable:end -->
This commit is contained in:
commit
8bd07ec586
10 changed files with 2042 additions and 1204 deletions
|
@ -18,7 +18,7 @@ use std::rc::Rc;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
|
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
|
||||||
use style::computed_values::{font_stretch, font_variant, font_weight};
|
use style::computed_values::{font_stretch, font_variant_caps, font_weight};
|
||||||
use text::Shaper;
|
use text::Shaper;
|
||||||
use text::glyph::{ByteIndex, GlyphData, GlyphId, GlyphStore};
|
use text::glyph::{ByteIndex, GlyphData, GlyphId, GlyphStore};
|
||||||
use text::shaping::ShaperMethods;
|
use text::shaping::ShaperMethods;
|
||||||
|
@ -105,7 +105,7 @@ pub struct FontMetrics {
|
||||||
pub struct Font {
|
pub struct Font {
|
||||||
pub handle: FontHandle,
|
pub handle: FontHandle,
|
||||||
pub metrics: FontMetrics,
|
pub metrics: FontMetrics,
|
||||||
pub variant: font_variant::T,
|
pub variant: font_variant_caps::T,
|
||||||
pub descriptor: FontTemplateDescriptor,
|
pub descriptor: FontTemplateDescriptor,
|
||||||
pub requested_pt_size: Au,
|
pub requested_pt_size: Au,
|
||||||
pub actual_pt_size: Au,
|
pub actual_pt_size: Au,
|
||||||
|
@ -117,7 +117,7 @@ pub struct Font {
|
||||||
|
|
||||||
impl Font {
|
impl Font {
|
||||||
pub fn new(handle: FontHandle,
|
pub fn new(handle: FontHandle,
|
||||||
variant: font_variant::T,
|
variant: font_variant_caps::T,
|
||||||
descriptor: FontTemplateDescriptor,
|
descriptor: FontTemplateDescriptor,
|
||||||
requested_pt_size: Au,
|
requested_pt_size: Au,
|
||||||
actual_pt_size: Au,
|
actual_pt_size: Au,
|
||||||
|
@ -262,8 +262,8 @@ impl Font {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
|
pub fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
|
||||||
let codepoint = match self.variant {
|
let codepoint = match self.variant {
|
||||||
font_variant::T::small_caps => codepoint.to_uppercase().next().unwrap(), //FIXME: #5938
|
font_variant_caps::T::small_caps => codepoint.to_uppercase().next().unwrap(), //FIXME: #5938
|
||||||
font_variant::T::normal => codepoint,
|
font_variant_caps::T::normal => codepoint,
|
||||||
};
|
};
|
||||||
self.handle.glyph_index(codepoint)
|
self.handle.glyph_index(codepoint)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ use std::hash::{BuildHasherDefault, Hash, Hasher};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
||||||
use style::computed_values::{font_style, font_variant};
|
use style::computed_values::{font_style, font_variant_caps};
|
||||||
use style::properties::style_structs;
|
use style::properties::style_structs;
|
||||||
use webrender_traits;
|
use webrender_traits;
|
||||||
|
|
||||||
|
@ -77,14 +77,14 @@ impl FontContext {
|
||||||
template: Arc<FontTemplateData>,
|
template: Arc<FontTemplateData>,
|
||||||
descriptor: FontTemplateDescriptor,
|
descriptor: FontTemplateDescriptor,
|
||||||
pt_size: Au,
|
pt_size: Au,
|
||||||
variant: font_variant::T,
|
variant: font_variant_caps::T,
|
||||||
font_key: webrender_traits::FontKey) -> Result<Font, ()> {
|
font_key: webrender_traits::FontKey) -> Result<Font, ()> {
|
||||||
// TODO: (Bug #3463): Currently we only support fake small-caps
|
// TODO: (Bug #3463): Currently we only support fake small-caps
|
||||||
// painting. We should also support true small-caps (where the
|
// painting. We should also support true small-caps (where the
|
||||||
// font supports it) in the future.
|
// font supports it) in the future.
|
||||||
let actual_pt_size = match variant {
|
let actual_pt_size = match variant {
|
||||||
font_variant::T::small_caps => pt_size.scale_by(SMALL_CAPS_SCALE_FACTOR),
|
font_variant_caps::T::small_caps => pt_size.scale_by(SMALL_CAPS_SCALE_FACTOR),
|
||||||
font_variant::T::normal => pt_size,
|
font_variant_caps::T::normal => pt_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
let handle = try!(FontHandle::new_from_template(&self.platform_handle,
|
let handle = try!(FontHandle::new_from_template(&self.platform_handle,
|
||||||
|
@ -146,7 +146,7 @@ impl FontContext {
|
||||||
let cached_font = (*cached_font_ref).borrow();
|
let cached_font = (*cached_font_ref).borrow();
|
||||||
if cached_font.descriptor == desc &&
|
if cached_font.descriptor == desc &&
|
||||||
cached_font.requested_pt_size == style.font_size &&
|
cached_font.requested_pt_size == style.font_size &&
|
||||||
cached_font.variant == style.font_variant {
|
cached_font.variant == style.font_variant_caps {
|
||||||
fonts.push((*cached_font_ref).clone());
|
fonts.push((*cached_font_ref).clone());
|
||||||
cache_hit = true;
|
cache_hit = true;
|
||||||
break;
|
break;
|
||||||
|
@ -164,7 +164,7 @@ impl FontContext {
|
||||||
let layout_font = self.create_layout_font(template_info.font_template,
|
let layout_font = self.create_layout_font(template_info.font_template,
|
||||||
desc.clone(),
|
desc.clone(),
|
||||||
style.font_size,
|
style.font_size,
|
||||||
style.font_variant,
|
style.font_variant_caps,
|
||||||
template_info.font_key
|
template_info.font_key
|
||||||
.expect("No font key present!"));
|
.expect("No font key present!"));
|
||||||
let font = match layout_font {
|
let font = match layout_font {
|
||||||
|
@ -198,7 +198,7 @@ impl FontContext {
|
||||||
let cached_font = cached_font_entry.font.borrow();
|
let cached_font = cached_font_entry.font.borrow();
|
||||||
if cached_font.descriptor == desc &&
|
if cached_font.descriptor == desc &&
|
||||||
cached_font.requested_pt_size == style.font_size &&
|
cached_font.requested_pt_size == style.font_size &&
|
||||||
cached_font.variant == style.font_variant {
|
cached_font.variant == style.font_variant_caps {
|
||||||
fonts.push(cached_font_entry.font.clone());
|
fonts.push(cached_font_entry.font.clone());
|
||||||
cache_hit = true;
|
cache_hit = true;
|
||||||
break;
|
break;
|
||||||
|
@ -210,7 +210,7 @@ impl FontContext {
|
||||||
let layout_font = self.create_layout_font(template_info.font_template,
|
let layout_font = self.create_layout_font(template_info.font_template,
|
||||||
desc.clone(),
|
desc.clone(),
|
||||||
style.font_size,
|
style.font_size,
|
||||||
style.font_variant,
|
style.font_variant_caps,
|
||||||
template_info.font_key.expect("No font key present!"));
|
template_info.font_key.expect("No font key present!"));
|
||||||
match layout_font {
|
match layout_font {
|
||||||
Ok(layout_font) => {
|
Ok(layout_font) => {
|
||||||
|
|
|
@ -281,6 +281,8 @@ partial interface CSSStyleDeclaration {
|
||||||
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-style;
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-style;
|
||||||
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontVariant;
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontVariant;
|
||||||
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-variant;
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-variant;
|
||||||
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontVariantCaps;
|
||||||
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-variant-caps;
|
||||||
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontWeight;
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontWeight;
|
||||||
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-weight;
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-weight;
|
||||||
|
|
||||||
|
|
|
@ -1916,6 +1916,13 @@ extern "C" {
|
||||||
pub fn Servo_DeclarationBlock_SetTextDecorationColorOverride(declarations:
|
pub fn Servo_DeclarationBlock_SetTextDecorationColorOverride(declarations:
|
||||||
RawServoDeclarationBlockBorrowed);
|
RawServoDeclarationBlockBorrowed);
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Servo_DeclarationBlock_SetBackgroundImage(declarations:
|
||||||
|
RawServoDeclarationBlockBorrowed,
|
||||||
|
value: *const nsAString,
|
||||||
|
extra_data:
|
||||||
|
*mut RawGeckoURLExtraData);
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Servo_MediaList_Create() -> RawServoMediaListStrong;
|
pub fn Servo_MediaList_Create() -> RawServoMediaListStrong;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -293,6 +293,26 @@ 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
|
||||||
///
|
///
|
||||||
|
@ -646,8 +666,6 @@ impl Debug for ${style_struct.gecko_struct_name} {
|
||||||
# Make a list of types we can't auto-generate.
|
# Make a list of types we can't auto-generate.
|
||||||
#
|
#
|
||||||
force_stub = [];
|
force_stub = [];
|
||||||
# These live in an nsFont member in Gecko. Should be straightforward to do manually.
|
|
||||||
force_stub += ["font-variant"]
|
|
||||||
# These have unusual representations in gecko.
|
# These have unusual representations in gecko.
|
||||||
force_stub += ["list-style-type"]
|
force_stub += ["list-style-type"]
|
||||||
|
|
||||||
|
@ -1262,7 +1280,9 @@ fn static_assert() {
|
||||||
|
|
||||||
<%
|
<%
|
||||||
skip_font_longhands = """font-family font-size font-size-adjust font-weight
|
skip_font_longhands = """font-family font-size font-size-adjust font-weight
|
||||||
font-synthesis -x-lang font-language-override"""
|
font-synthesis -x-lang font-variant-alternates
|
||||||
|
font-variant-east-asian font-variant-ligatures
|
||||||
|
font-variant-numeric font-language-override"""
|
||||||
%>
|
%>
|
||||||
<%self:impl_trait style_struct_name="Font"
|
<%self:impl_trait style_struct_name="Font"
|
||||||
skip_longhands="${skip_font_longhands}"
|
skip_longhands="${skip_font_longhands}"
|
||||||
|
@ -1408,6 +1428,76 @@ fn static_assert() {
|
||||||
self.gecko.mFont.languageOverride = v.0;
|
self.gecko.mFont.languageOverride = v.0;
|
||||||
}
|
}
|
||||||
${impl_simple_copy('font_language_override', 'mFont.languageOverride')}
|
${impl_simple_copy('font_language_override', 'mFont.languageOverride')}
|
||||||
|
|
||||||
|
<% font_variant_alternates_map = { "HISTORICAL_FORMS": "HISTORICAL",
|
||||||
|
"STYLISTIC": "STYLISTIC",
|
||||||
|
"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)]
|
||||||
|
pub fn copy_font_variant_alternates_from(&mut self, other: &Self) {
|
||||||
|
self.gecko.mFont.variantAlternates = other.gecko.mFont.variantAlternates;
|
||||||
|
// FIXME: Copy alternateValues as well.
|
||||||
|
// self.gecko.mFont.alternateValues = other.gecko.mFont.alternateValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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" } %>
|
||||||
|
${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')}
|
||||||
|
|
||||||
|
// 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" } %>
|
||||||
|
${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')}
|
||||||
|
|
||||||
|
// 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" } %>
|
||||||
|
${impl_bitflags_setter('font_variant_numeric',
|
||||||
|
'mFont.variantNumeric',
|
||||||
|
font_variant_numeric_map,
|
||||||
|
'NS_FONT_VARIANT_NUMERIC_')}
|
||||||
|
${impl_simple_copy('font_variant_numeric', 'mFont.variantNumeric')}
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%def name="impl_copy_animation_or_transition_value(type, ident, gecko_ffi_name)">
|
<%def name="impl_copy_animation_or_transition_value(type, ident, gecko_ffi_name)">
|
||||||
|
|
|
@ -228,11 +228,6 @@ ${helpers.single_keyword("font-style",
|
||||||
animation_type="none",
|
animation_type="none",
|
||||||
needs_conversion=True)}
|
needs_conversion=True)}
|
||||||
|
|
||||||
${helpers.single_keyword("font-variant",
|
|
||||||
"normal small-caps",
|
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant",
|
|
||||||
animation_type="none")}
|
|
||||||
|
|
||||||
|
|
||||||
<% font_variant_caps_custom_consts= { "small-caps": "SMALLCAPS",
|
<% font_variant_caps_custom_consts= { "small-caps": "SMALLCAPS",
|
||||||
"all-small": "ALLSMALL",
|
"all-small": "ALLSMALL",
|
||||||
|
@ -241,10 +236,10 @@ ${helpers.single_keyword("font-variant",
|
||||||
"titling-caps": "TITLING" } %>
|
"titling-caps": "TITLING" } %>
|
||||||
|
|
||||||
${helpers.single_keyword("font-variant-caps",
|
${helpers.single_keyword("font-variant-caps",
|
||||||
"normal small-caps all-small petite-caps unicase titling-caps",
|
"normal small-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",
|
||||||
gecko_ffi_name="mFont.variantCaps",
|
gecko_ffi_name="mFont.variantCaps",
|
||||||
products="gecko",
|
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
|
||||||
custom_consts=font_variant_caps_custom_consts,
|
custom_consts=font_variant_caps_custom_consts,
|
||||||
animation_type="none")}
|
animation_type="none")}
|
||||||
|
@ -893,6 +888,495 @@ ${helpers.single_keyword("font-kerning",
|
||||||
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")}
|
||||||
|
|
||||||
|
/// FIXME: Implement proper handling of each values.
|
||||||
|
/// https://github.com/servo/servo/issues/15957
|
||||||
|
<%helpers:longhand name="font-variant-alternates" products="gecko" animation_type="none"
|
||||||
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates">
|
||||||
|
use std::fmt;
|
||||||
|
use style_traits::ToCss;
|
||||||
|
use values::HasViewportPercentage;
|
||||||
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
|
||||||
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub flags SpecifiedValue: u8 {
|
||||||
|
const NORMAL = 0,
|
||||||
|
const HISTORICAL_FORMS = 0x01,
|
||||||
|
const STYLISTIC = 0x02,
|
||||||
|
const STYLESET = 0x04,
|
||||||
|
const CHARACTER_VARIANT = 0x08,
|
||||||
|
const SWASH = 0x10,
|
||||||
|
const ORNAMENTS = 0x20,
|
||||||
|
const ANNOTATION = 0x40,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for SpecifiedValue {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
if self.is_empty() {
|
||||||
|
return dest.write_str("normal")
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut has_any = false;
|
||||||
|
|
||||||
|
macro_rules! write_value {
|
||||||
|
($ident:ident => $str:expr) => {
|
||||||
|
if self.intersects($ident) {
|
||||||
|
if has_any {
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
}
|
||||||
|
has_any = true;
|
||||||
|
try!(dest.write_str($str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_value!(HISTORICAL_FORMS => "historical-forms");
|
||||||
|
write_value!(STYLISTIC => "stylistic");
|
||||||
|
write_value!(STYLESET => "styleset");
|
||||||
|
write_value!(CHARACTER_VARIANT => "character-variant");
|
||||||
|
write_value!(SWASH => "swash");
|
||||||
|
write_value!(ORNAMENTS => "ornaments");
|
||||||
|
write_value!(ANNOTATION => "annotation");
|
||||||
|
|
||||||
|
debug_assert!(has_any);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod computed_value {
|
||||||
|
pub type T = super::SpecifiedValue;
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
|
computed_value::T::empty()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||||
|
SpecifiedValue::empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// normal |
|
||||||
|
/// [ stylistic(<feature-value-name>) ||
|
||||||
|
/// historical-forms ||
|
||||||
|
/// styleset(<feature-value-name> #) ||
|
||||||
|
/// character-variant(<feature-value-name> #) ||
|
||||||
|
/// swash(<feature-value-name>) ||
|
||||||
|
/// ornaments(<feature-value-name>) ||
|
||||||
|
/// annotation(<feature-value-name>) ]
|
||||||
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
|
let mut result = SpecifiedValue::empty();
|
||||||
|
|
||||||
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
|
return Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||||
|
let flag = match_ignore_ascii_case! { &ident,
|
||||||
|
"stylistic" => STYLISTIC,
|
||||||
|
"historical-forms" => HISTORICAL_FORMS,
|
||||||
|
"styleset" => STYLESET,
|
||||||
|
"character-variant" => CHARACTER_VARIANT,
|
||||||
|
"swash" => SWASH,
|
||||||
|
"ornaments" => ORNAMENTS,
|
||||||
|
"annotation" => ANNOTATION,
|
||||||
|
_ => return Err(()),
|
||||||
|
};
|
||||||
|
if result.intersects(flag) {
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
|
result.insert(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !result.is_empty() {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
macro_rules! exclusive_value {
|
||||||
|
(($value:ident, $set:expr) => $ident:ident) => {
|
||||||
|
if $value.intersects($set) {
|
||||||
|
return Err(())
|
||||||
|
} else {
|
||||||
|
$ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<%helpers:longhand name="font-variant-east-asian" products="gecko" animation_type="none"
|
||||||
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-east-asian">
|
||||||
|
use std::fmt;
|
||||||
|
use style_traits::ToCss;
|
||||||
|
use values::HasViewportPercentage;
|
||||||
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
|
||||||
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub flags SpecifiedValue: u16 {
|
||||||
|
const NORMAL = 0,
|
||||||
|
const JIS78 = 0x01,
|
||||||
|
const JIS83 = 0x02,
|
||||||
|
const JIS90 = 0x04,
|
||||||
|
const JIS04 = 0x08,
|
||||||
|
const SIMPLIFIED = 0x10,
|
||||||
|
const TRADITIONAL = 0x20,
|
||||||
|
const FULL_WIDTH = 0x40,
|
||||||
|
const PROPORTIONAL_WIDTH = 0x80,
|
||||||
|
const RUBY = 0x100,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for SpecifiedValue {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
if self.is_empty() {
|
||||||
|
return dest.write_str("normal")
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut has_any = false;
|
||||||
|
|
||||||
|
macro_rules! write_value {
|
||||||
|
($ident:ident => $str:expr) => {
|
||||||
|
if self.intersects($ident) {
|
||||||
|
if has_any {
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
}
|
||||||
|
has_any = true;
|
||||||
|
try!(dest.write_str($str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_value!(JIS78 => "jis78");
|
||||||
|
write_value!(JIS83 => "jis83");
|
||||||
|
write_value!(JIS90 => "jis90");
|
||||||
|
write_value!(JIS04 => "jis04");
|
||||||
|
write_value!(SIMPLIFIED => "simplified");
|
||||||
|
write_value!(TRADITIONAL => "traditional");
|
||||||
|
write_value!(FULL_WIDTH => "full-width");
|
||||||
|
write_value!(PROPORTIONAL_WIDTH => "proportional-width");
|
||||||
|
write_value!(RUBY => "ruby");
|
||||||
|
|
||||||
|
debug_assert!(has_any);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod computed_value {
|
||||||
|
pub type T = super::SpecifiedValue;
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
|
computed_value::T::empty()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||||
|
SpecifiedValue::empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// normal | [ <east-asian-variant-values> || <east-asian-width-values> || ruby ]
|
||||||
|
/// <east-asian-variant-values> = [ jis78 | jis83 | jis90 | jis04 | simplified | traditional ]
|
||||||
|
/// <east-asian-width-values> = [ full-width | proportional-width ]
|
||||||
|
<% east_asian_variant_values = "JIS78 | JIS83 | JIS90 | JIS04 | SIMPLIFIED | TRADITIONAL" %>
|
||||||
|
<% east_asian_width_values = "FULL_WIDTH | PROPORTIONAL_WIDTH" %>
|
||||||
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
|
let mut result = SpecifiedValue::empty();
|
||||||
|
|
||||||
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
|
return Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||||
|
let flag = match_ignore_ascii_case! { &ident,
|
||||||
|
"jis78" =>
|
||||||
|
exclusive_value!((result, ${east_asian_variant_values}) => JIS78),
|
||||||
|
"jis83" =>
|
||||||
|
exclusive_value!((result, ${east_asian_variant_values}) => JIS83),
|
||||||
|
"jis90" =>
|
||||||
|
exclusive_value!((result, ${east_asian_variant_values}) => JIS90),
|
||||||
|
"jis04" =>
|
||||||
|
exclusive_value!((result, ${east_asian_variant_values}) => JIS04),
|
||||||
|
"simplified" =>
|
||||||
|
exclusive_value!((result, ${east_asian_variant_values}) => SIMPLIFIED),
|
||||||
|
"traditional" =>
|
||||||
|
exclusive_value!((result, ${east_asian_variant_values}) => TRADITIONAL),
|
||||||
|
"full-width" =>
|
||||||
|
exclusive_value!((result, ${east_asian_width_values}) => FULL_WIDTH),
|
||||||
|
"proportional-width" =>
|
||||||
|
exclusive_value!((result, ${east_asian_width_values}) => PROPORTIONAL_WIDTH),
|
||||||
|
"ruby" =>
|
||||||
|
exclusive_value!((result, RUBY) => RUBY),
|
||||||
|
_ => return Err(()),
|
||||||
|
};
|
||||||
|
result.insert(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !result.is_empty() {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
<%helpers:longhand name="font-variant-ligatures" products="gecko" animation_type="none"
|
||||||
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-ligatures">
|
||||||
|
use std::fmt;
|
||||||
|
use style_traits::ToCss;
|
||||||
|
use values::HasViewportPercentage;
|
||||||
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
|
||||||
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub flags SpecifiedValue: u16 {
|
||||||
|
const NORMAL = 0,
|
||||||
|
const NONE = 0x01,
|
||||||
|
const COMMON_LIGATURES = 0x02,
|
||||||
|
const NO_COMMON_LIGATURES = 0x04,
|
||||||
|
const DISCRETIONARY_LIGATURES = 0x08,
|
||||||
|
const NO_DISCRETIONARY_LIGATURES = 0x10,
|
||||||
|
const HISTORICAL_LIGATURES = 0x20,
|
||||||
|
const NO_HISTORICAL_LIGATURES = 0x40,
|
||||||
|
const CONTEXTUAL = 0x80,
|
||||||
|
const NO_CONTEXTUAL = 0x100,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for SpecifiedValue {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
if self.is_empty() {
|
||||||
|
return dest.write_str("normal")
|
||||||
|
}
|
||||||
|
if self.contains(NONE) {
|
||||||
|
return dest.write_str("none")
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut has_any = false;
|
||||||
|
|
||||||
|
macro_rules! write_value {
|
||||||
|
($ident:ident => $str:expr) => {
|
||||||
|
if self.intersects($ident) {
|
||||||
|
if has_any {
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
}
|
||||||
|
has_any = true;
|
||||||
|
try!(dest.write_str($str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_value!(COMMON_LIGATURES => "common-ligatures");
|
||||||
|
write_value!(NO_COMMON_LIGATURES => "no-common-ligatures");
|
||||||
|
write_value!(DISCRETIONARY_LIGATURES => "discretionary-ligatures");
|
||||||
|
write_value!(NO_DISCRETIONARY_LIGATURES => "no-discretionary-ligatures");
|
||||||
|
write_value!(HISTORICAL_LIGATURES => "historical-ligatures");
|
||||||
|
write_value!(NO_HISTORICAL_LIGATURES => "no-historical-ligatures");
|
||||||
|
write_value!(CONTEXTUAL => "contextual");
|
||||||
|
write_value!(NO_CONTEXTUAL => "no-contextual");
|
||||||
|
|
||||||
|
debug_assert!(has_any);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod computed_value {
|
||||||
|
pub type T = super::SpecifiedValue;
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
|
computed_value::T::empty()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||||
|
SpecifiedValue::empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// normal | none |
|
||||||
|
/// [ <common-lig-values> ||
|
||||||
|
/// <discretionary-lig-values> ||
|
||||||
|
/// <historical-lig-values> ||
|
||||||
|
/// <contextual-alt-values> ]
|
||||||
|
/// <common-lig-values> = [ common-ligatures | no-common-ligatures ]
|
||||||
|
/// <discretionary-lig-values> = [ discretionary-ligatures | no-discretionary-ligatures ]
|
||||||
|
/// <historical-lig-values> = [ historical-ligatures | no-historical-ligatures ]
|
||||||
|
/// <contextual-alt-values> = [ contextual | no-contextual ]
|
||||||
|
<% common_lig_values = "COMMON_LIGATURES | NO_COMMON_LIGATURES" %>
|
||||||
|
<% discretionary_lig_values = "DISCRETIONARY_LIGATURES | NO_DISCRETIONARY_LIGATURES" %>
|
||||||
|
<% historical_lig_values = "HISTORICAL_LIGATURES | NO_HISTORICAL_LIGATURES" %>
|
||||||
|
<% contextual_alt_values = "CONTEXTUAL | NO_CONTEXTUAL" %>
|
||||||
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
|
let mut result = SpecifiedValue::empty();
|
||||||
|
|
||||||
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
|
return Ok(result)
|
||||||
|
}
|
||||||
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
|
return Ok(NONE)
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||||
|
let flag = match_ignore_ascii_case! { &ident,
|
||||||
|
"common-ligatures" =>
|
||||||
|
exclusive_value!((result, ${common_lig_values}) => COMMON_LIGATURES),
|
||||||
|
"no-common-ligatures" =>
|
||||||
|
exclusive_value!((result, ${common_lig_values}) => NO_COMMON_LIGATURES),
|
||||||
|
"discretionary-ligatures" =>
|
||||||
|
exclusive_value!((result, ${discretionary_lig_values}) => DISCRETIONARY_LIGATURES),
|
||||||
|
"no-discretionary-ligatures" =>
|
||||||
|
exclusive_value!((result, ${discretionary_lig_values}) => NO_DISCRETIONARY_LIGATURES),
|
||||||
|
"historical-ligatures" =>
|
||||||
|
exclusive_value!((result, ${historical_lig_values}) => HISTORICAL_LIGATURES),
|
||||||
|
"no-historical-ligatures" =>
|
||||||
|
exclusive_value!((result, ${historical_lig_values}) => NO_HISTORICAL_LIGATURES),
|
||||||
|
"contextual" =>
|
||||||
|
exclusive_value!((result, ${contextual_alt_values}) => CONTEXTUAL),
|
||||||
|
"no-contextual" =>
|
||||||
|
exclusive_value!((result, ${contextual_alt_values}) => NO_CONTEXTUAL),
|
||||||
|
_ => return Err(()),
|
||||||
|
};
|
||||||
|
result.insert(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !result.is_empty() {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
<%helpers:longhand name="font-variant-numeric" products="gecko" animation_type="none"
|
||||||
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-numeric">
|
||||||
|
use std::fmt;
|
||||||
|
use style_traits::ToCss;
|
||||||
|
use values::HasViewportPercentage;
|
||||||
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
|
||||||
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub flags SpecifiedValue: u8 {
|
||||||
|
const NORMAL = 0,
|
||||||
|
const LINING_NUMS = 0x01,
|
||||||
|
const OLDSTYLE_NUMS = 0x02,
|
||||||
|
const PROPORTIONAL_NUMS = 0x04,
|
||||||
|
const TABULAR_NUMS = 0x08,
|
||||||
|
const DIAGONAL_FRACTIONS = 0x10,
|
||||||
|
const STACKED_FRACTIONS = 0x20,
|
||||||
|
const SLASHED_ZERO = 0x40,
|
||||||
|
const ORDINAL = 0x80,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for SpecifiedValue {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
if self.is_empty() {
|
||||||
|
return dest.write_str("normal")
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut has_any = false;
|
||||||
|
|
||||||
|
macro_rules! write_value {
|
||||||
|
($ident:ident => $str:expr) => {
|
||||||
|
if self.intersects($ident) {
|
||||||
|
if has_any {
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
}
|
||||||
|
has_any = true;
|
||||||
|
try!(dest.write_str($str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_value!(LINING_NUMS => "lining-nums");
|
||||||
|
write_value!(OLDSTYLE_NUMS => "oldstyle-nums");
|
||||||
|
write_value!(PROPORTIONAL_NUMS => "proportional-nums");
|
||||||
|
write_value!(TABULAR_NUMS => "tabular-nums");
|
||||||
|
write_value!(DIAGONAL_FRACTIONS => "diagonal-fractions");
|
||||||
|
write_value!(STACKED_FRACTIONS => "stacked-fractions");
|
||||||
|
write_value!(SLASHED_ZERO => "slashed-zero");
|
||||||
|
write_value!(ORDINAL => "ordinal");
|
||||||
|
|
||||||
|
debug_assert!(has_any);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod computed_value {
|
||||||
|
pub type T = super::SpecifiedValue;
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
|
computed_value::T::empty()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||||
|
SpecifiedValue::empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// normal |
|
||||||
|
/// [ <numeric-figure-values> ||
|
||||||
|
/// <numeric-spacing-values> ||
|
||||||
|
/// <numeric-fraction-values> ||
|
||||||
|
/// ordinal ||
|
||||||
|
/// slashed-zero ]
|
||||||
|
/// <numeric-figure-values> = [ lining-nums | oldstyle-nums ]
|
||||||
|
/// <numeric-spacing-values> = [ proportional-nums | tabular-nums ]
|
||||||
|
/// <numeric-fraction-values> = [ diagonal-fractions | stacked-fractions ]
|
||||||
|
<% numeric_figure_values = "LINING_NUMS | OLDSTYLE_NUMS" %>
|
||||||
|
<% numeric_spacing_values = "PROPORTIONAL_NUMS | TABULAR_NUMS" %>
|
||||||
|
<% numeric_fraction_values = "DIAGONAL_FRACTIONS | STACKED_FRACTIONS" %>
|
||||||
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
|
let mut result = SpecifiedValue::empty();
|
||||||
|
|
||||||
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
|
return Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||||
|
let flag = match_ignore_ascii_case! { &ident,
|
||||||
|
"ordinal" =>
|
||||||
|
exclusive_value!((result, ORDINAL) => ORDINAL),
|
||||||
|
"slashed-zero" =>
|
||||||
|
exclusive_value!((result, SLASHED_ZERO) => SLASHED_ZERO),
|
||||||
|
"lining-nums" =>
|
||||||
|
exclusive_value!((result, ${numeric_figure_values}) => LINING_NUMS ),
|
||||||
|
"oldstyle-nums" =>
|
||||||
|
exclusive_value!((result, ${numeric_figure_values}) => OLDSTYLE_NUMS ),
|
||||||
|
"proportional-nums" =>
|
||||||
|
exclusive_value!((result, ${numeric_spacing_values}) => PROPORTIONAL_NUMS ),
|
||||||
|
"tabular-nums" =>
|
||||||
|
exclusive_value!((result, ${numeric_spacing_values}) => TABULAR_NUMS ),
|
||||||
|
"diagonal-fractions" =>
|
||||||
|
exclusive_value!((result, ${numeric_fraction_values}) => DIAGONAL_FRACTIONS ),
|
||||||
|
"stacked-fractions" =>
|
||||||
|
exclusive_value!((result, ${numeric_fraction_values}) => STACKED_FRACTIONS ),
|
||||||
|
_ => return Err(()),
|
||||||
|
};
|
||||||
|
result.insert(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !result.is_empty() {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</%helpers:longhand>
|
||||||
|
|
||||||
${helpers.single_keyword("font-variant-position",
|
${helpers.single_keyword("font-variant-position",
|
||||||
"normal sub super",
|
"normal sub super",
|
||||||
products="gecko",
|
products="gecko",
|
||||||
|
|
|
@ -5,26 +5,36 @@
|
||||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||||
|
|
||||||
<%helpers:shorthand name="font"
|
<%helpers:shorthand name="font"
|
||||||
sub_properties="font-style font-variant font-weight font-stretch
|
sub_properties="font-style font-variant-caps font-weight font-stretch
|
||||||
font-size line-height font-family
|
font-size line-height font-family
|
||||||
${'font-size-adjust' if product == 'gecko' or data.testing else ''}
|
${'font-size-adjust' if product == 'gecko' or data.testing else ''}
|
||||||
${'font-kerning' if product == 'gecko' or data.testing else ''}
|
${'font-kerning' if product == 'gecko' or data.testing else ''}
|
||||||
${'font-variant-caps' if product == 'gecko' or data.testing else ''}
|
${'font-variant-alternates' if product == 'gecko' or data.testing else ''}
|
||||||
|
${'font-variant-east-asian' if product == 'gecko' or data.testing else ''}
|
||||||
|
${'font-variant-ligatures' if product == 'gecko' or data.testing else ''}
|
||||||
|
${'font-variant-numeric' if product == 'gecko' or data.testing else ''}
|
||||||
${'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, font_weight, font_stretch};
|
use properties::longhands::{font_style, font_variant_caps, font_weight, font_stretch};
|
||||||
use properties::longhands::{font_size, line_height};
|
use properties::longhands::{font_size, line_height};
|
||||||
|
<%
|
||||||
|
gecko_sub_properties = "kerning language_override size_adjust \
|
||||||
|
variant_alternates variant_east_asian \
|
||||||
|
variant_ligatures variant_numeric \
|
||||||
|
variant_position".split()
|
||||||
|
%>
|
||||||
% if product == "gecko" or data.testing:
|
% if product == "gecko" or data.testing:
|
||||||
use properties::longhands::{font_size_adjust, font_kerning, font_variant_caps, font_variant_position,
|
% for prop in gecko_sub_properties:
|
||||||
font_language_override};
|
use properties::longhands::font_${prop};
|
||||||
|
% endfor
|
||||||
% endif
|
% endif
|
||||||
use properties::longhands::font_family::SpecifiedValue as FontFamily;
|
use properties::longhands::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;
|
||||||
let mut style = None;
|
let mut style = None;
|
||||||
let mut variant = None;
|
let mut variant_caps = None;
|
||||||
let mut weight = None;
|
let mut weight = None;
|
||||||
let mut stretch = None;
|
let mut stretch = None;
|
||||||
let size;
|
let size;
|
||||||
|
@ -48,9 +58,9 @@
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if variant.is_none() {
|
if variant_caps.is_none() {
|
||||||
if let Ok(value) = input.try(|input| font_variant::parse(context, input)) {
|
if let Ok(value) = input.try(|input| font_variant_caps::parse(context, input)) {
|
||||||
variant = Some(value);
|
variant_caps = Some(value);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +77,8 @@
|
||||||
fn count<T>(opt: &Option<T>) -> u8 {
|
fn count<T>(opt: &Option<T>) -> u8 {
|
||||||
if opt.is_some() { 1 } else { 0 }
|
if opt.is_some() { 1 } else { 0 }
|
||||||
}
|
}
|
||||||
if size.is_none() || (count(&style) + count(&weight) + count(&variant) + count(&stretch) + nb_normals) > 4 {
|
if size.is_none() ||
|
||||||
|
(count(&style) + count(&weight) + count(&variant_caps) + count(&stretch) + nb_normals) > 4 {
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
|
let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
|
||||||
|
@ -77,13 +88,13 @@
|
||||||
};
|
};
|
||||||
let family = FontFamily::parse(input)?;
|
let family = FontFamily::parse(input)?;
|
||||||
Ok(Longhands {
|
Ok(Longhands {
|
||||||
% for name in "style variant weight stretch size".split():
|
% for name in "style variant_caps weight stretch size".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),
|
||||||
font_family: family,
|
font_family: family,
|
||||||
% if product == "gecko" or data.testing:
|
% if product == "gecko" or data.testing:
|
||||||
% for name in "size_adjust kerning variant_caps variant_position language_override".split():
|
% for name in gecko_sub_properties:
|
||||||
font_${name}: font_${name}::get_initial_specified_value(),
|
font_${name}: font_${name}::get_initial_specified_value(),
|
||||||
% endfor
|
% endfor
|
||||||
% endif
|
% endif
|
||||||
|
@ -95,14 +106,14 @@
|
||||||
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" or data.testing:
|
% if product == "gecko" or data.testing:
|
||||||
% for name in "size_adjust kerning variant_caps variant_position language_override".split():
|
% for name in gecko_sub_properties:
|
||||||
if self.font_${name} != &font_${name}::get_initial_specified_value() {
|
if self.font_${name} != &font_${name}::get_initial_specified_value() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
% endfor
|
% endfor
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
% for name in "style variant weight stretch".split():
|
% for name in "style variant_caps weight stretch".split():
|
||||||
self.font_${name}.to_css(dest)?;
|
self.font_${name}.to_css(dest)?;
|
||||||
dest.write_str(" ")?;
|
dest.write_str(" ")?;
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -124,3 +135,76 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:shorthand>
|
</%helpers:shorthand>
|
||||||
|
|
||||||
|
<%helpers:shorthand name="font-variant"
|
||||||
|
sub_properties="font-variant-caps
|
||||||
|
${'font-variant-alternates' if product == 'gecko' or data.testing else ''}
|
||||||
|
${'font-variant-east-asian' if product == 'gecko' or data.testing else ''}
|
||||||
|
${'font-variant-ligatures' if product == 'gecko' or data.testing else ''}
|
||||||
|
${'font-variant-numeric' if product == 'gecko' or data.testing else ''}
|
||||||
|
${'font-variant-position' if product == 'gecko' or data.testing else ''}"
|
||||||
|
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-variant">
|
||||||
|
use properties::longhands::font_variant_caps;
|
||||||
|
<% gecko_sub_properties = "alternates east_asian ligatures numeric position".split() %>
|
||||||
|
% if product == "gecko" or data.testing:
|
||||||
|
% for prop in gecko_sub_properties:
|
||||||
|
use properties::longhands::font_variant_${prop};
|
||||||
|
% endfor
|
||||||
|
% endif
|
||||||
|
|
||||||
|
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||||
|
let mut nb_normals = 0;
|
||||||
|
let mut caps = None;
|
||||||
|
loop {
|
||||||
|
// Special-case 'normal' because it is valid in each of
|
||||||
|
// all sub properties.
|
||||||
|
// Leaves the values to None, 'normal' is the initial value for each of them.
|
||||||
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
|
nb_normals += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if caps.is_none() {
|
||||||
|
if let Ok(value) = input.try(|input| font_variant_caps::parse(context, input)) {
|
||||||
|
caps = Some(value);
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn count<T>(opt: &Option<T>) -> u8 {
|
||||||
|
if opt.is_some() { 1 } else { 0 }
|
||||||
|
}
|
||||||
|
let count = count(&caps) + nb_normals;
|
||||||
|
if count == 0 || count > 1 {
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
|
Ok(Longhands {
|
||||||
|
font_variant_caps: unwrap_or_initial!(font_variant_caps, caps),
|
||||||
|
// FIXME: Bug 1356134 - parse all sub properties.
|
||||||
|
% if product == "gecko" or data.testing:
|
||||||
|
% for name in gecko_sub_properties:
|
||||||
|
font_variant_${name}: font_variant_${name}::get_initial_specified_value(),
|
||||||
|
% endfor
|
||||||
|
% endif
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
|
||||||
|
% if product == "gecko" or data.testing:
|
||||||
|
% for name in gecko_sub_properties:
|
||||||
|
// FIXME: Bug 1356134 - handle all sub properties.
|
||||||
|
if self.font_variant_${name} != &font_variant_${name}::get_initial_specified_value() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
% endfor
|
||||||
|
% endif
|
||||||
|
|
||||||
|
self.font_variant_caps.to_css(dest)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</%helpers:shorthand>
|
||||||
|
|
|
@ -201,7 +201,7 @@ fn compute_damage(old: &ServoComputedValues, new: &ServoComputedValues) -> Servo
|
||||||
get_inheritedtext.text_transform, get_inheritedtext.word_spacing,
|
get_inheritedtext.text_transform, get_inheritedtext.word_spacing,
|
||||||
get_inheritedtext.overflow_wrap, get_inheritedtext.text_justify,
|
get_inheritedtext.overflow_wrap, get_inheritedtext.text_justify,
|
||||||
get_inheritedtext.white_space, get_inheritedtext.word_break, get_text.text_overflow,
|
get_inheritedtext.white_space, get_inheritedtext.word_break, get_text.text_overflow,
|
||||||
get_font.font_family, get_font.font_style, get_font.font_variant, get_font.font_weight,
|
get_font.font_family, get_font.font_style, get_font.font_variant_caps, get_font.font_weight,
|
||||||
get_font.font_size, get_font.font_stretch,
|
get_font.font_size, get_font.font_stretch,
|
||||||
get_inheritedbox.direction, get_inheritedbox.writing_mode,
|
get_inheritedbox.direction, get_inheritedbox.writing_mode,
|
||||||
get_text.text_decoration_line, get_text.unicode_bidi,
|
get_text.text_decoration_line, get_text.unicode_bidi,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue