aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/macros.rs10
-rw-r--r--components/style/properties/longhand/font.mako.rs154
-rw-r--r--components/style/values/computed/font.rs3
-rw-r--r--components/style/values/computed/mod.rs3
-rw-r--r--components/style/values/specified/font.rs244
-rw-r--r--components/style/values/specified/mod.rs3
-rw-r--r--ports/geckolib/glue.rs1
7 files changed, 270 insertions, 148 deletions
diff --git a/components/style/macros.rs b/components/style/macros.rs
index c614a2292ca..236a03f1f8a 100644
--- a/components/style/macros.rs
+++ b/components/style/macros.rs
@@ -4,6 +4,16 @@
//! Various macro helpers.
+macro_rules! exclusive_value {
+ (($value:ident, $set:expr) => $ident:path) => {
+ if $value.intersects($set) {
+ return Err(())
+ } else {
+ $ident
+ }
+ }
+}
+
macro_rules! trivial_to_computed_value {
($name:ty) => {
impl $crate::values::computed::ToComputedValue for $name {
diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs
index 4defee919a8..428d9d8c1c1 100644
--- a/components/style/properties/longhand/font.mako.rs
+++ b/components/style/properties/longhand/font.mako.rs
@@ -690,152 +690,14 @@ macro_rules! exclusive_value {
}
}
-<%helpers:longhand name="font-variant-east-asian" products="gecko" animation_value_type="discrete"
- flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
- spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-east-asian">
- use properties::longhands::system_font::SystemFont;
- use std::fmt;
- use style_traits::ToCss;
-
-
- bitflags! {
- #[derive(MallocSizeOf)]
- pub struct VariantEastAsian: 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;
- }
- }
-
- #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
- #[derive(Clone, Debug, PartialEq, ToCss)]
- 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 = { "VariantEastAsian::JIS78": "JIS78",
- "VariantEastAsian::JIS83": "JIS83",
- "VariantEastAsian::JIS90": "JIS90",
- "VariantEastAsian::JIS04": "JIS04",
- "VariantEastAsian::SIMPLIFIED": "SIMPLIFIED",
- "VariantEastAsian::TRADITIONAL": "TRADITIONAL",
- "VariantEastAsian::FULL_WIDTH": "FULL_WIDTH",
- "VariantEastAsian::PROPORTIONAL_WIDTH": "PROP_WIDTH",
- "VariantEastAsian::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 {
- if self.is_empty() {
- return dest.write_str("normal")
- }
-
- let mut has_any = false;
-
- macro_rules! write_value {
- ($ident:path => $str:expr) => {
- if self.intersects($ident) {
- if has_any {
- dest.write_str(" ")?;
- }
- has_any = true;
- dest.write_str($str)?;
- }
- }
- }
-
- write_value!(VariantEastAsian::JIS78 => "jis78");
- write_value!(VariantEastAsian::JIS83 => "jis83");
- write_value!(VariantEastAsian::JIS90 => "jis90");
- write_value!(VariantEastAsian::JIS04 => "jis04");
- write_value!(VariantEastAsian::SIMPLIFIED => "simplified");
- write_value!(VariantEastAsian::TRADITIONAL => "traditional");
- write_value!(VariantEastAsian::FULL_WIDTH => "full-width");
- write_value!(VariantEastAsian::PROPORTIONAL_WIDTH => "proportional-width");
- write_value!(VariantEastAsian::RUBY => "ruby");
-
- debug_assert!(has_any);
- Ok(())
- }
- }
-
- pub mod computed_value {
- pub type T = super::VariantEastAsian;
- }
- #[inline]
- pub fn get_initial_value() -> computed_value::T {
- computed_value::T::empty()
- }
- #[inline]
- pub fn get_initial_specified_value() -> SpecifiedValue {
- SpecifiedValue::Value(VariantEastAsian::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 = """VariantEastAsian::JIS78 | VariantEastAsian::JIS83 |
- VariantEastAsian::JIS90 | VariantEastAsian::JIS04 |
- VariantEastAsian::SIMPLIFIED | VariantEastAsian::TRADITIONAL""" %>
- <% east_asian_width_values = "VariantEastAsian::FULL_WIDTH | VariantEastAsian::PROPORTIONAL_WIDTH" %>
- pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
- -> Result<SpecifiedValue, ParseError<'i>> {
- let mut result = VariantEastAsian::empty();
-
- if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
- return Ok(SpecifiedValue::Value(result))
- }
-
- while let Ok(flag) = input.try(|input| {
- Ok(match_ignore_ascii_case! { &input.expect_ident().map_err(|_| ())?,
- "jis78" =>
- exclusive_value!((result, ${east_asian_variant_values}) => VariantEastAsian::JIS78),
- "jis83" =>
- exclusive_value!((result, ${east_asian_variant_values}) => VariantEastAsian::JIS83),
- "jis90" =>
- exclusive_value!((result, ${east_asian_variant_values}) => VariantEastAsian::JIS90),
- "jis04" =>
- exclusive_value!((result, ${east_asian_variant_values}) => VariantEastAsian::JIS04),
- "simplified" =>
- exclusive_value!((result, ${east_asian_variant_values}) => VariantEastAsian::SIMPLIFIED),
- "traditional" =>
- exclusive_value!((result, ${east_asian_variant_values}) => VariantEastAsian::TRADITIONAL),
- "full-width" =>
- exclusive_value!((result, ${east_asian_width_values}) => VariantEastAsian::FULL_WIDTH),
- "proportional-width" =>
- exclusive_value!((result, ${east_asian_width_values}) => VariantEastAsian::PROPORTIONAL_WIDTH),
- "ruby" =>
- exclusive_value!((result, VariantEastAsian::RUBY) => VariantEastAsian::RUBY),
- _ => return Err(()),
- })
- }) {
- result.insert(flag);
- }
-
- if !result.is_empty() {
- Ok(SpecifiedValue::Value(result))
- } else {
- Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
- }
- }
-
- #[cfg(feature = "gecko")]
- impl_gecko_keyword_conversions!(VariantEastAsian, u16);
-</%helpers:longhand>
+${helpers.predefined_type("font-variant-east-asian",
+ "FontVariantEastAsian",
+ products="gecko",
+ initial_value="computed::FontVariantEastAsian::empty()",
+ initial_specified_value="specified::FontVariantEastAsian::empty()",
+ animation_value_type="discrete",
+ flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
+ spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-east-asian")}
<%helpers:longhand name="font-variant-ligatures" products="gecko" animation_value_type="discrete"
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs
index cc3487f7a12..70981d6bf74 100644
--- a/components/style/values/computed/font.rs
+++ b/components/style/values/computed/font.rs
@@ -277,6 +277,9 @@ impl FontVariantAlternates {
}
}
+/// Use VariantEastAsian as computed type of FontVariantEastAsian
+pub type FontVariantEastAsian = specified::VariantEastAsian;
+
/// font-language-override can only have a single three-letter
/// OpenType "language system" tag, so we should be able to compute
/// it and store it as a 32-bit integer
diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs
index e613ee18d16..d5dda639464 100644
--- a/components/style/values/computed/mod.rs
+++ b/components/style/values/computed/mod.rs
@@ -37,7 +37,8 @@ pub use self::background::{BackgroundSize, BackgroundRepeat};
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
pub use self::border::{BorderRadius, BorderCornerRadius, BorderSpacing};
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
-pub use self::font::{FontLanguageOverride, FontVariantSettings, MozScriptLevel, MozScriptMinSize, XTextZoom};
+pub use self::font::{FontLanguageOverride, FontVariantSettings, FontVariantEastAsian};
+pub use self::font::{MozScriptLevel, MozScriptMinSize, XTextZoom};
pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs
index a078283565e..839978e1222 100644
--- a/components/style/values/specified/font.rs
+++ b/components/style/values/specified/font.rs
@@ -851,6 +851,250 @@ impl Parse for FontVariantAlternates {
}
}
+bitflags! {
+ #[derive(MallocSizeOf)]
+ /// Vairants for east asian variant
+ pub struct VariantEastAsian: u16 {
+ /// None of the features
+ const NORMAL = 0;
+ /// Enables rendering of JIS78 forms (OpenType feature: jp78)
+ const JIS78 = 0x01;
+ /// Enables rendering of JIS83 forms (OpenType feature: jp83).
+ const JIS83 = 0x02;
+ /// Enables rendering of JIS90 forms (OpenType feature: jp90).
+ const JIS90 = 0x04;
+ /// Enables rendering of JIS2004 forms (OpenType feature: jp04).
+ const JIS04 = 0x08;
+ /// Enables rendering of simplified forms (OpenType feature: smpl).
+ const SIMPLIFIED = 0x10;
+ /// Enables rendering of traditional forms (OpenType feature: trad).
+ const TRADITIONAL = 0x20;
+ /// Enables rendering of full-width variants (OpenType feature: fwid).
+ const FULL_WIDTH = 0x40;
+ /// Enables rendering of proportionally-spaced variants (OpenType feature: pwid).
+ const PROPORTIONAL_WIDTH = 0x80;
+ /// Enables display of ruby variant glyphs (OpenType feature: ruby).
+ const RUBY = 0x100;
+ }
+}
+
+#[cfg(feature = "gecko")]
+impl VariantEastAsian {
+ /// Obtain a specified value from a Gecko keyword value
+ ///
+ /// Intended for use with presentation attributes, not style structs
+ pub fn from_gecko_keyword(kw: u16) -> Self {
+ Self::from_bits_truncate(kw)
+ }
+
+ /// Transform into gecko keyword
+ pub fn to_gecko_keyword(self) -> u16 {
+ self.bits()
+ }
+}
+
+impl ToCss for VariantEastAsian {
+ 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:path => $str:expr) => {
+ if self.intersects($ident) {
+ if has_any {
+ dest.write_str(" ")?;
+ }
+ has_any = true;
+ dest.write_str($str)?;
+ }
+ }
+ }
+
+ write_value!(VariantEastAsian::JIS78 => "jis78");
+ write_value!(VariantEastAsian::JIS83 => "jis83");
+ write_value!(VariantEastAsian::JIS90 => "jis90");
+ write_value!(VariantEastAsian::JIS04 => "jis04");
+ write_value!(VariantEastAsian::SIMPLIFIED => "simplified");
+ write_value!(VariantEastAsian::TRADITIONAL => "traditional");
+ write_value!(VariantEastAsian::FULL_WIDTH => "full-width");
+ write_value!(VariantEastAsian::PROPORTIONAL_WIDTH => "proportional-width");
+ write_value!(VariantEastAsian::RUBY => "ruby");
+
+ debug_assert!(has_any);
+ Ok(())
+ }
+}
+
+#[cfg(feature = "gecko")]
+impl From<u16> for VariantEastAsian {
+ fn from(bits: u16) -> VariantEastAsian {
+ VariantEastAsian::from_gecko_keyword(bits)
+ }
+}
+
+#[cfg(feature = "gecko")]
+impl From<VariantEastAsian> for u16 {
+ fn from(v: VariantEastAsian) -> u16 {
+ v.to_gecko_keyword()
+ }
+}
+
+/// Asserts that all variant-east-asian matches its NS_FONT_VARIANT_EAST_ASIAN_* value.
+#[cfg(feature = "gecko")]
+#[inline]
+pub fn assert_variant_east_asian_matches() {
+ use gecko_bindings::structs;
+
+ macro_rules! check_variant_east_asian {
+ ( $( $a:ident => $b:path),*, ) => {
+ if cfg!(debug_assertions) {
+ $(
+ assert_eq!(structs::$a as u16, $b.bits());
+ )*
+ }
+ }
+ }
+
+ check_variant_east_asian! {
+ NS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH => VariantEastAsian::FULL_WIDTH,
+ NS_FONT_VARIANT_EAST_ASIAN_JIS04 => VariantEastAsian::JIS04,
+ NS_FONT_VARIANT_EAST_ASIAN_JIS78 => VariantEastAsian::JIS78,
+ NS_FONT_VARIANT_EAST_ASIAN_JIS83 => VariantEastAsian::JIS83,
+ NS_FONT_VARIANT_EAST_ASIAN_JIS90 => VariantEastAsian::JIS90,
+ NS_FONT_VARIANT_EAST_ASIAN_PROP_WIDTH => VariantEastAsian::PROPORTIONAL_WIDTH,
+ NS_FONT_VARIANT_EAST_ASIAN_RUBY => VariantEastAsian::RUBY,
+ NS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED => VariantEastAsian::SIMPLIFIED,
+ NS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL => VariantEastAsian::TRADITIONAL,
+ }
+}
+
+#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
+#[derive(Clone, Debug, PartialEq, ToCss)]
+/// Allows control of glyph substitution and sizing in East Asian text.
+pub enum FontVariantEastAsian {
+ /// Value variant with `variant-east-asian`
+ Value(VariantEastAsian),
+ /// System font variant
+ System(SystemFont)
+}
+
+impl FontVariantEastAsian {
+ #[inline]
+ /// Get default `font-variant-east-asian` with `empty` variant
+ pub fn empty() -> Self {
+ FontVariantEastAsian::Value(VariantEastAsian::empty())
+ }
+
+ /// Get `font-variant-east-asian` with system font
+ pub fn system_font(f: SystemFont) -> Self {
+ FontVariantEastAsian::System(f)
+ }
+
+ /// Get system font
+ pub fn get_system(&self) -> Option<SystemFont> {
+ if let FontVariantEastAsian::System(s) = *self {
+ Some(s)
+ } else {
+ None
+ }
+ }
+}
+
+impl ToComputedValue for FontVariantEastAsian {
+ type ComputedValue = computed::FontVariantEastAsian;
+
+ fn to_computed_value(&self, _context: &Context) -> computed::FontVariantEastAsian {
+ match *self {
+ FontVariantEastAsian::Value(ref v) => v.clone(),
+ FontVariantEastAsian::System(_) => {
+ #[cfg(feature = "gecko")] {
+ _context.cached_system_font.as_ref().unwrap().font_variant_east_asian.clone()
+ }
+ #[cfg(feature = "servo")] {
+ unreachable!()
+ }
+ }
+ }
+ }
+
+ fn from_computed_value(other: &computed::FontVariantEastAsian) -> Self {
+ FontVariantEastAsian::Value(other.clone())
+ }
+}
+
+impl Parse for FontVariantEastAsian {
+ /// 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 ]
+ fn parse<'i, 't>(
+ _context: &ParserContext,
+ input: &mut Parser<'i, 't>
+ ) -> Result<FontVariantEastAsian, ParseError<'i>> {
+ let mut result = VariantEastAsian::empty();
+
+ if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
+ return Ok(FontVariantEastAsian::Value(result))
+ }
+
+ while let Ok(flag) = input.try(|input| {
+ Ok(match_ignore_ascii_case! { &input.expect_ident().map_err(|_| ())?,
+ "jis78" =>
+ exclusive_value!((result, VariantEastAsian::JIS78 | VariantEastAsian::JIS83 |
+ VariantEastAsian::JIS90 | VariantEastAsian::JIS04 |
+ VariantEastAsian::SIMPLIFIED | VariantEastAsian::TRADITIONAL
+ ) => VariantEastAsian::JIS78),
+ "jis83" =>
+ exclusive_value!((result, VariantEastAsian::JIS78 | VariantEastAsian::JIS83 |
+ VariantEastAsian::JIS90 | VariantEastAsian::JIS04 |
+ VariantEastAsian::SIMPLIFIED | VariantEastAsian::TRADITIONAL
+ ) => VariantEastAsian::JIS83),
+ "jis90" =>
+ exclusive_value!((result, VariantEastAsian::JIS78 | VariantEastAsian::JIS83 |
+ VariantEastAsian::JIS90 | VariantEastAsian::JIS04 |
+ VariantEastAsian::SIMPLIFIED | VariantEastAsian::TRADITIONAL
+ ) => VariantEastAsian::JIS90),
+ "jis04" =>
+ exclusive_value!((result, VariantEastAsian::JIS78 | VariantEastAsian::JIS83 |
+ VariantEastAsian::JIS90 | VariantEastAsian::JIS04 |
+ VariantEastAsian::SIMPLIFIED | VariantEastAsian::TRADITIONAL
+ ) => VariantEastAsian::JIS04),
+ "simplified" =>
+ exclusive_value!((result, VariantEastAsian::JIS78 | VariantEastAsian::JIS83 |
+ VariantEastAsian::JIS90 | VariantEastAsian::JIS04 |
+ VariantEastAsian::SIMPLIFIED | VariantEastAsian::TRADITIONAL
+ ) => VariantEastAsian::SIMPLIFIED),
+ "traditional" =>
+ exclusive_value!((result, VariantEastAsian::JIS78 | VariantEastAsian::JIS83 |
+ VariantEastAsian::JIS90 | VariantEastAsian::JIS04 |
+ VariantEastAsian::SIMPLIFIED | VariantEastAsian::TRADITIONAL
+ ) => VariantEastAsian::TRADITIONAL),
+ "full-width" =>
+ exclusive_value!((result, VariantEastAsian::FULL_WIDTH |
+ VariantEastAsian::PROPORTIONAL_WIDTH
+ ) => VariantEastAsian::FULL_WIDTH),
+ "proportional-width" =>
+ exclusive_value!((result, VariantEastAsian::FULL_WIDTH |
+ VariantEastAsian::PROPORTIONAL_WIDTH
+ ) => VariantEastAsian::PROPORTIONAL_WIDTH),
+ "ruby" =>
+ exclusive_value!((result, VariantEastAsian::RUBY) => VariantEastAsian::RUBY),
+ _ => return Err(()),
+ })
+ }) {
+ result.insert(flag);
+ }
+
+ if !result.is_empty() {
+ Ok(FontVariantEastAsian::Value(result))
+ } else {
+ Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
+ }
+ }
+}
+
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
/// Whether user agents are allowed to synthesize bold or oblique font faces
/// when a font family lacks bold or italic faces
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index 2dab11fb457..d85ecb7d435 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -31,7 +31,8 @@ pub use self::background::{BackgroundRepeat, BackgroundSize};
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
-pub use self::font::{FontLanguageOverride, FontVariantSettings, MozScriptLevel, MozScriptMinSize, XTextZoom};
+pub use self::font::{FontLanguageOverride, FontVariantSettings, FontVariantEastAsian};
+pub use self::font::{MozScriptLevel, MozScriptMinSize, XTextZoom};
pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs
index e0032eea5c9..f002d440185 100644
--- a/ports/geckolib/glue.rs
+++ b/ports/geckolib/glue.rs
@@ -186,6 +186,7 @@ pub extern "C" fn Servo_Initialize(dummy_url_data: *mut URLExtraData) {
origin_flags::assert_flags_match();
parser::assert_parsing_mode_match();
traversal_flags::assert_traversal_flags_match();
+ specified::font::assert_variant_east_asian_matches();
// Initialize the dummy url data
unsafe { DUMMY_URL_DATA = dummy_url_data; }